From owner-freebsd-net Tue Aug 11 12:15:08 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id MAA19485 for freebsd-net-outgoing; Tue, 11 Aug 1998 12:15:08 -0700 (PDT) (envelope-from owner-freebsd-net@FreeBSD.ORG) Received: from khavrinen.lcs.mit.edu (khavrinen.lcs.mit.edu [18.24.4.193]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id MAA19454 for ; Tue, 11 Aug 1998 12:14:41 -0700 (PDT) (envelope-from wollman@khavrinen.lcs.mit.edu) Received: (from wollman@localhost) by khavrinen.lcs.mit.edu (8.8.8/8.8.8) id PAA15085; Tue, 11 Aug 1998 15:14:10 -0400 (EDT) (envelope-from wollman) Date: Tue, 11 Aug 1998 15:14:10 -0400 (EDT) From: Garrett Wollman Message-Id: <199808111914.PAA15085@khavrinen.lcs.mit.edu> To: net@FreeBSD.ORG Subject: socket option patch, mk. II Sender: owner-freebsd-net@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org 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 #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 #include #include +#include #include #include #include @@ -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 + /* 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 +#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