Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 11 Aug 1998 15:14:10 -0400 (EDT)
From:      Garrett Wollman <wollman@khavrinen.lcs.mit.edu>
To:        net@FreeBSD.ORG
Subject:   socket option patch, mk. II
Message-ID:  <199808111914.PAA15085@khavrinen.lcs.mit.edu>

next in thread | raw e-mail | index | archive | help
I have updated my socket option patch to include all of the necessary
changes to allow LINT to compile.  This includes IPX, IPFW (ewww),
BOOTP, KRPC, multicast routing, and RSVP.

If I hear no screams, and experience no problems on my own machine
(which uses none of these), then I will be committing it this weekend.

Index: kern/uipc_socket.c
===================================================================
RCS file: /home/cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.42
diff -u -r1.42 uipc_socket.c
--- uipc_socket.c	1998/07/18 18:48:45	1.42
+++ uipc_socket.c	1998/08/11 18:46:35
@@ -898,31 +898,69 @@
 	sbrelease(&asb);
 }
 
+/*
+ * Perhaps this routine, and sooptcopyout(), below, ought to come in
+ * an additional variant to handle the case where the option value needs
+ * to be some kind of integer, but not a specific size.
+ * In addition to their use here, these functions are also called by the
+ * protocol-level pr_ctloutput() routines.
+ */
 int
-sosetopt(so, level, optname, m0, p)
-	register struct socket *so;
-	int level, optname;
-	struct mbuf *m0;
-	struct proc *p;
+sooptcopyin(sopt, buf, len, minlen)
+	struct	sockopt *sopt;
+	void	*buf;
+	size_t	len;
+	size_t	minlen;
 {
-	int error = 0;
-	register struct mbuf *m = m0;
+	size_t	valsize;
 
-	if (level != SOL_SOCKET) {
+	/*
+	 * If the user gives us more than we wanted, we ignore it,
+	 * but if we don't get the minimum length the caller
+	 * wants, we return EINVAL.  On success, sopt->sopt_valsize
+	 * is set to however much we actually retrieved.
+	 */
+	if ((valsize = sopt->sopt_valsize) < minlen)
+		return EINVAL;
+	if (valsize > len)
+		sopt->sopt_valsize = valsize = len;
+
+	if (sopt->sopt_p != 0)
+		return (copyin(sopt->sopt_val, buf, valsize));
+
+	bcopy(sopt->sopt_val, buf, valsize);
+	return 0;
+}
+
+int
+sosetopt(so, sopt)
+	struct socket *so;
+	struct sockopt *sopt;
+{
+	int	error, optval;
+	struct	linger l;
+	struct	timeval tv;
+	short	val;
+
+	error = 0;
+	if (sopt->sopt_level != SOL_SOCKET) {
 		if (so->so_proto && so->so_proto->pr_ctloutput)
 			return ((*so->so_proto->pr_ctloutput)
-				  (PRCO_SETOPT, so, level, optname, &m0, p));
+				  (so, sopt));
 		error = ENOPROTOOPT;
 	} else {
-		switch (optname) {
-
+		switch (sopt->sopt_name) {
 		case SO_LINGER:
-			if (m == NULL || m->m_len != sizeof (struct linger)) {
-				error = EINVAL;
+			error = sooptcopyin(sopt, &l, sizeof l, sizeof l);
+			if (error)
 				goto bad;
-			}
-			so->so_linger = mtod(m, struct linger *)->l_linger;
-			/* fall thru... */
+
+			so->so_linger = l.l_linger;
+			if (l.l_onoff)
+				so->so_options |= SO_LINGER;
+			else
+				so->so_options &= ~SO_LINGER;
+			break;
 
 		case SO_DEBUG:
 		case SO_KEEPALIVE:
@@ -933,45 +971,40 @@
 		case SO_REUSEPORT:
 		case SO_OOBINLINE:
 		case SO_TIMESTAMP:
-			if (m == NULL || m->m_len < sizeof (int)) {
-				error = EINVAL;
+			error = sooptcopyin(sopt, &optval, sizeof optval,
+					    sizeof optval);
+			if (error)
 				goto bad;
-			}
-			if (*mtod(m, int *))
-				so->so_options |= optname;
+			if (optval)
+				so->so_options |= sopt->sopt_name;
 			else
-				so->so_options &= ~optname;
+				so->so_options &= ~sopt->sopt_name;
 			break;
 
 		case SO_SNDBUF:
 		case SO_RCVBUF:
 		case SO_SNDLOWAT:
 		case SO_RCVLOWAT:
-		    {
-			int optval;
-
-			if (m == NULL || m->m_len < sizeof (int)) {
-				error = EINVAL;
+			error = sooptcopyin(sopt, &optval, sizeof optval,
+					    sizeof optval);
+			if (error)
 				goto bad;
-			}
 
 			/*
 			 * Values < 1 make no sense for any of these
 			 * options, so disallow them.
 			 */
-			optval = *mtod(m, int *);
 			if (optval < 1) {
 				error = EINVAL;
 				goto bad;
 			}
 
-			switch (optname) {
-
+			switch (sopt->sopt_name) {
 			case SO_SNDBUF:
 			case SO_RCVBUF:
-				if (sbreserve(optname == SO_SNDBUF ?
-				    &so->so_snd : &so->so_rcv,
-				    (u_long) optval) == 0) {
+				if (sbreserve(sopt->sopt_name == SO_SNDBUF ?
+					      &so->so_snd : &so->so_rcv,
+					      (u_long) optval) == 0) {
 					error = ENOBUFS;
 					goto bad;
 				}
@@ -993,27 +1026,21 @@
 				break;
 			}
 			break;
-		    }
 
 		case SO_SNDTIMEO:
 		case SO_RCVTIMEO:
-		    {
-			struct timeval *tv;
-			short val;
-
-			if (m == NULL || m->m_len < sizeof (*tv)) {
-				error = EINVAL;
+			error = sooptcopyin(sopt, &tv, sizeof tv,
+					    sizeof tv);
+			if (error)
 				goto bad;
-			}
-			tv = mtod(m, struct timeval *);
-			if (tv->tv_sec > SHRT_MAX / hz - hz) {
+
+			if (tv.tv_sec > SHRT_MAX / hz - hz) {
 				error = EDOM;
 				goto bad;
 			}
-			val = tv->tv_sec * hz + tv->tv_usec / tick;
-
-			switch (optname) {
+			val = tv.tv_sec * hz + tv.tv_usec / tick;
 
+			switch (sopt->sopt_name) {
 			case SO_SNDTIMEO:
 				so->so_snd.sb_timeo = val;
 				break;
@@ -1022,7 +1049,6 @@
 				break;
 			}
 			break;
-		    }
 
 		default:
 			error = ENOPROTOOPT;
@@ -1030,42 +1056,69 @@
 		}
 		if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) {
 			(void) ((*so->so_proto->pr_ctloutput)
-				  (PRCO_SETOPT, so, level, optname, &m0, p));
-			m = NULL;	/* freed by protocol */
+				  (so, sopt));
 		}
 	}
 bad:
-	if (m)
-		(void) m_free(m);
 	return (error);
 }
 
+/* Helper routine for getsockopt */
 int
-sogetopt(so, level, optname, mp, p)
-	register struct socket *so;
-	int level, optname;
-	struct mbuf **mp;
-	struct proc *p;
+sooptcopyout(sopt, buf, len)
+	struct	sockopt *sopt;
+	void	*buf;
+	size_t	len;
 {
-	register struct mbuf *m;
+	int	error;
+	size_t	valsize;
+
+	error = 0;
+
+	/*
+	 * Documented get behavior is that we always return a value,
+	 * possibly truncated to fit in the user's buffer.
+	 * We leave the correct length in sopt->sopt_valsize,
+	 * to be copied out in getsockopt().  Note that this
+	 * interface is not idempotent; the entire answer must
+	 * generated ahead of time.
+	 */
+	valsize = len;
+	if (sopt->sopt_valsize < valsize) {
+		valsize = sopt->sopt_valsize;
+		sopt->sopt_valsize = len;
+	}
+	if (sopt->sopt_val != 0) {
+		if (sopt->sopt_p != 0)
+			error = copyout(buf, sopt->sopt_val, valsize);
+		else
+			bcopy(buf, sopt->sopt_val, valsize);
+	}
+	return error;
+}
 
-	if (level != SOL_SOCKET) {
+int
+sogetopt(so, sopt)
+	struct socket *so;
+	struct sockopt *sopt;
+{
+	int	error, optval;
+	struct	linger l;
+	struct	timeval tv;
+
+	error = 0;
+	if (sopt->sopt_level != SOL_SOCKET) {
 		if (so->so_proto && so->so_proto->pr_ctloutput) {
 			return ((*so->so_proto->pr_ctloutput)
-				  (PRCO_GETOPT, so, level, optname, mp, p));
+				  (so, sopt));
 		} else
 			return (ENOPROTOOPT);
 	} else {
-		m = m_get(M_WAIT, MT_SOOPTS);
-		m->m_len = sizeof (int);
-
-		switch (optname) {
-
+		switch (sopt->sopt_name) {
 		case SO_LINGER:
-			m->m_len = sizeof (struct linger);
-			mtod(m, struct linger *)->l_onoff =
-				so->so_options & SO_LINGER;
-			mtod(m, struct linger *)->l_linger = so->so_linger;
+			l.l_onoff = so->so_options & SO_LINGER;
+			l.l_linger = so->so_linger;
+			error = sooptcopyout(sopt, &l, sizeof l);
 			break;
 
 		case SO_USELOOPBACK:
@@ -1077,53 +1130,51 @@
 		case SO_BROADCAST:
 		case SO_OOBINLINE:
 		case SO_TIMESTAMP:
-			*mtod(m, int *) = so->so_options & optname;
+			optval = so->so_options & sopt->sopt_name;
+integer:
+			error = sooptcopyout(sopt, &optval, sizeof optval);
 			break;
 
 		case SO_TYPE:
-			*mtod(m, int *) = so->so_type;
-			break;
+			optval = so->so_type;
+			goto integer;
 
 		case SO_ERROR:
-			*mtod(m, int *) = so->so_error;
+			optval = so->so_error;
 			so->so_error = 0;
-			break;
+			goto integer;
 
 		case SO_SNDBUF:
-			*mtod(m, int *) = so->so_snd.sb_hiwat;
-			break;
+			optval = so->so_snd.sb_hiwat;
+			goto integer;
 
 		case SO_RCVBUF:
-			*mtod(m, int *) = so->so_rcv.sb_hiwat;
-			break;
+			optval = so->so_rcv.sb_hiwat;
+			goto integer;
 
 		case SO_SNDLOWAT:
-			*mtod(m, int *) = so->so_snd.sb_lowat;
-			break;
+			optval = so->so_snd.sb_lowat;
+			goto integer;
 
 		case SO_RCVLOWAT:
-			*mtod(m, int *) = so->so_rcv.sb_lowat;
-			break;
+			optval = so->so_rcv.sb_lowat;
+			goto integer;
 
 		case SO_SNDTIMEO:
 		case SO_RCVTIMEO:
-		    {
-			int val = (optname == SO_SNDTIMEO ?
-			     so->so_snd.sb_timeo : so->so_rcv.sb_timeo);
-
-			m->m_len = sizeof(struct timeval);
-			mtod(m, struct timeval *)->tv_sec = val / hz;
-			mtod(m, struct timeval *)->tv_usec =
-			    (val % hz) * tick;
-			break;
-		    }
+			optval = (sopt->sopt_name == SO_SNDTIMEO ?
+				  so->so_snd.sb_timeo : so->so_rcv.sb_timeo);
+
+			tv.tv_sec = optval / hz;
+			tv.tv_usec = (optval % hz) * tick;
+			error = sooptcopyout(sopt, &tv, sizeof tv);
+			break;			
 
 		default:
-			(void)m_free(m);
-			return (ENOPROTOOPT);
+			error = ENOPROTOOPT;
+			break;
 		}
-		*mp = m;
-		return (0);
+		return (error);
 	}
 }
 
Index: kern/uipc_syscalls.c
===================================================================
RCS file: /home/cvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.40
diff -u -r1.40 uipc_syscalls.c
--- uipc_syscalls.c	1998/06/10 10:30:23	1.40
+++ uipc_syscalls.c	1998/08/11 18:46:36
@@ -981,34 +981,26 @@
 	} */ *uap;
 {
 	struct file *fp;
-	struct mbuf *m = NULL;
+	struct sockopt sopt;
 	int error;
 
+	if (uap->val == 0 && uap->valsize != 0)
+		return (EFAULT);
+	if (uap->valsize < 0)
+		return (EINVAL);
+
 	error = getsock(p->p_fd, uap->s, &fp);
 	if (error)
 		return (error);
-	if (uap->valsize > MCLBYTES)
-		return (EINVAL);
-	if (uap->val) {
-		m = m_get(M_WAIT, MT_SOOPTS);
-		if (m == NULL)
-			return (ENOBUFS);
-		if (uap->valsize > MLEN) {
-			MCLGET(m, M_WAIT);
-			if(!(m->m_flags & M_EXT)) {
-				m_free(m);
-				return (ENOBUFS);
-			}
-		}
-		error = copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize);
-		if (error) {
-			(void) m_free(m);
-			return (error);
-		}
-		m->m_len = uap->valsize;
-	}
-	return (sosetopt((struct socket *)fp->f_data, uap->level,
-	    uap->name, m, p));
+
+	sopt.sopt_dir = SOPT_SET;
+	sopt.sopt_level = uap->level;
+	sopt.sopt_name = uap->name;
+	sopt.sopt_val = uap->val;
+	sopt.sopt_valsize = uap->valsize;
+	sopt.sopt_p = p;
+
+	return (sosetopt((struct socket *)fp->f_data, &sopt));
 }
 
 /* ARGSUSED */
@@ -1023,9 +1015,9 @@
 		int	*avalsize;
 	} */ *uap;
 {
-	struct file *fp;
-	struct mbuf *m = NULL, *m0;
-	int op, i, valsize, error;
+	int	valsize, error;
+	struct	file *fp;
+	struct	sockopt sopt;
 
 	error = getsock(p->p_fd, uap->s, &fp);
 	if (error)
@@ -1035,26 +1027,24 @@
 		    sizeof (valsize));
 		if (error)
 			return (error);
+		if (valsize < 0)
+			return (EINVAL);
 	} else
 		valsize = 0;
-	if ((error = sogetopt((struct socket *)fp->f_data, uap->level,
-	    uap->name, &m, p)) == 0 && uap->val && valsize && m != NULL) {
-		op = 0;
-		while (m && !error && op < valsize) {
-			i = min(m->m_len, (valsize - op));
-			error = copyout(mtod(m, caddr_t), uap->val, (u_int)i);
-			op += i;
-			uap->val += i;
-			m0 = m;
-			MFREE(m0,m);
-		}
-		valsize = op;
-		if (error == 0)
-			error = copyout((caddr_t)&valsize,
-			    (caddr_t)uap->avalsize, sizeof (valsize));
+
+	sopt.sopt_dir = SOPT_GET;
+	sopt.sopt_level = uap->level;
+	sopt.sopt_name = uap->name;
+	sopt.sopt_val = uap->val;
+	sopt.sopt_valsize = (size_t)valsize; /* checked non-negative above */
+	sopt.sopt_p = p;
+
+	error = sogetopt((struct socket *)fp->f_data, &sopt);
+	if (error == 0) {
+		valsize = sopt.sopt_valsize;
+		error = copyout((caddr_t)&valsize,
+				(caddr_t)uap->avalsize, sizeof (valsize));
 	}
-	if (m != NULL)
-		(void) m_free(m);
 	return (error);
 }
 
Index: net/if_vlan.c
===================================================================
RCS file: /home/cvs/src/sys/net/if_vlan.c,v
retrieving revision 1.2
diff -u -r1.2 if_vlan.c
--- if_vlan.c	1998/05/15 20:02:47	1.2
+++ if_vlan.c	1998/08/11 18:46:40
@@ -80,7 +80,7 @@
 
 static	void vlan_start(struct ifnet *ifp);
 static	void vlan_ifinit(void *foo);
-static	int vlan_ioctl(struct ifnet *ifp, int cmd, caddr_t addr);
+static	int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr);
 
 static void
 vlaninit(void *dummy)
@@ -262,7 +262,7 @@
 }
 
 static int
-vlan_ioctl(struct ifnet *ifp, int cmd, caddr_t data)
+vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 {
 	struct ifaddr *ifa;
 	struct ifnet *p;
Index: netinet/in.h
===================================================================
RCS file: /home/cvs/src/sys/netinet/in.h,v
retrieving revision 1.36
diff -u -r1.36 in.h
--- in.h	1998/07/06 03:20:12	1.36
+++ in.h	1998/08/11 18:46:41
@@ -429,21 +429,6 @@
 int	 in_localaddr __P((struct in_addr));
 char 	*inet_ntoa __P((struct in_addr)); /* in libkern */
 
-/* Firewall hooks */
-struct ip;
-typedef	int ip_fw_chk_t __P((struct ip**, int, struct ifnet*, u_int16_t*, struct mbuf**, struct sockaddr_in**));
-typedef	int ip_fw_ctl_t __P((int, struct mbuf**));
-extern	ip_fw_chk_t *ip_fw_chk_ptr;
-extern	ip_fw_ctl_t *ip_fw_ctl_ptr;
-
-/* IP NAT hooks */
-typedef	int ip_nat_t __P((struct ip**, struct mbuf**, struct ifnet*, int));
-typedef	int ip_nat_ctl_t __P((int, struct mbuf**));
-extern	ip_nat_t *ip_nat_ptr;
-extern	ip_nat_ctl_t *ip_nat_ctl_ptr;
-#define	IP_NAT_IN	0x00000001
-#define	IP_NAT_OUT	0x00000002
-
 #endif /* KERNEL */
 
 #endif
Index: netinet/in_proto.c
===================================================================
RCS file: /home/cvs/src/sys/netinet/in_proto.c,v
retrieving revision 1.46
diff -u -r1.46 in_proto.c
--- in_proto.c	1998/03/21 11:33:57	1.46
+++ in_proto.c	1998/08/11 18:46:41
@@ -71,15 +71,6 @@
 #include <netns/ns_if.h>
 #endif
 
-#ifdef TPIP
-void	tpip_input(), tpip_ctlinput(), tp_init(), tp_slowtimo(), tp_drain();
-int	tp_ctloutput(), tp_usrreq();
-#endif
-
-#ifdef EON
-void	eoninput(), eonctlinput(), eonprotoinit();
-#endif /* EON */
-
 extern	struct domain inetdomain;
 static	struct pr_usrreqs nousrreqs;
 
Index: netinet/ip_fw.c
===================================================================
RCS file: /home/cvs/src/sys/netinet/ip_fw.c,v
retrieving revision 1.94
diff -u -r1.94 ip_fw.c
--- ip_fw.c	1998/08/03 17:23:37	1.94
+++ ip_fw.c	1998/08/11 18:46:41
@@ -34,6 +34,7 @@
 #include <sys/mbuf.h>
 #include <sys/kernel.h>
 #include <sys/socket.h>
+#include <sys/socketvar.h>
 #include <sys/sysctl.h>
 #include <net/if.h>
 #include <netinet/in.h>
@@ -60,6 +61,8 @@
 static int fw_verbose_limit = 0;
 #endif
 
+#define	IPFW_DEFAULT_RULE	((u_int)(u_short)~0)
+
 static LIST_HEAD (ip_fw_head, ip_fw_chain) ip_fw_chain;
 
 static MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's");
@@ -82,9 +85,8 @@
 
 static int	add_entry __P((struct ip_fw_head *chainptr, struct ip_fw *frwl));
 static int	del_entry __P((struct ip_fw_head *chainptr, u_short number));
-static int	zero_entry __P((struct mbuf *m));
-static struct ip_fw *check_ipfw_struct __P((struct ip_fw *m));
-static struct ip_fw *check_ipfw_mbuf __P((struct mbuf *fw));
+static int	zero_entry __P((struct ip_fw *));
+static int	check_ipfw_struct __P((struct ip_fw *m));
 static __inline int
 		iface_match __P((struct ifnet *ifp, union ip_fw_if *ifu,
 				 int byname));
@@ -105,7 +107,7 @@
 static int	ip_fw_chk __P((struct ip **pip, int hlen,
 			struct ifnet *oif, u_int16_t *cookie, struct mbuf **m,
 			struct sockaddr_in **next_hop));
-static int	ip_fw_ctl __P((int stage, struct mbuf **mm));
+static int	ip_fw_ctl __P((struct sockopt *sopt));
 
 static char err_prefix[] = "ip_fw_ctl:";
 
@@ -423,7 +425,7 @@
 	 */
 	chain = LIST_FIRST(&ip_fw_chain);
 	if ( skipto ) {
-		if (skipto >= 65535)
+		if (skipto >= IPFW_DEFAULT_RULE)
 			goto dropit;
 		while (chain && (chain->rule->fw_number <= skipto)) {
 			chain = LIST_NEXT(chain, chain);
@@ -644,7 +646,7 @@
 	}
 
 #ifdef DIAGNOSTIC
-	/* Rule 65535 should always be there and should always match */
+	/* Rule IPFW_DEFAULT_RULE should always be there and should always match */
 	if (!chain)
 		panic("ip_fw: chain");
 #endif
@@ -733,16 +735,10 @@
 	
 	s = splnet();
 
-	if (!LIST_FIRST(chainptr)) {
+	if (chainptr->lh_first == 0) {
 		LIST_INSERT_HEAD(chainptr, fwc, chain);
 		splx(s);
 		return(0);
-        } else if (ftmp->fw_number == (u_short)-1) {
-		if (fwc)  free(fwc, M_IPFW);
-		if (ftmp) free(ftmp, M_IPFW);
-		splx(s);
-		dprintf(("%s bad rule number\n", err_prefix));
-		return (EINVAL);
         }
 
 	/* If entry number is 0, find highest numbered rule and add 100 */
@@ -753,7 +749,7 @@
 			else
 				break;
 		}
-		if (nbr < (u_short)-1 - 100)
+		if (nbr < IPFW_DEFAULT_RULE - 100)
 			nbr += 100;
 		ftmp->fw_number = nbr;
 	}
@@ -808,21 +804,12 @@
 }
 
 static int
-zero_entry(struct mbuf *m)
+zero_entry(struct ip_fw *frwl)
 {
-	struct ip_fw *frwl;
 	struct ip_fw_chain *fcp;
-	int s;
-
-	if (m) {
-		if (m->m_len != sizeof(struct ip_fw))
-			return(EINVAL);
-		frwl = mtod(m, struct ip_fw *);
-	}
-	else
-		frwl = NULL;
+	int s, cleared;
 
-	if (!frwl) {
+	if (frwl == 0) {
 		s = splnet();
 		for (fcp = LIST_FIRST(&ip_fw_chain); fcp; fcp = LIST_NEXT(fcp, chain)) {
 			fcp->rule->fw_bcnt = fcp->rule->fw_pcnt = 0;
@@ -831,7 +818,7 @@
 		splx(s);
 	}
 	else {
-		int cleared = 0;
+		cleared = 0;
 
 		/*
 		 *	It's possible to insert multiple chain entries with the
@@ -850,8 +837,8 @@
 				cleared = 1;
 				break;
 			}
-		if (!cleared)
-			return(EINVAL);	/* we didn't find any matching rules */
+		if (!cleared)	/* we didn't find any matching rules */
+			return (EINVAL);
 	}
 
 	if (fw_verbose) {
@@ -861,34 +848,22 @@
 			printf("ipfw: Accounting cleared.\n");
 	}
 
-	return(0);
-}
-
-static struct ip_fw *
-check_ipfw_mbuf(struct mbuf *m)
-{
-	/* Check length */
-	if (m->m_len != sizeof(struct ip_fw)) {
-		dprintf(("%s len=%d, want %d\n", err_prefix, m->m_len,
-		    sizeof(struct ip_fw)));
-		return (NULL);
-	}
-	return(check_ipfw_struct(mtod(m, struct ip_fw *)));
+	return (0);
 }
 
-static struct ip_fw *
+static int
 check_ipfw_struct(struct ip_fw *frwl)
 {
 	/* Check for invalid flag bits */
 	if ((frwl->fw_flg & ~IP_FW_F_MASK) != 0) {
 		dprintf(("%s undefined flag bits set (flags=%x)\n",
 		    err_prefix, frwl->fw_flg));
-		return (NULL);
+		return (EINVAL);
 	}
 	/* Must apply to incoming or outgoing (or both) */
 	if (!(frwl->fw_flg & (IP_FW_F_IN | IP_FW_F_OUT))) {
 		dprintf(("%s neither in nor out\n", err_prefix));
-		return (NULL);
+		return (EINVAL);
 	}
 	/* Empty interface name is no good */
 	if (((frwl->fw_flg & IP_FW_F_IIFNAME)
@@ -896,7 +871,7 @@
 	    || ((frwl->fw_flg & IP_FW_F_OIFNAME)
 	      && !*frwl->fw_out_if.fu_via_if.name)) {
 		dprintf(("%s empty interface name\n", err_prefix));
-		return (NULL);
+		return (EINVAL);
 	}
 	/* Sanity check interface matching */
 	if ((frwl->fw_flg & IF_FW_F_VIAHACK) == IF_FW_F_VIAHACK) {
@@ -905,23 +880,23 @@
 	    && (frwl->fw_flg & IP_FW_F_OIFACE)) {
 		dprintf(("%s outgoing interface check on incoming\n",
 		    err_prefix));
-		return (NULL);
+		return (EINVAL);
 	}
 	/* Sanity check port ranges */
 	if ((frwl->fw_flg & IP_FW_F_SRNG) && IP_FW_GETNSRCP(frwl) < 2) {
 		dprintf(("%s src range set but n_src_p=%d\n",
 		    err_prefix, IP_FW_GETNSRCP(frwl)));
-		return (NULL);
+		return (EINVAL);
 	}
 	if ((frwl->fw_flg & IP_FW_F_DRNG) && IP_FW_GETNDSTP(frwl) < 2) {
 		dprintf(("%s dst range set but n_dst_p=%d\n",
 		    err_prefix, IP_FW_GETNDSTP(frwl)));
-		return (NULL);
+		return (EINVAL);
 	}
 	if (IP_FW_GETNSRCP(frwl) + IP_FW_GETNDSTP(frwl) > IP_FW_MAX_PORTS) {
 		dprintf(("%s too many ports (%d+%d)\n",
 		    err_prefix, IP_FW_GETNSRCP(frwl), IP_FW_GETNDSTP(frwl)));
-		return (NULL);
+		return (EINVAL);
 	}
 	/*
 	 *	Protocols other than TCP/UDP don't use port range
@@ -931,7 +906,7 @@
 	    (IP_FW_GETNSRCP(frwl) || IP_FW_GETNDSTP(frwl))) {
 		dprintf(("%s port(s) specified for non TCP/UDP rule\n",
 		    err_prefix));
-		return(NULL);
+		return (EINVAL);
 	}
 
 	/*
@@ -942,19 +917,19 @@
 	if ((frwl->fw_src.s_addr & (~frwl->fw_smsk.s_addr)) || 
 		(frwl->fw_dst.s_addr & (~frwl->fw_dmsk.s_addr))) {
 		dprintf(("%s rule never matches\n", err_prefix));
-		return(NULL);
+		return (EINVAL);
 	}
 
 	if ((frwl->fw_flg & IP_FW_F_FRAG) &&
 		(frwl->fw_prot == IPPROTO_UDP || frwl->fw_prot == IPPROTO_TCP)) {
 		if (frwl->fw_nports) {
 			dprintf(("%s cannot mix 'frag' and ports\n", err_prefix));
-			return(NULL);
+			return (EINVAL);
 		}
 		if (frwl->fw_prot == IPPROTO_TCP &&
 			frwl->fw_tcpf != frwl->fw_tcpnf) {
 			dprintf(("%s cannot mix 'frag' and TCP flags\n", err_prefix));
-			return(NULL);
+			return (EINVAL);
 		}
 	}
 
@@ -966,14 +941,14 @@
 		    && !(frwl->fw_prot == IPPROTO_TCP
 		      && frwl->fw_reject_code == IP_FW_REJECT_RST)) {
 			dprintf(("%s unknown reject code\n", err_prefix));
-			return(NULL);
+			return (EINVAL);
 		}
 		break;
 	case IP_FW_F_DIVERT:		/* Diverting to port zero is invalid */
 	case IP_FW_F_TEE:
 		if (frwl->fw_divert_port == 0) {
 			dprintf(("%s can't divert to port 0\n", err_prefix));
-			return (NULL);
+			return (EINVAL);
 		}
 		break;
 	case IP_FW_F_DENY:
@@ -986,117 +961,102 @@
 		break;
 	default:
 		dprintf(("%s invalid command\n", err_prefix));
-		return(NULL);
+		return (EINVAL);
 	}
 
-	return frwl;
+	return 0;
 }
 
 static int
-ip_fw_ctl(int stage, struct mbuf **mm)
+ip_fw_ctl(struct sockopt *sopt)
 {
-	int error;
-	/* 
-	 * If we have any number of rules, then it's worth while
-	 * using clusters for this. The smaller case is rare.
-	 * Note that using clusters for setsockopt is only in 3.0 at this time.
-	 */
-	struct mbuf *m;
+	int error, s;
+	size_t size;
+	char *buf, *bp;
+	struct ip_fw_chain *fcp;
+	struct ip_fw frwl;
 
-	if (stage == IP_FW_GET) {
-		/* 
-	 	 * If we have any number of rules, then it's worth while
-		 * using clusters for this. The smaller case is rare.
-		 * Note that using clusters for setsockopt is only in
-		 * 3.0 at this time.
-		 */
-		struct ip_fw_chain *fcp = LIST_FIRST(&ip_fw_chain);
-		*mm = m = m_get(M_WAIT, MT_SOOPTS);
-		if (m == NULL)  
-			return (ENOBUFS);
-		MCLGET(m, M_WAIT);
-		if (!(m->m_flags & M_EXT)) {
-abort:			m_freem(*mm);
-			*mm = NULL;
-			return (ENOBUFS);
+	/* Disallow sets in really-really secure mode. */
+	if (sopt->sopt_dir == SOPT_SET && securelevel >= 3)
+			return (EPERM);
+	error = 0;
+
+	switch (sopt->sopt_name) {
+	case IP_FW_GET:
+		for (fcp = LIST_FIRST(&ip_fw_chain), size = 0; fcp;
+		     fcp = LIST_NEXT(fcp, chain))
+			size += sizeof *fcp->rule;
+		buf = malloc(size, M_TEMP, M_WAITOK);
+		if (buf == 0) {
+			error = ENOBUFS;
+			break;
 		}
-		m->m_len = 0;
-		for (; fcp; fcp = LIST_NEXT(fcp, chain)) {
-			/* Will we need a new cluster? */
-			if ((m->m_len + sizeof *(fcp->rule)) > MCLBYTES) {
-				m = m->m_next = m_get(M_WAIT, MT_SOOPTS);
-				if (m == NULL) {
-					goto abort;
-				}
-				MCLGET(m, M_WAIT);
-				if (!(m->m_flags & M_EXT)) {
-					goto abort;
-				}
-				m->m_len = 0;
-			}
-			memcpy(m->m_data + m->m_len, fcp->rule,
-					sizeof *(fcp->rule));
-			m->m_len += sizeof *(fcp->rule);
-		}
-		return (0);
-	}
-	m = *mm;
-	/* only allow get calls if secure mode > 2 */
-	if (securelevel > 2) {
-		if (m) (void)m_free(m);
-		return(EPERM);
-	}
-	if (stage == IP_FW_FLUSH) {
-		while (LIST_FIRST(&ip_fw_chain) != NULL && 
-		    LIST_FIRST(&ip_fw_chain)->rule->fw_number != (u_short)-1) {
-			struct ip_fw_chain *fcp = LIST_FIRST(&ip_fw_chain);
-			int s = splnet();
-			LIST_REMOVE(LIST_FIRST(&ip_fw_chain), chain);
+
+		for (fcp = LIST_FIRST(&ip_fw_chain), bp = buf; fcp;
+		     fcp = LIST_NEXT(fcp, chain)) {
+			bcopy(fcp->rule, bp, sizeof *fcp->rule);
+			bp += sizeof *fcp->rule;
+		}
+		error = sooptcopyout(sopt, buf, size);
+		FREE(buf, M_TEMP);
+		break;
+
+	case IP_FW_FLUSH:
+		for (fcp = ip_fw_chain.lh_first; 
+		     fcp != 0 && fcp->rule->fw_number != IPFW_DEFAULT_RULE;
+		     fcp = ip_fw_chain.lh_first) {
+			s = splnet();
+			LIST_REMOVE(fcp, chain);
+			FREE(fcp->rule, M_IPFW);
+			FREE(fcp, M_IPFW);
 			splx(s);
-			free(fcp->rule, M_IPFW);
-			free(fcp, M_IPFW);
 		}
-		if (m) (void)m_free(m);
-		return (0);
-	}
-	if (stage == IP_FW_ZERO) {
-		error = zero_entry(m);
-		if (m) (void)m_free(m);
-		return (error);
-	}
-	if (m == NULL) {
-		printf("%s NULL mbuf ptr\n", err_prefix);
-		return (EINVAL);
-	}
+		break;
+
+	case IP_FW_ZERO:
+		if (sopt->sopt_val != 0) {
+			error = sooptcopyin(sopt, &frwl, sizeof frwl,
+					    sizeof frwl);
+			if (error || (error = zero_entry(&frwl)))
+				break;
+		} else {
+			error = zero_entry(0);
+		}
+		break;
 
-	if (stage == IP_FW_ADD) {
-		struct ip_fw *frwl = check_ipfw_mbuf(m);
+	case IP_FW_ADD:
+		error = sooptcopyin(sopt, &frwl, sizeof frwl, sizeof frwl);
+		if (error || (error = check_ipfw_struct(&frwl)))
+			break;
 
-		if (!frwl)
-			error = EINVAL;
-		else
-			error = add_entry(&ip_fw_chain, frwl);
-		if (m) (void)m_free(m);
-		return error;
-	}
-	if (stage == IP_FW_DEL) {
-		if (m->m_len != sizeof(struct ip_fw)) {
-			dprintf(("%s len=%d, want %d\n", err_prefix, m->m_len,
-			    sizeof(struct ip_fw)));
+		if (frwl.fw_number == IPFW_DEFAULT_RULE) {
+			dprintf(("%s can't add rule %u\n", err_prefix,
+				 (unsigned)IPFW_DEFAULT_RULE));
 			error = EINVAL;
-		} else if (mtod(m, struct ip_fw *)->fw_number == (u_short)-1) {
-			dprintf(("%s can't delete rule 65535\n", err_prefix));
+		} else {
+			error = add_entry(&ip_fw_chain, &frwl);
+		}
+		break;
+
+	case IP_FW_DEL:
+		error = sooptcopyin(sopt, &frwl, sizeof frwl, sizeof frwl);
+		if (error)
+			break;
+
+		if (frwl.fw_number == IPFW_DEFAULT_RULE) {
+			dprintf(("%s can't delete rule %u\n", err_prefix,
+				 (unsigned)IPFW_DEFAULT_RULE));
 			error = EINVAL;
-		} else
-			error = del_entry(&ip_fw_chain,
-			    mtod(m, struct ip_fw *)->fw_number);
-		if (m) (void)m_free(m);
-		return error;
+		} else {
+			error = del_entry(&ip_fw_chain, frwl.fw_number);
+		}
+		break;
+
+	default:
+		panic("ip_fw_ctl");
 	}
 
-	dprintf(("%s unknown request %d\n", err_prefix, stage));
-	if (m) (void)m_free(m);
-	return (EINVAL);
+	return (error);
 }
 
 void
@@ -1110,14 +1070,14 @@
 
 	bzero(&default_rule, sizeof default_rule);
 	default_rule.fw_prot = IPPROTO_IP;
-	default_rule.fw_number = (u_short)-1;
+	default_rule.fw_number = IPFW_DEFAULT_RULE;
 #ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
 	default_rule.fw_flg |= IP_FW_F_ACCEPT;
 #else
 	default_rule.fw_flg |= IP_FW_F_DENY;
 #endif
 	default_rule.fw_flg |= IP_FW_F_IN | IP_FW_F_OUT;
-	if (check_ipfw_struct(&default_rule) == NULL ||
+	if (check_ipfw_struct(&default_rule) != 0 ||
 	    add_entry(&ip_fw_chain, &default_rule))
 		panic("ip_fw_init");
 
Index: netinet/ip_fw.h
===================================================================
RCS file: /home/cvs/src/sys/netinet/ip_fw.h,v
retrieving revision 1.33
diff -u -r1.33 ip_fw.h
--- ip_fw.h	1998/07/06 03:20:15	1.33
+++ ip_fw.h	1998/08/11 18:46:41
@@ -184,6 +184,23 @@
  */
 void ip_fw_init __P((void));
 
+/* Firewall hooks */
+struct ip;
+struct sockopt;
+typedef	int ip_fw_chk_t __P((struct ip **, int, struct ifnet *, u_int16_t *,
+			     struct mbuf **, struct sockaddr_in **));
+typedef	int ip_fw_ctl_t __P((struct sockopt *));
+extern	ip_fw_chk_t *ip_fw_chk_ptr;
+extern	ip_fw_ctl_t *ip_fw_ctl_ptr;
+
+/* IP NAT hooks */
+typedef	int ip_nat_t __P((struct ip **, struct mbuf **, struct ifnet *, int));
+typedef	int ip_nat_ctl_t __P((struct sockopt *));
+extern	ip_nat_t *ip_nat_ptr;
+extern	ip_nat_ctl_t *ip_nat_ctl_ptr;
+#define	IP_NAT_IN	0x00000001
+#define	IP_NAT_OUT	0x00000002
+
 #endif /* KERNEL */
 
 #endif /* _IP_FW_H */
Index: netinet/ip_input.c
===================================================================
RCS file: /home/cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.97
diff -u -r1.97 ip_input.c
--- ip_input.c	1998/07/13 12:12:24	1.97
+++ ip_input.c	1998/08/11 18:46:41
@@ -142,6 +142,9 @@
 #endif
 
 #ifdef COMPAT_IPFW
+
+#include <netinet/ip_fw.h>
+
 /* Firewall hooks */
 ip_fw_chk_t *ip_fw_chk_ptr;
 ip_fw_ctl_t *ip_fw_ctl_ptr;
@@ -1234,7 +1237,7 @@
 
 	if (ip_nhops == 0)
 		return ((struct mbuf *)0);
-	m = m_get(M_DONTWAIT, MT_SOOPTS);
+	m = m_get(M_DONTWAIT, MT_HEADER);
 	if (m == 0)
 		return ((struct mbuf *)0);
 
Index: netinet/ip_mroute.c
===================================================================
RCS file: /home/cvs/src/sys/netinet/ip_mroute.c,v
retrieving revision 1.47
diff -u -r1.47 ip_mroute.c
--- ip_mroute.c	1998/06/30 10:56:31	1.47
+++ ip_mroute.c	1998/08/11 18:46:41
@@ -54,10 +54,8 @@
 extern int	_ip_mforward __P((struct ip *ip, struct ifnet *ifp,
 				  struct mbuf *m, struct ip_moptions *imo));
 extern int	_ip_mrouter_done __P((void));
-extern int	_ip_mrouter_get __P((int cmd, struct socket *so,
-				     struct mbuf **m));
-extern int	_ip_mrouter_set __P((int cmd, struct socket *so,
-				     struct mbuf *m));
+extern int	_ip_mrouter_get __P((struct socket *so, struct sockopt *sopt));
+extern int	_ip_mrouter_set __P((struct socket *so, struct sockopt *sopt));
 extern int	_mrt_ioctl __P((int req, caddr_t data, struct proc *p));
 
 /*
@@ -70,27 +68,25 @@
 u_int		rsvpdebug = 0;
 
 int
-_ip_mrouter_set(cmd, so, m)
-	int cmd;
+_ip_mrouter_set(so, sopt)
 	struct socket *so;
-	struct mbuf *m;
+	struct sockopt *sopt;
 {
 	return(EOPNOTSUPP);
 }
 
-int (*ip_mrouter_set)(int, struct socket *, struct mbuf *) = _ip_mrouter_set;
+int (*ip_mrouter_set)(struct socket *, struct sockopt *) = _ip_mrouter_set;
 
 
 int
-_ip_mrouter_get(cmd, so, m)
-	int cmd;
+_ip_mrouter_get(so, sopt)
 	struct socket *so;
-	struct mbuf **m;
+	struct sockopt *sopt;
 {
 	return(EOPNOTSUPP);
 }
 
-int (*ip_mrouter_get)(int, struct socket *, struct mbuf **) = _ip_mrouter_get;
+int (*ip_mrouter_get)(struct socket *, struct sockopt *) = _ip_mrouter_get;
 
 int
 _ip_mrouter_done()
@@ -161,17 +157,17 @@
 u_long (*ip_mcast_src)(int) = _ip_mcast_src;
 
 int
-ip_rsvp_vif_init(so, m)
+ip_rsvp_vif_init(so, sopt)
     struct socket *so;
-    struct mbuf *m;
+    struct sockopt *sopt;
 {
     return(EINVAL);
 }
 
 int
-ip_rsvp_vif_done(so, m)
+ip_rsvp_vif_done(so, sopt)
     struct socket *so;
-    struct mbuf *m;
+    struct sockopt *sopt;
 {
     return(EINVAL);
 }
@@ -279,22 +275,20 @@
 static u_long	X_ip_mcast_src __P((int vifi));
 static int	X_ip_mforward __P((struct ip *ip, struct ifnet *ifp, struct mbuf *m, struct ip_moptions *imo));
 static int	X_ip_mrouter_done __P((void));
-static int	X_ip_mrouter_get __P((int cmd, struct socket *so, struct mbuf **m));
-static int	X_ip_mrouter_set __P((int cmd, struct socket *so, struct mbuf *m));
+static int	X_ip_mrouter_get __P((struct socket *so, struct sockopt *m));
+static int	X_ip_mrouter_set __P((struct socket *so, struct sockopt *m));
 static int	X_legal_vif_num __P((int vif));
 static int	X_mrt_ioctl __P((int cmd, caddr_t data));
 
 static int get_sg_cnt(struct sioc_sg_req *);
 static int get_vif_cnt(struct sioc_vif_req *);
-static int ip_mrouter_init(struct socket *, struct mbuf *);
+static int ip_mrouter_init(struct socket *, int);
 static int add_vif(struct vifctl *);
-static int del_vif(vifi_t *);
+static int del_vif(vifi_t);
 static int add_mfc(struct mfcctl *);
 static int del_mfc(struct mfcctl *);
 static int socket_send(struct socket *, struct mbuf *, struct sockaddr_in *);
-static int get_version(struct mbuf *);
-static int get_assert(struct mbuf *);
-static int set_assert(int *);
+static int set_assert(int);
 static void expire_upcalls(void *);
 static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *,
 		  vifi_t);
@@ -386,53 +380,102 @@
  * Handle MRT setsockopt commands to modify the multicast routing tables.
  */
 static int
-X_ip_mrouter_set(cmd, so, m)
-    int cmd;
-    struct socket *so;
-    struct mbuf *m;
+X_ip_mrouter_set(so, sopt)
+	struct socket *so;
+	struct sockopt *sopt;
 {
-   if (cmd != MRT_INIT && so != ip_mrouter) return EACCES;
+	int	error, optval;
+	vifi_t	vifi;
+	struct	vifctl vifc;
+	struct	mfcctl mfc;
+
+	if (so != ip_mrouter && sopt->sopt_name != MRT_INIT)
+		return (EPERM);
+
+	error = 0;
+	switch (sopt->sopt_name) {
+	case MRT_INIT:
+		error = sooptcopyin(sopt, &optval, sizeof optval, 
+				    sizeof optval);
+		if (error)
+			break;
+		error = ip_mrouter_init(so, optval);
+		break;
 
-    switch (cmd) {
-	case MRT_INIT:     return ip_mrouter_init(so, m);
-	case MRT_DONE:     return ip_mrouter_done();
-	case MRT_ADD_VIF:  return add_vif (mtod(m, struct vifctl *));
-	case MRT_DEL_VIF:  return del_vif (mtod(m, vifi_t *));
-	case MRT_ADD_MFC:  return add_mfc (mtod(m, struct mfcctl *));
-	case MRT_DEL_MFC:  return del_mfc (mtod(m, struct mfcctl *));
-	case MRT_ASSERT:   return set_assert(mtod(m, int *));
-	default:             return EOPNOTSUPP;
-    }
+	case MRT_DONE:
+		error = ip_mrouter_done();
+		break;
+
+	case MRT_ADD_VIF:
+		error = sooptcopyin(sopt, &vifc, sizeof vifc, sizeof vifc);
+		if (error)
+			break;
+		error = add_vif(&vifc);
+		break;
+
+	case MRT_DEL_VIF:
+		error = sooptcopyin(sopt, &vifi, sizeof vifi, sizeof vifi);
+		if (error)
+			break;
+		error = del_vif(vifi);
+		break;
+
+	case MRT_ADD_MFC:
+	case MRT_DEL_MFC:
+		error = sooptcopyin(sopt, &mfc, sizeof mfc, sizeof mfc);
+		if (error)
+			break;
+		if (sopt->sopt_name == MRT_ADD_MFC)
+			error = add_mfc(&mfc);
+		else
+			error = del_mfc(&mfc);
+
+	case MRT_ASSERT:
+		error = sooptcopyin(sopt, &optval, sizeof optval, 
+				    sizeof optval);
+		if (error)
+			break;
+		set_assert(optval);
+
+	default:
+		error = EOPNOTSUPP;
+		break;
+	}
+	return (error);
 }
 
 #ifndef MROUTE_LKM
-int (*ip_mrouter_set)(int, struct socket *, struct mbuf *) = X_ip_mrouter_set;
+int (*ip_mrouter_set)(struct socket *, struct sockopt *) = X_ip_mrouter_set;
 #endif
 
 /*
  * Handle MRT getsockopt commands
  */
 static int
-X_ip_mrouter_get(cmd, so, m)
-    int cmd;
-    struct socket *so;
-    struct mbuf **m;
+X_ip_mrouter_get(so, sopt)
+	struct socket *so;
+	struct sockopt *sopt;
 {
-    struct mbuf *mb;
+	int error;
+	static int version = 0x0305; /* !!! why is this here? XXX */
 
-    if (so != ip_mrouter) return EACCES;
+	switch (sopt->sopt_name) {
+	case MRT_VERSION:
+		error = sooptcopyout(sopt, &version, sizeof version);
+		break;
 
-    *m = mb = m_get(M_WAIT, MT_SOOPTS);
-  
-    switch (cmd) {
-	case MRT_VERSION:   return get_version(mb);
-	case MRT_ASSERT:    return get_assert(mb);
-	default:            return EOPNOTSUPP;
-    }
+	case MRT_ASSERT:
+		error = sooptcopyout(sopt, &pim_assert, sizeof pim_assert);
+		break;
+	default:
+		error = EOPNOTSUPP;
+		break;
+	}
+	return (error);
 }
 
 #ifndef MROUTE_LKM
-int (*ip_mrouter_get)(int, struct socket *, struct mbuf **) = X_ip_mrouter_get;
+int (*ip_mrouter_get)(struct socket *, struct sockopt *) = X_ip_mrouter_get;
 #endif
 
 /*
@@ -509,9 +552,9 @@
  * Enable multicast routing
  */
 static int
-ip_mrouter_init(so, m)
+ip_mrouter_init(so, version)
 	struct socket *so;
-	struct mbuf *m;
+	int version;
 {
     int *v;
 
@@ -522,11 +565,7 @@
     if (so->so_type != SOCK_RAW ||
 	so->so_proto->pr_protocol != IPPROTO_IGMP) return EOPNOTSUPP;
 
-    if (!m || (m->m_len != sizeof(int *)))
-	return ENOPROTOOPT;
-
-    v = mtod(m, int *);
-    if (*v != 1)
+    if (version != 1)
 	return ENOPROTOOPT;
 
     if (ip_mrouter != NULL) return EADDRINUSE;
@@ -626,47 +665,17 @@
 int (*ip_mrouter_done)(void) = X_ip_mrouter_done;
 #endif
 
-static int
-get_version(mb)
-    struct mbuf *mb;
-{
-    int *v;
-
-    v = mtod(mb, int *);
-
-    *v = 0x0305;	/* XXX !!!! */
-    mb->m_len = sizeof(int);
-
-    return 0;
-}
-
 /*
  * Set PIM assert processing global
  */
 static int
 set_assert(i)
-    int *i;
+	int i;
 {
-    if ((*i != 1) && (*i != 0))
+    if ((i != 1) && (i != 0))
 	return EINVAL;
 
-    pim_assert = *i;
-
-    return 0;
-}
-
-/*
- * Get PIM assert processing global
- */
-static int
-get_assert(m)
-    struct mbuf *m;
-{
-    int *i;
-
-    i = mtod(m, int *);
-
-    *i = pim_assert;
+    pim_assert = i;
 
     return 0;
 }
@@ -777,17 +786,16 @@
  * Delete a vif from the vif table
  */
 static int
-del_vif(vifip)
-    vifi_t *vifip;
+del_vif(vifi)
+	vifi_t vifi;
 {
-    register struct vif *vifp = viftable + *vifip;
-    register vifi_t vifi;
+    register struct vif *vifp = &viftable[vifi];
     register struct mbuf *m;
     struct ifnet *ifp;
     struct ifreq ifr;
     int s;
 
-    if (*vifip >= numvifs) return EINVAL;
+    if (vifi >= numvifs) return EINVAL;
     if (vifp->v_lcl_addr.s_addr == 0) return EADDRNOTAVAIL;
 
     s = splnet();
@@ -816,6 +824,9 @@
     bzero((caddr_t)vifp->v_tbf, sizeof(*(vifp->v_tbf)));
     bzero((caddr_t)vifp, sizeof (*vifp));
 
+    if (mrtdebug)
+      log(LOG_DEBUG, "del_vif %d, numvifs %d\n", vifi, numvifs);
+
     /* Adjust numvifs down */
     for (vifi = numvifs; vifi > 0; vifi--)
 	if (viftable[vifi-1].v_lcl_addr.s_addr != 0) break;
@@ -823,9 +834,6 @@
 
     splx(s);
 
-    if (mrtdebug)
-      log(LOG_DEBUG, "del_vif %d, numvifs %d\n", *vifip, numvifs);
-
     return 0;
 }
 
@@ -2007,12 +2015,11 @@
  */
 
 int
-ip_rsvp_vif_init(so, m)
-    struct socket *so;
-    struct mbuf *m;
+ip_rsvp_vif_init(so, sopt)
+	struct socket *so;
+	struct sockopt *sopt;
 {
-    int i;
-    register int s;
+    int error, i, s;
 
     if (rsvpdebug)
 	printf("ip_rsvp_vif_init: so_type = %d, pr_protocol = %d\n",
@@ -2022,13 +2029,12 @@
 	return EOPNOTSUPP;
 
     /* Check mbuf. */
-    if (m == NULL || m->m_len != sizeof(int)) {
-	return EINVAL;
-    }
-    i = *(mtod(m, int *));
+    error = sooptcopyin(sopt, &i, sizeof i, sizeof i);
+    if (error)
+	    return (error);
  
     if (rsvpdebug)
-	printf("ip_rsvp_vif_init: vif = %d rsvp_on = %d\n",i,rsvp_on);
+	printf("ip_rsvp_vif_init: vif = %d rsvp_on = %d\n", i, rsvp_on);
  
     s = splnet();
 
@@ -2058,49 +2064,48 @@
 }
 
 int
-ip_rsvp_vif_done(so, m)
-    struct socket *so;
-    struct mbuf *m;
+ip_rsvp_vif_done(so, sopt)
+	struct socket *so;
+	struct sockopt *sopt;
 {
-	int i;
-	register int s;
+	int error, i, s;
  
-    if (rsvpdebug)
-	printf("ip_rsvp_vif_done: so_type = %d, pr_protocol = %d\n",
-	       so->so_type, so->so_proto->pr_protocol);
+	if (rsvpdebug)
+		printf("ip_rsvp_vif_done: so_type = %d, pr_protocol = %d\n",
+		       so->so_type, so->so_proto->pr_protocol);
  
-    if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)
-	return EOPNOTSUPP;
+	if (so->so_type != SOCK_RAW || 
+	    so->so_proto->pr_protocol != IPPROTO_RSVP)
+		return EOPNOTSUPP;
  
-    /* Check mbuf. */
-    if (m == NULL || m->m_len != sizeof(int)) {
-	    return EINVAL;
-    }
-    i = *(mtod(m, int *));
+	error = sooptcopyin(sopt, &i, sizeof i, sizeof i);
+	if (error)
+		return (error);
  
-    s = splnet();
+	s = splnet();
  
-    /* Check vif. */
-    if (!legal_vif_num(i)) {
-	splx(s);
-        return EADDRNOTAVAIL;
-    }
+	/* Check vif. */
+	if (!legal_vif_num(i)) {
+		splx(s);
+		return EADDRNOTAVAIL;
+	}
 
-    if (rsvpdebug)
-	printf("ip_rsvp_vif_done: v_rsvpd = %p so = %p\n",
-	       viftable[i].v_rsvpd, so);
+	if (rsvpdebug)
+		printf("ip_rsvp_vif_done: v_rsvpd = %p so = %p\n",
+		       viftable[i].v_rsvpd, so);
 
-    viftable[i].v_rsvpd = NULL;
-    /* This may seem silly, but we need to be sure we don't over-decrement
-     * the RSVP counter, in case something slips up.
-     */
-    if (viftable[i].v_rsvp_on) {
-	viftable[i].v_rsvp_on = 0;
-	rsvp_on--;
-    }
+	viftable[i].v_rsvpd = NULL;
+	/*
+	 * This may seem silly, but we need to be sure we don't over-decrement
+	 * the RSVP counter, in case something slips up.
+	 */
+	if (viftable[i].v_rsvp_on) {
+		viftable[i].v_rsvp_on = 0;
+		rsvp_on--;
+	}
 
-    splx(s);
-    return 0;
+	splx(s);
+	return 0;
 }
 
 void
Index: netinet/ip_mroute.h
===================================================================
RCS file: /home/cvs/src/sys/netinet/ip_mroute.h,v
retrieving revision 1.13
diff -u -r1.13 ip_mroute.h
--- ip_mroute.h	1997/02/22 09:41:35	1.13
+++ ip_mroute.h	1998/08/11 18:46:41
@@ -248,8 +248,10 @@
 
 #ifdef KERNEL
 
-extern int	(*ip_mrouter_set) __P((int, struct socket *, struct mbuf *));
-extern int	(*ip_mrouter_get) __P((int, struct socket *, struct mbuf **));
+struct sockopt;
+
+extern int	(*ip_mrouter_set) __P((struct socket *, struct sockopt *));
+extern int	(*ip_mrouter_get) __P((struct socket *, struct sockopt *));
 extern int	(*ip_mrouter_done) __P((void));
 #ifdef MROUTING
 extern int	(*mrt_ioctl) __P((int, caddr_t));
Index: netinet/ip_output.c
===================================================================
RCS file: /home/cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.80
diff -u -r1.80 ip_output.c
--- ip_output.c	1998/08/01 08:44:33	1.80
+++ ip_output.c	1998/08/11 18:46:41
@@ -72,6 +72,10 @@
 #undef COMPAT_IPFW
 #endif
 
+#ifdef COMPAT_IPFW
+#include <netinet/ip_fw.h>
+#endif
+
 #ifdef IPFIREWALL_FORWARD_DEBUG
 #define print_ip(a)	 printf("%ld.%ld.%ld.%ld",(ntohl(a.s_addr)>>24)&0xFF,\
 				 		  (ntohl(a.s_addr)>>16)&0xFF,\
@@ -85,10 +89,10 @@
 static void	ip_mloopback
 	__P((struct ifnet *, struct mbuf *, struct sockaddr_in *, int));
 static int	ip_getmoptions
-	__P((int, struct ip_moptions *, struct mbuf **));
-static int	ip_pcbopts __P((struct mbuf **, struct mbuf *));
+	__P((struct sockopt *, struct ip_moptions *));
+static int	ip_pcbopts __P((int, struct mbuf **, struct mbuf *));
 static int	ip_setmoptions
-	__P((int, struct ip_moptions **, struct mbuf *));
+	__P((struct sockopt *, struct ip_moptions **));
 
 #if defined(IPFILTER_LKM) || defined(IPFILTER)
 int	ip_optcopy __P((struct ip *, struct ip *));
@@ -742,33 +746,43 @@
  * IP socket option processing.
  */
 int
-ip_ctloutput(op, so, level, optname, mp, p)
-	int op;
+ip_ctloutput(so, sopt)
 	struct socket *so;
-	int level, optname;
-	struct mbuf **mp;
-	struct proc *p;
+	struct sockopt *sopt;
 {
-	register struct inpcb *inp = sotoinpcb(so);
-	register struct mbuf *m = *mp;
-	register int optval = 0;
-	int error = 0;
+	struct	inpcb *inp = sotoinpcb(so);
+	int	error, optval;
 
-	if (level != IPPROTO_IP) {
-		error = EINVAL;
-		if (op == PRCO_SETOPT && *mp)
-			(void) m_free(*mp);
-	} else switch (op) {
+	error = optval = 0;
+	if (sopt->sopt_level != IPPROTO_IP) {
+		return (EINVAL);
+	}
 
-	case PRCO_SETOPT:
-		switch (optname) {
+	switch (sopt->sopt_dir) {
+	case SOPT_SET:
+		switch (sopt->sopt_name) {
 		case IP_OPTIONS:
 #ifdef notyet
 		case IP_RETOPTS:
-			return (ip_pcbopts(optname, &inp->inp_options, m));
-#else
-			return (ip_pcbopts(&inp->inp_options, m));
 #endif
+		{
+			struct mbuf *m;
+			if (sopt->sopt_valsize > MLEN) {
+				error = EMSGSIZE;
+				break;
+			}
+			MGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT, MT_HEADER);
+			if (m == 0) {
+				error = ENOBUFS;
+				break;
+			}
+			m->m_len = sopt->sopt_valsize;
+			error = sooptcopyin(sopt, mtod(m, char *), m->m_len,
+					    m->m_len);
+			
+			return (ip_pcbopts(sopt->sopt_name, &inp->inp_options,
+					   m));
+		}
 
 		case IP_TOS:
 		case IP_TTL:
@@ -776,41 +790,40 @@
 		case IP_RECVRETOPTS:
 		case IP_RECVDSTADDR:
 		case IP_RECVIF:
-			if (m == 0 || m->m_len != sizeof(int))
-				error = EINVAL;
-			else {
-				optval = *mtod(m, int *);
-				switch (optname) {
+			error = sooptcopyin(sopt, &optval, sizeof optval,
+					    sizeof optval);
+			if (error)
+				break;
 
-				case IP_TOS:
-					inp->inp_ip_tos = optval;
-					break;
+			switch (sopt->sopt_name) {
+			case IP_TOS:
+				inp->inp_ip_tos = optval;
+				break;
 
-				case IP_TTL:
-					inp->inp_ip_ttl = optval;
-					break;
+			case IP_TTL:
+				inp->inp_ip_ttl = optval;
+				break;
 #define	OPTSET(bit) \
 	if (optval) \
 		inp->inp_flags |= bit; \
 	else \
 		inp->inp_flags &= ~bit;
 
-				case IP_RECVOPTS:
-					OPTSET(INP_RECVOPTS);
-					break;
+			case IP_RECVOPTS:
+				OPTSET(INP_RECVOPTS);
+				break;
 
-				case IP_RECVRETOPTS:
-					OPTSET(INP_RECVRETOPTS);
-					break;
+			case IP_RECVRETOPTS:
+				OPTSET(INP_RECVRETOPTS);
+				break;
 
-				case IP_RECVDSTADDR:
-					OPTSET(INP_RECVDSTADDR);
-					break;
+			case IP_RECVDSTADDR:
+				OPTSET(INP_RECVDSTADDR);
+				break;
 
-				case IP_RECVIF:
-					OPTSET(INP_RECVIF);
-					break;
-				}
+			case IP_RECVIF:
+				OPTSET(INP_RECVIF);
+				break;
 			}
 			break;
 #undef OPTSET
@@ -821,36 +834,34 @@
 		case IP_MULTICAST_LOOP:
 		case IP_ADD_MEMBERSHIP:
 		case IP_DROP_MEMBERSHIP:
-			error = ip_setmoptions(optname, &inp->inp_moptions, m);
+			error = ip_setmoptions(sopt, &inp->inp_moptions);
 			break;
 
 		case IP_PORTRANGE:
-			if (m == 0 || m->m_len != sizeof(int))
-				error = EINVAL;
-			else {
-				optval = *mtod(m, int *);
-
-				switch (optval) {
+			error = sooptcopyin(sopt, &optval, sizeof optval,
+					    sizeof optval);
+			if (error)
+				break;
 
-				case IP_PORTRANGE_DEFAULT:
-					inp->inp_flags &= ~(INP_LOWPORT);
-					inp->inp_flags &= ~(INP_HIGHPORT);
-					break;
+			switch (optval) {
+			case IP_PORTRANGE_DEFAULT:
+				inp->inp_flags &= ~(INP_LOWPORT);
+				inp->inp_flags &= ~(INP_HIGHPORT);
+				break;
 
-				case IP_PORTRANGE_HIGH:
-					inp->inp_flags &= ~(INP_LOWPORT);
-					inp->inp_flags |= INP_HIGHPORT;
-					break;
+			case IP_PORTRANGE_HIGH:
+				inp->inp_flags &= ~(INP_LOWPORT);
+				inp->inp_flags |= INP_HIGHPORT;
+				break;
 
-				case IP_PORTRANGE_LOW:
-					inp->inp_flags &= ~(INP_HIGHPORT);
-					inp->inp_flags |= INP_LOWPORT;
-					break;
+			case IP_PORTRANGE_LOW:
+				inp->inp_flags &= ~(INP_HIGHPORT);
+				inp->inp_flags |= INP_LOWPORT;
+				break;
 
-				default:
-					error = EINVAL;
-					break;
-				}
+			default:
+				error = EINVAL;
+				break;
 			}
 			break;
 
@@ -858,21 +869,19 @@
 			error = ENOPROTOOPT;
 			break;
 		}
-		if (m)
-			(void)m_free(m);
 		break;
 
-	case PRCO_GETOPT:
-		switch (optname) {
+	case SOPT_GET:
+		switch (sopt->sopt_name) {
 		case IP_OPTIONS:
 		case IP_RETOPTS:
-			*mp = m = m_get(M_WAIT, MT_SOOPTS);
-			if (inp->inp_options) {
-				m->m_len = inp->inp_options->m_len;
-				bcopy(mtod(inp->inp_options, void *),
-				    mtod(m, void *), m->m_len);
-			} else
-				m->m_len = 0;
+			if (inp->inp_options)
+				error = sooptcopyout(sopt, 
+						     mtod(inp->inp_options,
+							  char *),
+						     inp->inp_options->m_len);
+			else
+				sopt->sopt_valsize = 0;
 			break;
 
 		case IP_TOS:
@@ -881,9 +890,8 @@
 		case IP_RECVRETOPTS:
 		case IP_RECVDSTADDR:
 		case IP_RECVIF:
-			*mp = m = m_get(M_WAIT, MT_SOOPTS);
-			m->m_len = sizeof(int);
-			switch (optname) {
+		case IP_PORTRANGE:
+			switch (sopt->sopt_name) {
 
 			case IP_TOS:
 				optval = inp->inp_ip_tos;
@@ -910,8 +918,17 @@
 			case IP_RECVIF:
 				optval = OPTBIT(INP_RECVIF);
 				break;
+
+			case IP_PORTRANGE:
+				if (inp->inp_flags & INP_HIGHPORT)
+					optval = IP_PORTRANGE_HIGH;
+				else if (inp->inp_flags & INP_LOWPORT)
+					optval = IP_PORTRANGE_LOW;
+				else
+					optval = 0;
+				break;
 			}
-			*mtod(m, int *) = optval;
+			error = sooptcopyout(sopt, &optval, sizeof optval);
 			break;
 
 		case IP_MULTICAST_IF:
@@ -920,21 +937,7 @@
 		case IP_MULTICAST_LOOP:
 		case IP_ADD_MEMBERSHIP:
 		case IP_DROP_MEMBERSHIP:
-			error = ip_getmoptions(optname, inp->inp_moptions, mp);
-			break;
-
-		case IP_PORTRANGE:
-			*mp = m = m_get(M_WAIT, MT_SOOPTS);
-			m->m_len = sizeof(int);
-
-			if (inp->inp_flags & INP_HIGHPORT)
-				optval = IP_PORTRANGE_HIGH;
-			else if (inp->inp_flags & INP_LOWPORT)
-				optval = IP_PORTRANGE_LOW;
-			else
-				optval = 0;
-
-			*mtod(m, int *) = optval;
+			error = ip_getmoptions(sopt, inp->inp_moptions);
 			break;
 
 		default:
@@ -952,12 +955,8 @@
  * with destination address if source routed.
  */
 static int
-#ifdef notyet
 ip_pcbopts(optname, pcbopt, m)
 	int optname;
-#else
-ip_pcbopts(pcbopt, m)
-#endif
 	struct mbuf **pcbopt;
 	register struct mbuf *m;
 {
@@ -1054,23 +1053,28 @@
 }
 
 /*
+ * XXX
+ * The whole multicast option thing needs to be re-thought.
+ * Several of these options are equally applicable to non-multicast
+ * transmission, and one (IP_MULTICAST_TTL) totally duplicates a
+ * standard option (IP_TTL).
+ */
+/*
  * Set the IP multicast options in response to user setsockopt().
  */
 static int
-ip_setmoptions(optname, imop, m)
-	int optname;
+ip_setmoptions(sopt, imop)
+	struct sockopt *sopt;
 	struct ip_moptions **imop;
-	struct mbuf *m;
 {
-	register int error = 0;
-	u_char loop;
-	register int i;
+	int error = 0;
+	int i;
 	struct in_addr addr;
-	register struct ip_mreq *mreq;
-	register struct ifnet *ifp;
-	register struct ip_moptions *imo = *imop;
+	struct ip_mreq mreq;
+	struct ifnet *ifp;
+	struct ip_moptions *imo = *imop;
 	struct route ro;
-	register struct sockaddr_in *dst;
+	struct sockaddr_in *dst;
 	int s;
 
 	if (imo == NULL) {
@@ -1091,18 +1095,16 @@
 		imo->imo_num_memberships = 0;
 	}
 
-	switch (optname) {
+	switch (sopt->sopt_name) {
 	/* store an index number for the vif you wanna use in the send */
 	case IP_MULTICAST_VIF:
-		if (!legal_vif_num) {
+		if (legal_vif_num == 0) {
 			error = EOPNOTSUPP;
 			break;
 		}
-		if (m == NULL || m->m_len != sizeof(int)) {
-			error = EINVAL;
+		error = sooptcopyin(sopt, &i, sizeof i, sizeof i);
+		if (error)
 			break;
-		}
-		i = *(mtod(m, int *));
 		if (!legal_vif_num(i) && (i != -1)) {
 			error = EINVAL;
 			break;
@@ -1114,11 +1116,9 @@
 		/*
 		 * Select the interface for outgoing multicast packets.
 		 */
-		if (m == NULL || m->m_len != sizeof(struct in_addr)) {
-			error = EINVAL;
+		error = sooptcopyin(sopt, &addr, sizeof addr, sizeof addr);
+		if (error)
 			break;
-		}
-		addr = *(mtod(m, struct in_addr *));
 		/*
 		 * INADDR_ANY is used to remove a previous selection.
 		 * When no interface is selected, a default one is
@@ -1147,25 +1147,50 @@
 	case IP_MULTICAST_TTL:
 		/*
 		 * Set the IP time-to-live for outgoing multicast packets.
-		 */
-		if (m == NULL || m->m_len != 1) {
-			error = EINVAL;
-			break;
+		 * The original multicast API required a char argument,
+		 * which is inconsistent with the rest of the socket API.
+		 * We allow either a char or an int.
+		 */
+		if (sopt->sopt_valsize == 1) {
+			u_char ttl;
+			error = sooptcopyin(sopt, &ttl, 1, 1);
+			if (error)
+				break;
+			imo->imo_multicast_ttl = ttl;
+		} else {
+			u_int ttl;
+			error = sooptcopyin(sopt, &ttl, sizeof ttl, 
+					    sizeof ttl);
+			if (error)
+				break;
+			if (ttl > 255)
+				error = EINVAL;
+			else
+				imo->imo_multicast_ttl = ttl;
 		}
-		imo->imo_multicast_ttl = *(mtod(m, u_char *));
 		break;
 
 	case IP_MULTICAST_LOOP:
 		/*
 		 * Set the loopback flag for outgoing multicast packets.
-		 * Must be zero or one.
-		 */
-		if (m == NULL || m->m_len != 1 ||
-		   (loop = *(mtod(m, u_char *))) > 1) {
-			error = EINVAL;
-			break;
+		 * Must be zero or one.  The original multicast API required a
+		 * char argument, which is inconsistent with the rest
+		 * of the socket API.  We allow either a char or an int.
+		 */
+		if (sopt->sopt_valsize == 1) {
+			u_char loop;
+			error = sooptcopyin(sopt, &loop, 1, 1);
+			if (error)
+				break;
+			imo->imo_multicast_loop = !!loop;
+		} else {
+			u_int loop;
+			error = sooptcopyin(sopt, &loop, sizeof loop,
+					    sizeof loop);
+			if (error)
+				break;
+			imo->imo_multicast_loop = !!loop;
 		}
-		imo->imo_multicast_loop = loop;
 		break;
 
 	case IP_ADD_MEMBERSHIP:
@@ -1173,12 +1198,11 @@
 		 * Add a multicast group membership.
 		 * Group must be a valid IP multicast address.
 		 */
-		if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
-			error = EINVAL;
+		error = sooptcopyin(sopt, &mreq, sizeof mreq, sizeof mreq);
+		if (error)
 			break;
-		}
-		mreq = mtod(m, struct ip_mreq *);
-		if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) {
+
+		if (!IN_MULTICAST(ntohl(mreq.imr_multiaddr.s_addr))) {
 			error = EINVAL;
 			break;
 		}
@@ -1187,12 +1211,12 @@
 		 * If no interface address was provided, use the interface of
 		 * the route to the given multicast address.
 		 */
-		if (mreq->imr_interface.s_addr == INADDR_ANY) {
+		if (mreq.imr_interface.s_addr == INADDR_ANY) {
 			bzero((caddr_t)&ro, sizeof(ro));
 			dst = (struct sockaddr_in *)&ro.ro_dst;
 			dst->sin_len = sizeof(*dst);
 			dst->sin_family = AF_INET;
-			dst->sin_addr = mreq->imr_multiaddr;
+			dst->sin_addr = mreq.imr_multiaddr;
 			rtalloc(&ro);
 			if (ro.ro_rt == NULL) {
 				error = EADDRNOTAVAIL;
@@ -1203,7 +1227,7 @@
 			rtfree(ro.ro_rt);
 		}
 		else {
-			INADDR_TO_IFP(mreq->imr_interface, ifp);
+			INADDR_TO_IFP(mreq.imr_interface, ifp);
 		}
 
 		/*
@@ -1222,7 +1246,7 @@
 		for (i = 0; i < imo->imo_num_memberships; ++i) {
 			if (imo->imo_membership[i]->inm_ifp == ifp &&
 			    imo->imo_membership[i]->inm_addr.s_addr
-						== mreq->imr_multiaddr.s_addr)
+						== mreq.imr_multiaddr.s_addr)
 				break;
 		}
 		if (i < imo->imo_num_memberships) {
@@ -1240,7 +1264,7 @@
 		 * address list for the given interface.
 		 */
 		if ((imo->imo_membership[i] =
-		    in_addmulti(&mreq->imr_multiaddr, ifp)) == NULL) {
+		    in_addmulti(&mreq.imr_multiaddr, ifp)) == NULL) {
 			error = ENOBUFS;
 			splx(s);
 			break;
@@ -1254,12 +1278,11 @@
 		 * Drop a multicast group membership.
 		 * Group must be a valid IP multicast address.
 		 */
-		if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
-			error = EINVAL;
+		error = sooptcopyin(sopt, &mreq, sizeof mreq, sizeof mreq);
+		if (error)
 			break;
-		}
-		mreq = mtod(m, struct ip_mreq *);
-		if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) {
+
+		if (!IN_MULTICAST(ntohl(mreq.imr_multiaddr.s_addr))) {
 			error = EINVAL;
 			break;
 		}
@@ -1269,10 +1292,10 @@
 		 * If an interface address was specified, get a pointer
 		 * to its ifnet structure.
 		 */
-		if (mreq->imr_interface.s_addr == INADDR_ANY)
+		if (mreq.imr_interface.s_addr == INADDR_ANY)
 			ifp = NULL;
 		else {
-			INADDR_TO_IFP(mreq->imr_interface, ifp);
+			INADDR_TO_IFP(mreq.imr_interface, ifp);
 			if (ifp == NULL) {
 				error = EADDRNOTAVAIL;
 				splx(s);
@@ -1286,7 +1309,7 @@
 			if ((ifp == NULL ||
 			     imo->imo_membership[i]->inm_ifp == ifp) &&
 			     imo->imo_membership[i]->inm_addr.s_addr ==
-			     mreq->imr_multiaddr.s_addr)
+			     mreq.imr_multiaddr.s_addr)
 				break;
 		}
 		if (i == imo->imo_num_memberships) {
@@ -1332,57 +1355,63 @@
  * Return the IP multicast options in response to user getsockopt().
  */
 static int
-ip_getmoptions(optname, imo, mp)
-	int optname;
+ip_getmoptions(sopt, imo)
+	struct sockopt *sopt;
 	register struct ip_moptions *imo;
-	register struct mbuf **mp;
 {
-	u_char *ttl;
-	u_char *loop;
-	struct in_addr *addr;
+	struct in_addr addr;
 	struct in_ifaddr *ia;
+	int error, optval;
+	u_char coptval;
 
-	*mp = m_get(M_WAIT, MT_SOOPTS);
-
-	switch (optname) {
-
+	error = 0;
+	switch (sopt->sopt_name) {
 	case IP_MULTICAST_VIF: 
 		if (imo != NULL)
-			*(mtod(*mp, int *)) = imo->imo_multicast_vif;
+			optval = imo->imo_multicast_vif;
 		else
-			*(mtod(*mp, int *)) = -1;
-		(*mp)->m_len = sizeof(int);
-		return(0);
+			optval = -1;
+		error = sooptcopyout(sopt, &optval, sizeof optval);
+		break;
 
 	case IP_MULTICAST_IF:
-		addr = mtod(*mp, struct in_addr *);
-		(*mp)->m_len = sizeof(struct in_addr);
 		if (imo == NULL || imo->imo_multicast_ifp == NULL)
-			addr->s_addr = INADDR_ANY;
+			addr.s_addr = INADDR_ANY;
 		else {
 			IFP_TO_IA(imo->imo_multicast_ifp, ia);
-			addr->s_addr = (ia == NULL) ? INADDR_ANY
-					: IA_SIN(ia)->sin_addr.s_addr;
+			addr.s_addr = (ia == NULL) ? INADDR_ANY
+				: IA_SIN(ia)->sin_addr.s_addr;
 		}
-		return (0);
+		error = sooptcopyout(sopt, &addr, sizeof addr);
+		break;
 
 	case IP_MULTICAST_TTL:
-		ttl = mtod(*mp, u_char *);
-		(*mp)->m_len = 1;
-		*ttl = (imo == NULL) ? IP_DEFAULT_MULTICAST_TTL
-				     : imo->imo_multicast_ttl;
-		return (0);
+		if (imo == 0)
+			optval = coptval = IP_DEFAULT_MULTICAST_TTL;
+		else
+			optval = coptval = imo->imo_multicast_ttl;
+		if (sopt->sopt_valsize == 1)
+			error = sooptcopyout(sopt, &coptval, 1);
+		else
+			error = sooptcopyout(sopt, &optval, sizeof optval);
+		break;
 
 	case IP_MULTICAST_LOOP:
-		loop = mtod(*mp, u_char *);
-		(*mp)->m_len = 1;
-		*loop = (imo == NULL) ? IP_DEFAULT_MULTICAST_LOOP
-				      : imo->imo_multicast_loop;
-		return (0);
+		if (imo == 0)
+			optval = coptval = IP_DEFAULT_MULTICAST_LOOP;
+		else
+			optval = coptval = imo->imo_multicast_loop;
+		if (sopt->sopt_valsize == 1)
+			error = sooptcopyout(sopt, &coptval, 1);
+		else
+			error = sooptcopyout(sopt, &optval, sizeof optval);
+		break;
 
 	default:
-		return (EOPNOTSUPP);
+		error = ENOPROTOOPT;
+		break;
 	}
+	return (error);
 }
 
 /*
Index: netinet/ip_var.h
===================================================================
RCS file: /home/cvs/src/sys/netinet/ip_var.h,v
retrieving revision 1.43
diff -u -r1.43 ip_var.h
--- ip_var.h	1998/07/13 12:20:07	1.43
+++ ip_var.h	1998/08/11 18:46:41
@@ -160,8 +160,10 @@
 #define	IP_ROUTETOIF		SO_DONTROUTE	/* bypass routing tables */
 #define	IP_ALLOWBROADCAST	SO_BROADCAST	/* can send broadcast packets */
 
+struct ip;
 struct inpcb;
 struct route;
+struct sockopt;
 
 extern struct	ipstat	ipstat;
 extern u_short	ip_id;				/* ip packet ctr, for ids */
@@ -175,8 +177,7 @@
 extern int rsvp_on;
 extern struct	pr_usrreqs rip_usrreqs;
 
-int	 ip_ctloutput __P((int, struct socket *, int, int, struct mbuf **,
-			   struct proc *));
+int	 ip_ctloutput __P((struct socket *, struct sockopt *sopt));
 void	 ip_drain __P((void));
 void	 ip_freemoptions __P((struct ip_moptions *));
 void	 ip_init __P((void));
@@ -190,8 +191,7 @@
 struct mbuf *
 	 ip_srcroute __P((void));
 void	 ip_stripoptions __P((struct mbuf *, struct mbuf *));
-int	 rip_ctloutput __P((int, struct socket *, int, int, struct mbuf **,
-			    struct proc *p));
+int	 rip_ctloutput __P((struct socket *, struct sockopt *));
 void	 rip_ctlinput __P((int, struct sockaddr *, void *));
 void	 rip_init __P((void));
 void	 rip_input __P((struct mbuf *, int));
@@ -200,8 +200,8 @@
 void	rsvp_input __P((struct mbuf *, int));
 int	ip_rsvp_init __P((struct socket *));
 int	ip_rsvp_done __P((void));
-int	ip_rsvp_vif_init __P((struct socket *, struct mbuf *));
-int	ip_rsvp_vif_done __P((struct socket *, struct mbuf *));
+int	ip_rsvp_vif_init __P((struct socket *, struct sockopt *));
+int	ip_rsvp_vif_done __P((struct socket *, struct sockopt *));
 void	ip_rsvp_force_done __P((struct socket *));
 
 #ifdef IPDIVERT
Index: netinet/raw_ip.c
===================================================================
RCS file: /home/cvs/src/sys/netinet/raw_ip.c,v
retrieving revision 1.54
diff -u -r1.54 raw_ip.c
--- raw_ip.c	1998/05/15 20:11:34	1.54
+++ raw_ip.c	1998/08/11 18:46:41
@@ -225,101 +225,127 @@
  * Raw IP socket option processing.
  */
 int
-rip_ctloutput(op, so, level, optname, m, p)
-	int op;
+rip_ctloutput(so, sopt)
 	struct socket *so;
-	int level, optname;
-	struct mbuf **m;
-	struct proc *p;
+	struct sockopt *sopt;
 {
-	register struct inpcb *inp = sotoinpcb(so);
-	register int error;
+	struct	inpcb *inp = sotoinpcb(so);
+	int	error, optval;
 
-	if (level != IPPROTO_IP) {
-		if (op == PRCO_SETOPT && *m)
-			(void)m_free(*m);
+	if (sopt->sopt_level != IPPROTO_IP)
 		return (EINVAL);
-	}
 
-	switch (optname) {
+	error = 0;
 
-	case IP_HDRINCL:
-		error = 0;
-		if (op == PRCO_SETOPT) {
-			if (m == 0 || *m == 0 || (*m)->m_len < sizeof (int))
-				error = EINVAL;
-			else if (*mtod(*m, int *))
-				inp->inp_flags |= INP_HDRINCL;
-			else
-				inp->inp_flags &= ~INP_HDRINCL;
-			if (*m)
-				(void)m_free(*m);
-		} else {
-			*m = m_get(M_WAIT, MT_SOOPTS);
-			(*m)->m_len = sizeof (int);
-			*mtod(*m, int *) = inp->inp_flags & INP_HDRINCL;
-		}
-		return (error);
+	switch (sopt->sopt_dir) {
+	case SOPT_GET:
+		switch (sopt->sopt_name) {
+		case IP_HDRINCL:
+			optval = inp->inp_flags & INP_HDRINCL;
+			error = sooptcopyout(sopt, &optval, sizeof optval);
+			break;
 
 #ifdef COMPAT_IPFW
-	case IP_FW_GET:
-		if (ip_fw_ctl_ptr == NULL || op == PRCO_SETOPT) {
-			if (*m) (void)m_free(*m);
-			return(EINVAL);
-		}
-		return (*ip_fw_ctl_ptr)(optname, m); 
-
-	case IP_FW_ADD:
-	case IP_FW_DEL:
-	case IP_FW_FLUSH:
-	case IP_FW_ZERO:
-		if (ip_fw_ctl_ptr == NULL || op != PRCO_SETOPT) {
-			if (*m) (void)m_free(*m);
-			return(EINVAL);
-		}
-		return (*ip_fw_ctl_ptr)(optname, m); 
+		case IP_FW_GET:
+			if (ip_fw_ctl_ptr == 0)
+				error = ENOPROTOOPT;
+			else
+				error = ip_fw_ctl_ptr(sopt);
+			break;
 
-	case IP_NAT:
-		if (ip_nat_ctl_ptr == NULL) {
-			if (*m) (void)m_free(*m);
-			return(EINVAL);
+		case IP_NAT:
+			if (ip_nat_ctl_ptr == 0)
+				error = ENOPROTOOPT;
+			else
+				error = ip_nat_ctl_ptr(sopt);
+			break;
+#endif /* COMPAT_IPFW */
+
+		case MRT_INIT:
+		case MRT_DONE:
+		case MRT_ADD_VIF:
+		case MRT_DEL_VIF:
+		case MRT_ADD_MFC:
+		case MRT_DEL_MFC:
+		case MRT_VERSION:
+		case MRT_ASSERT:
+			error = ip_mrouter_get(so, sopt);
+			break;
+
+		default:
+			error = ip_ctloutput(so, sopt);
+			break;
 		}
-		return (*ip_nat_ctl_ptr)(op, m); 
-
-#endif
-	case IP_RSVP_ON:
-		return ip_rsvp_init(so);
 		break;
 
-	case IP_RSVP_OFF:
-		return ip_rsvp_done();
-		break;
-
-	case IP_RSVP_VIF_ON:
-		return ip_rsvp_vif_init(so, *m);
+	case SOPT_SET:
+		switch (sopt->sopt_name) {
+		case IP_HDRINCL:
+			error = sooptcopyin(sopt, &optval, sizeof optval,
+					    sizeof optval);
+			if (error)
+				break;
+			if (optval)
+				inp->inp_flags |= INP_HDRINCL;
+			else
+				inp->inp_flags &= ~INP_HDRINCL;
+			break;
 
-	case IP_RSVP_VIF_OFF:
-		return ip_rsvp_vif_done(so, *m);
+#ifdef COMPAT_IPFW
+		case IP_FW_ADD:
+		case IP_FW_DEL:
+		case IP_FW_FLUSH:
+		case IP_FW_ZERO:
+			if (ip_fw_ctl_ptr == 0)
+				error = ENOPROTOOPT;
+			else
+				error = ip_fw_ctl_ptr(sopt);
+			break;
 
-	case MRT_INIT:
-	case MRT_DONE:
-	case MRT_ADD_VIF:
-	case MRT_DEL_VIF:
-	case MRT_ADD_MFC:
-	case MRT_DEL_MFC:
-	case MRT_VERSION:
-	case MRT_ASSERT:
-		if (op == PRCO_SETOPT) {
-			error = ip_mrouter_set(optname, so, *m);
-			if (*m)
-				(void)m_free(*m);
-		} else if (op == PRCO_GETOPT) {
-			error = ip_mrouter_get(optname, so, m);
-		} else
-			error = EINVAL;
-		return (error);
+		case IP_NAT:
+			if (ip_nat_ctl_ptr == 0)
+				error = ENOPROTOOPT;
+			else
+				error = ip_nat_ctl_ptr(sopt);
+			break;
+#endif /* COMPAT_IPFW */
+
+		case IP_RSVP_ON:
+			error = ip_rsvp_init(so);
+			break;
+
+		case IP_RSVP_OFF:
+			error = ip_rsvp_done();
+			break;
+
+			/* XXX - should be combined */
+		case IP_RSVP_VIF_ON:
+			error = ip_rsvp_vif_init(so, sopt);
+			break;
+			
+		case IP_RSVP_VIF_OFF:
+			error = ip_rsvp_vif_done(so, sopt);
+			break;
+
+		case MRT_INIT:
+		case MRT_DONE:
+		case MRT_ADD_VIF:
+		case MRT_DEL_VIF:
+		case MRT_ADD_MFC:
+		case MRT_DEL_MFC:
+		case MRT_VERSION:
+		case MRT_ASSERT:
+			error = ip_mrouter_set(so, sopt);
+			break;
+
+		default:
+			error = ip_ctloutput(so, sopt);
+			break;
+		}
+		break;
 	}
-	return (ip_ctloutput(op, so, level, optname, m, p));
+
+	return (error);
 }
 
 /*
@@ -340,7 +366,7 @@
 	int err;
 	int flags;
 
-	switch(cmd) {
+	switch (cmd) {
 	case PRC_IFDOWN:
 		for (ia = in_ifaddrhead.tqh_first; ia;
 		     ia = ia->ia_link.tqe_next) {
Index: netinet/tcp_usrreq.c
===================================================================
RCS file: /home/cvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.37
diff -u -r1.37 tcp_usrreq.c
--- tcp_usrreq.c	1998/01/27 09:15:11	1.37
+++ tcp_usrreq.c	1998/08/11 18:46:41
@@ -560,104 +560,107 @@
 	return 0;
 }
 
+/*
+ * The new sockopt interface makes it possible for us to block in the
+ * copyin/out step (if we take a page fault).  Taking a page fault at
+ * splnet() is probably a Bad Thing.  (Since sockets and pcbs both now
+ * use TSM, there probably isn't any need for this function to run at
+ * splnet() any more.  This needs more examination.)
+ */
 int
-tcp_ctloutput(op, so, level, optname, mp, p)
-	int op;
+tcp_ctloutput(so, sopt)
 	struct socket *so;
-	int level, optname;
-	struct mbuf **mp;
-	struct proc *p;
+	struct sockopt *sopt;
 {
-	int error = 0, s;
-	struct inpcb *inp;
-	register struct tcpcb *tp;
-	register struct mbuf *m;
-	register int i;
+	int	error, opt, optval, s;
+	struct	inpcb *inp;
+	struct	tcpcb *tp;
+	struct	mbuf *m;
 
-	s = splnet();
+	error = 0;
+	s = splnet();		/* XXX */
 	inp = sotoinpcb(so);
 	if (inp == NULL) {
 		splx(s);
-		if (op == PRCO_SETOPT && *mp)
-			(void) m_free(*mp);
 		return (ECONNRESET);
 	}
-	if (level != IPPROTO_TCP) {
-		error = ip_ctloutput(op, so, level, optname, mp, p);
+	if (sopt->sopt_level != IPPROTO_TCP) {
+		error = ip_ctloutput(so, sopt);
 		splx(s);
 		return (error);
 	}
 	tp = intotcpcb(inp);
 
-	switch (op) {
-
-	case PRCO_SETOPT:
-		m = *mp;
-		switch (optname) {
-
+	switch (sopt->sopt_dir) {
+	case SOPT_SET:
+		switch (sopt->sopt_name) {
 		case TCP_NODELAY:
-			if (m == NULL || m->m_len < sizeof (int))
-				error = EINVAL;
-			else if (*mtod(m, int *))
-				tp->t_flags |= TF_NODELAY;
+		case TCP_NOOPT:
+		case TCP_NOPUSH:
+			error = sooptcopyin(sopt, &optval, sizeof optval,
+					    sizeof optval);
+			if (error)
+				break;
+
+			switch (sopt->sopt_name) {
+			case TCP_NODELAY:
+				opt = TF_NODELAY;
+				break;
+			case TCP_NOOPT:
+				opt = TF_NOOPT;
+				break;
+			case TCP_NOPUSH:
+				opt = TF_NOPUSH;
+				break;
+			default:
+				opt = 0; /* dead code to fool gcc */
+				break;
+			}
+
+			if (optval)
+				tp->t_flags |= opt;
 			else
-				tp->t_flags &= ~TF_NODELAY;
+				tp->t_flags &= ~opt;
 			break;
 
 		case TCP_MAXSEG:
-			if (m && (i = *mtod(m, int *)) > 0 && i <= tp->t_maxseg)
-				tp->t_maxseg = i;
-			else
-				error = EINVAL;
-			break;
+			error = sooptcopyin(sopt, &optval, sizeof optval,
+					    sizeof optval);
+			if (error)
+				break;
 
-		case TCP_NOOPT:
-			if (m == NULL || m->m_len < sizeof (int))
-				error = EINVAL;
-			else if (*mtod(m, int *))
-				tp->t_flags |= TF_NOOPT;
+			if (optval > 0 && optval <= tp->t_maxseg)
+				tp->t_maxseg = optval;
 			else
-				tp->t_flags &= ~TF_NOOPT;
-			break;
-
-		case TCP_NOPUSH:
-			if (m == NULL || m->m_len < sizeof (int))
 				error = EINVAL;
-			else if (*mtod(m, int *))
-				tp->t_flags |= TF_NOPUSH;
-			else
-				tp->t_flags &= ~TF_NOPUSH;
 			break;
 
 		default:
 			error = ENOPROTOOPT;
 			break;
 		}
-		if (m)
-			(void) m_free(m);
 		break;
 
-	case PRCO_GETOPT:
-		*mp = m = m_get(M_WAIT, MT_SOOPTS);
-		m->m_len = sizeof(int);
-
-		switch (optname) {
+	case SOPT_GET:
+		switch (sopt->sopt_name) {
 		case TCP_NODELAY:
-			*mtod(m, int *) = tp->t_flags & TF_NODELAY;
+			optval = tp->t_flags & TF_NODELAY;
 			break;
 		case TCP_MAXSEG:
-			*mtod(m, int *) = tp->t_maxseg;
+			optval = tp->t_maxseg;
 			break;
 		case TCP_NOOPT:
-			*mtod(m, int *) = tp->t_flags & TF_NOOPT;
+			optval = tp->t_flags & TF_NOOPT;
 			break;
 		case TCP_NOPUSH:
-			*mtod(m, int *) = tp->t_flags & TF_NOPUSH;
+			optval = tp->t_flags & TF_NOPUSH;
 			break;
 		default:
 			error = ENOPROTOOPT;
 			break;
 		}
+		if (error == 0)
+			error = sooptcopyout(sopt, &optval, sizeof optval);
 		break;
 	}
 	splx(s);
Index: netinet/tcp_var.h
===================================================================
RCS file: /home/cvs/src/sys/netinet/tcp_var.h,v
retrieving revision 1.46
diff -u -r1.46 tcp_var.h
--- tcp_var.h	1998/07/13 11:09:52	1.46
+++ tcp_var.h	1998/08/11 18:46:41
@@ -344,8 +344,7 @@
 struct tcpcb *
 	 tcp_close __P((struct tcpcb *));
 void	 tcp_ctlinput __P((int, struct sockaddr *, void *));
-int	 tcp_ctloutput __P((int, struct socket *, int, int, struct mbuf **,
-			    struct proc *));
+int	 tcp_ctloutput __P((struct socket *, struct sockopt *));
 struct tcpcb *
 	 tcp_drop __P((struct tcpcb *, int));
 void	 tcp_drain __P((void));
Index: netipx/ipx_ip.c
===================================================================
RCS file: /home/cvs/src/sys/netipx/ipx_ip.c,v
retrieving revision 1.21
diff -u -r1.21 ipx_ip.c
--- ipx_ip.c	1998/06/07 17:12:19	1.21
+++ ipx_ip.c	1998/08/11 18:46:42
@@ -316,17 +316,23 @@
 static struct ifreq ifr_ipxip = {"ipxip0"};
 
 int
-ipxip_route(so, m, p)
+ipxip_route(so, sopt)
 	struct socket *so;
-	register struct mbuf *m;
-	struct proc *p;
+	struct sockopt *sopt;
 {
-	register struct ipxip_req *rq = mtod(m, struct ipxip_req *);
-	struct sockaddr_ipx *ipx_dst = (struct sockaddr_ipx *)&rq->rq_ipx;
-	struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip;
-	struct route ro;
+	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:
@@ -387,14 +393,14 @@
 	ifr_ipxip.ifr_name[4] = '0' + ipxipif.if_unit - 1;
 	ifr_ipxip.ifr_dstaddr = *(struct sockaddr *)ipx_dst;
 	ipx_control(so, (int)SIOCSIFDSTADDR, (caddr_t)&ifr_ipxip,
-			(struct ifnet *)ifn, p);
+			(struct ifnet *)ifn, sopt->sopt_p);
 
 	/* 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, p));
+			(struct ifnet *)ifn, sopt->sopt_p));
 }
 
 static int
Index: netipx/ipx_ip.h
===================================================================
RCS file: /home/cvs/src/sys/netipx/ipx_ip.h,v
retrieving revision 1.11
diff -u -r1.11 ipx_ip.h
--- ipx_ip.h	1997/06/26 19:35:50	1.11
+++ ipx_ip.h	1998/08/11 18:46:42
@@ -53,7 +53,7 @@
 
 void	ipxip_ctlinput __P((int cmd, struct sockaddr *sa, void *arg));
 void	ipxip_input __P((struct mbuf *m, int hlen));
-int	ipxip_route __P((struct socket *so, struct mbuf *m, struct proc *p));
+int	ipxip_route __P((struct socket *so, struct sockopt *sopt));
 
 #endif /* KERNEL */
 
Index: netipx/ipx_usrreq.c
===================================================================
RCS file: /home/cvs/src/sys/netipx/ipx_usrreq.c,v
retrieving revision 1.19
diff -u -r1.19 ipx_usrreq.c
--- ipx_usrreq.c	1998/02/09 06:10:25	1.19
+++ ipx_usrreq.c	1998/08/11 18:46:42
@@ -310,30 +310,23 @@
 }
 
 int
-ipx_ctloutput(req, so, level, name, value, p)
-	int req, level;
+ipx_ctloutput(so, sopt)
 	struct socket *so;
-	int name;
-	struct mbuf **value;
-	struct proc *p;
+	struct sockopt *sopt;
 {
 	register struct mbuf *m;
 	struct ipxpcb *ipxp = sotoipxpcb(so);
-	int mask, error = 0;
+	int mask, error, optval;
+	short soptval;
+	struct ipx ioptval;
 
+	error = 0;
 	if (ipxp == NULL)
 		return (EINVAL);
 
-	switch (req) {
-
-	case PRCO_GETOPT:
-		if (value == NULL)
-			return (EINVAL);
-		m = m_get(M_DONTWAIT, MT_DATA);
-		if (m == NULL)
-			return (ENOBUFS);
-		switch (name) {
-
+	switch (sopt->sopt_dir) {
+	case SOPT_GET:
+		switch (sopt->sopt_name) {
 		case SO_ALL_PACKETS:
 			mask = IPXP_ALL_PACKETS;
 			goto get_flags;
@@ -345,38 +338,33 @@
 		case SO_HEADERS_ON_OUTPUT:
 			mask = IPXP_RAWOUT;
 		get_flags:
-			m->m_len = sizeof(short);
-			*mtod(m, short *) = ipxp->ipxp_flags & mask;
+			soptval = ipxp->ipxp_flags & mask;
+			error = sooptcopyout(sopt, &soptval, sizeof soptval);
 			break;
 
 		case SO_DEFAULT_HEADERS:
-			m->m_len = sizeof(struct ipx);
-			{
-				register struct ipx *ipx = mtod(m, struct ipx *);
-				ipx->ipx_len = 0;
-				ipx->ipx_sum = 0;
-				ipx->ipx_tc = 0;
-				ipx->ipx_pt = ipxp->ipxp_dpt;
-				ipx->ipx_dna = ipxp->ipxp_faddr;
-				ipx->ipx_sna = ipxp->ipxp_laddr;
-			}
+			ioptval.ipx_len = 0;
+			ioptval.ipx_sum = 0;
+			ioptval.ipx_tc = 0;
+			ioptval.ipx_pt = ipxp->ipxp_dpt;
+			ioptval.ipx_dna = ipxp->ipxp_faddr;
+			ioptval.ipx_sna = ipxp->ipxp_laddr;
+			error = sooptcopyout(sopt, &soptval, sizeof soptval);
 			break;
 
 		case SO_SEQNO:
-			m->m_len = sizeof(long);
-			*mtod(m, long *) = ipx_pexseq++;
+			error = sooptcopyout(sopt, &ipx_pexseq, 
+					     sizeof ipx_pexseq);
+			ipx_pexseq++;
 			break;
 
 		default:
 			error = EINVAL;
 		}
-		*value = m;
 		break;
 
-	case PRCO_SETOPT:
-		switch (name) {
-			int *ok;
-
+	case SOPT_SET:
+		switch (sopt->sopt_name) {
 		case SO_ALL_PACKETS:
 			mask = IPXP_ALL_PACKETS;
 			goto set_head;
@@ -388,39 +376,38 @@
 		case SO_HEADERS_ON_OUTPUT:
 			mask = IPXP_RAWOUT;
 		set_head:
-			if (value && *value) {
-				ok = mtod(*value, int *);
-				if (*ok)
-					ipxp->ipxp_flags |= mask;
-				else
-					ipxp->ipxp_flags &= ~mask;
-			} else error = EINVAL;
+			error = sooptcopyin(sopt, &optval, sizeof optval,
+					    sizeof optval);
+			if (error)
+				break;
+			if (optval)
+				ipxp->ipxp_flags |= mask;
+			else
+				ipxp->ipxp_flags &= ~mask;
 			break;
 
 		case SO_DEFAULT_HEADERS:
-			{
-				register struct ipx *ipx
-				    = mtod(*value, struct ipx *);
-				ipxp->ipxp_dpt = ipx->ipx_pt;
-			}
+			error = sooptcopyin(sopt, &ioptval, sizeof ioptval,
+					    sizeof ioptval);
+			if (error)
+				break;
+			ipxp->ipxp_dpt = ioptval.ipx_pt;
 			break;
 #ifdef IPXIP
 		case SO_IPXIP_ROUTE:
-			error = ipxip_route(so, *value, p);
+			error = ipxip_route(so, sopt);
 			break;
 #endif /* IPXIP */
 #ifdef IPTUNNEL
 #if 0
 		case SO_IPXTUNNEL_ROUTE:
-			error = ipxtun_route(so, *value, p);
+			error = ipxtun_route(so, sopt);
 			break;
 #endif
 #endif
 		default:
 			error = EINVAL;
 		}
-		if (value && *value)
-			m_freem(*value);
 		break;
 	}
 	return (error);
Index: netipx/ipx_var.h
===================================================================
RCS file: /home/cvs/src/sys/netipx/ipx_var.h,v
retrieving revision 1.10
diff -u -r1.10 ipx_var.h
--- ipx_var.h	1998/06/07 17:12:20	1.10
+++ ipx_var.h	1998/08/11 18:46:42
@@ -79,14 +79,14 @@
 struct route;
 struct sockaddr;
 struct socket;
+struct sockopt;
 
 void	ipx_abort __P((struct ipxpcb *ipxp));
 u_short	ipx_cksum __P((struct mbuf *m, int len));
 int	ipx_control __P((struct socket *so, u_long cmd, caddr_t data,
 			 struct ifnet *ifp, struct proc *p));
 void	ipx_ctlinput __P((int cmd, struct sockaddr *arg_as_sa, void *dummy));
-int	ipx_ctloutput __P((int req, struct socket *so, int level, int name,
-			   struct mbuf **value, struct proc *p));
+int	ipx_ctloutput __P((struct socket *so, struct sockopt *sopt));
 void	ipx_drop __P((struct ipxpcb *ipxp, int errno));
 void	ipx_init __P((void));
 void	ipx_input __P((struct mbuf *m, struct ipxpcb *ipxp));
Index: netipx/spx.h
===================================================================
RCS file: /home/cvs/src/sys/netipx/spx.h,v
retrieving revision 1.13
diff -u -r1.13 spx.h
--- spx.h	1997/06/26 19:36:00	1.13
+++ spx.h	1998/08/11 18:46:42
@@ -173,8 +173,7 @@
 extern struct pr_usrreqs spx_usrreq_sps;
 
 void	spx_ctlinput __P((int cmd, struct sockaddr *arg_as_sa, void *dummy));
-int	spx_ctloutput __P((int req, struct socket *so, int level, int name,
-			   struct mbuf **value, struct proc *p));
+int	spx_ctloutput __P((struct socket *so, struct sockopt *sopt));
 void	spx_fasttimo __P((void));
 void	spx_init __P((void));
 void	spx_input __P((struct mbuf *m, struct ipxpcb *ipxp));
Index: netipx/spx_usrreq.c
===================================================================
RCS file: /home/cvs/src/sys/netipx/spx_usrreq.c,v
retrieving revision 1.19
diff -u -r1.19 spx_usrreq.c
--- spx_usrreq.c	1998/05/01 18:30:02	1.19
+++ spx_usrreq.c	1998/08/11 18:46:42
@@ -1154,39 +1154,33 @@
 }
 
 int
-spx_ctloutput(req, so, level, name, value, p)
-	int req;
+spx_ctloutput(so, sopt)
 	struct socket *so;
-	int level, name;
-	struct mbuf **value;
-	struct proc *p;
+	struct sockopt *sopt;
 {
 	register struct mbuf *m;
 	struct ipxpcb *ipxp = sotoipxpcb(so);
 	register struct spxpcb *cb;
-	int mask, error = 0;
+	int mask, error;
+	short soptval;
+	u_short usoptval;
+	int optval;
 
-	if (level != IPXPROTO_SPX) {
+	error = 0;
+
+	if (sopt->sopt_level != IPXPROTO_SPX) {
 		/* This will have to be changed when we do more general
 		   stacking of protocols */
-		return (ipx_ctloutput(req, so, level, name, value, p));
+		return (ipx_ctloutput(so, sopt));
 	}
-	if (ipxp == NULL) {
-		error = EINVAL;
-		goto release;
-	} else
+	if (ipxp == NULL)
+		return (EINVAL);
+	else
 		cb = ipxtospxpcb(ipxp);
 
-	switch (req) {
-
-	case PRCO_GETOPT:
-		if (value == NULL)
-			return (EINVAL);
-		m = m_get(M_DONTWAIT, MT_DATA);
-		if (m == NULL)
-			return (ENOBUFS);
-		switch (name) {
-
+	switch (sopt->sopt_dir) {
+	case SOPT_GET:
+		switch (sopt->sopt_name) {
 		case SO_HEADERS_ON_INPUT:
 			mask = SF_HI;
 			goto get_flags;
@@ -1194,39 +1188,34 @@
 		case SO_HEADERS_ON_OUTPUT:
 			mask = SF_HO;
 		get_flags:
-			m->m_len = sizeof(short);
-			*mtod(m, short *) = cb->s_flags & mask;
+			soptval = cb->s_flags & mask;
+			error = sooptcopyout(sopt, &soptval, sizeof soptval);
 			break;
 
 		case SO_MTU:
-			m->m_len = sizeof(u_short);
-			*mtod(m, short *) = cb->s_mtu;
+			usoptval = cb->s_mtu;
+			error = sooptcopyout(sopt, &usoptval, sizeof usoptval);
 			break;
 
 		case SO_LAST_HEADER:
-			m->m_len = sizeof(struct spxhdr);
-			*mtod(m, struct spxhdr *) = cb->s_rhdr;
+			error = sooptcopyout(sopt, &cb->s_rhdr, 
+					     sizeof cb->s_rhdr);
 			break;
 
 		case SO_DEFAULT_HEADERS:
-			m->m_len = sizeof(struct spx);
-			*mtod(m, struct spxhdr *) = cb->s_shdr;
+			error = sooptcopyout(sopt, &cb->s_shdr, 
+					     sizeof cb->s_shdr);
 			break;
 
 		default:
-			error = EINVAL;
+			error = ENOPROTOOPT;
 		}
-		*value = m;
 		break;
 
-	case PRCO_SETOPT:
-		if (value == 0 || *value == 0) {
-			error = EINVAL;
-			break;
-		}
-		switch (name) {
-			int *ok;
-
+	case SOPT_SET:
+		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;
@@ -1234,9 +1223,13 @@
 		case SO_HEADERS_ON_OUTPUT:
 			mask = SF_HO;
 		set_head:
+			error = sooptcopyin(sopt, &optval, sizeof optval,
+					    sizeof optval);
+			if (error)
+				break;
+
 			if (cb->s_flags & SF_PI) {
-				ok = mtod(*value, int *);
-				if (*ok)
+				if (optval)
 					cb->s_flags |= mask;
 				else
 					cb->s_flags &= ~mask;
@@ -1244,13 +1237,20 @@
 			break;
 
 		case SO_MTU:
-			cb->s_mtu = *(mtod(*value, u_short *));
+			error = sooptcopyin(sopt, &usoptval, sizeof usoptval,
+					    sizeof usoptval);
+			if (error)
+				break;
+			cb->s_mtu = usoptval;
 			break;
 
 #ifdef SF_NEWCALL
 		case SO_NEWCALL:
-			ok = mtod(*value, int *);
-			if (*ok) {
+			error = sooptcopyin(sopt, &optval, sizeof optval,
+					    sizeof optval);
+			if (error)
+				break;
+			if (optval) {
 				cb->s_flags2 |= SF_NEWCALL;
 				spx_newchecks[5]++;
 			} else {
@@ -1262,21 +1262,23 @@
 
 		case SO_DEFAULT_HEADERS:
 			{
-				register struct spxhdr *sp
-						= mtod(*value, struct spxhdr *);
-				cb->s_dt = sp->spx_dt;
-				cb->s_cc = sp->spx_cc & SPX_EM;
+				struct spxhdr sp;
+
+				error = sooptcopyin(sopt, &sp, sizeof sp,
+						    sizeof sp);
+				if (error)
+					break;
+				cb->s_dt = sp.spx_dt;
+				cb->s_cc = sp.spx_cc & SPX_EM;
 			}
 			break;
 
 		default:
-			error = EINVAL;
+			error = ENOPROTOOPT;
 		}
-		m_freem(*value);
 		break;
 	}
-	release:
-		return (error);
+	return (error);
 }
 
 static int
Index: nfs/bootp_subr.c
===================================================================
RCS file: /home/cvs/src/sys/nfs/bootp_subr.c,v
retrieving revision 1.13
diff -u -r1.13 bootp_subr.c
--- bootp_subr.c	1998/03/30 09:53:38	1.13
+++ bootp_subr.c	1998/08/11 18:46:43
@@ -264,8 +264,10 @@
 	struct sockaddr_in *sin, sa;
 	struct mbuf *m;
 	struct uio auio;
+	struct sockopt sopt;
 	struct iovec aio;
-	int error, rcvflg, timo, secs, len;
+	struct timeval tv;
+	int error, on, len, rcvflg, secs, timo;
 	u_int tport;
 
 	/*
@@ -274,36 +276,26 @@
 	if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)))
 		goto out;
 
-	m = m_get(M_WAIT, MT_SOOPTS);
-	if (m == NULL) {
-		error = ENOBUFS;
+	tv.tv_sec = 1;
+	tv.tv_usec = 0;
+	bzero(&sopt, sizeof sopt);
+	sopt.sopt_level = SOL_SOCKET;
+	sopt.sopt_name = SO_RCVTIMEO;
+	sopt.sopt_val = &tv;
+	sopt.sopt_valsize = sizeof tv;
+
+	if (error = sosetopt(so, &sopt))
 		goto out;
-	} else {
-		struct timeval *tv;
-		tv = mtod(m, struct timeval *);
-		m->m_len = sizeof(*tv);
-		tv->tv_sec = 1;
-		tv->tv_usec = 0;
-		if ((error = sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m, procp)))
-			goto out;
-	}
 
 	/*
 	 * Enable broadcast.
 	 */
-	{
-		int *on;
-		m = m_get(M_WAIT, MT_SOOPTS);
-		if (m == NULL) {
-			error = ENOBUFS;
-			goto out;
-		}
-		on = mtod(m, int *);
-		m->m_len = sizeof(*on);
-		*on = 1;
-		if ((error = sosetopt(so, SOL_SOCKET, SO_BROADCAST, m, procp)))
-			goto out;
-	}
+	on = 1;
+	sopt.sopt_val = &on;
+	sopt.sopt_valsize = sizeof on;
+	sopt.sopt_name = SO_BROADCAST;
+	if (error = sosetopt(so, &sopt))
+		goto out;
 
 	/*
 	 * Bind the local endpoint to a bootp client port.
Index: nfs/krpc_subr.c
===================================================================
RCS file: /home/cvs/src/sys/nfs/krpc_subr.c,v
retrieving revision 1.9
diff -u -r1.9 krpc_subr.c
--- krpc_subr.c	1998/03/28 10:33:15	1.9
+++ krpc_subr.c	1998/08/11 18:46:43
@@ -198,6 +198,8 @@
 	struct mbuf *m, *nam, *mhead;
 	struct rpc_call *call;
 	struct rpc_reply *reply;
+	struct sockopt sopt;
+	struct timeval tv;
 	struct uio auio;
 	int error, rcvflg, timo, secs, len;
 	static u_int32_t xid = ~0xFF;
@@ -220,34 +222,26 @@
 	if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0, procp)))
 		goto out;
 
-	m = m_get(M_WAIT, MT_SOOPTS);
-	if (m == NULL) {
-		error = ENOBUFS;
+	tv.tv_sec = 1;
+	tv.tv_usec = 0;
+	bzero(&sopt, sizeof sopt);
+	sopt.sopt_level = SOL_SOCKET;
+	sopt.sopt_name = SO_RCVTIMEO;
+	sopt.sopt_val = &tv;
+	sopt.sopt_valsize = sizeof tv;
+
+	if (error = sosetopt(so, &sopt))
 		goto out;
-	} else {
-		struct timeval *tv;
-		tv = mtod(m, struct timeval *);
-		m->m_len = sizeof(*tv);
-		tv->tv_sec = 1;
-		tv->tv_usec = 0;
-		if ((error = sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m, procp)))
-			goto out;
-	}
 
 	/*
 	 * Enable broadcast if necessary.
 	 */
 	if (from_p) {
-		int32_t *on;
-		m = m_get(M_WAIT, MT_SOOPTS);
-		if (m == NULL) {
-			error = ENOBUFS;
-			goto out;
-		}
-		on = mtod(m, int32_t *);
-		m->m_len = sizeof(*on);
-		*on = 1;
-		if ((error = sosetopt(so, SOL_SOCKET, SO_BROADCAST, m, procp)))
+		int on = 1;
+		sopt.sopt_name = SO_BROADCAST;
+		sopt.sopt_val = &on;
+		sopt.sopt_valsize = sizeof on;
+		if (error = sosetopt(so, &sopt))
 			goto out;
 	}
 
Index: nfs/nfs.h
===================================================================
RCS file: /home/cvs/src/sys/nfs/nfs.h,v
retrieving revision 1.42
diff -u -r1.42 nfs.h
--- nfs.h	1998/06/30 11:19:22	1.42
+++ nfs.h	1998/08/11 18:46:43
@@ -722,7 +722,7 @@
 			   struct proc *procp, struct mbuf **mrq));
 int	nfsrv_write __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
 			 struct proc *procp, struct mbuf **mrq));
-void	nfsrv_rcv __P((struct socket *so, caddr_t arg, int waitflag));
+void	nfsrv_rcv __P((struct socket *so, void *arg, int waitflag));
 void	nfsrv_slpderef __P((struct nfssvc_sock *slp));
 #endif	/* KERNEL */
 
Index: nfs/nfs_socket.c
===================================================================
RCS file: /home/cvs/src/sys/nfs/nfs_socket.c,v
retrieving revision 1.43
diff -u -r1.43 nfs_socket.c
--- nfs_socket.c	1998/08/01 09:04:02	1.43
+++ nfs_socket.c	1998/08/11 18:46:43
@@ -282,16 +282,28 @@
 		if (nmp->nm_sotype != SOCK_STREAM)
 			panic("nfscon sotype");
 		if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
-			MGET(m, M_WAIT, MT_SOOPTS);
-			*mtod(m, int32_t *) = 1;
-			m->m_len = sizeof(int32_t);
-			sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m, p);
+			struct sockopt sopt;
+			int val;
+
+			bzero(&sopt, sizeof sopt);
+			sopt.sopt_level = SOL_SOCKET;
+			sopt.sopt_name = SO_KEEPALIVE;
+			sopt.sopt_val = &val;
+			sopt.sopt_valsize = sizeof val;
+			val = 1;
+			sosetopt(so, &sopt);
 		}
 		if (so->so_proto->pr_protocol == IPPROTO_TCP) {
-			MGET(m, M_WAIT, MT_SOOPTS);
-			*mtod(m, int32_t *) = 1;
-			m->m_len = sizeof(int32_t);
-			sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m, p);
+			struct sockopt sopt;
+			int val;
+
+			bzero(&sopt, sizeof sopt);
+			sopt.sopt_level = IPPROTO_TCP;
+			sopt.sopt_name = TCP_NODELAY;
+			sopt.sopt_val = &val;
+			sopt.sopt_valsize = sizeof val;
+			val = 1;
+			sosetopt(so, &sopt);
 		}
 		sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR +
 		    sizeof (u_int32_t)) * 2;
@@ -1952,7 +1964,7 @@
 void
 nfsrv_rcv(so, arg, waitflag)
 	struct socket *so;
-	caddr_t arg;
+	void *arg;
 	int waitflag;
 {
 	register struct nfssvc_sock *slp = (struct nfssvc_sock *)arg;
Index: nfs/nfs_syscalls.c
===================================================================
RCS file: /home/cvs/src/sys/nfs/nfs_syscalls.c,v
retrieving revision 1.41
diff -u -r1.41 nfs_syscalls.c
--- nfs_syscalls.c	1998/05/31 20:08:55	1.41
+++ nfs_syscalls.c	1998/08/11 18:46:44
@@ -400,17 +400,29 @@
 	 * repeatedly for the same socket, but that isn't harmful.
 	 */
 	if (so->so_type == SOCK_STREAM) {
-		MGET(m, M_WAIT, MT_SOOPTS);
-		*mtod(m, int32_t *) = 1;
-		m->m_len = sizeof(int32_t);
-		sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m, p);
+		struct sockopt sopt;
+		int val;
+
+		bzero(&sopt, sizeof sopt);
+		sopt.sopt_level = SOL_SOCKET;
+		sopt.sopt_name = SO_KEEPALIVE;
+		sopt.sopt_val = &val;
+		sopt.sopt_valsize = sizeof val;
+		val = 1;
+		sosetopt(so, &sopt);
 	}
 	if (so->so_proto->pr_domain->dom_family == AF_INET &&
 	    so->so_proto->pr_protocol == IPPROTO_TCP) {
-		MGET(m, M_WAIT, MT_SOOPTS);
-		*mtod(m, int32_t *) = 1;
-		m->m_len = sizeof(int32_t);
-		sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m, p);
+		struct sockopt sopt;
+		int val;
+
+		bzero(&sopt, sizeof sopt);
+		sopt.sopt_level = IPPROTO_TCP;
+		sopt.sopt_name = TCP_NODELAY;
+		sopt.sopt_val = &val;
+		sopt.sopt_valsize = sizeof val;
+		val = 1;
+		sosetopt(so, &sopt);
 	}
 	so->so_rcv.sb_flags &= ~SB_NOINTR;
 	so->so_rcv.sb_timeo = 0;
Index: sys/mbuf.h
===================================================================
RCS file: /home/cvs/src/sys/sys/mbuf.h,v
retrieving revision 1.27
diff -u -r1.27 mbuf.h
--- mbuf.h	1998/07/15 04:17:53	1.27
+++ mbuf.h	1998/08/11 18:46:48
@@ -138,7 +138,7 @@
 /*efine	MT_HTABLE	6*/	/* IMP host tables */
 /*efine	MT_ATABLE	7*/	/* address resolution tables */
 #define	MT_SONAME	8	/* socket name */
-#define	MT_SOOPTS	10	/* socket options */
+/*efine	MT_SOOPTS	10*/	/* socket options */
 #define	MT_FTABLE	11	/* fragment reassembly header */
 /*efine	MT_RIGHTS	12*/	/* access rights */
 /*efine	MT_IFADDR	13*/	/* interface address */
@@ -168,10 +168,10 @@
  * drivers.
  */
 #define	MBUFLOCK(code) \
-	{ int ms = splimp(); \
+	do { int ms = splimp(); \
 	  { code } \
 	  splx(ms); \
-	}
+	} while(0)
 
 /*
  * mbuf allocation/deallocation macros:
@@ -348,10 +348,10 @@
 }
 
 /* change mbuf to new type */
-#define MCHTYPE(m, t) { \
-	MBUFLOCK(mbstat.m_mtypes[(m)->m_type]--; mbstat.m_mtypes[t]++;) \
+#define MCHTYPE(m, t) do { \
+	MBUFLOCK(mbstat.m_mtypes[(m)->m_type]--; mbstat.m_mtypes[t]++;); \
 	(m)->m_type = t;\
-}
+} while(0)
 
 /* length to m_copy to copy all */
 #define	M_COPYALL	1000000000
Index: sys/protosw.h
===================================================================
RCS file: /home/cvs/src/sys/sys/protosw.h,v
retrieving revision 1.24
diff -u -r1.24 protosw.h
--- protosw.h	1998/06/07 17:13:03	1.24
+++ protosw.h	1998/08/11 18:46:48
@@ -42,6 +42,7 @@
 struct proc;
 struct sockaddr;
 struct socket;
+struct sockopt;
 
 /*#ifdef KERNEL*/
 /*
@@ -58,13 +59,13 @@
  *
  * Protocols pass data between themselves as chains of mbufs using
  * the pr_input and pr_output hooks.  Pr_input passes data up (towards
- * UNIX) and pr_output passes it down (towards the imps); control
+ * the users) and pr_output passes it down (towards the interfaces); control
  * information passes up and down on pr_ctlinput and pr_ctloutput.
  * The protocol is responsible for the space occupied by any the
  * arguments to these entries and must dispose it.
  *
- * The userreq routine interfaces protocols to the system and is
- * described below.
+ * In retrospect, it would be a lot nicer to use an interface
+ * similar to the vnode VOP interface.
  */
 struct protosw {
 	short	pr_type;		/* socket type used for */
@@ -78,8 +79,7 @@
 					/* output to protocol (from above) */
 	void	(*pr_ctlinput)__P((int, struct sockaddr *, void *));
 					/* control input (from below) */
-	int	(*pr_ctloutput)__P((int, struct socket *, int, int,
-				    struct mbuf **, struct proc *));
+	int	(*pr_ctloutput)__P((struct socket *, struct sockopt *));
 					/* control output (from above) */
 /* user-protocol hook */
 	void	*pr_ousrreq;
Index: sys/socketvar.h
===================================================================
RCS file: /home/cvs/src/sys/sys/socketvar.h,v
retrieving revision 1.28
diff -u -r1.28 socketvar.h
--- socketvar.h	1998/06/07 17:13:03	1.28
+++ socketvar.h	1998/08/11 18:46:48
@@ -102,9 +102,10 @@
 #define	SB_UPCALL	0x20		/* someone wants an upcall */
 #define	SB_NOINTR	0x40		/* operations not interruptible */
 
-	void	(*so_upcall) __P((struct socket *so, caddr_t arg, int waitf));
-	caddr_t	so_upcallarg;		/* Arg for above */
+	void	(*so_upcall) __P((struct socket *, void *, int));
+	void	*so_upcallarg;
 	uid_t	so_uid;			/* who opened the socket */
+	/* NB: generation count must not be first; easiest to make it last. */
 	so_gen_t so_gencnt;		/* generation count */
 };
 
@@ -119,7 +120,6 @@
 #define	SS_CANTRCVMORE		0x0020	/* can't receive more data from peer */
 #define	SS_RCVATMARK		0x0040	/* at mark on input */
 
-/*efine	SS_PRIV			0x0080	   privileged for broadcast, raw... */
 #define	SS_NBIO			0x0100	/* non-blocking ops */
 #define	SS_ASYNC		0x0200	/* async i/o notify */
 #define	SS_ISCONFIRMING		0x0400	/* deciding to accept connection req */
@@ -242,6 +242,20 @@
 
 #ifdef KERNEL
 
+/*
+ * Argument structure for sosetopt et seq.  This is in the KERNEL
+ * section because it will never be visible to user code.
+ */
+enum sopt_dir { SOPT_GET, SOPT_SET };
+struct sockopt {
+	enum	sopt_dir sopt_dir; /* is this a get or a set? */
+	int	sopt_level;	/* second arg of [gs]etsockopt */
+	int	sopt_name;	/* third arg of [gs]etsockopt */
+	void   *sopt_val;	/* fourth arg of [gs]etsockopt */
+	size_t	sopt_valsize;	/* (almost) fifth arg of [gs]etsockopt */
+	struct	proc *sopt_p;	/* calling process or null if kernel */
+};
+
 #ifdef MALLOC_DECLARE
 MALLOC_DECLARE(M_PCB);
 MALLOC_DECLARE(M_SONAME);
@@ -309,8 +323,7 @@
 void	sodealloc __P((struct socket *so));
 int	sodisconnect __P((struct socket *so));
 void	sofree __P((struct socket *so));
-int	sogetopt __P((struct socket *so, int level, int optname,
-	    struct mbuf **mp, struct proc *p));
+int	sogetopt __P((struct socket *so, struct sockopt *sopt));
 void	sohasoutofband __P((struct socket *so));
 void	soisconnected __P((struct socket *so));
 void	soisconnecting __P((struct socket *so));
@@ -321,6 +334,9 @@
 	sodropablereq __P((struct socket *head));
 struct socket *
 	sonewconn __P((struct socket *head, int connstatus));
+int	sooptcopyin __P((struct sockopt *sopt, void *buf, size_t len,
+			 size_t minlen));
+int	sooptcopyout __P((struct sockopt *sopt, void *buf, size_t len));
 int	sopoll __P((struct socket *so, int events, struct ucred *cred,
 		    struct proc *p));
 int	soreceive __P((struct socket *so, struct sockaddr **paddr,
@@ -331,8 +347,7 @@
 int	sosend __P((struct socket *so, struct sockaddr *addr, struct uio *uio,
 		    struct mbuf *top, struct mbuf *control, int flags,
 		    struct proc *p));
-int	sosetopt __P((struct socket *so, int level, int optname,
-	    struct mbuf *m0, struct proc *p));
+int	sosetopt __P((struct socket *so, struct sockopt *sopt));
 int	soshutdown __P((struct socket *so, int how));
 void	sotoxsocket __P((struct socket *so, struct xsocket *xso));
 void	sowakeup __P((struct socket *so, struct sockbuf *sb));

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199808111914.PAA15085>