[Midnightbsd-cvs] src: sys/netipx: Sync with enhancements from FreeBSD 7.

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Mon Sep 15 20:23:40 EDT 2008


Log Message:
-----------
Sync with enhancements from FreeBSD 7.

Modified Files:
--------------
    src/sys/netipx:
        README (r1.1.1.1 -> r1.2)
        ipx.c (r1.1.1.1 -> r1.2)
        ipx.h (r1.1.1.1 -> r1.2)
        ipx_cksum.c (r1.1.1.1 -> r1.2)
        ipx_if.h (r1.1.1.1 -> r1.2)
        ipx_input.c (r1.1.1.2 -> r1.2)
        ipx_outputfl.c (r1.1.1.1 -> r1.2)
        ipx_pcb.c (r1.1.1.1 -> r1.2)
        ipx_pcb.h (r1.1.1.1 -> r1.2)
        ipx_proto.c (r1.1.1.1 -> r1.2)
        ipx_usrreq.c (r1.1.1.1 -> r1.2)
        ipx_var.h (r1.1.1.1 -> r1.2)
        spx.h (r1.1.1.1 -> r1.2)
        spx_debug.c (r1.1.1.1 -> r1.2)
        spx_debug.h (r1.1.1.1 -> r1.2)
        spx_timer.h (r1.1.1.1 -> r1.2)
        spx_usrreq.c (r1.1.1.1 -> r1.2)
        spx_var.h (r1.1.1.1 -> r1.2)

Removed Files:
-------------
    src/sys/netipx:
        ipx_ip.c
        ipx_ip.h

-------------- next part --------------
Index: spx_debug.h
===================================================================
RCS file: /home/cvs/src/sys/netipx/spx_debug.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/spx_debug.h -L sys/netipx/spx_debug.h -u -r1.1.1.1 -r1.2
--- sys/netipx/spx_debug.h
+++ sys/netipx/spx_debug.h
@@ -1,5 +1,4 @@
 /*-
- * Copyright (c) 1995, Mike Mitchell
  * Copyright (c) 1984, 1985, 1986, 1987, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -11,6 +10,32 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1995, Mike Mitchell
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *	This product includes software developed by the University of
@@ -33,7 +58,7 @@
  *
  *	@(#)spx_debug.h
  *
- * $FreeBSD: src/sys/netipx/spx_debug.h,v 1.15 2005/01/07 01:45:47 imp Exp $
+ * $FreeBSD: src/sys/netipx/spx_debug.h,v 1.18 2007/07/30 11:06:42 des Exp $
  */
 
 #ifndef _NETIPX_SPX_DEBUG_H_
@@ -70,10 +95,9 @@
 #ifdef _KERNEL
 extern char *prurequests[];
 extern char *sanames[];
-extern char *tcpstates[];
 
-void	spx_trace(int act, int ostate, struct spxpcb *sp, struct spx *si,
-		       int req);
+void	spx_trace(short act, u_char ostate, struct spxpcb *sp, struct spx *si,
+	    int req);
 #endif
 
 #endif /* !_NETIPX_SPX_DEBUG_H_ */
Index: ipx_outputfl.c
===================================================================
RCS file: /home/cvs/src/sys/netipx/ipx_outputfl.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/ipx_outputfl.c -L sys/netipx/ipx_outputfl.c -u -r1.1.1.1 -r1.2
--- sys/netipx/ipx_outputfl.c
+++ sys/netipx/ipx_outputfl.c
@@ -1,5 +1,4 @@
 /*-
- * Copyright (c) 1995, Mike Mitchell
  * Copyright (c) 1984, 1985, 1986, 1987, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -11,6 +10,32 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1995, Mike Mitchell
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *	This product includes software developed by the University of
@@ -35,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/netipx/ipx_outputfl.c,v 1.22 2005/01/07 01:45:47 imp Exp $");
+__FBSDID("$FreeBSD: src/sys/netipx/ipx_outputfl.c,v 1.24 2007/05/11 10:38:34 rwatson Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -52,13 +77,10 @@
 static int ipx_copy_output = 0;
 
 int
-ipx_outputfl(m0, ro, flags)
-	struct mbuf *m0;
-	struct route *ro;
-	int flags;
+ipx_outputfl(struct mbuf *m0, struct route *ro, int flags)
 {
-	register struct ipx *ipx = mtod(m0, struct ipx *);
-	register struct ifnet *ifp = NULL;
+	struct ipx *ipx = mtod(m0, struct ipx *);
+	struct ifnet *ifp = NULL;
 	int error = 0;
 	struct sockaddr_ipx *dst;
 	struct route ipxroute;
@@ -157,10 +179,9 @@
  * that have ipx configured and isn't in the list yet.
  */
 int
-ipx_output_type20(m)
-	struct mbuf *m;
+ipx_output_type20(struct mbuf *m)
 {
-	register struct ipx *ipx;
+	struct ipx *ipx;
 	union ipx_net *nbnet;
 	struct ipx_ifaddr *ia, *tia = NULL;
 	int error = 0;
Index: ipx_input.c
===================================================================
RCS file: /home/cvs/src/sys/netipx/ipx_input.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -L sys/netipx/ipx_input.c -L sys/netipx/ipx_input.c -u -r1.1.1.2 -r1.2
--- sys/netipx/ipx_input.c
+++ sys/netipx/ipx_input.c
@@ -1,8 +1,35 @@
 /*-
+ * Copyright (c) 1984, 1985, 1986, 1987, 1993
+ *	The Regents of the University of California.
  * Copyright (c) 2004-2005 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
  * Copyright (c) 1995, Mike Mitchell
- * Copyright (c) 1984, 1985, 1986, 1987, 1993
- *	The Regents of the University of California.  All rights reserved.
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -36,7 +63,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/netipx/ipx_input.c,v 1.51.2.1 2006/02/14 21:35:07 rwatson Exp $");
+__FBSDID("$FreeBSD: src/sys/netipx/ipx_input.c,v 1.57 2007/05/11 10:38:34 rwatson Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -107,7 +134,7 @@
  */
 
 void
-ipx_init()
+ipx_init(void)
 {
 
 	read_random(&ipx_pexseq, sizeof ipx_pexseq);
@@ -135,8 +162,8 @@
 static void
 ipxintr(struct mbuf *m)
 {
-	register struct ipx *ipx;
-	register struct ipxpcb *ipxp;
+	struct ipx *ipx;
+	struct ipxpcb *ipxp;
 	struct ipx_ifaddr *ia;
 	int len;
 
@@ -294,28 +321,8 @@
 	struct sockaddr *arg_as_sa;	/* XXX should be swapped with dummy */
 	void *dummy;
 {
-	caddr_t arg = (/* XXX */ caddr_t)arg_as_sa;
-	struct ipx_addr *ipx;
-
-	if (cmd < 0 || cmd >= PRC_NCMDS)
-		return;
-	switch (cmd) {
-		struct sockaddr_ipx *sipx;
-
-	case PRC_IFDOWN:
-	case PRC_HOSTDEAD:
-	case PRC_HOSTUNREACH:
-		sipx = (struct sockaddr_ipx *)arg;
-		if (sipx->sipx_family != AF_IPX)
-			return;
-		ipx = &sipx->sipx_addr;
-		break;
 
-	default:
-		if (ipxprintfs)
-			printf("ipx_ctlinput: cmd %d.\n", cmd);
-		break;
-	}
+	/* Currently, nothing. */
 }
 
 /*
@@ -327,11 +334,10 @@
 static struct route ipx_sroute;
 
 static void
-ipx_forward(m)
-struct mbuf *m;
+ipx_forward(struct mbuf *m)
 {
-	register struct ipx *ipx = mtod(m, struct ipx *);
-	register int error;
+	struct ipx *ipx = mtod(m, struct ipx *);
+	int error;
 	int agedelta = 1;
 	int flags = IPX_FORWARDING;
 	int ok_there = 0;
@@ -417,9 +423,7 @@
 }
 
 static int
-ipx_do_route(src, ro)
-struct ipx_addr *src;
-struct route *ro;
+ipx_do_route(struct ipx_addr *src, struct route *ro)
 {
 	struct sockaddr_ipx *dst;
 
@@ -439,22 +443,25 @@
 }
 
 static void
-ipx_undo_route(ro)
-register struct route *ro;
+ipx_undo_route(struct route *ro)
 {
+
 	if (ro->ro_rt != NULL) {
 		RTFREE(ro->ro_rt);
 	}
 }
 
+/*
+ * XXXRW: This code should be run in its own netisr dispatch to avoid a call
+ * back into the socket code from the IPX output path.
+ */
 void
-ipx_watch_output(m, ifp)
-struct mbuf *m;
-struct ifnet *ifp;
+ipx_watch_output(struct mbuf *m, struct ifnet *ifp)
 {
-	register struct ipxpcb *ipxp;
-	register struct ifaddr *ifa;
-	register struct ipx_ifaddr *ia;
+	struct ipxpcb *ipxp;
+	struct ifaddr *ifa;
+	struct ipx_ifaddr *ia;
+
 	/*
 	 * Give any raw listeners a crack at the packet
 	 */
@@ -462,7 +469,7 @@
 	LIST_FOREACH(ipxp, &ipxrawpcb_list, ipxp_list) {
 		struct mbuf *m0 = m_copy(m, 0, (int)M_COPYALL);
 		if (m0 != NULL) {
-			register struct ipx *ipx;
+			struct ipx *ipx;
 
 			M_PREPEND(m0, sizeof(*ipx), M_DONTWAIT);
 			if (m0 == NULL)
Index: spx_usrreq.c
===================================================================
RCS file: /home/cvs/src/sys/netipx/spx_usrreq.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/spx_usrreq.c -L sys/netipx/spx_usrreq.c -u -r1.1.1.1 -r1.2
--- sys/netipx/spx_usrreq.c
+++ sys/netipx/spx_usrreq.c
@@ -1,8 +1,35 @@
 /*-
- * Copyright (c) 2004-2005 Robert N. M. Watson
- * Copyright (c) 1995, Mike Mitchell
  * Copyright (c) 1984, 1985, 1986, 1987, 1993
- *	The Regents of the University of California.  All rights reserved.
+ *	The Regents of the University of California.
+ * Copyright (c) 2004-2006 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1995, Mike Mitchell
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -36,7 +63,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/netipx/spx_usrreq.c,v 1.62 2005/02/21 21:58:17 rwatson Exp $");
+__FBSDID("$FreeBSD: src/sys/netipx/spx_usrreq.c,v 1.86 2007/01/08 22:14:00 rwatson Exp $");
 
 #include <sys/param.h>
 #include <sys/lock.h>
@@ -65,13 +92,18 @@
 /*
  * SPX protocol implementation.
  */
+static struct	mtx spx_mtx;			/* Protects only spx_iss. */
 static u_short 	spx_iss;
 static u_short	spx_newchecks[50];
 static int	spx_hardnosed;
 static int	spx_use_delack = 0;
 static int	traceallspxs = 0;
-static struct	spx 	spx_savesi;
 static struct	spx_istat spx_istat;
+static int	spxrexmtthresh = 3;
+
+#define	SPX_LOCK_INIT()	mtx_init(&spx_mtx, "spx_mtx", NULL, MTX_DEF)
+#define	SPX_LOCK()	mtx_lock(&spx_mtx)
+#define	SPX_UNLOCK()	mtx_unlock(&spx_mtx)
 
 /* Following was struct spxstat spxstat; */
 #ifndef spxstat
@@ -88,18 +120,20 @@
 static	int spx_reass(struct spxpcb *cb, struct spx *si);
 static	void spx_setpersist(struct spxpcb *cb);
 static	void spx_template(struct spxpcb *cb);
-static	struct spxpcb *spx_timers(struct spxpcb *cb, int timer);
+static	void spx_timers(struct spxpcb *cb, int timer);
 static	void spx_usrclosed(struct spxpcb *cb);
 
-static	int spx_usr_abort(struct socket *so);
+static	void spx_usr_abort(struct socket *so);
 static	int spx_accept(struct socket *so, struct sockaddr **nam);
 static	int spx_attach(struct socket *so, int proto, struct thread *td);
 static	int spx_bind(struct socket *so, struct sockaddr *nam, struct thread *td);
+static	void spx_usr_close(struct socket *so);
 static	int spx_connect(struct socket *so, struct sockaddr *nam,
 			struct thread *td);
-static	int spx_detach(struct socket *so);
+static	void spx_detach(struct socket *so);
+static	void spx_pcbdetach(struct ipxpcb *ipxp);
 static	int spx_usr_disconnect(struct socket *so);
-static	int spx_listen(struct socket *so, struct thread *td);
+static	int spx_listen(struct socket *so, int backlog, struct thread *td);
 static	int spx_rcvd(struct socket *so, int flags);
 static	int spx_rcvoob(struct socket *so, struct mbuf *m, int flags);
 static	int spx_send(struct socket *so, int flags, struct mbuf *m,
@@ -124,6 +158,7 @@
 	.pru_send =		spx_send,
 	.pru_shutdown =		spx_shutdown,
 	.pru_sockaddr =		ipx_sockaddr,
+	.pru_close =		spx_usr_close,
 };
 
 struct	pr_usrreqs spx_usrreq_sps = {
@@ -142,28 +177,29 @@
 	.pru_send =		spx_send,
 	.pru_shutdown =		spx_shutdown,
 	.pru_sockaddr =		ipx_sockaddr,
+	.pru_close =		spx_usr_close,
 };
 
 void
-spx_init()
+spx_init(void)
 {
 
+	SPX_LOCK_INIT();
 	spx_iss = 1; /* WRONG !! should fish it out of TODR */
 }
 
 void
-spx_input(m, ipxp)
-	register struct mbuf *m;
-	register struct ipxpcb *ipxp;
-{
-	register struct spxpcb *cb;
-	register struct spx *si = mtod(m, struct spx *);
-	register struct socket *so;
+spx_input(struct mbuf *m, struct ipxpcb *ipxp)
+{
+	struct spxpcb *cb;
+	struct spx *si = mtod(m, struct spx *);
+	struct socket *so;
+	struct spx spx_savesi;
 	int dropsocket = 0;
 	short ostate = 0;
 
 	spxstat.spxs_rcvtotal++;
-	KASSERT(ipxp != NULL, ("spx_input: NULL ipxpcb"));
+	KASSERT(ipxp != NULL, ("spx_input: ipxpcb == NULL"));
 
 	/*
 	 * spx_input() assumes that the caller will hold both the pcb list
@@ -175,8 +211,10 @@
 	IPX_LOCK_ASSERT(ipxp);
 
 	cb = ipxtospxpcb(ipxp);
-	if (cb == NULL)
-		goto bad;
+	KASSERT(cb != NULL, ("spx_input: cb == NULL"));
+
+	if (ipxp->ipxp_flags & IPXP_DROPPED)
+		goto drop;
 
 	if (m->m_len < sizeof(*si)) {
 		if ((m = m_pullup(m, sizeof(*si))) == NULL) {
@@ -192,6 +230,7 @@
 	si->si_alo = ntohs(si->si_alo);
 
 	so = ipxp->ipxp_socket;
+	KASSERT(so != NULL, ("spx_input: so == NULL"));
 
 	if (so->so_options & SO_DEBUG || traceallspxs) {
 		ostate = cb->s_state;
@@ -201,19 +240,26 @@
 		struct spxpcb *ocb = cb;
 
 		so = sonewconn(so, 0);
-		if (so == NULL) {
+		if (so == NULL)
 			goto drop;
-		}
+
 		/*
 		 * This is ugly, but ....
 		 *
-		 * Mark socket as temporary until we're
-		 * committed to keeping it.  The code at
-		 * ``drop'' and ``dropwithreset'' check the
-		 * flag dropsocket to see if the temporary
-		 * socket created here should be discarded.
-		 * We mark the socket as discardable until
-		 * we're committed to it below in TCPS_LISTEN.
+		 * Mark socket as temporary until we're committed to keeping
+		 * it.  The code at ``drop'' and ``dropwithreset'' check the
+		 * flag dropsocket to see if the temporary socket created
+		 * here should be discarded.  We mark the socket as
+		 * discardable until we're committed to it below in
+		 * TCPS_LISTEN.
+		 *
+		 * XXXRW: In the new world order of real kernel parallelism,
+		 * temporarily allocating the socket when we're "not sure"
+		 * seems like a bad idea, as we might race to remove it if
+		 * the listen socket is closed...?
+		 *
+		 * We drop the lock of the listen socket ipxp, and acquire
+		 * the lock of the new socket ippx.
 		 */
 		dropsocket++;
 		IPX_UNLOCK(ipxp);
@@ -226,24 +272,24 @@
 		cb->s_flags2 = ocb->s_flags2;	/* preserve sockopts */
 		cb->s_state = TCPS_LISTEN;
 	}
+	IPX_LOCK_ASSERT(ipxp);
 
 	/*
-	 * Packet received on connection.
-	 * reset idle time and keep-alive timer;
+	 * Packet received on connection.  Reset idle time and keep-alive
+	 * timer.
 	 */
 	cb->s_idle = 0;
 	cb->s_timer[SPXT_KEEP] = SPXTV_KEEP;
 
 	switch (cb->s_state) {
-
 	case TCPS_LISTEN:{
 		struct sockaddr_ipx *sipx, ssipx;
 		struct ipx_addr laddr;
 
 		/*
-		 * If somebody here was carying on a conversation
-		 * and went away, and his pen pal thinks he can
-		 * still talk, we get the misdirected packet.
+		 * If somebody here was carying on a conversation and went
+		 * away, and his pen pal thinks he can still talk, we get the
+		 * misdirected packet.
 		 */
 		if (spx_hardnosed && (si->si_did != 0 || si->si_seq != 0)) {
 			spx_istat.gonawy++;
@@ -275,13 +321,13 @@
 		cb->s_timer[SPXT_KEEP] = SPXTV_KEEP;
 		}
 		break;
-	/*
-	 * This state means that we have heard a response
-	 * to our acceptance of their connection
-	 * It is probably logically unnecessary in this
-	 * implementation.
-	 */
+
 	 case TCPS_SYN_RECEIVED: {
+		/*
+		 * This state means that we have heard a response to our
+		 * acceptance of their connection.  It is probably logically
+		 * unnecessary in this implementation.
+		 */
 		if (si->si_did != cb->s_sid) {
 			spx_istat.wrncon++;
 			goto drop;
@@ -296,16 +342,15 @@
 		}
 		break;
 
-	/*
-	 * This state means that we have gotten a response
-	 * to our attempt to establish a connection.
-	 * We fill in the data from the other side,
-	 * telling us which port to respond to, instead of the well-
-	 * known one we might have sent to in the first place.
-	 * We also require that this is a response to our
-	 * connection id.
-	 */
 	case TCPS_SYN_SENT:
+		/*
+		 * This state means that we have gotten a response to our
+		 * attempt to establish a connection.  We fill in the data
+		 * from the other side, telling us which port to respond to,
+		 * instead of the well-known one we might have sent to in the
+		 * first place.  We also require that this is a response to
+		 * our connection id.
+		 */
 		if (si->si_did != cb->s_sid) {
 			spx_istat.notme++;
 			goto drop;
@@ -319,7 +364,9 @@
 		cb->s_flags |= SF_ACKNOW;
 		soisconnected(so);
 		cb->s_state = TCPS_ESTABLISHED;
-		/* Use roundtrip time of connection request for initial rtt */
+		/*
+		 * Use roundtrip time of connection request for initial rtt.
+		 */
 		if (cb->s_rtt) {
 			cb->s_srtt = cb->s_rtt << 3;
 			cb->s_rttvar = cb->s_rtt << 1;
@@ -329,6 +376,7 @@
 			    cb->s_rtt = 0;
 		}
 	}
+
 	if (so->so_options & SO_DEBUG || traceallspxs)
 		spx_trace(SA_INPUT, (u_char)ostate, cb, &spx_savesi, 0);
 
@@ -336,9 +384,8 @@
 	m->m_pkthdr.len -= sizeof(struct ipx);
 	m->m_data += sizeof(struct ipx);
 
-	if (spx_reass(cb, si)) {
+	if (spx_reass(cb, si))
 		m_freem(m);
-	}
 	if (cb->s_force || (cb->s_flags & (SF_ACKNOW|SF_WIN|SF_RXT)))
 		spx_output(cb, NULL);
 	cb->s_flags &= ~(SF_WIN|SF_RXT);
@@ -347,6 +394,10 @@
 	return;
 
 dropwithreset:
+	IPX_LOCK_ASSERT(ipxp);
+	if (cb == NULL || (cb->s_ipxpcb->ipxp_socket->so_options & SO_DEBUG ||
+	    traceallspxs))
+		spx_trace(SA_DROP, (u_char)ostate, cb, &spx_savesi, 0);
 	IPX_UNLOCK(ipxp);
 	if (dropsocket) {
 		struct socket *head;
@@ -360,43 +411,31 @@
 		so->so_head = NULL;
 		ACCEPT_UNLOCK();
 		soabort(so);
-		cb = NULL;
 	}
 	IPX_LIST_UNLOCK();
-	si->si_seq = ntohs(si->si_seq);
-	si->si_ack = ntohs(si->si_ack);
-	si->si_alo = ntohs(si->si_alo);
 	m_freem(dtom(si));
-	if (cb == NULL || cb->s_ipxpcb->ipxp_socket->so_options & SO_DEBUG ||
-	    traceallspxs)
-		spx_trace(SA_DROP, (u_char)ostate, cb, &spx_savesi, 0);
 	return;
 
 drop:
-bad:
-	if (cb == NULL || cb->s_ipxpcb->ipxp_socket->so_options & SO_DEBUG ||
-            traceallspxs)
+	IPX_LOCK_ASSERT(ipxp);
+	if (cb->s_ipxpcb->ipxp_socket->so_options & SO_DEBUG || traceallspxs)
 		spx_trace(SA_DROP, (u_char)ostate, cb, &spx_savesi, 0);
 	IPX_UNLOCK(ipxp);
 	IPX_LIST_UNLOCK();
 	m_freem(m);
 }
 
-static int spxrexmtthresh = 3;
-
 /*
- * This is structurally similar to the tcp reassembly routine
- * but its function is somewhat different:  It merely queues
- * packets up, and suppresses duplicates.
+ * This is structurally similar to the tcp reassembly routine but its
+ * function is somewhat different:  It merely queues packets up, and
+ * suppresses duplicates.
  */
 static int
-spx_reass(cb, si)
-register struct spxpcb *cb;
-register struct spx *si;
-{
-	register struct spx_q *q;
-	register struct mbuf *m;
-	register struct socket *so = cb->s_ipxpcb->ipxp_socket;
+spx_reass(struct spxpcb *cb, struct spx *si)
+{
+	struct spx_q *q;
+	struct mbuf *m;
+	struct socket *so = cb->s_ipxpcb->ipxp_socket;
 	char packetp = cb->s_flags & SF_HI;
 	int incr;
 	char wakeup = 0;
@@ -416,10 +455,10 @@
 		if ((si->si_cc & SPX_SP) && cb->s_rack != (cb->s_smax + 1)) {
 			spxstat.spxs_rcvdupack++;
 			/*
-			 * If this is a completely duplicate ack
-			 * and other conditions hold, we assume
-			 * a packet has been dropped and retransmit
-			 * it exactly as in tcp_input().
+			 * If this is a completely duplicate ack and other
+			 * conditions hold, we assume a packet has been
+			 * dropped and retransmit it exactly as in
+			 * tcp_input().
 			 */
 			if (si->si_ack != cb->s_rack ||
 			    si->si_alo != cb->s_ralo)
@@ -445,25 +484,26 @@
 		goto update_window;
 	}
 	cb->s_dupacks = 0;
+
 	/*
-	 * If our correspondent acknowledges data we haven't sent
-	 * TCP would drop the packet after acking.  We'll be a little
-	 * more permissive
+	 * If our correspondent acknowledges data we haven't sent TCP would
+	 * drop the packet after acking.  We'll be a little more permissive.
 	 */
 	if (SSEQ_GT(si->si_ack, (cb->s_smax + 1))) {
 		spxstat.spxs_rcvacktoomuch++;
 		si->si_ack = cb->s_smax + 1;
 	}
 	spxstat.spxs_rcvackpack++;
+
 	/*
-	 * If transmit timer is running and timed sequence
-	 * number was acked, update smoothed round trip time.
-	 * See discussion of algorithm in tcp_input.c
+	 * If transmit timer is running and timed sequence number was acked,
+	 * update smoothed round trip time.  See discussion of algorithm in
+	 * tcp_input.c
 	 */
 	if (cb->s_rtt && SSEQ_GT(si->si_ack, cb->s_rtseq)) {
 		spxstat.spxs_rttupdated++;
 		if (cb->s_srtt != 0) {
-			register short delta;
+			short delta;
 			delta = cb->s_rtt - (cb->s_srtt >> 3);
 			if ((cb->s_srtt += delta) <= 0)
 				cb->s_srtt = 1;
@@ -474,7 +514,7 @@
 				cb->s_rttvar = 1;
 		} else {
 			/*
-			 * No rtt measurement yet
+			 * No rtt measurement yet.
 			 */
 			cb->s_srtt = cb->s_rtt << 3;
 			cb->s_rttvar = cb->s_rtt << 1;
@@ -485,27 +525,30 @@
 			((cb->s_srtt >> 2) + cb->s_rttvar) >> 1,
 			SPXTV_MIN, SPXTV_REXMTMAX);
 	}
+
 	/*
-	 * If all outstanding data is acked, stop retransmit
-	 * timer and remember to restart (more output or persist).
-	 * If there is more data to be acked, restart retransmit
-	 * timer, using current (possibly backed-off) value;
+	 * If all outstanding data is acked, stop retransmit timer and
+	 * remember to restart (more output or persist).  If there is more
+	 * data to be acked, restart retransmit timer, using current
+	 * (possibly backed-off) value;
 	 */
 	if (si->si_ack == cb->s_smax + 1) {
 		cb->s_timer[SPXT_REXMT] = 0;
 		cb->s_flags |= SF_RXT;
 	} else if (cb->s_timer[SPXT_PERSIST] == 0)
 		cb->s_timer[SPXT_REXMT] = cb->s_rxtcur;
+
 	/*
-	 * When new data is acked, open the congestion window.
-	 * If the window gives us less than ssthresh packets
-	 * in flight, open exponentially (maxseg at a time).
-	 * Otherwise open linearly (maxseg^2 / cwnd at a time).
+	 * When new data is acked, open the congestion window.  If the window
+	 * gives us less than ssthresh packets in flight, open exponentially
+	 * (maxseg at a time).  Otherwise open linearly (maxseg^2 / cwnd at a
+	 * time).
 	 */
 	incr = CUNIT;
 	if (cb->s_cwnd > cb->s_ssthresh)
 		incr = max(incr * incr / cb->s_cwnd, 1);
 	cb->s_cwnd = min(cb->s_cwnd + incr, cb->s_cwmx);
+
 	/*
 	 * Trim Acked data from output queue.
 	 */
@@ -538,9 +581,10 @@
 			cb->s_smxw = cb->s_swnd;
 		cb->s_flags |= SF_WIN;
 	}
+
 	/*
-	 * If this packet number is higher than that which
-	 * we have allocated refuse it, unless urgent
+	 * If this packet number is higher than that which we have allocated
+	 * refuse it, unless urgent.
 	 */
 	if (SSEQ_GT(si->si_seq, cb->s_alo)) {
 		if (si->si_cc & SPX_SP) {
@@ -561,7 +605,7 @@
 			 * which are then touched by spx_input() after the
 			 * return from spx_reass().
 			 */
-			/*register struct socket *so = cb->s_ipxpcb->ipxp_socket;
+			/*struct socket *so = cb->s_ipxpcb->ipxp_socket;
 			if (so->so_state && SS_NOFDREF) {
 				spx_close(cb);
 			} else
@@ -572,13 +616,14 @@
 			return (0);
 		}
 	}
+
 	/*
-	 * If this is a system packet, we don't need to
-	 * queue it up, and won't update acknowledge #
+	 * If this is a system packet, we don't need to queue it up, and
+	 * won't update acknowledge #.
 	 */
-	if (si->si_cc & SPX_SP) {
+	if (si->si_cc & SPX_SP)
 		return (1);
-	}
+
 	/*
 	 * We have already seen this packet, so drop.
 	 */
@@ -589,9 +634,10 @@
 			spx_istat.lstdup++;
 		return (1);
 	}
+
 	/*
-	 * Loop through all packets queued up to insert in
-	 * appropriate sequence.
+	 * Loop through all packets queued up to insert in appropriate
+	 * sequence.
 	 */
 	for (q = cb->s_q.si_next; q != &cb->s_q; q = q->si_next) {
 		if (si->si_seq == SI(q)->si_seq) {
@@ -615,10 +661,11 @@
 present:
 #define SPINC sizeof(struct spxhdr)
 	SOCKBUF_LOCK(&so->so_rcv);
+
 	/*
-	 * Loop through all packets queued up to update acknowledge
-	 * number, and present all acknowledged data to user;
-	 * If in packet interface mode, show packet headers.
+	 * Loop through all packets queued up to update acknowledge number,
+	 * and present all acknowledged data to user; if in packet interface
+	 * mode, show packet headers.
 	 */
 	for (q = cb->s_q.si_next; q != &cb->s_q; q = q->si_next) {
 		  if (SI(q)->si_seq == cb->s_ack) {
@@ -673,9 +720,9 @@
 					sbappend_locked(&so->so_rcv, m);
 			} else
 #endif
-			if (packetp) {
+			if (packetp)
 				sbappendrecord_locked(&so->so_rcv, m);
-			} else {
+			else {
 				cb->s_rhdr = *mtod(m, struct spxhdr *);
 				m->m_data += SPINC;
 				m->m_len -= SPINC;
@@ -693,46 +740,19 @@
 }
 
 void
-spx_ctlinput(cmd, arg_as_sa, dummy)
-	int cmd;
-	struct sockaddr *arg_as_sa;	/* XXX should be swapped with dummy */
-	void *dummy;
-{
-	caddr_t arg = (/* XXX */ caddr_t)arg_as_sa;
-	struct ipx_addr *na;
-	struct sockaddr_ipx *sipx;
-
-	if (cmd < 0 || cmd >= PRC_NCMDS)
-		return;
-
-	switch (cmd) {
-
-	case PRC_ROUTEDEAD:
-		return;
-
-	case PRC_IFDOWN:
-	case PRC_HOSTDEAD:
-	case PRC_HOSTUNREACH:
-		sipx = (struct sockaddr_ipx *)arg;
-		if (sipx->sipx_family != AF_IPX)
-			return;
-		na = &sipx->sipx_addr;
-		break;
+spx_ctlinput(int cmd, struct sockaddr *arg_as_sa, void *dummy)
+{
 
-	default:
-		break;
-	}
+	/* Currently, nothing. */
 }
 
 static int
-spx_output(cb, m0)
-	register struct spxpcb *cb;
-	struct mbuf *m0;
+spx_output(struct spxpcb *cb, struct mbuf *m0)
 {
 	struct socket *so = cb->s_ipxpcb->ipxp_socket;
-	register struct mbuf *m;
-	register struct spx *si = NULL;
-	register struct sockbuf *sb = &so->so_snd;
+	struct mbuf *m;
+	struct spx *si = NULL;
+	struct sockbuf *sb = &so->so_snd;
 	int len = 0, win, rcv_win;
 	short span, off, recordp = 0;
 	u_short alo;
@@ -747,6 +767,7 @@
 	if (m0 != NULL) {
 		int mtu = cb->s_mtu;
 		int datalen;
+
 		/*
 		 * Make sure that packet isn't too big.
 		 */
@@ -767,12 +788,12 @@
 
 				cb->s_cc &= ~SPX_EM;
 				while (len > mtu) {
-					/*
-					 * Here we are only being called
-					 * from usrreq(), so it is OK to
-					 * block.
-					 */
-					m = m_copym(m0, 0, mtu, M_TRYWAIT);
+					m = m_copym(m0, 0, mtu, M_DONTWAIT);
+					if (m == NULL) {
+					    cb->s_cc |= oldEM;
+					    m_freem(m0);
+					    return (ENOBUFS);
+					}
 					if (cb->s_flags & SF_NEWCALL) {
 					    struct mbuf *mm = m;
 					    spx_newchecks[7]++;
@@ -793,6 +814,7 @@
 				cb->s_cc |= oldEM;
 			}
 		}
+
 		/*
 		 * Force length even, by adding a "garbage byte" if
 		 * necessary.
@@ -813,14 +835,15 @@
 				m->m_next = m1;
 			}
 		}
-		m = m_gethdr(M_DONTWAIT, MT_HEADER);
+		m = m_gethdr(M_DONTWAIT, MT_DATA);
 		if (m == NULL) {
 			m_freem(m0);
 			return (ENOBUFS);
 		}
+
 		/*
-		 * Fill in mbuf with extended SP header
-		 * and addresses and length put into network format.
+		 * Fill in mbuf with extended SP header and addresses and
+		 * length put into network format.
 		 */
 		MH_ALIGN(m, sizeof(struct spx));
 		m->m_len = sizeof(struct spx);
@@ -829,7 +852,7 @@
 		si->si_i = *cb->s_ipx;
 		si->si_s = cb->s_shdr;
 		if ((cb->s_flags & SF_PI) && (cb->s_flags & SF_HO)) {
-			register struct spxhdr *sh;
+			struct spxhdr *sh;
 			if (m0->m_len < sizeof(*sh)) {
 				if((m0 = m_pullup(m0, sizeof(*sh))) == NULL) {
 					m_free(m);
@@ -852,12 +875,11 @@
 		}
 		if (cb->s_oobflags & SF_SOOB) {
 			/*
-			 * Per jqj at cornell:
-			 * make sure OB packets convey exactly 1 byte.
-			 * If the packet is 1 byte or larger, we
-			 * have already guaranted there to be at least
-			 * one garbage byte for the checksum, and
-			 * extra bytes shouldn't hurt!
+			 * Per jqj at cornell: Make sure OB packets convey
+			 * exactly 1 byte.  If the packet is 1 byte or
+			 * larger, we have already guaranted there to be at
+			 * least one garbage byte for the checksum, and extra
+			 * bytes shouldn't hurt!
 			 */
 			if (len > sizeof(*si)) {
 				si->si_cc |= SPX_OB;
@@ -866,8 +888,9 @@
 		}
 		si->si_len = htons((u_short)len);
 		m->m_pkthdr.len = ((len - 1) | 1) + 1;
+
 		/*
-		 * queue stuff up for output
+		 * Queue stuff up for output.
 		 */
 		sbappendrecord(sb, m);
 		cb->s_seq++;
@@ -881,10 +904,9 @@
 	win = min(cb->s_swnd, (cb->s_cwnd / CUNIT));
 
 	/*
-	 * If in persist timeout with window of 0, send a probe.
-	 * Otherwise, if window is small but nonzero
-	 * and timer expired, send what we can and go into
-	 * transmit state.
+	 * If in persist timeout with window of 0, send a probe.  Otherwise,
+	 * if window is small but nonzero and timer expired, send what we can
+	 * and go into transmit state.
 	 */
 	if (cb->s_force == 1 + SPXT_PERSIST) {
 		if (win != 0) {
@@ -897,12 +919,10 @@
 
 	if (len < 0) {
 		/*
-		 * Window shrank after we went into it.
-		 * If window shrank to 0, cancel pending
-		 * restransmission and pull s_snxt back
-		 * to (closed) window.  We will enter persist
-		 * state below.  If the widndow didn't close completely,
-		 * just wait for an ACK.
+		 * Window shrank after we went into it.  If window shrank to
+		 * 0, cancel pending restransmission and pull s_snxt back to
+		 * (closed) window.  We will enter persist state below.  If
+		 * the widndow didn't close completely, just wait for an ACK.
 		 */
 		len = 0;
 		if (win == 0) {
@@ -919,7 +939,7 @@
 	 */
 	if (cb->s_oobflags & SF_SOOB) {
 		/*
-		 * must transmit this out of band packet
+		 * Must transmit this out of band packet.
 		 */
 		cb->s_oobflags &= ~ SF_SOOB;
 		sendalot = 1;
@@ -930,18 +950,18 @@
 		goto send;
 	if (cb->s_state < TCPS_ESTABLISHED)
 		goto send;
+
 	/*
-	 * Silly window can't happen in spx.
-	 * Code from tcp deleted.
+	 * Silly window can't happen in spx.  Code from TCP deleted.
 	 */
 	if (len)
 		goto send;
+
 	/*
-	 * Compare available window to amount of window
-	 * known to peer (as advertised window less
-	 * next expected input.)  If the difference is at least two
-	 * packets or at least 35% of the mximum possible window,
-	 * then want to send a window update to peer.
+	 * Compare available window to amount of window known to peer (as
+	 * advertised window less next expected input.)  If the difference is
+	 * at least two packets or at least 35% of the mximum possible
+	 * window, then want to send a window update to peer.
 	 */
 	if (rcv_win > 0) {
 		u_short delta =  1 + cb->s_alo - cb->s_ack;
@@ -955,20 +975,20 @@
 		}
 
 	}
+
 	/*
-	 * Many comments from tcp_output.c are appropriate here
-	 * including . . .
+	 * Many comments from tcp_output.c are appropriate here including ...
 	 * If send window is too small, there is data to transmit, and no
-	 * retransmit or persist is pending, then go to persist state.
-	 * If nothing happens soon, send when timer expires:
-	 * if window is nonzero, transmit what we can,
-	 * otherwise send a probe.
+	 * retransmit or persist is pending, then go to persist state.  If
+	 * nothing happens soon, send when timer expires: if window is
+	 * nonzero, transmit what we can, otherwise send a probe.
 	 */
 	if (so->so_snd.sb_cc && cb->s_timer[SPXT_REXMT] == 0 &&
-		cb->s_timer[SPXT_PERSIST] == 0) {
-			cb->s_rxtshift = 0;
-			spx_setpersist(cb);
+	    cb->s_timer[SPXT_PERSIST] == 0) {
+		cb->s_rxtshift = 0;
+		spx_setpersist(cb);
 	}
+
 	/*
 	 * No reason to send a packet, just return.
 	 */
@@ -995,8 +1015,9 @@
 					spxstat.spxs_sndvoid++, si = 0;
 		}
 	}
+
 	/*
-	 * update window
+	 * Update window.
 	 */
 	if (rcv_win < 0)
 		rcv_win = 0;
@@ -1006,13 +1027,12 @@
 
 	if (si != NULL) {
 		/*
-		 * must make a copy of this packet for
-		 * ipx_output to monkey with
+		 * Must make a copy of this packet for ipx_output to monkey
+		 * with.
 		 */
 		m = m_copy(dtom(si), 0, (int)M_COPYALL);
-		if (m == NULL) {
+		if (m == NULL)
 			return (ENOBUFS);
-		}
 		si = mtod(m, struct spx *);
 		if (SSEQ_LT(si->si_seq, cb->s_smax))
 			spxstat.spxs_sndrexmitpack++;
@@ -1020,18 +1040,19 @@
 			spxstat.spxs_sndpack++;
 	} else if (cb->s_force || cb->s_flags & SF_ACKNOW) {
 		/*
-		 * Must send an acknowledgement or a probe
+		 * Must send an acknowledgement or a probe.
 		 */
 		if (cb->s_force)
 			spxstat.spxs_sndprobe++;
 		if (cb->s_flags & SF_ACKNOW)
 			spxstat.spxs_sndacks++;
-		m = m_gethdr(M_DONTWAIT, MT_HEADER);
+		m = m_gethdr(M_DONTWAIT, MT_DATA);
 		if (m == NULL)
 			return (ENOBUFS);
+
 		/*
-		 * Fill in mbuf with extended SP header
-		 * and addresses and length put into network format.
+		 * Fill in mbuf with extended SP header and addresses and
+		 * length put into network format.
 		 */
 		MH_ALIGN(m, sizeof(struct spx));
 		m->m_len = sizeof(*si);
@@ -1066,12 +1087,13 @@
 					cb->s_rtt = 1;
 				}
 			}
+
 			/*
-			 * Set rexmt timer if not currently set,
-			 * Initial value for retransmit timer is smoothed
-			 * round-trip time + 2 * round-trip time variance.
-			 * Initialize shift counter which is used for backoff
-			 * of retransmit time.
+			 * Set rexmt timer if not currently set, initial
+			 * value for retransmit timer is smoothed round-trip
+			 * time + 2 * round-trip time variance.  Initialize
+			 * shift counter which is used for backoff of
+			 * retransmit time.
 			 */
 			if (cb->s_timer[SPXT_REXMT] == 0 &&
 			    cb->s_snxt != cb->s_rack) {
@@ -1081,49 +1103,46 @@
 					cb->s_rxtshift = 0;
 				}
 			}
-		} else if (SSEQ_LT(cb->s_smax, si->si_seq)) {
+		} else if (SSEQ_LT(cb->s_smax, si->si_seq))
 			cb->s_smax = si->si_seq;
-		}
 	} else if (cb->s_state < TCPS_ESTABLISHED) {
 		if (cb->s_rtt == 0)
 			cb->s_rtt = 1; /* Time initial handshake */
 		if (cb->s_timer[SPXT_REXMT] == 0)
 			cb->s_timer[SPXT_REXMT] = cb->s_rxtcur;
 	}
-	{
-		/*
-		 * Do not request acks when we ack their data packets or
-		 * when we do a gratuitous window update.
-		 */
-		if (((si->si_cc & SPX_SP) == 0) || cb->s_force)
-				si->si_cc |= SPX_SA;
-		si->si_seq = htons(si->si_seq);
-		si->si_alo = htons(alo);
-		si->si_ack = htons(cb->s_ack);
 
-		if (ipxcksum) {
-			si->si_sum = ipx_cksum(m, ntohs(si->si_len));
-		} else
-			si->si_sum = 0xffff;
+	/*
+	 * Do not request acks when we ack their data packets or when we do a
+	 * gratuitous window update.
+	 */
+	if (((si->si_cc & SPX_SP) == 0) || cb->s_force)
+		si->si_cc |= SPX_SA;
+	si->si_seq = htons(si->si_seq);
+	si->si_alo = htons(alo);
+	si->si_ack = htons(cb->s_ack);
 
-		cb->s_outx = 4;
-		if (so->so_options & SO_DEBUG || traceallspxs)
-			spx_trace(SA_OUTPUT, cb->s_state, cb, si, 0);
+	if (ipxcksum)
+		si->si_sum = ipx_cksum(m, ntohs(si->si_len));
+	else
+		si->si_sum = 0xffff;
 
-		if (so->so_options & SO_DONTROUTE)
-			error = ipx_outputfl(m, NULL, IPX_ROUTETOIF);
-		else
-			error = ipx_outputfl(m, &cb->s_ipxpcb->ipxp_route, 0);
-	}
-	if (error) {
+	cb->s_outx = 4;
+	if (so->so_options & SO_DEBUG || traceallspxs)
+		spx_trace(SA_OUTPUT, cb->s_state, cb, si, 0);
+
+	if (so->so_options & SO_DONTROUTE)
+		error = ipx_outputfl(m, NULL, IPX_ROUTETOIF);
+	else
+		error = ipx_outputfl(m, &cb->s_ipxpcb->ipxp_route, 0);
+	if (error)
 		return (error);
-	}
 	spxstat.spxs_sndtotal++;
+
 	/*
-	 * Data sent (as far as we can tell).
-	 * If this advertises a larger window than any other segment,
-	 * then remember the size of the advertized window.
-	 * Any pending ACK has now been sent.
+	 * Data sent (as far as we can tell).  If this advertises a larger
+	 * window than any other segment, then remember the size of the
+	 * advertized window.  Any pending ACK has now been sent.
 	 */
 	cb->s_force = 0;
 	cb->s_flags &= ~(SF_ACKNOW|SF_DELACK);
@@ -1138,15 +1157,15 @@
 static int spx_do_persist_panics = 0;
 
 static void
-spx_setpersist(cb)
-	register struct spxpcb *cb;
+spx_setpersist(struct spxpcb *cb)
 {
-	register int t = ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1;
+	int t = ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1;
 
 	IPX_LOCK_ASSERT(cb->s_ipxpcb);
 
 	if (cb->s_timer[SPXT_REXMT] && spx_do_persist_panics)
 		panic("spx_output REXMT");
+
 	/*
 	 * Start/restart persistance timer.
 	 */
@@ -1158,29 +1177,37 @@
 }
 
 int
-spx_ctloutput(so, sopt)
-	struct socket *so;
-	struct sockopt *sopt;
+spx_ctloutput(struct socket *so, struct sockopt *sopt)
 {
-	struct ipxpcb *ipxp = sotoipxpcb(so);
-	register struct spxpcb *cb;
+	struct spxhdr spxhdr;
+	struct ipxpcb *ipxp;
+	struct spxpcb *cb;
 	int mask, error;
 	short soptval;
 	u_short usoptval;
 	int optval;
 
-	error = 0;
+	ipxp = sotoipxpcb(so);
+	KASSERT(ipxp != NULL, ("spx_ctloutput: ipxp == NULL"));
 
-	if (sopt->sopt_level != IPXPROTO_SPX) {
-		/* This will have to be changed when we do more general
-		   stacking of protocols */
+	/*
+	 * This will have to be changed when we do more general stacking of
+	 * protocols.
+	 */
+	if (sopt->sopt_level != IPXPROTO_SPX)
 		return (ipx_ctloutput(so, sopt));
+
+	IPX_LOCK(ipxp);
+	if (ipxp->ipxp_flags & IPXP_DROPPED) {
+		IPX_UNLOCK(ipxp);
+		return (ECONNRESET);
 	}
-	if (ipxp == NULL)
-		return (EINVAL);
-	else
-		cb = ipxtospxpcb(ipxp);
 
+	IPX_LOCK(ipxp);
+	cb = ipxtospxpcb(ipxp);
+	KASSERT(cb != NULL, ("spx_ctloutput: cb == NULL"));
+
+	error = 0;
 	switch (sopt->sopt_dir) {
 	case SOPT_GET:
 		switch (sopt->sopt_name) {
@@ -1191,38 +1218,47 @@
 		case SO_HEADERS_ON_OUTPUT:
 			mask = SF_HO;
 		get_flags:
-			/* Unlocked read. */
 			soptval = cb->s_flags & mask;
-			error = sooptcopyout(sopt, &soptval, sizeof soptval);
+			IPX_UNLOCK(ipxp);
+			error = sooptcopyout(sopt, &soptval,
+			    sizeof(soptval));
 			break;
 
 		case SO_MTU:
-			/* Unlocked read. */
 			usoptval = cb->s_mtu;
-			error = sooptcopyout(sopt, &usoptval, sizeof usoptval);
+			IPX_UNLOCK(ipxp);
+			error = sooptcopyout(sopt, &usoptval,
+			    sizeof(usoptval));
 			break;
 
 		case SO_LAST_HEADER:
-			/* Unlocked read. */
-			error = sooptcopyout(sopt, &cb->s_rhdr,
-					     sizeof cb->s_rhdr);
+			spxhdr = cb->s_rhdr;
+			IPX_UNLOCK(ipxp);
+			error = sooptcopyout(sopt, &spxhdr, sizeof(spxhdr));
 			break;
 
 		case SO_DEFAULT_HEADERS:
-			/* Unlocked read. */
-			error = sooptcopyout(sopt, &cb->s_shdr,
-					     sizeof cb->s_shdr);
+			spxhdr = cb->s_shdr;
+			IPX_UNLOCK(ipxp);
+			error = sooptcopyout(sopt, &spxhdr, sizeof(spxhdr));
 			break;
 
 		default:
+			IPX_UNLOCK(ipxp);
 			error = ENOPROTOOPT;
 		}
 		break;
 
 	case SOPT_SET:
+		/*
+		 * XXX Why are these shorts on get and ints on set?  That
+		 * doesn't make any sense...
+		 *
+		 * XXXRW: Note, when we re-acquire the ipxp lock, we should
+		 * re-check that it's not dropped.
+		 */
+		IPX_UNLOCK(ipxp);
 		switch (sopt->sopt_name) {
-			/* XXX why are these shorts on get and ints on set?
-			   that doesn't make any sense... */
 		case SO_HEADERS_ON_INPUT:
 			mask = SF_HI;
 			goto set_head;
@@ -1291,41 +1327,45 @@
 			error = ENOPROTOOPT;
 		}
 		break;
+
+	default:
+		panic("spx_ctloutput: bad socket option direction");
 	}
 	return (error);
 }
 
-static int
-spx_usr_abort(so)
-	struct socket *so;
+static void
+spx_usr_abort(struct socket *so)
 {
 	struct ipxpcb *ipxp;
 	struct spxpcb *cb;
 
 	ipxp = sotoipxpcb(so);
+	KASSERT(ipxp != NULL, ("spx_usr_abort: ipxp == NULL"));
+
 	cb = ipxtospxpcb(ipxp);
+	KASSERT(cb != NULL, ("spx_usr_abort: cb == NULL"));
 
 	IPX_LIST_LOCK();
 	IPX_LOCK(ipxp);
 	spx_drop(cb, ECONNABORTED);
+	IPX_UNLOCK(ipxp);
 	IPX_LIST_UNLOCK();
-	return (0);
 }
 
 /*
- * Accept a connection.  Essentially all the work is
- * done at higher levels; just return the address
- * of the peer, storing through addr.
+ * Accept a connection.  Essentially all the work is done at higher levels;
+ * just return the address of the peer, storing through addr.
  */
 static int
-spx_accept(so, nam)
-	struct socket *so;
-	struct sockaddr **nam;
+spx_accept(struct socket *so, struct sockaddr **nam)
 {
 	struct ipxpcb *ipxp;
 	struct sockaddr_ipx *sipx, ssipx;
 
 	ipxp = sotoipxpcb(so);
+	KASSERT(ipxp != NULL, ("spx_accept: ipxp == NULL"));
+
 	sipx = &ssipx;
 	bzero(sipx, sizeof *sipx);
 	sipx->sipx_len = sizeof *sipx;
@@ -1338,10 +1378,7 @@
 }
 
 static int
-spx_attach(so, proto, td)
-	struct socket *so;
-	int proto;
-	struct thread *td;
+spx_attach(struct socket *so, int proto, struct thread *td)
 {
 	struct ipxpcb *ipxp;
 	struct spxpcb *cb;
@@ -1350,35 +1387,34 @@
 	int error;
 
 	ipxp = sotoipxpcb(so);
-	cb = ipxtospxpcb(ipxp);
+	KASSERT(ipxp == NULL, ("spx_attach: ipxp != NULL"));
 
-	if (ipxp != NULL)
-		return (EISCONN);
-	IPX_LIST_LOCK();
-	error = ipx_pcballoc(so, &ipxpcb_list, td);
-	if (error)
-		goto spx_attach_end;
 	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
 		error = soreserve(so, (u_long) 3072, (u_long) 3072);
 		if (error)
-			goto spx_attach_end;
+			return (error);
 	}
-	ipxp = sotoipxpcb(so);
 
 	MALLOC(cb, struct spxpcb *, sizeof *cb, M_PCB, M_NOWAIT | M_ZERO);
-
-	if (cb == NULL) {
-		error = ENOBUFS;
-		goto spx_attach_end;
+	if (cb == NULL)
+		return (ENOBUFS);
+	mm = m_getclr(M_DONTWAIT, MT_DATA);
+	if (mm == NULL) {
+		FREE(cb, M_PCB);
+		return (ENOBUFS);
 	}
-	sb = &so->so_snd;
 
-	mm = m_getclr(M_DONTWAIT, MT_HEADER);
-	if (mm == NULL) {
+	IPX_LIST_LOCK();
+	error = ipx_pcballoc(so, &ipxpcb_list, td);
+	if (error) {
+		IPX_LIST_UNLOCK();
+		m_free(mm);
 		FREE(cb, M_PCB);
-		error = ENOBUFS;
-		goto spx_attach_end;
+		return (error);
 	}
+	ipxp = sotoipxpcb(so);
+	ipxp->ipxp_flags |= IPXP_SPX;
+
 	cb->s_ipx = mtod(mm, struct ipx *);
 	cb->s_state = TCPS_LISTEN;
 	cb->s_smax = -1;
@@ -1386,62 +1422,116 @@
 	cb->s_q.si_next = cb->s_q.si_prev = &cb->s_q;
 	cb->s_ipxpcb = ipxp;
 	cb->s_mtu = 576 - sizeof(struct spx);
+	sb = &so->so_snd;
 	cb->s_cwnd = sbspace(sb) * CUNIT / cb->s_mtu;
 	cb->s_ssthresh = cb->s_cwnd;
 	cb->s_cwmx = sbspace(sb) * CUNIT / (2 * sizeof(struct spx));
-	/* Above is recomputed when connecting to account
-	   for changed buffering or mtu's */
+	/*
+	 * Above is recomputed when connecting to account for changed
+	 * buffering or mtu's.
+	 */
 	cb->s_rtt = SPXTV_SRTTBASE;
 	cb->s_rttvar = SPXTV_SRTTDFLT << 2;
 	SPXT_RANGESET(cb->s_rxtcur,
 	    ((SPXTV_SRTTBASE >> 2) + (SPXTV_SRTTDFLT << 2)) >> 1,
 	    SPXTV_MIN, SPXTV_REXMTMAX);
 	ipxp->ipxp_pcb = (caddr_t)cb;
-spx_attach_end:
 	IPX_LIST_UNLOCK();
-	return (error);
+	return (0);
+}
+
+static void
+spx_pcbdetach(struct ipxpcb *ipxp)
+{
+	struct spxpcb *cb;
+	struct spx_q *s;
+	struct mbuf *m;
+
+	IPX_LOCK_ASSERT(ipxp);
+
+	cb = ipxtospxpcb(ipxp);
+	KASSERT(cb != NULL, ("spx_pcbdetach: cb == NULL"));
+
+	s = cb->s_q.si_next;
+	while (s != &(cb->s_q)) {
+		s = s->si_next;
+		remque(s);
+		m = dtom(s);
+		m_freem(m);
+	}
+	m_free(dtom(cb->s_ipx));
+	FREE(cb, M_PCB);
+	ipxp->ipxp_pcb = NULL;
 }
 
 static int
-spx_bind(so, nam, td)
-	struct socket *so;
-	struct sockaddr *nam;
-	struct thread *td;
+spx_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
 {
 	struct ipxpcb *ipxp;
 	int error;
 
 	ipxp = sotoipxpcb(so);
+	KASSERT(ipxp != NULL, ("spx_bind: ipxp == NULL"));
 
 	IPX_LIST_LOCK();
 	IPX_LOCK(ipxp);
+	if (ipxp->ipxp_flags & IPXP_DROPPED) {
+		error = EINVAL;
+		goto out;
+	}
 	error = ipx_pcbbind(ipxp, nam, td);
+out:
 	IPX_UNLOCK(ipxp);
 	IPX_LIST_UNLOCK();
 	return (error);
 }
 
+static void
+spx_usr_close(struct socket *so)
+{
+	struct ipxpcb *ipxp;
+	struct spxpcb *cb;
+
+	ipxp = sotoipxpcb(so);
+	KASSERT(ipxp != NULL, ("spx_usr_close: ipxp == NULL"));
+
+	cb = ipxtospxpcb(ipxp);
+	KASSERT(cb != NULL, ("spx_usr_close: cb == NULL"));
+
+	IPX_LIST_LOCK();
+	IPX_LOCK(ipxp);
+	if (cb->s_state > TCPS_LISTEN)
+		spx_disconnect(cb);
+	else
+		spx_close(cb);
+	IPX_UNLOCK(ipxp);
+	IPX_LIST_UNLOCK();
+}
+
 /*
- * Initiate connection to peer.
- * Enter SYN_SENT state, and mark socket as connecting.
- * Start keep-alive timer, setup prototype header,
- * Send initial system packet requesting connection.
+ * Initiate connection to peer.  Enter SYN_SENT state, and mark socket as
+ * connecting.  Start keep-alive timer, setup prototype header, send initial
+ * system packet requesting connection.
  */
 static int
-spx_connect(so, nam, td)
-	struct socket *so;
-	struct sockaddr *nam;
-	struct thread *td;
+spx_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
 {
 	struct ipxpcb *ipxp;
 	struct spxpcb *cb;
 	int error;
 
 	ipxp = sotoipxpcb(so);
+	KASSERT(ipxp != NULL, ("spx_connect: ipxp == NULL"));
+
 	cb = ipxtospxpcb(ipxp);
+	KASSERT(cb != NULL, ("spx_connect: cb == NULL"));
 
 	IPX_LIST_LOCK();
 	IPX_LOCK(ipxp);
+	if (ipxp->ipxp_flags & IPXP_DROPPED) {
+		error = EINVAL;
+		goto spx_connect_end;
+	}
 	if (ipxp->ipxp_lport == 0) {
 		error = ipx_pcbbind(ipxp, NULL, td);
 		if (error)
@@ -1458,11 +1548,9 @@
 	cb->s_timer[SPXT_KEEP] = SPXTV_KEEP;
 	cb->s_force = 1 + SPXTV_KEEP;
 	/*
-	 * Other party is required to respond to
-	 * the port I send from, but he is not
-	 * required to answer from where I am sending to,
-	 * so allow wildcarding.
-	 * original port I am sending to is still saved in
+	 * Other party is required to respond to the port I send from, but he
+	 * is not required to answer from where I am sending to, so allow
+	 * wildcarding.  Original port I am sending to is still saved in
 	 * cb->s_dport.
 	 */
 	ipxp->ipxp_fport = 0;
@@ -1473,54 +1561,61 @@
 	return (error);
 }
 
-static int
-spx_detach(so)
-	struct socket *so;
+static void
+spx_detach(struct socket *so)
 {
 	struct ipxpcb *ipxp;
 	struct spxpcb *cb;
 
+	/*
+	 * XXXRW: Should assert appropriately detached.
+	 */
 	ipxp = sotoipxpcb(so);
+	KASSERT(ipxp != NULL, ("spx_detach: ipxp == NULL"));
+
 	cb = ipxtospxpcb(ipxp);
+	KASSERT(cb != NULL, ("spx_detach: cb == NULL"));
 
-	if (ipxp == NULL)
-		return (ENOTCONN);
 	IPX_LIST_LOCK();
 	IPX_LOCK(ipxp);
-	if (cb->s_state > TCPS_LISTEN)
-		spx_disconnect(cb);
-	else
-		spx_close(cb);
+	spx_pcbdetach(ipxp);
+	ipx_pcbfree(ipxp);
 	IPX_LIST_UNLOCK();
-	return (0);
 }
 
 /*
- * We may decide later to implement connection closing
- * handshaking at the spx level optionally.
- * here is the hook to do it:
+ * We may decide later to implement connection closing handshaking at the spx
+ * level optionally.  Here is the hook to do it:
  */
 static int
-spx_usr_disconnect(so)
-	struct socket *so;
+spx_usr_disconnect(struct socket *so)
 {
 	struct ipxpcb *ipxp;
 	struct spxpcb *cb;
+	int error;
 
 	ipxp = sotoipxpcb(so);
+	KASSERT(ipxp != NULL, ("spx_usr_disconnect: ipxp == NULL"));
+
 	cb = ipxtospxpcb(ipxp);
+	KASSERT(cb != NULL, ("spx_usr_disconnect: cb == NULL"));
 
 	IPX_LIST_LOCK();
 	IPX_LOCK(ipxp);
+	if (ipxp->ipxp_flags & IPXP_DROPPED) {
+		error = EINVAL;
+		goto out;
+	}
 	spx_disconnect(cb);
+	error = 0;
+out:
+	IPX_UNLOCK(ipxp);
 	IPX_LIST_UNLOCK();
-	return (0);
+	return (error);
 }
 
 static int
-spx_listen(so, td)
-	struct socket *so;
-	struct thread *td;
+spx_listen(struct socket *so, int backlog, struct thread *td)
 {
 	int error;
 	struct ipxpcb *ipxp;
@@ -1528,90 +1623,116 @@
 
 	error = 0;
 	ipxp = sotoipxpcb(so);
+	KASSERT(ipxp != NULL, ("spx_listen: ipxp == NULL"));
+
 	cb = ipxtospxpcb(ipxp);
+	KASSERT(cb != NULL, ("spx_listen: cb == NULL"));
 
 	IPX_LIST_LOCK();
 	IPX_LOCK(ipxp);
+	if (ipxp->ipxp_flags & IPXP_DROPPED) {
+		error = EINVAL;
+		goto out;
+	}
 	SOCK_LOCK(so);
 	error = solisten_proto_check(so);
 	if (error == 0 && ipxp->ipxp_lport == 0)
 		error = ipx_pcbbind(ipxp, NULL, td);
 	if (error == 0) {
 		cb->s_state = TCPS_LISTEN;
-		solisten_proto(so);
+		solisten_proto(so, backlog);
 	}
 	SOCK_UNLOCK(so);
+out:
 	IPX_UNLOCK(ipxp);
 	IPX_LIST_UNLOCK();
 	return (error);
 }
 
 /*
- * After a receive, possibly send acknowledgment
- * updating allocation.
+ * After a receive, possibly send acknowledgment updating allocation.
  */
 static int
-spx_rcvd(so, flags)
-	struct socket *so;
-	int flags;
+spx_rcvd(struct socket *so, int flags)
 {
 	struct ipxpcb *ipxp;
 	struct spxpcb *cb;
+	int error;
 
 	ipxp = sotoipxpcb(so);
+	KASSERT(ipxp != NULL, ("spx_rcvd: ipxp == NULL"));
+
 	cb = ipxtospxpcb(ipxp);
+	KASSERT(cb != NULL, ("spx_rcvd: cb == NULL"));
 
 	IPX_LOCK(ipxp);
+	if (ipxp->ipxp_flags & IPXP_DROPPED) {
+		error = EINVAL;
+		goto out;
+	}
 	cb->s_flags |= SF_RVD;
 	spx_output(cb, NULL);
 	cb->s_flags &= ~SF_RVD;
+	error = 0;
+out:
 	IPX_UNLOCK(ipxp);
-	return (0);
+	return (error);
 }
 
 static int
-spx_rcvoob(so, m, flags)
-	struct socket *so;
-	struct mbuf *m;
-	int flags;
+spx_rcvoob(struct socket *so, struct mbuf *m, int flags)
 {
 	struct ipxpcb *ipxp;
 	struct spxpcb *cb;
+	int error;
 
 	ipxp = sotoipxpcb(so);
+	KASSERT(ipxp != NULL, ("spx_rcvoob: ipxp == NULL"));
+
 	cb = ipxtospxpcb(ipxp);
+	KASSERT(cb != NULL, ("spx_rcvoob: cb == NULL"));
 
+	IPX_LOCK(ipxp);
+	if (ipxp->ipxp_flags & IPXP_DROPPED) {
+		error = EINVAL;
+		goto out;
+	}
 	SOCKBUF_LOCK(&so->so_rcv);
 	if ((cb->s_oobflags & SF_IOOB) || so->so_oobmark ||
 	    (so->so_rcv.sb_state & SBS_RCVATMARK)) {
 		SOCKBUF_UNLOCK(&so->so_rcv);
 		m->m_len = 1;
-		/* Unlocked read. */
 		*mtod(m, caddr_t) = cb->s_iobc;
-		return (0);
+		error = 0;
+		goto out;
 	}
 	SOCKBUF_UNLOCK(&so->so_rcv);
-	return (EINVAL);
+	error = EINVAL;
+out:
+	IPX_UNLOCK(ipxp);
+	return (error);
 }
 
 static int
-spx_send(so, flags, m, addr, controlp, td)
-	struct socket *so;
-	int flags;
-	struct mbuf *m;
-	struct sockaddr *addr;
-	struct mbuf *controlp;
-	struct thread *td;
+spx_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
+    struct mbuf *controlp, struct thread *td)
 {
-	int error;
 	struct ipxpcb *ipxp;
 	struct spxpcb *cb;
+	int error;
 
-	error = 0;
 	ipxp = sotoipxpcb(so);
+	KASSERT(ipxp != NULL, ("spx_send: ipxp == NULL"));
+
 	cb = ipxtospxpcb(ipxp);
+	KASSERT(cb != NULL, ("spx_send: cb == NULL"));
 
+	error = 0;
 	IPX_LOCK(ipxp);
+	if (ipxp->ipxp_flags & IPXP_DROPPED) {
+		error = ECONNRESET;
+		goto spx_send_end;
+	}
 	if (flags & PRUS_OOB) {
 		if (sbspace(&so->so_snd) < -512) {
 			error = ENOBUFS;
@@ -1641,114 +1762,116 @@
 }
 
 static int
-spx_shutdown(so)
-	struct socket *so;
+spx_shutdown(struct socket *so)
 {
 	struct ipxpcb *ipxp;
 	struct spxpcb *cb;
+	int error;
 
 	ipxp = sotoipxpcb(so);
+	KASSERT(ipxp != NULL, ("spx_shutdown: ipxp == NULL"));
+
 	cb = ipxtospxpcb(ipxp);
+	KASSERT(cb != NULL, ("spx_shutdown: cb == NULL"));
 
 	socantsendmore(so);
 	IPX_LIST_LOCK();
 	IPX_LOCK(ipxp);
+	if (ipxp->ipxp_flags & IPXP_DROPPED) {
+		error = EINVAL;
+		goto out;
+	}
 	spx_usrclosed(cb);
+	error = 0;
+out:
+	IPX_UNLOCK(ipxp);
 	IPX_LIST_UNLOCK();
-	return (0);
+	return (error);
 }
 
 static int
-spx_sp_attach(so, proto, td)
-	struct socket *so;
-	int proto;
-	struct thread *td;
+spx_sp_attach(struct socket *so, int proto, struct thread *td)
 {
-	int error;
 	struct ipxpcb *ipxp;
+	struct spxpcb *cb;
+	int error;
+
+	KASSERT(so->so_pcb == NULL, ("spx_sp_attach: so_pcb != NULL"));
 
 	error = spx_attach(so, proto, td);
-	if (error == 0) {
-		ipxp = sotoipxpcb(so);
-		((struct spxpcb *)ipxp->ipxp_pcb)->s_flags |=
-					(SF_HI | SF_HO | SF_PI);
-	}
-	return (error);
+	if (error)
+		return (error);
+
+	ipxp = sotoipxpcb(so);
+	KASSERT(ipxp != NULL, ("spx_sp_attach: ipxp == NULL"));
+
+	cb = ipxtospxpcb(ipxp);
+	KASSERT(cb != NULL, ("spx_sp_attach: cb == NULL"));
+
+	IPX_LOCK(ipxp);
+	cb->s_flags |= (SF_HI | SF_HO | SF_PI);
+	IPX_UNLOCK(ipxp);
+	return (0);
 }
 
 /*
- * Create template to be used to send spx packets on a connection.
- * Called after host entry created, fills
- * in a skeletal spx header (choosing connection id),
- * minimizing the amount of work necessary when the connection is used.
+ * Create template to be used to send spx packets on a connection.  Called
+ * after host entry created, fills in a skeletal spx header (choosing
+ * connection id), minimizing the amount of work necessary when the
+ * connection is used.
  */
 static void
-spx_template(cb)
-	register struct spxpcb *cb;
+spx_template(struct spxpcb *cb)
 {
-	register struct ipxpcb *ipxp = cb->s_ipxpcb;
-	register struct ipx *ipx = cb->s_ipx;
-	register struct sockbuf *sb = &(ipxp->ipxp_socket->so_snd);
+	struct ipxpcb *ipxp = cb->s_ipxpcb;
+	struct ipx *ipx = cb->s_ipx;
+	struct sockbuf *sb = &(ipxp->ipxp_socket->so_snd);
 
 	IPX_LOCK_ASSERT(ipxp);
 
 	ipx->ipx_pt = IPXPROTO_SPX;
 	ipx->ipx_sna = ipxp->ipxp_laddr;
 	ipx->ipx_dna = ipxp->ipxp_faddr;
+	SPX_LOCK();
 	cb->s_sid = htons(spx_iss);
 	spx_iss += SPX_ISSINCR/2;
+	SPX_UNLOCK();
 	cb->s_alo = 1;
 	cb->s_cwnd = (sbspace(sb) * CUNIT) / cb->s_mtu;
-	cb->s_ssthresh = cb->s_cwnd; /* Try to expand fast to full complement
-					of large packets */
+	/* Try to expand fast to full complement of large packets. */
+	cb->s_ssthresh = cb->s_cwnd;
 	cb->s_cwmx = (sbspace(sb) * CUNIT) / (2 * sizeof(struct spx));
+	/* But allow for lots of little packets as well. */
 	cb->s_cwmx = max(cb->s_cwmx, cb->s_cwnd);
-		/* But allow for lots of little packets as well */
 }
 
 /*
- * Close a SPIP control block:
- *	discard spx control block itself
- *	discard ipx protocol control block
- *	wake up any sleepers
- * cb will always be invalid after this call.
+ * Close a SPIP control block.  Wake up any sleepers.  We used to free any
+ * queued packets and cb->s_ipx here, but now we defer that until the pcb is
+ * discarded.
  */
 void
-spx_close(cb)
-	register struct spxpcb *cb;
+spx_close(struct spxpcb *cb)
 {
-	register struct spx_q *s;
 	struct ipxpcb *ipxp = cb->s_ipxpcb;
 	struct socket *so = ipxp->ipxp_socket;
-	register struct mbuf *m;
 
+	KASSERT(ipxp != NULL, ("spx_close: ipxp == NULL"));
 	IPX_LIST_LOCK_ASSERT();
 	IPX_LOCK_ASSERT(ipxp);
 
-	s = cb->s_q.si_next;
-	while (s != &(cb->s_q)) {
-		s = s->si_next;
-		m = dtom(s->si_prev);
-		remque(s->si_prev);
-		m_freem(m);
-	}
-	m_free(dtom(cb->s_ipx));
-	FREE(cb, M_PCB);
-	ipxp->ipxp_pcb = NULL;
+	ipxp->ipxp_flags |= IPXP_DROPPED;
 	soisdisconnected(so);
-	ipx_pcbdetach(ipxp);
 	spxstat.spxs_closed++;
 }
 
 /*
- *	Someday we may do level 3 handshaking
- *	to close a connection or send a xerox style error.
- *	For now, just close.
- * cb will always be invalid after this call.
+ * Someday we may do level 3 handshaking to close a connection or send a
+ * xerox style error.  For now, just close.  cb will always be invalid after
+ * this call.
  */
 static void
-spx_usrclosed(cb)
-	register struct spxpcb *cb;
+spx_usrclosed(struct spxpcb *cb)
 {
 
 	IPX_LIST_LOCK_ASSERT();
@@ -1761,8 +1884,7 @@
  * cb will always be invalid after this call.
  */
 static void
-spx_disconnect(cb)
-	register struct spxpcb *cb;
+spx_disconnect(struct spxpcb *cb)
 {
 
 	IPX_LIST_LOCK_ASSERT();
@@ -1772,14 +1894,11 @@
 }
 
 /*
- * Drop connection, reporting
- * the specified error.
- * cb will always be invalid after this call.
+ * Drop connection, reporting the specified error.  cb will always be invalid
+ * after this call.
  */
 static void
-spx_drop(cb, errno)
-	register struct spxpcb *cb;
-	int errno;
+spx_drop(struct spxpcb *cb, int errno)
 {
 	struct socket *so = cb->s_ipxpcb->ipxp_socket;
 
@@ -1787,9 +1906,8 @@
 	IPX_LOCK_ASSERT(cb->s_ipxpcb);
 
 	/*
-	 * someday, in the xerox world
-	 * we will generate error protocol packets
-	 * announcing that the socket has gone away.
+	 * Someday, in the xerox world we will generate error protocol
+	 * packets announcing that the socket has gone away.
 	 */
 	if (TCPS_HAVERCVDSYN(cb->s_state)) {
 		spxstat.spxs_drops++;
@@ -1802,10 +1920,10 @@
 }
 
 /*
- * Fast timeout routine for processing delayed acks
+ * Fast timeout routine for processing delayed acks.
  */
 void
-spx_fasttimo()
+spx_fasttimo(void)
 {
 	struct ipxpcb *ipxp;
 	struct spxpcb *cb;
@@ -1813,8 +1931,13 @@
 	IPX_LIST_LOCK();
 	LIST_FOREACH(ipxp, &ipxpcb_list, ipxp_list) {
 		IPX_LOCK(ipxp);
-		if ((cb = (struct spxpcb *)ipxp->ipxp_pcb) != NULL &&
-		    (cb->s_flags & SF_DELACK)) {
+		if (!(ipxp->ipxp_flags & IPXP_SPX) ||
+		    (ipxp->ipxp_flags & IPXP_DROPPED)) {
+			IPX_UNLOCK(ipxp);
+			continue;
+		}
+		cb = ipxtospxpcb(ipxp);
+		if (cb->s_flags & SF_DELACK) {
 			cb->s_flags &= ~SF_DELACK;
 			cb->s_flags |= SF_ACKNOW;
 			spxstat.spxs_delack++;
@@ -1826,59 +1949,56 @@
 }
 
 /*
- * spx protocol timeout routine called every 500 ms.
- * Updates the timers in all active pcb's and
- * causes finite state machine actions if timers expire.
+ * spx protocol timeout routine called every 500 ms.  Updates the timers in
+ * all active pcb's and causes finite state machine actions if timers expire.
  */
 void
-spx_slowtimo()
+spx_slowtimo(void)
 {
-	struct ipxpcb *ip, *ip_temp;
+	struct ipxpcb *ipxp;
 	struct spxpcb *cb;
 	int i;
 
 	/*
-	 * Search through tcb's and update active timers.  Note that timers
-	 * may free the ipxpcb, so be sure to handle that case.
-	 *
-	 * spx_timers() may remove an ipxpcb entry, so we have to be ready to
-	 * continue despite that.  The logic here is a bit obfuscated.
+	 * Search through tcb's and update active timers.  Once, timers could
+	 * free ipxp's, but now we do that only when detaching a socket.
 	 */
 	IPX_LIST_LOCK();
-	LIST_FOREACH_SAFE(ip, &ipxpcb_list, ipxp_list, ip_temp) {
-		cb = ipxtospxpcb(ip);
-		if (cb == NULL)
+	LIST_FOREACH(ipxp, &ipxpcb_list, ipxp_list) {
+		IPX_LOCK(ipxp);
+		if (!(ipxp->ipxp_flags & IPXP_SPX) ||
+		    (ipxp->ipxp_flags & IPXP_DROPPED)) {
+			IPX_UNLOCK(ipxp);
 			continue;
-		IPX_LOCK(cb->s_ipxpcb);
+		}
+
+		cb = (struct spxpcb *)ipxp->ipxp_pcb;
+		KASSERT(cb != NULL, ("spx_slowtimo: cb == NULL"));
 		for (i = 0; i < SPXT_NTIMERS; i++) {
 			if (cb->s_timer[i] && --cb->s_timer[i] == 0) {
-				/*
-				 * spx_timers() returns (NULL) if it free'd
-				 * the pcb.
-				 */
-				cb = spx_timers(cb, i);
-				if (cb == NULL)
+				spx_timers(cb, i);
+				if (ipxp->ipxp_flags & IPXP_DROPPED)
 					break;
 			}
 		}
-		if (cb != NULL) {
+		if (!(ipxp->ipxp_flags & IPXP_DROPPED)) {
 			cb->s_idle++;
 			if (cb->s_rtt)
 				cb->s_rtt++;
-			IPX_UNLOCK(cb->s_ipxpcb);
 		}
+		IPX_UNLOCK(ipxp);
 	}
-	spx_iss += SPX_ISSINCR/PR_SLOWHZ;		/* increment iss */
 	IPX_LIST_UNLOCK();
+	SPX_LOCK();
+	spx_iss += SPX_ISSINCR/PR_SLOWHZ;		/* increment iss */
+	SPX_UNLOCK();
 }
 
 /*
  * SPX timer processing.
  */
-static struct spxpcb *
-spx_timers(cb, timer)
-	register struct spxpcb *cb;
-	int timer;
+static void
+spx_timers(struct spxpcb *cb, int timer)
 {
 	long rexmt;
 	int win;
@@ -1888,27 +2008,25 @@
 
 	cb->s_force = 1 + timer;
 	switch (timer) {
-
-	/*
-	 * 2 MSL timeout in shutdown went off.  TCP deletes connection
-	 * control block.
-	 */
 	case SPXT_2MSL:
+		/*
+		 * 2 MSL timeout in shutdown went off.  TCP deletes
+		 * connection control block.
+		 */
 		printf("spx: SPXT_2MSL went off for no reason\n");
 		cb->s_timer[timer] = 0;
 		break;
 
-	/*
-	 * Retransmission timer went off.  Message has not
-	 * been acked within retransmit interval.  Back off
-	 * to a longer retransmit interval and retransmit one packet.
-	 */
 	case SPXT_REXMT:
+		/*
+		 * Retransmission timer went off.  Message has not been acked
+		 * within retransmit interval.  Back off to a longer
+		 * retransmit interval and retransmit one packet.
+		 */
 		if (++cb->s_rxtshift > SPX_MAXRXTSHIFT) {
 			cb->s_rxtshift = SPX_MAXRXTSHIFT;
 			spxstat.spxs_timeoutdrop++;
 			spx_drop(cb, ETIMEDOUT);
-			cb = NULL;
 			break;
 		}
 		spxstat.spxs_rexmttimeo++;
@@ -1916,25 +2034,27 @@
 		rexmt *= spx_backoff[cb->s_rxtshift];
 		SPXT_RANGESET(cb->s_rxtcur, rexmt, SPXTV_MIN, SPXTV_REXMTMAX);
 		cb->s_timer[SPXT_REXMT] = cb->s_rxtcur;
+
 		/*
-		 * If we have backed off fairly far, our srtt
-		 * estimate is probably bogus.  Clobber it
-		 * so we'll take the next rtt measurement as our srtt;
-		 * move the current srtt into rttvar to keep the current
-		 * retransmit times until then.
+		 * If we have backed off fairly far, our srtt estimate is
+		 * probably bogus.  Clobber it so we'll take the next rtt
+		 * measurement as our srtt; move the current srtt into rttvar
+		 * to keep the current retransmit times until then.
 		 */
 		if (cb->s_rxtshift > SPX_MAXRXTSHIFT / 4 ) {
 			cb->s_rttvar += (cb->s_srtt >> 2);
 			cb->s_srtt = 0;
 		}
 		cb->s_snxt = cb->s_rack;
+
 		/*
 		 * If timing a packet, stop the timer.
 		 */
 		cb->s_rtt = 0;
+
 		/*
 		 * See very long discussion in tcp_timer.c about congestion
-		 * window and sstrhesh
+		 * window and sstrhesh.
 		 */
 		win = min(cb->s_swnd, (cb->s_cwnd/CUNIT)) / 2;
 		if (win < 2)
@@ -1944,21 +2064,21 @@
 		spx_output(cb, NULL);
 		break;
 
-	/*
-	 * Persistance timer into zero window.
-	 * Force a probe to be sent.
-	 */
 	case SPXT_PERSIST:
+		/*
+		 * Persistance timer into zero window.  Force a probe to be
+		 * sent.
+		 */
 		spxstat.spxs_persisttimeo++;
 		spx_setpersist(cb);
 		spx_output(cb, NULL);
 		break;
 
-	/*
-	 * Keep-alive timer went off; send something
-	 * or drop connection if idle for too long.
-	 */
 	case SPXT_KEEP:
+		/*
+		 * Keep-alive timer went off; send something or drop
+		 * connection if idle for too long.
+		 */
 		spxstat.spxs_keeptimeo++;
 		if (cb->s_state < TCPS_ESTABLISHED)
 			goto dropit;
@@ -1971,11 +2091,13 @@
 			cb->s_idle = 0;
 		cb->s_timer[SPXT_KEEP] = SPXTV_KEEP;
 		break;
+
 	dropit:
 		spxstat.spxs_keepdrops++;
 		spx_drop(cb, ETIMEDOUT);
-		cb = NULL;
 		break;
+
+	default:
+		panic("spx_timers: unknown timer %d", timer);
 	}
-	return (cb);
 }
Index: ipx_var.h
===================================================================
RCS file: /home/cvs/src/sys/netipx/ipx_var.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/ipx_var.h -L sys/netipx/ipx_var.h -u -r1.1.1.1 -r1.2
--- sys/netipx/ipx_var.h
+++ sys/netipx/ipx_var.h
@@ -1,5 +1,4 @@
 /*-
- * Copyright (c) 1995, Mike Mitchell
  * Copyright (c) 1984, 1985, 1986, 1987, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -11,6 +10,32 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1995, Mike Mitchell
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *	This product includes software developed by the University of
@@ -33,7 +58,7 @@
  *
  *	@(#)ipx_var.h
  *
- * $FreeBSD: src/sys/netipx/ipx_var.h,v 1.22 2005/01/07 01:45:47 imp Exp $
+ * $FreeBSD: src/sys/netipx/ipx_var.h,v 1.24 2007/05/11 10:38:34 rwatson Exp $
  */
 
 #ifndef _NETIPX_IPX_VAR_H_
@@ -88,7 +113,7 @@
 
 u_short	ipx_cksum(struct mbuf *m, int len);
 int	ipx_control(struct socket *so, u_long cmd, caddr_t data,
-			 struct ifnet *ifp, struct thread *td);
+	    struct ifnet *ifp, struct thread *td);
 void	ipx_ctlinput(int cmd, struct sockaddr *arg_as_sa, void *dummy);
 int	ipx_ctloutput(struct socket *so, struct sockopt *sopt);
 void	ipx_drop(struct ipxpcb *ipxp, int errno);
Index: ipx_pcb.h
===================================================================
RCS file: /home/cvs/src/sys/netipx/ipx_pcb.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/ipx_pcb.h -L sys/netipx/ipx_pcb.h -u -r1.1.1.1 -r1.2
--- sys/netipx/ipx_pcb.h
+++ sys/netipx/ipx_pcb.h
@@ -1,8 +1,35 @@
 /*-
- * Copyright (c) 2004-2005 Robert N. M. Watson
- * Copyright (c) 1995, Mike Mitchell
  * Copyright (c) 1984, 1985, 1986, 1987, 1993
- *	The Regents of the University of California.  All rights reserved.
+ *	The Regents of the University of California.
+ * Copyright (c) 2004-2006 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1995, Mike Mitchell
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,7 +61,7 @@
  *
  *	@(#)ipx_pcb.h
  *
- * $FreeBSD: src/sys/netipx/ipx_pcb.h,v 1.23 2005/01/09 05:00:41 rwatson Exp $
+ * $FreeBSD: src/sys/netipx/ipx_pcb.h,v 1.29 2007/05/11 10:38:34 rwatson Exp $
  */
 
 #ifndef _NETIPX_IPX_PCB_H_
@@ -68,13 +95,16 @@
 extern struct mtx	ipxpcb_list_mtx;
 #endif
 
-/* possible flags */
-
-#define IPXP_IN_ABORT		0x1	/* calling abort through socket */
-#define IPXP_RAWIN		0x2	/* show headers on input */
-#define IPXP_RAWOUT		0x4	/* show header on output */
-#define IPXP_ALL_PACKETS	0x8	/* Turn off higher proto processing */
-#define	IPXP_CHECKSUM		0x10	/* use checksum on this socket */
+/*
+ * IPX/SPX PCB flags.
+ */
+#define IPXP_IN_ABORT		0x1	/* Calling abort through socket. */
+#define IPXP_RAWIN		0x2	/* Show headers on input. */
+#define IPXP_RAWOUT		0x4	/* Show header on output. */
+#define IPXP_ALL_PACKETS	0x8	/* Turn off higher proto processing. */
+#define	IPXP_CHECKSUM		0x10	/* Use checksum on this socket. */
+#define	IPXP_DROPPED		0x20	/* Connection dropped. */
+#define	IPXP_SPX		0x40	/* SPX PCB. */
 
 #define	IPX_WILDCARD		1
 
@@ -91,17 +121,17 @@
 
 #ifdef _KERNEL
 int	ipx_pcballoc(struct socket *so, struct ipxpcbhead *head,
-			  struct thread *p);
+	    struct thread *p);
 int	ipx_pcbbind(struct ipxpcb *ipxp, struct sockaddr *nam,
-			 struct thread *p);
+	    struct thread *p);
 int	ipx_pcbconnect(struct ipxpcb *ipxp, struct sockaddr *nam,
-			    struct thread *p);
+	    struct thread *p);
 void	ipx_pcbdetach(struct ipxpcb *ipxp);
 void	ipx_pcbdisconnect(struct ipxpcb *ipxp);
-struct ipxpcb *
-	ipx_pcblookup(struct ipx_addr *faddr, int lport, int wildp);
-void	ipx_setpeeraddr(struct ipxpcb *ipxp, struct sockaddr **nam);
-void	ipx_setsockaddr(struct ipxpcb *ipxp, struct sockaddr **nam);
+void	ipx_pcbfree(struct ipxpcb *ipxp);
+struct ipxpcb *ipx_pcblookup(struct ipx_addr *faddr, u_short lport, int wildp);
+void	ipx_getpeeraddr(struct ipxpcb *ipxp, struct sockaddr **nam);
+void	ipx_getsockaddr(struct ipxpcb *ipxp, struct sockaddr **nam);
 
 #define	IPX_LIST_LOCK_INIT()	mtx_init(&ipxpcb_list_mtx, "ipx_list_mtx", \
 				    NULL, MTX_DEF | MTX_RECURSE)
Index: ipx_if.h
===================================================================
RCS file: /home/cvs/src/sys/netipx/ipx_if.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/ipx_if.h -L sys/netipx/ipx_if.h -u -r1.1.1.1 -r1.2
--- sys/netipx/ipx_if.h
+++ sys/netipx/ipx_if.h
@@ -1,5 +1,4 @@
 /*-
- * Copyright (c) 1995, Mike Mitchell
  * Copyright (c) 1984, 1985, 1986, 1987, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -11,6 +10,32 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+
+ * Copyright (c) 1995, Mike Mitchell
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *	This product includes software developed by the University of
@@ -33,7 +58,7 @@
  *
  *	@(#)ipx_if.h
  *
- * $FreeBSD: src/sys/netipx/ipx_if.h,v 1.15 2005/01/07 01:45:47 imp Exp $
+ * $FreeBSD: src/sys/netipx/ipx_if.h,v 1.18 2007/06/13 14:01:43 rwatson Exp $
  */
 
 #ifndef _NETIPX_IPX_IF_H_
@@ -79,18 +104,10 @@
 
 #define	ETHERTYPE_IPX		0x8137	/* Only  Ethernet_II Available */
 
-#ifdef	IPXIP
-struct ipxip_req {
-	struct sockaddr rq_ipx;	/* must be ipx format destination */
-	struct sockaddr rq_ip;	/* must be ip format gateway */
-	short rq_flags;
-};
-#endif
-
 #ifdef	_KERNEL
 extern struct	ipx_ifaddr *ipx_ifaddr;
 
-struct ipx_ifaddr *ipx_iaonnetof(struct ipx_addr *dst);
+struct ipx_ifaddr	*ipx_iaonnetof(struct ipx_addr *dst);
 #endif
 
 #endif /* !_NETIPX_IPX_IF_H_ */
Index: ipx_usrreq.c
===================================================================
RCS file: /home/cvs/src/sys/netipx/ipx_usrreq.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/ipx_usrreq.c -L sys/netipx/ipx_usrreq.c -u -r1.1.1.1 -r1.2
--- sys/netipx/ipx_usrreq.c
+++ sys/netipx/ipx_usrreq.c
@@ -1,8 +1,35 @@
 /*-
- * Copyright (c) 2004-2005 Robert N. M. Watson
- * Copyright (c) 1995, Mike Mitchell
  * Copyright (c) 1984, 1985, 1986, 1987, 1993
- *	The Regents of the University of California.  All rights reserved.
+ *	The Regents of the University of California.
+ * Copyright (c) 2004-2006 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1995, Mike Mitchell
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -36,7 +63,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/netipx/ipx_usrreq.c,v 1.52 2005/01/09 05:15:59 rwatson Exp $");
+__FBSDID("$FreeBSD: src/sys/netipx/ipx_usrreq.c,v 1.62 2007/06/13 14:01:43 rwatson Exp $");
 
 #include "opt_ipx.h"
 
@@ -44,6 +71,7 @@
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/mbuf.h>
+#include <sys/priv.h>
 #include <sys/protosw.h>
 #include <sys/signalvar.h>
 #include <sys/socket.h>
@@ -59,7 +87,6 @@
 
 #include <netipx/ipx.h>
 #include <netipx/ipx_if.h>
-#include <netipx/ipx_ip.h>
 #include <netipx/ipx_pcb.h>
 #include <netipx/ipx_var.h>
 
@@ -74,12 +101,12 @@
 SYSCTL_INT(_net_ipx_ipx, OID_AUTO, ipxrecvspace, CTLFLAG_RW,
             &ipxrecvspace, 0, "");
 
-static	int ipx_usr_abort(struct socket *so);
+static	void ipx_usr_abort(struct socket *so);
 static	int ipx_attach(struct socket *so, int proto, struct thread *td);
 static	int ipx_bind(struct socket *so, struct sockaddr *nam, struct thread *td);
 static	int ipx_connect(struct socket *so, struct sockaddr *nam,
 			struct thread *td);
-static	int ipx_detach(struct socket *so);
+static	void ipx_detach(struct socket *so);
 static	int ipx_disconnect(struct socket *so);
 static	int ipx_send(struct socket *so, int flags, struct mbuf *m,
 		     struct sockaddr *addr, struct mbuf *control,
@@ -87,6 +114,7 @@
 static	int ipx_shutdown(struct socket *so);
 static	int ripx_attach(struct socket *so, int proto, struct thread *td);
 static	int ipx_output(struct ipxpcb *ipxp, struct mbuf *m0);
+static	void ipx_usr_close(struct socket *so);
 
 struct	pr_usrreqs ipx_usrreqs = {
 	.pru_abort =		ipx_usr_abort,
@@ -100,6 +128,7 @@
 	.pru_send =		ipx_send,
 	.pru_shutdown =		ipx_shutdown,
 	.pru_sockaddr =		ipx_sockaddr,
+	.pru_close =		ipx_usr_close,
 };
 
 struct	pr_usrreqs ripx_usrreqs = {
@@ -114,17 +143,16 @@
 	.pru_send =		ipx_send,
 	.pru_shutdown =		ipx_shutdown,
 	.pru_sockaddr =		ipx_sockaddr,
+	.pru_close =		ipx_usr_close,
 };
 
 /*
  *  This may also be called for raw listeners.
  */
 void
-ipx_input(m, ipxp)
-	struct mbuf *m;
-	register struct ipxpcb *ipxp;
+ipx_input(struct mbuf *m, struct ipxpcb *ipxp)
 {
-	register struct ipx *ipx = mtod(m, struct ipx *);
+	struct ipx *ipx = mtod(m, struct ipx *);
 	struct ifnet *ifp = m->m_pkthdr.rcvif;
 	struct sockaddr_ipx ipx_ipx;
 
@@ -140,7 +168,7 @@
 	ipx_ipx.sipx_zero[0] = '\0';
 	ipx_ipx.sipx_zero[1] = '\0';
 	if (ipx_neteqnn(ipx->ipx_sna.x_net, ipx_zeronet) && ifp != NULL) {
-		register struct ifaddr *ifa;
+		struct ifaddr *ifa;
 
 		for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa != NULL;
 		     ifa = TAILQ_NEXT(ifa, ifa_link)) {
@@ -169,9 +197,7 @@
  * the specified error.
  */
 void
-ipx_drop(ipxp, errno)
-	register struct ipxpcb *ipxp;
-	int errno;
+ipx_drop(struct ipxpcb *ipxp, int errno)
 {
 	struct socket *so = ipxp->ipxp_socket;
 
@@ -195,14 +221,12 @@
 }
 
 static int
-ipx_output(ipxp, m0)
-	struct ipxpcb *ipxp;
-	struct mbuf *m0;
-{
-	register struct ipx *ipx;
-	register struct socket *so;
-	register int len = 0;
-	register struct route *ro;
+ipx_output(struct ipxpcb *ipxp, struct mbuf *m0)
+{
+	struct ipx *ipx;
+	struct socket *so;
+	int len = 0;
+	struct route *ro;
 	struct mbuf *m;
 	struct mbuf *mprev = NULL;
 
@@ -297,7 +321,7 @@
 
 			}
 			if ((ro->ro_rt->rt_flags & RTF_GATEWAY) == 0) {
-				register struct ipx_addr *dst =
+				struct ipx_addr *dst =
 						&satoipx_addr(ro->ro_dst);
 				dst->x_host = ipx->ipx_dna.x_host;
 			}
@@ -317,9 +341,7 @@
 }
 
 int
-ipx_ctloutput(so, sopt)
-	struct socket *so;
-	struct sockopt *sopt;
+ipx_ctloutput(struct socket *so, struct sockopt *sopt)
 {
 	struct ipxpcb *ipxp = sotoipxpcb(so);
 	int mask, error, optval;
@@ -327,9 +349,8 @@
 	struct ipx ioptval;
 	long seq;
 
+	KASSERT(ipxp != NULL, ("ipx_ctloutput: ipxp == NULL"));
 	error = 0;
-	if (ipxp == NULL)
-		return (EINVAL);
 
 	switch (sopt->sopt_dir) {
 	case SOPT_GET:
@@ -415,11 +436,6 @@
 			/* Unlocked write. */
 			ipxp->ipxp_dpt = ioptval.ipx_pt;
 			break;
-#ifdef IPXIP
-		case SO_IPXIP_ROUTE:
-			error = ipxip_route(so, sopt);
-			break;
-#endif /* IPXIP */
 		default:
 			error = EINVAL;
 		}
@@ -428,51 +444,39 @@
 	return (error);
 }
 
-static int
-ipx_usr_abort(so)
-	struct socket *so;
+static void
+ipx_usr_abort(struct socket *so)
 {
-	struct ipxpcb *ipxp = sotoipxpcb(so);
 
-	IPX_LIST_LOCK();
-	IPX_LOCK(ipxp);
-	ipx_pcbdetach(ipxp);
-	IPX_LIST_UNLOCK();
+	/* XXXRW: Possibly ipx_disconnect() here? */
 	soisdisconnected(so);
-	ACCEPT_LOCK();
-	SOCK_LOCK(so);
-	sotryfree(so);
-	return (0);
 }
 
 static int
-ipx_attach(so, proto, td)
-	struct socket *so;
-	int proto;
-	struct thread *td;
+ipx_attach(struct socket *so, int proto, struct thread *td)
 {
+#ifdef INVARIANTS
 	struct ipxpcb *ipxp = sotoipxpcb(so);
+#endif
 	int error;
 
-	if (ipxp != NULL)
-		return (EINVAL);
+	KASSERT(ipxp == NULL, ("ipx_attach: ipxp != NULL"));
+	error = soreserve(so, ipxsendspace, ipxrecvspace);
+	if (error != 0)
+		return (error);
 	IPX_LIST_LOCK();
 	error = ipx_pcballoc(so, &ipxpcb_list, td);
 	IPX_LIST_UNLOCK();
-	if (error == 0)
-		error = soreserve(so, ipxsendspace, ipxrecvspace);
 	return (error);
 }
 
 static int
-ipx_bind(so, nam, td)
-	struct socket *so;
-	struct sockaddr *nam;
-	struct thread *td;
+ipx_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
 {
 	struct ipxpcb *ipxp = sotoipxpcb(so);
 	int error;
 
+	KASSERT(ipxp != NULL, ("ipx_bind: ipxp == NULL"));
 	IPX_LIST_LOCK();
 	IPX_LOCK(ipxp);
 	error = ipx_pcbbind(ipxp, nam, td);
@@ -481,15 +485,21 @@
 	return (error);
 }
 
+static void
+ipx_usr_close(struct socket *so)
+{
+
+	/* XXXRW: Possibly ipx_disconnect() here? */
+	soisdisconnected(so);
+}
+
 static int
-ipx_connect(so, nam, td)
-	struct socket *so;
-	struct sockaddr *nam;
-	struct thread *td;
+ipx_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
 {
 	struct ipxpcb *ipxp = sotoipxpcb(so);
 	int error;
 
+	KASSERT(ipxp != NULL, ("ipx_connect: ipxp == NULL"));
 	IPX_LIST_LOCK();
 	IPX_LOCK(ipxp);
 	if (!ipx_nullhost(ipxp->ipxp_faddr)) {
@@ -505,28 +515,27 @@
 	return (error);
 }
 
-static int
-ipx_detach(so)
-	struct socket *so;
+static void
+ipx_detach(struct socket *so)
 {
 	struct ipxpcb *ipxp = sotoipxpcb(so);
 
-	if (ipxp == NULL)
-		return (ENOTCONN);
+	/* XXXRW: Should assert detached. */
+	KASSERT(ipxp != NULL, ("ipx_detach: ipxp == NULL"));
 	IPX_LIST_LOCK();
 	IPX_LOCK(ipxp);
 	ipx_pcbdetach(ipxp);
+	ipx_pcbfree(ipxp);
 	IPX_LIST_UNLOCK();
-	return (0);
 }
 
 static int
-ipx_disconnect(so)
-	struct socket *so;
+ipx_disconnect(struct socket *so)
 {
 	struct ipxpcb *ipxp = sotoipxpcb(so);
 	int error;
 
+	KASSERT(ipxp != NULL, ("ipx_disconnect: ipxp == NULL"));
 	IPX_LIST_LOCK();
 	IPX_LOCK(ipxp);
 	error = 0;
@@ -543,29 +552,24 @@
 }
 
 int
-ipx_peeraddr(so, nam)
-	struct socket *so;
-	struct sockaddr **nam;
+ipx_peeraddr(struct socket *so, struct sockaddr **nam)
 {
 	struct ipxpcb *ipxp = sotoipxpcb(so);
 
-	ipx_setpeeraddr(ipxp, nam);
+	KASSERT(ipxp != NULL, ("ipx_peeraddr: ipxp == NULL"));
+	ipx_getpeeraddr(ipxp, nam);
 	return (0);
 }
 
 static int
-ipx_send(so, flags, m, nam, control, td)
-	struct socket *so;
-	int flags;
-	struct mbuf *m;
-	struct sockaddr *nam;
-	struct mbuf *control;
-	struct thread *td;
+ipx_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
+    struct mbuf *control, struct thread *td)
 {
 	int error;
 	struct ipxpcb *ipxp = sotoipxpcb(so);
 	struct ipx_addr laddr;
 
+	KASSERT(ipxp != NULL, ("ipxp_send: ipxp == NULL"));
 	/*
 	 * Attempt to only acquire the necessary locks: if the socket is
 	 * already connected, we don't need to hold the IPX list lock to be
@@ -619,32 +623,36 @@
 ipx_shutdown(so)
 	struct socket *so;
 {
+
+	KASSERT(so->so_pcb != NULL, ("ipx_shutdown: so_pcb == NULL"));
 	socantsendmore(so);
 	return (0);
 }
 
 int
-ipx_sockaddr(so, nam)
-	struct socket *so;
-	struct sockaddr **nam;
+ipx_sockaddr(struct socket *so, struct sockaddr **nam)
 {
 	struct ipxpcb *ipxp = sotoipxpcb(so);
 
-	ipx_setsockaddr(ipxp, nam);
+	KASSERT(ipxp != NULL, ("ipx_sockaddr: ipxp == NULL"));
+	ipx_getsockaddr(ipxp, nam);
 	return (0);
 }
 
 static int
-ripx_attach(so, proto, td)
-	struct socket *so;
-	int proto;
-	struct thread *td;
+ripx_attach(struct socket *so, int proto, struct thread *td)
 {
 	int error = 0;
 	struct ipxpcb *ipxp = sotoipxpcb(so);
 
-	if (td != NULL && (error = suser(td)) != 0)
-		return (error);
+	KASSERT(ipxp == NULL, ("ripx_attach: ipxp != NULL"));
+
+	if (td != NULL) {
+		error = priv_check(td, PRIV_NETIPX_RAW);
+		if (error)
+			return (error);
+	}
+
 	/*
 	 * We hold the IPX list lock for the duration as address parameters
 	 * of the IPX pcb are changed.  Since no one else holds a reference
--- sys/netipx/ipx_ip.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*-
- * Copyright (c) 1995, Mike Mitchell
- * Copyright (c) 1984, 1985, 1986, 1987, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)ipxip.h
- *
- * $FreeBSD: src/sys/netipx/ipx_ip.h,v 1.17 2005/06/10 16:49:22 brooks Exp $
- */
-
-#ifndef _NETIPX_IPXIP_H_
-#define	_NETIPX_IPXIP_H_
-
-struct ifnet_en {
-	struct ifnet *ifen_ifp;
-	struct route ifen_route;
-	struct in_addr ifen_src;
-	struct in_addr ifen_dst;
-	struct ifnet_en *ifen_next;
-};
-
-#define LOMTU	(1024+512)	/* XXX this is TINY_LOMTU */
-
-#ifdef _KERNEL
-
-void	ipxip_ctlinput(int cmd, struct sockaddr *sa, void *arg);
-void	ipxip_input(struct mbuf *m, int hlen);
-int	ipxip_route(struct socket *so, struct sockopt *sopt);
-
-#endif
-
-#endif /* !_NETIPX_IPXIP_H_ */
Index: ipx_proto.c
===================================================================
RCS file: /home/cvs/src/sys/netipx/ipx_proto.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/ipx_proto.c -L sys/netipx/ipx_proto.c -u -r1.1.1.1 -r1.2
--- sys/netipx/ipx_proto.c
+++ sys/netipx/ipx_proto.c
@@ -1,5 +1,4 @@
 /*-
- * Copyright (c) 1995, Mike Mitchell
  * Copyright (c) 1984, 1985, 1986, 1987, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -11,6 +10,32 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1995, Mike Mitchell
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *	This product includes software developed by the University of
@@ -35,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/netipx/ipx_proto.c,v 1.19.2.1 2005/11/16 10:31:23 ru Exp $");
+__FBSDID("$FreeBSD: src/sys/netipx/ipx_proto.c,v 1.22 2007/01/08 22:14:00 rwatson Exp $");
 
 #include "opt_ipx.h"
 
@@ -53,13 +78,14 @@
 #include <netipx/ipx_var.h>
 #include <netipx/spx.h>
 
-extern	struct domain ipxdomain;
 static	struct pr_usrreqs nousrreqs;
 
 /*
  * IPX protocol family: IPX, ERR, PXP, SPX, ROUTE.
  */
 
+static	struct domain ipxdomain;
+
 static struct protosw ipxsw[] = {
 {
 	.pr_domain =		&ipxdomain,
Index: spx_var.h
===================================================================
RCS file: /home/cvs/src/sys/netipx/spx_var.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/spx_var.h -L sys/netipx/spx_var.h -u -r1.1.1.1 -r1.2
--- sys/netipx/spx_var.h
+++ sys/netipx/spx_var.h
@@ -1,5 +1,4 @@
 /*-
- * Copyright (c) 1995, Mike Mitchell
  * Copyright (c) 1984, 1985, 1986, 1987, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -11,6 +10,32 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1995, Mike Mitchell
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *	This product includes software developed by the University of
@@ -33,7 +58,7 @@
  *
  *	@(#)spx_var.h
  *
- * $FreeBSD: src/sys/netipx/spx_var.h,v 1.10 2005/01/07 01:45:47 imp Exp $
+ * $FreeBSD: src/sys/netipx/spx_var.h,v 1.11 2007/01/08 22:14:00 rwatson Exp $
  */
 
 #ifndef _NETIPX_SPX_VAR_H_
Index: ipx_cksum.c
===================================================================
RCS file: /home/cvs/src/sys/netipx/ipx_cksum.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/ipx_cksum.c -L sys/netipx/ipx_cksum.c -u -r1.1.1.1 -r1.2
--- sys/netipx/ipx_cksum.c
+++ sys/netipx/ipx_cksum.c
@@ -1,5 +1,4 @@
 /*-
- * Copyright (c) 1995, Mike Mitchell
  * Copyright (c) 1982, 1992, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -11,6 +10,32 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1995, Mike Mitchell
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *	This product includes software developed by the University of
@@ -35,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/netipx/ipx_cksum.c,v 1.13 2005/01/07 01:45:47 imp Exp $");
+__FBSDID("$FreeBSD: src/sys/netipx/ipx_cksum.c,v 1.15 2007/05/11 10:38:34 rwatson Exp $");
 
 #include <sys/param.h>
 #include <sys/mbuf.h>
@@ -48,7 +73,8 @@
 #define SUMADV	sum += *w++
 
 u_short
-ipx_cksum(struct mbuf *m, int len) {
+ipx_cksum(struct mbuf *m, int len)
+{
 	u_int32_t sum = 0;
 	u_char *w;
 	u_char oldtc;
Index: spx_timer.h
===================================================================
RCS file: /home/cvs/src/sys/netipx/spx_timer.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/spx_timer.h -L sys/netipx/spx_timer.h -u -r1.1.1.1 -r1.2
--- sys/netipx/spx_timer.h
+++ sys/netipx/spx_timer.h
@@ -1,5 +1,4 @@
 /*-
- * Copyright (c) 1995, Mike Mitchell
  * Copyright (c) 1982, 1986, 1988, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -11,6 +10,32 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1995, Mike Mitchell
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *	This product includes software developed by the University of
@@ -33,7 +58,7 @@
  *
  *	@(#)spx_timer.h
  *
- * $FreeBSD: src/sys/netipx/spx_timer.h,v 1.11 2005/01/07 01:45:47 imp Exp $
+ * $FreeBSD: src/sys/netipx/spx_timer.h,v 1.12 2007/01/08 22:14:00 rwatson Exp $
  */
 
 #ifndef _NETIPX_SPX_TIMER_H_
Index: spx_debug.c
===================================================================
RCS file: /home/cvs/src/sys/netipx/spx_debug.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/spx_debug.c -L sys/netipx/spx_debug.c -u -r1.1.1.1 -r1.2
--- sys/netipx/spx_debug.c
+++ sys/netipx/spx_debug.c
@@ -1,5 +1,4 @@
 /*-
- * Copyright (c) 1995, Mike Mitchell
  * Copyright (c) 1984, 1985, 1986, 1987, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -11,6 +10,32 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1995, Mike Mitchell
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *	This product includes software developed by the University of
@@ -35,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/netipx/spx_debug.c,v 1.16 2005/01/07 01:45:47 imp Exp $");
+__FBSDID("$FreeBSD: src/sys/netipx/spx_debug.c,v 1.19 2007/07/30 11:06:42 des Exp $");
 
 #include "opt_inet.h"
 #include "opt_tcpdebug.h"
@@ -44,6 +69,8 @@
 #include <sys/systm.h>
 #include <sys/protosw.h>
 
+#define TCPSTATES		/* for logging */
+
 #include <netinet/in_systm.h>
 #include <netinet/tcp_fsm.h>
 
@@ -65,12 +92,8 @@
  * spx debug routines
  */
 void
-spx_trace(act, ostate, sp, si, req)
-	short act;
-	u_char ostate;
-	struct spxpcb *sp;
-	struct spx *si;
-	int req;
+spx_trace(short act, u_char ostate, struct spxpcb *sp, struct spx *si,
+    int req)
 {
 #ifdef INET
 #ifdef TCPDEBUG
Index: ipx.h
===================================================================
RCS file: /home/cvs/src/sys/netipx/ipx.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/ipx.h -L sys/netipx/ipx.h -u -r1.1.1.1 -r1.2
--- sys/netipx/ipx.h
+++ sys/netipx/ipx.h
@@ -1,5 +1,4 @@
 /*-
- * Copyright (c) 1995, Mike Mitchell
  * Copyright (c) 1984, 1985, 1986, 1987, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -11,6 +10,32 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1995, Mike Mitchell
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *	This product includes software developed by the University of
@@ -33,7 +58,7 @@
  *
  *	@(#)ipx.h
  *
- * $FreeBSD: src/sys/netipx/ipx.h,v 1.21 2005/05/27 12:25:42 rwatson Exp $
+ * $FreeBSD: src/sys/netipx/ipx.h,v 1.24 2007/06/13 14:01:43 rwatson Exp $
  */
 
 #ifndef _NETIPX_IPX_H_
@@ -90,7 +115,7 @@
 #define	SO_HEADERS_ON_OUTPUT	2
 #define	SO_DEFAULT_HEADERS	3
 #define	SO_LAST_HEADER		4
-#define	SO_IPXIP_ROUTE		5
+#define	SO_IPXIP_ROUTE		5	/* No longer implemented. */
 #define SO_SEQNO		6
 #define	SO_ALL_PACKETS		7
 #define SO_MTU			8
@@ -162,8 +187,8 @@
 #include <sys/cdefs.h>
 
 __BEGIN_DECLS
-struct	ipx_addr ipx_addr(const char *);
-char	*ipx_ntoa(struct ipx_addr);
+struct ipx_addr	 ipx_addr(const char *);
+char		*ipx_ntoa(struct ipx_addr);
 __END_DECLS
 
 #endif /* !_NETIPX_IPX_H_ */
Index: spx.h
===================================================================
RCS file: /home/cvs/src/sys/netipx/spx.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/spx.h -L sys/netipx/spx.h -u -r1.1.1.1 -r1.2
--- sys/netipx/spx.h
+++ sys/netipx/spx.h
@@ -1,5 +1,4 @@
 /*-
- * Copyright (c) 1995, Mike Mitchell
  * Copyright (c) 1984, 1985, 1986, 1987, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -11,6 +10,32 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1995, Mike Mitchell
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *	This product includes software developed by the University of
@@ -33,7 +58,7 @@
  *
  *	@(#)spx.h
  *
- * $FreeBSD: src/sys/netipx/spx.h,v 1.19 2005/01/07 01:45:47 imp Exp $
+ * $FreeBSD: src/sys/netipx/spx.h,v 1.20 2007/01/08 22:14:00 rwatson Exp $
  */
 
 #ifndef _NETIPX_SPX_H_
Index: ipx_pcb.c
===================================================================
RCS file: /home/cvs/src/sys/netipx/ipx_pcb.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/ipx_pcb.c -L sys/netipx/ipx_pcb.c -u -r1.1.1.1 -r1.2
--- sys/netipx/ipx_pcb.c
+++ sys/netipx/ipx_pcb.c
@@ -1,8 +1,35 @@
 /*-
- * Copyright (c) 2004-2005 Robert N. M. Watson
- * Copyright (c) 1995, Mike Mitchell
  * Copyright (c) 1984, 1985, 1986, 1987, 1993
- *	The Regents of the University of California.  All rights reserved.
+ *	The Regents of the University of California.
+ * Copyright (c) 2004-2006 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1995, Mike Mitchell
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -36,11 +63,12 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/netipx/ipx_pcb.c,v 1.43 2005/01/09 05:10:43 rwatson Exp $");
+__FBSDID("$FreeBSD: src/sys/netipx/ipx_pcb.c,v 1.49 2007/05/11 10:38:34 rwatson Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/malloc.h>
+#include <sys/priv.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 
@@ -56,13 +84,11 @@
 static u_short	ipxpcb_lport_cache;
 
 int
-ipx_pcballoc(so, head, td)
-	struct socket *so;
-	struct ipxpcbhead *head;
-	struct thread *td;
+ipx_pcballoc(struct socket *so, struct ipxpcbhead *head, struct thread *td)
 {
-	register struct ipxpcb *ipxp;
+	struct ipxpcb *ipxp;
 
+	KASSERT(so->so_pcb == NULL, ("ipx_pcballoc: so_pcb != NULL"));
 	IPX_LIST_LOCK_ASSERT();
 
 	MALLOC(ipxp, struct ipxpcb *, sizeof *ipxp, M_PCB, M_NOWAIT | M_ZERO);
@@ -78,12 +104,9 @@
 }
 
 int
-ipx_pcbbind(ipxp, nam, td)
-	register struct ipxpcb *ipxp;
-	struct sockaddr *nam;
-	struct thread *td;
+ipx_pcbbind(struct ipxpcb *ipxp, struct sockaddr *nam, struct thread *td)
 {
-	register struct sockaddr_ipx *sipx;
+	struct sockaddr_ipx *sipx;
 	u_short lport = 0;
 
 	IPX_LIST_LOCK_ASSERT();
@@ -105,11 +128,10 @@
 	lport = sipx->sipx_port;
 	if (lport) {
 		u_short aport = ntohs(lport);
-		int error;
 
-		if (aport < IPXPORT_RESERVED &&
-		    td != NULL && (error = suser(td)) != 0)
-			return (error);
+		if (aport < IPXPORT_RESERVED && td != NULL &&
+		    priv_check(td, PRIV_NETIPX_RESERVEDPORT))
+			return (EACCES);
 		if (ipx_pcblookup(&zeroipx_addr, lport, 0))
 			return (EADDRINUSE);
 	}
@@ -134,15 +156,12 @@
  * then pick one.
  */
 int
-ipx_pcbconnect(ipxp, nam, td)
-	struct ipxpcb *ipxp;
-	struct sockaddr *nam;
-	struct thread *td;
+ipx_pcbconnect(struct ipxpcb *ipxp, struct sockaddr *nam, struct thread *td)
 {
 	struct ipx_ifaddr *ia;
-	register struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)nam;
-	register struct ipx_addr *dst;
-	register struct route *ro;
+	struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)nam;
+	struct ipx_addr *dst;
+	struct route *ro;
 	struct ifnet *ifp;
 
 	IPX_LIST_LOCK_ASSERT();
@@ -264,31 +283,36 @@
 }
 
 void
-ipx_pcbdisconnect(ipxp)
-	struct ipxpcb *ipxp;
+ipx_pcbdisconnect(struct ipxpcb *ipxp)
 {
 
 	IPX_LIST_LOCK_ASSERT();
 	IPX_LOCK_ASSERT(ipxp);
 
 	ipxp->ipxp_faddr = zeroipx_addr;
-	if (ipxp->ipxp_socket->so_state & SS_NOFDREF)
-		ipx_pcbdetach(ipxp);
 }
 
 void
-ipx_pcbdetach(ipxp)
-	struct ipxpcb *ipxp;
+ipx_pcbdetach(struct ipxpcb *ipxp)
 {
 	struct socket *so = ipxp->ipxp_socket;
 
 	IPX_LIST_LOCK_ASSERT();
 	IPX_LOCK_ASSERT(ipxp);
 
-	ACCEPT_LOCK();
-	SOCK_LOCK(so);
 	so->so_pcb = NULL;
-	sotryfree(so);
+	ipxp->ipxp_socket = NULL;
+}
+
+void
+ipx_pcbfree(struct ipxpcb *ipxp)
+{
+
+	KASSERT(ipxp->ipxp_socket == NULL,
+	    ("ipx_pcbfree: ipxp_socket != NULL"));
+	IPX_LIST_LOCK_ASSERT();
+	IPX_LOCK_ASSERT(ipxp);
+
 	if (ipxp->ipxp_route.ro_rt != NULL)
 		RTFREE(ipxp->ipxp_route.ro_rt);
 	LIST_REMOVE(ipxp, ipxp_list);
@@ -297,9 +321,7 @@
 }
 
 void
-ipx_setsockaddr(ipxp, nam)
-	register struct ipxpcb *ipxp;
-	struct sockaddr **nam;
+ipx_getsockaddr(struct ipxpcb *ipxp, struct sockaddr **nam)
 {
 	struct sockaddr_ipx *sipx, ssipx;
 
@@ -314,9 +336,7 @@
 }
 
 void
-ipx_setpeeraddr(ipxp, nam)
-	register struct ipxpcb *ipxp;
-	struct sockaddr **nam;
+ipx_getpeeraddr(struct ipxpcb *ipxp, struct sockaddr **nam)
 {
 	struct sockaddr_ipx *sipx, ssipx;
 
@@ -331,12 +351,9 @@
 }
 
 struct ipxpcb *
-ipx_pcblookup(faddr, lport, wildp)
-	struct ipx_addr *faddr;
-	u_short lport;
-	int wildp;
+ipx_pcblookup(struct ipx_addr *faddr, u_short lport, int wildp)
 {
-	register struct ipxpcb *ipxp, *match = NULL;
+	struct ipxpcb *ipxp, *match = NULL;
 	int matchwild = 3, wildcard;
 	u_short fport;
 
Index: ipx.c
===================================================================
RCS file: /home/cvs/src/sys/netipx/ipx.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/ipx.c -L sys/netipx/ipx.c -u -r1.1.1.1 -r1.2
--- sys/netipx/ipx.c
+++ sys/netipx/ipx.c
@@ -1,5 +1,4 @@
 /*-
- * Copyright (c) 1995, Mike Mitchell
  * Copyright (c) 1984, 1985, 1986, 1987, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
@@ -11,6 +10,32 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1995, Mike Mitchell
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *	This product includes software developed by the University of
@@ -35,12 +60,13 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/netipx/ipx.c,v 1.30 2005/01/09 05:34:37 rwatson Exp $");
+__FBSDID("$FreeBSD: src/sys/netipx/ipx.c,v 1.33 2007/06/13 22:42:43 rwatson Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/systm.h>
 #include <sys/malloc.h>
+#include <sys/priv.h>
 #include <sys/sockio.h>
 #include <sys/socket.h>
 
@@ -64,16 +90,12 @@
  * Generic internet control operations (ioctl's).
  */
 int
-ipx_control(so, cmd, data, ifp, td)
-	struct socket *so;
-	u_long cmd;
-	caddr_t data;
-	register struct ifnet *ifp;
-	struct thread *td;
+ipx_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
+    struct thread *td)
 {
-	register struct ifreq *ifr = (struct ifreq *)data;
-	register struct ipx_aliasreq *ifra = (struct ipx_aliasreq *)data;
-	register struct ipx_ifaddr *ia;
+	struct ifreq *ifr = (struct ifreq *)data;
+	struct ipx_aliasreq *ifra = (struct ipx_aliasreq *)data;
+	struct ipx_ifaddr *ia;
 	struct ifaddr *ifa;
 	struct ipx_ifaddr *oia;
 	int dstIsNew, hostIsNew;
@@ -237,10 +259,9 @@
 * Delete any previous route for an old address.
 */
 static void
-ipx_ifscrub(ifp, ia)
-	register struct ifnet *ifp;
-	register struct ipx_ifaddr *ia;
+ipx_ifscrub(struct ifnet *ifp, struct ipx_ifaddr *ia)
 {
+
 	if (ia->ia_flags & IFA_ROUTE) {
 		if (ifp->if_flags & IFF_POINTOPOINT) {
 			rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
@@ -254,11 +275,8 @@
  * and routing table entry.
  */
 static int
-ipx_ifinit(ifp, ia, sipx, scrub)
-	register struct ifnet *ifp;
-	register struct ipx_ifaddr *ia;
-	register struct sockaddr_ipx *sipx;
-	int scrub;
+ipx_ifinit(struct ifnet *ifp, struct ipx_ifaddr *ia,
+    struct sockaddr_ipx *sipx, int scrub)
 {
 	struct sockaddr_ipx oldaddr;
 	int s = splimp(), error;
@@ -310,12 +328,11 @@
  * Return address info for specified internet network.
  */
 struct ipx_ifaddr *
-ipx_iaonnetof(dst)
-	register struct ipx_addr *dst;
+ipx_iaonnetof(struct ipx_addr *dst)
 {
-	register struct ipx_ifaddr *ia;
-	register struct ipx_addr *compare;
-	register struct ifnet *ifp;
+	struct ipx_ifaddr *ia;
+	struct ipx_addr *compare;
+	struct ifnet *ifp;
 	struct ipx_ifaddr *ia_maybe = NULL;
 	union ipx_net net = dst->x_net;
 
@@ -338,13 +355,12 @@
 
 
 void
-ipx_printhost(addr)
-register struct ipx_addr *addr;
+ipx_printhost(struct ipx_addr *addr)
 {
 	u_short port;
 	struct ipx_addr work = *addr;
-	register char *p; register u_char *q;
-	register char *net = "", *host = "";
+	char *p; u_char *q;
+	char *net = "", *host = "";
 	char cport[10], chost[15], cnet[15];
 
 	port = ntohs(work.x_port);
--- sys/netipx/ipx_ip.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/*-
- * Copyright (c) 1995, Mike Mitchell
- * Copyright (c) 1984, 1985, 1986, 1987, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *	@(#)ipx_ip.c
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/netipx/ipx_ip.c,v 1.40.2.1 2006/03/29 12:42:43 rwatson Exp $");
-
-/*
- * Software interface driver for encapsulating IPX in IP.
- */
-
-#include "opt_inet.h"
-#include "opt_ipx.h"
-
-#ifdef IPXIP
-#ifndef INET
-#error The option IPXIP requires option INET.
-#endif
-
-#include <sys/param.h>
-#include <sys/kernel.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/protosw.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/sockio.h>
-
-#include <net/if.h>
-#include <net/if_types.h>
-#include <net/netisr.h>
-#include <net/route.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#include <netinet/ip_var.h>
-
-#include <netipx/ipx.h>
-#include <netipx/ipx_if.h>
-#include <netipx/ipx_ip.h>
-#include <netipx/ipx_var.h>
-
-NET_NEEDS_GIANT("ipx_ip");
-
-static struct	ifnet ipxipif;
-static int	ipxipif_units;
-
-/* list of all hosts and gateways or broadcast addrs */
-static struct	ifnet_en *ipxip_list;
-
-static	struct ifnet_en *ipxipattach(void);
-static	int ipxip_free(struct ifnet *ifp);
-static	int ipxipioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
-static	int ipxipoutput(struct ifnet *ifp, struct mbuf *m,
-			struct sockaddr *dst, struct rtentry *rt);
-static	void ipxip_rtchange(struct in_addr *dst);
-static	void ipxipstart(struct ifnet *ifp);
-
-static struct ifnet_en *
-ipxipattach()
-{
-	register struct ifnet_en *m;
-	register struct ifnet *ifp;
-
-	if (ipxipif.if_mtu == 0) {
-		ifp = &ipxipif;
-		if_initname(ifp, "ipxip", ipxipif_units);
-		ifp->if_mtu = LOMTU;
-		ifp->if_ioctl = ipxipioctl;
-		ifp->if_output = ipxipoutput;
-		ifp->if_start = ipxipstart;
-		ifp->if_flags = IFF_POINTOPOINT;
-	}
-
-	MALLOC((m), struct ifnet_en *, sizeof(*m), M_PCB, M_NOWAIT | M_ZERO);
-	if (m == NULL)
-		return (NULL);
-	m->ifen_next = ipxip_list;
-	ipxip_list = m;
-	ifp = m->ifen_ifp = if_alloc(IFT_IPXIP);
-	if (ifp == NULL) {
-		FREE(m, M_PCB);
-		return (NULL);
-	}
-
-	if_initname(ifp, "ipxip", ipxipif_units++);
-	ifp->if_mtu = LOMTU;
-	ifp->if_ioctl = ipxipioctl;
-	ifp->if_output = ipxipoutput;
-	ifp->if_start = ipxipstart;
-	ifp->if_flags = IFF_POINTOPOINT;
-	ifp->if_softc = m;
-	if_attach(ifp);
-
-	return (m);
-}
-
-
-/*
- * Process an ioctl request.
- */
-static int
-ipxipioctl(ifp, cmd, data)
-	register struct ifnet *ifp;
-	u_long cmd;
-	caddr_t data;
-{
-	int error = 0;
-	struct ifreq *ifr;
-
-	switch (cmd) {
-
-	case SIOCSIFADDR:
-		ifp->if_flags |= IFF_UP;
-		/* FALLTHROUGH */
-
-	case SIOCSIFDSTADDR:
-		/*
-		 * Everything else is done at a higher level.
-		 */
-		break;
-
-	case SIOCSIFFLAGS:
-		ifr = (struct ifreq *)data;
-		if ((ifr->ifr_flags & IFF_UP) == 0)
-			error = ipxip_free(ifp);
-
-
-	default:
-		error = EINVAL;
-	}
-	return (error);
-}
-
-static struct mbuf *ipxip_badlen;
-static struct mbuf *ipxip_lastin;
-static int ipxip_hold_input;
-
-void
-ipxip_input(m, hlen)
-	register struct mbuf *m;
-	int hlen;
-{
-	register struct ip *ip;
-	register struct ipx *ipx;
-	int len, s;
-
-	if (ipxip_hold_input) {
-		if (ipxip_lastin != NULL) {
-			m_freem(ipxip_lastin);
-		}
-		ipxip_lastin = m_copym(m, 0, (int)M_COPYALL, M_DONTWAIT);
-	}
-	/*
-	 * Get IP and IPX header together in first mbuf.
-	 */
-	ipxipif.if_ipackets++;
-	s = sizeof(struct ip) + sizeof(struct ipx);
-	if (((m->m_flags & M_EXT) || m->m_len < s) &&
-	    (m = m_pullup(m, s)) == NULL) {
-		ipxipif.if_ierrors++;
-		return;
-	}
-	ip = mtod(m, struct ip *);
-	if (ip->ip_hl > (sizeof(struct ip) >> 2)) {
-		ip_stripoptions(m, (struct mbuf *)NULL);
-		if (m->m_len < s) {
-			if ((m = m_pullup(m, s)) == NULL) {
-				ipxipif.if_ierrors++;
-				return;
-			}
-			ip = mtod(m, struct ip *);
-		}
-	}
-
-	/*
-	 * Make mbuf data length reflect IPX length.
-	 * If not enough data to reflect IPX length, drop.
-	 */
-	m->m_data += sizeof(struct ip);
-	m->m_len -= sizeof(struct ip);
-	m->m_pkthdr.len -= sizeof(struct ip);
-	ipx = mtod(m, struct ipx *);
-	len = ntohs(ipx->ipx_len);
-	if (len & 1)
-		len++;		/* Preserve Garbage Byte */
-	if (ip->ip_len != len) {
-		if (len > ip->ip_len) {
-			ipxipif.if_ierrors++;
-			if (ipxip_badlen)
-				m_freem(ipxip_badlen);
-			ipxip_badlen = m;
-			return;
-		}
-		/* Any extra will be trimmed off by the IPX routines */
-	}
-
-	/*
-	 * Deliver to IPX
-	 */
-	netisr_dispatch(NETISR_IPX, m);
-}
-
-static int
-ipxipoutput(ifp, m, dst, rt)
-	struct ifnet *ifp;
-	struct mbuf *m;
-	struct sockaddr *dst;
-	struct rtentry *rt;
-{
-	register struct ifnet_en *ifn = (struct ifnet_en *)ifp->if_softc;
-	register struct ip *ip;
-	register struct route *ro = &(ifn->ifen_route);
-	register int len = 0;
-	register struct ipx *ipx = mtod(m, struct ipx *);
-	int error;
-
-	ifn->ifen_ifp->if_opackets++;
-	ipxipif.if_opackets++;
-
-	/*
-	 * Calculate data length and make space
-	 * for IP header.
-	 */
-	len =  ntohs(ipx->ipx_len);
-	if (len & 1)
-		len++;		/* Preserve Garbage Byte */
-	/* following clause not necessary on vax */
-	if (3 & (intptr_t)m->m_data) {
-		/* force longword alignment of ip hdr */
-		struct mbuf *m0 = m_gethdr(MT_HEADER, M_DONTWAIT);
-		if (m0 == NULL) {
-			m_freem(m);
-			return (ENOBUFS);
-		}
-		MH_ALIGN(m0, sizeof(struct ip));
-		m0->m_flags = m->m_flags & M_COPYFLAGS;
-		m0->m_next = m;
-		m0->m_len = sizeof(struct ip);
-		m0->m_pkthdr.len = m0->m_len + m->m_len;
-		m->m_flags &= ~M_PKTHDR;
-		m = m0;
-	} else {
-		M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
-		if (m == NULL)
-			return (ENOBUFS);
-	}
-	/*
-	 * Fill in IP header.
-	 */
-	ip = mtod(m, struct ip *);
-	*(long *)ip = 0;
-	ip->ip_p = IPPROTO_IDP;
-	ip->ip_src = ifn->ifen_src;
-	ip->ip_dst = ifn->ifen_dst;
-	ip->ip_len = (u_short)len + sizeof(struct ip);
-	ip->ip_ttl = MAXTTL;
-
-	/*
-	 * Output final datagram.
-	 */
-	error =  (ip_output(m, (struct mbuf *)NULL, ro, SO_BROADCAST, NULL, NULL));
-	if (error) {
-		ifn->ifen_ifp->if_oerrors++;
-		ifn->ifen_ifp->if_ierrors = error;
-	}
-	return (error);
-	m_freem(m);
-	return (ENETUNREACH);
-}
-
-static void
-ipxipstart(ifp)
-struct ifnet *ifp;
-{
-	panic("ipxip_start called\n");
-}
-
-static struct ifreq ifr_ipxip = {"ipxip0"};
-
-int
-ipxip_route(so, sopt)
-	struct socket *so;
-	struct sockopt *sopt;
-{
-	int error;
-	struct ifnet_en *ifn;
-	struct sockaddr_in *src;
-	struct ipxip_req rq;
-	struct sockaddr_ipx *ipx_dst;
-	struct sockaddr_in *ip_dst;
-	struct route ro;
-
-	error = sooptcopyin(sopt, &rq, sizeof rq, sizeof rq);
-	if (error)
-		return (error);
-	ipx_dst = (struct sockaddr_ipx *)&rq.rq_ipx;
-	ip_dst = (struct sockaddr_in *)&rq.rq_ip;
-
-	/*
-	 * First, make sure we already have an IPX address:
-	 */
-	if (ipx_ifaddr == NULL)
-		return (EADDRNOTAVAIL);
-	/*
-	 * Now, determine if we can get to the destination
-	 */
-	bzero((caddr_t)&ro, sizeof(ro));
-	ro.ro_dst = *(struct sockaddr *)ip_dst;
-	rtalloc_ign(&ro, 0);
-	if (ro.ro_rt == NULL || ro.ro_rt->rt_ifp == NULL) {
-		return (ENETUNREACH);
-	}
-
-	/*
-	 * And see how he's going to get back to us:
-	 * i.e., what return ip address do we use?
-	 */
-	{
-		register struct in_ifaddr *ia;
-		struct ifnet *ifp = ro.ro_rt->rt_ifp;
-
-		for (ia = TAILQ_FIRST(&in_ifaddrhead); ia != NULL;
-		     ia = TAILQ_NEXT(ia, ia_link))
-			if (ia->ia_ifp == ifp)
-				break;
-		if (ia == NULL)
-			ia = TAILQ_FIRST(&in_ifaddrhead);
-		if (ia == NULL) {
-			RTFREE(ro.ro_rt);
-			return (EADDRNOTAVAIL);
-		}
-		src = (struct sockaddr_in *)&ia->ia_addr;
-	}
-
-	/*
-	 * Is there a free (pseudo-)interface or space?
-	 */
-	for (ifn = ipxip_list; ifn != NULL; ifn = ifn->ifen_next) {
-		if ((ifn->ifen_ifp->if_flags & IFF_UP) == 0)
-			break;
-	}
-	if (ifn == NULL)
-		ifn = ipxipattach();
-	if (ifn == NULL) {
-		RTFREE(ro.ro_rt);
-		return (ENOBUFS);
-	}
-	ifn->ifen_route = ro;
-	ifn->ifen_dst =  ip_dst->sin_addr;
-	ifn->ifen_src = src->sin_addr;
-
-	/*
-	 * now configure this as a point to point link
-	 */
-	ifr_ipxip.ifr_name[4] = '0' + ipxipif_units - 1;
-	ifr_ipxip.ifr_dstaddr = *(struct sockaddr *)ipx_dst;
-	ipx_control(so, (int)SIOCSIFDSTADDR, (caddr_t)&ifr_ipxip,
-			(struct ifnet *)ifn, sopt->sopt_td);
-
-	/* use any of our addresses */
-	satoipx_addr(ifr_ipxip.ifr_addr).x_host =
-			ipx_ifaddr->ia_addr.sipx_addr.x_host;
-
-	return (ipx_control(so, (int)SIOCSIFADDR, (caddr_t)&ifr_ipxip,
-			(struct ifnet *)ifn, sopt->sopt_td));
-}
-
-static int
-ipxip_free(ifp)
-struct ifnet *ifp;
-{
-	register struct ifnet_en *ifn = (struct ifnet_en *)ifp->if_softc;
-	struct route *ro = & ifn->ifen_route;
-
-	if (ro->ro_rt != NULL) {
-		RTFREE(ro->ro_rt);
-		ro->ro_rt = NULL;
-	}
-	ifp->if_flags &= ~IFF_UP;
-	return (0);
-}
-
-void
-ipxip_ctlinput(cmd, sa, dummy)
-	int cmd;
-	struct sockaddr *sa;
-	void *dummy;
-{
-	struct sockaddr_in *sin;
-
-	if ((unsigned)cmd >= PRC_NCMDS)
-		return;
-	if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK)
-		return;
-	sin = (struct sockaddr_in *)sa;
-	if (sin->sin_addr.s_addr == INADDR_ANY)
-		return;
-
-	switch (cmd) {
-
-	case PRC_ROUTEDEAD:
-	case PRC_REDIRECT_NET:
-	case PRC_REDIRECT_HOST:
-	case PRC_REDIRECT_TOSNET:
-	case PRC_REDIRECT_TOSHOST:
-		ipxip_rtchange(&sin->sin_addr);
-		break;
-	}
-}
-
-static void
-ipxip_rtchange(dst)
-	register struct in_addr *dst;
-{
-	register struct ifnet_en *ifn;
-
-	for (ifn = ipxip_list; ifn != NULL; ifn = ifn->ifen_next) {
-		if (ifn->ifen_dst.s_addr == dst->s_addr &&
-			ifn->ifen_route.ro_rt != NULL) {
-				RTFREE(ifn->ifen_route.ro_rt);
-				ifn->ifen_route.ro_rt = NULL;
-		}
-	}
-}
-#endif /* IPXIP */
Index: README
===================================================================
RCS file: /home/cvs/src/sys/netipx/README,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -L sys/netipx/README -L sys/netipx/README -u -r1.1.1.1 -r1.2
--- sys/netipx/README
+++ sys/netipx/README
@@ -1,4 +1,4 @@
-$FreeBSD: src/sys/netipx/README,v 1.6 2005/04/10 18:05:46 rwatson Exp $
+$FreeBSD: src/sys/netipx/README,v 1.8 2006/03/27 09:10:09 rwatson Exp $
 
 This protocol implements IPX/SPX over Ethernet_II frame type 0x8137.
 Please note: the SPX implementation may require further work and testing
@@ -14,14 +14,36 @@
 Some Address
 jhay at mikom.csir.co.za
 
+Adapted for multi-processor, multi-threaded network stack by Robert N. M.
+Watson, Computer Laboratory, University of Cambridge.
+
 --- Copyright Information ---
 /*-
 
 Copyright (c) 1984, 1985, 1986, 1987, 1993
 The Regents of the University of California.  All rights reserved.
 
-Modifications Copyright (c) 2004-2005 Robert N. M. Watson
 Modifications Copyright (c) 1995, Mike Mitchell
 Modifications Copyright (c) 1995, John Hay
+Modifications Copyright (c) 2004-2006 Robert N. M. Watson
 
 */
+
+--- TODO ---
+
+(1) netipx default socket buffer sizes are very small by contemporary
+    standards, and should be increased following testing and measurement.
+
+(2) SPX will free the PCB and socket buffer memory on close(), which means
+    close() in effects terminates the transfer of any outstanding buffered
+    but unsent data.  As with TCP, it should instead grab its own
+    reference to the socket so that it is not released, as hold onto it
+    until the data transfer is complete.
+
+(3) Raw socket capture of IPX output intercepts packets in the SPX output
+    routine in order to feed them back into the raw socket.  This results
+    in recursion into the socket code in the transmit path; instead,
+    captured packets should be fed into a netisr that reinjects them into
+    raw sockets from a new (asynchronous) context.
+
+(4) IPX over IP encapsulation needs work to make it properly MPSAFE.


More information about the Midnightbsd-cvs mailing list