Index: compat/linux/common/linux_socket.c =================================================================== RCS file: /usr/cvs/src/sys/compat/linux/common/linux_socket.c,v retrieving revision 1.85 diff -u -p -r1.85 linux_socket.c --- compat/linux/common/linux_socket.c 20 Dec 2007 23:02:56 -0000 1.85 +++ compat/linux/common/linux_socket.c 21 Dec 2007 00:03:29 -0000 @@ -323,15 +323,12 @@ linux_sys_socket(struct lwp *l, const st struct file *fp; if (getsock(p->p_fd, *retval, &fp) == 0) { - struct mbuf *m; - - m = m_get(M_WAIT, MT_SOOPTS); - m->m_len = sizeof(int); - *mtod(m, int *) = 0; + int val; /* ignore error */ - (void) sosetopt((struct socket *)fp->f_data, - IPPROTO_IPV6, IPV6_V6ONLY, m); + val = 0; + (void)so_setsockopt(l, (struct socket *)fp->f_data, + IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val)); FILE_UNUSE(fp, l); } Index: kern/uipc_socket.c =================================================================== RCS file: /usr/cvs/src/sys/kern/uipc_socket.c,v retrieving revision 1.150 diff -u -p -r1.150 uipc_socket.c --- kern/uipc_socket.c 16 Dec 2007 21:25:59 -0000 1.150 +++ kern/uipc_socket.c 29 Dec 2007 12:49:07 -0000 @@ -1457,20 +1457,187 @@ sorflush(struct socket *so) sbrelease(&asb, so); } +void +sockopt_destroy(struct sockopt *sopt) +{ + if (sopt->sopt_m != NULL) { + m_freem(sopt->sopt_m); + sopt->sopt_m = NULL; + sopt->sopt_un = NULL; + } else if (sopt->sopt_un != NULL) { + free(sopt->sopt_un, M_SOOPTS); + sopt->sopt_un = NULL; + } +} + +static int +sockopt_ensure_writable(struct sockopt *sopt, size_t len) +{ +#if 0 + /* check role */ + if (sopt->sopt_dir != SOPT_SET) { + return ENOMEM; + } +#endif + + /* do not overwrite shared storage */ + if (sopt->sopt_m != NULL) { + m_freem(sopt->sopt_m); + sopt->sopt_m = NULL; + sopt->sopt_un = NULL; + } + + if (sopt->sopt_un != NULL && sopt->sopt_size >= len) + return 0; + + if (sopt->sopt_un != NULL) + free(sopt->sopt_un, M_SOOPTS); + + sopt->sopt_un = malloc(len, M_SOOPTS, + sopt->sopt_waitok ? M_WAITOK : M_NOWAIT); + + if (sopt->sopt_un == NULL) + return ENOMEM; + + sopt->sopt_size = len; + + return 0; +} + +int +sockopt_set(struct sockopt *sopt, const void *buf, size_t len) +{ + int rc; + + if ((rc = sockopt_ensure_writable(sopt, len)) != 0) + return rc; + + KASSERT(sopt->sopt_size >= len); + + memcpy(sopt->sopt_un, buf, len); + sopt->sopt_size = len; + + return 0; +} + +int +sockopt_setint(struct sockopt *sopt, int val) +{ + const int len = sizeof(int); + int rc; + + if ((rc = sockopt_ensure_writable(sopt, len)) != 0) + return rc; + + sopt->sopt_un->un_int = val; + sopt->sopt_size = len; + + return 0; +} + +void * +sockopt_get(const struct sockopt *sopt, size_t len) +{ + if (sopt->sopt_un == NULL || sopt->sopt_size != len) + return NULL; + + return (void *)sopt->sopt_un; +} + +int * +sockopt_getintptr(const struct sockopt *sopt) +{ + if (sopt->sopt_un == NULL || sopt->sopt_size != sizeof(int)) + return NULL; + + return &sopt->sopt_un->un_int; +} + +struct mbuf * +sockopt_getmbuf(const struct sockopt *sopt) +{ + struct mbuf *m; + struct sockopt *p; + int waitok; + +#if 0 + /* check role */ + if (sopt->sopt_dir != SOPT_SET) { + return NULL; +#endif + + waitok = sopt->sopt_waitok ? M_WAIT : M_DONTWAIT; + + if (sopt->sopt_m != NULL) + goto out; + + m = m_get(waitok, MT_SOOPTS); + + if (m == NULL) + return NULL; + + MEXTADD(m, sopt->sopt_un, sopt->sopt_size, M_SOOPTS, NULL, NULL); + + if ((m->m_flags & M_EXT) == 0) { + m_freem(m); + return NULL; + } + + p = __UNCONST(sopt); + p->sopt_m = m; + +out: + return m_copym(sopt->sopt_m, 0, M_COPYALL, waitok); +} + +int +sockopt_setmbuf(struct sockopt *sopt, struct mbuf *m) +{ + int rc; + u_int len; + + len = m_length(m); + + if (!M_UNWRITABLE(m, len)) { + if (sopt->sopt_m != NULL) + m_freem(sopt->sopt_m); + else if (sopt->sopt_un != NULL) + free(sopt->sopt_un, M_SOOPTS); + sopt->sopt_m = m; + sopt->sopt_un = mtod(m, union sopt_union *); + sopt->sopt_size = len; + return 0; + } + + if ((rc = sockopt_ensure_writable(sopt, len)) != 0) + goto out; + + m_copydata(m, 0, len, sopt->sopt_un); + sopt->sopt_size = len; + +out: + m_freem(m); + return rc; +} + static int -sosetopt1(struct socket *so, int level, int optname, struct mbuf *m) +sosetopt1(struct socket *so, struct sockopt *sopt) { int optval, val; - struct linger *l; - struct sockbuf *sb; + struct linger *l; + struct sockbuf *sb; struct timeval *tv; + void *v; - switch (optname) { + if (sopt == NULL) + return (EINVAL); + switch (sopt->sopt_name) { case SO_LINGER: - if (m == NULL || m->m_len != sizeof(struct linger)) - return EINVAL; - l = mtod(m, struct linger *); + l = sockopt_get(sopt, sizeof(*l)); + if (l == NULL) + return (EINVAL); + if (l->l_linger < 0 || l->l_linger > USHRT_MAX || l->l_linger > (INT_MAX / hz)) return EDOM; @@ -1490,34 +1657,40 @@ sosetopt1(struct socket *so, int level, case SO_REUSEPORT: case SO_OOBINLINE: case SO_TIMESTAMP: - if (m == NULL || m->m_len < sizeof(int)) - return EINVAL; - if (*mtod(m, int *)) - so->so_options |= optname; + v = sockopt_getintptr(sopt); + if (v == NULL) + return (EINVAL); + + optval = *((int *)v); + + 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: - if (m == NULL || m->m_len < sizeof(int)) - return EINVAL; + v = sockopt_getintptr(sopt); + if (v == NULL) + return (EINVAL); + + optval = *((int *)v); /* * Values < 1 make no sense for any of these * options, so disallow them. */ - optval = *mtod(m, int *); if (optval < 1) return EINVAL; - switch (optname) { + switch (sopt->sopt_name) { case SO_SNDBUF: case SO_RCVBUF: - sb = (optname == SO_SNDBUF) ? + sb = (sopt->sopt_name == SO_SNDBUF) ? &so->so_snd : &so->so_rcv; if (sbreserve(sb, (u_long)optval, so) == 0) return ENOBUFS; @@ -1543,17 +1716,17 @@ sosetopt1(struct socket *so, int level, case SO_SNDTIMEO: case SO_RCVTIMEO: - if (m == NULL || m->m_len < sizeof(*tv)) - return EINVAL; - tv = mtod(m, struct timeval *); + tv = sockopt_get(sopt, sizeof(*tv)); + if (tv == NULL) + return (EINVAL); + if (tv->tv_sec > (INT_MAX - tv->tv_usec / tick) / hz) return EDOM; val = tv->tv_sec * hz + tv->tv_usec / tick; if (val == 0 && tv->tv_usec != 0) val = 1; - switch (optname) { - + switch (sopt->sopt_name) { case SO_SNDTIMEO: so->so_snd.sb_timeo = val; break; @@ -1570,52 +1743,76 @@ sosetopt1(struct socket *so, int level, } int -sosetopt(struct socket *so, int level, int optname, struct mbuf *m) +sosetopt(struct socket *so, struct sockopt *sopt) { int error, prerr; - if (level == SOL_SOCKET) - error = sosetopt1(so, level, optname, m); + if (sopt == NULL) + return (EINVAL); + + if (sopt->sopt_level == SOL_SOCKET) + error = sosetopt1(so, sopt); else error = ENOPROTOOPT; if ((error == 0 || error == ENOPROTOOPT) && so->so_proto != NULL && so->so_proto->pr_ctloutput != NULL) { /* give the protocol stack a shot */ - prerr = (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so, level, - optname, &m); + prerr = (*so->so_proto->pr_ctloutput)(so, sopt); if (prerr == 0) error = 0; else if (prerr != ENOPROTOOPT) error = prerr; - } else if (m != NULL) - (void)m_free(m); + } return error; } int -sogetopt(struct socket *so, int level, int optname, struct mbuf **mp) +so_setsockopt(struct lwp *l, struct socket *so, int level, int name, void *val, + socklen_t valsize) { - struct mbuf *m; + struct sockopt sopt; + + /*if (val == NULL && valsize != 0) + return (EFAULT); + if ((int)valsize < 0 || (int)valsize > sizeof(sopt.sopt_val)) + return (EINVAL);*/ + + memset(&sopt, 0, sizeof(sopt)); + sopt.sopt_dir = SOPT_SET; + sopt.sopt_level = level; + sopt.sopt_name = name; + /* memcpy(sopt.sopt_val, val, valsize); + sopt.sopt_valsize = valsize; */ + sockopt_set(&sopt, val, valsize); + sopt.sopt_lwp = l; + + return (sosetopt(so, &sopt)); +} - if (level != SOL_SOCKET) { +int +sogetopt(struct socket *so, struct sockopt *sopt) +{ + int error = 0; + int optval; + + 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)); + return ((*so->so_proto->pr_ctloutput)(so, sopt)); } else return (ENOPROTOOPT); } else { - m = m_get(M_WAIT, MT_SOOPTS); - m->m_len = sizeof(int); + switch (sopt->sopt_name) { - switch (optname) { + case SO_LINGER: { + struct linger lgr; - case SO_LINGER: - m->m_len = sizeof(struct linger); - mtod(m, struct linger *)->l_onoff = - (so->so_options & SO_LINGER) ? 1 : 0; - mtod(m, struct linger *)->l_linger = so->so_linger; + lgr.l_onoff = (so->so_options & SO_LINGER) ? 1 : 0; + lgr.l_linger = so->so_linger; + + error = sockopt_set(sopt, &lgr, sizeof(lgr)); break; + } case SO_USELOOPBACK: case SO_DONTROUTE: @@ -1626,57 +1823,60 @@ sogetopt(struct socket *so, int level, i case SO_BROADCAST: case SO_OOBINLINE: case SO_TIMESTAMP: - *mtod(m, int *) = (so->so_options & optname) ? 1 : 0; + optval = so->so_options & sopt->sopt_name; + + integer: + error = sockopt_set(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 ? + case SO_RCVTIMEO: { + struct timeval tv; + + optval = (sopt->sopt_name == 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; + tv.tv_sec = optval / hz; + tv.tv_usec = (optval % hz) * tick; + + error = sockopt_set(sopt, &tv, sizeof(tv)); break; - } + } case SO_OVERFLOWED: - *mtod(m, int *) = so->so_rcv.sb_overflowed; - break; + optval = so->so_rcv.sb_overflowed; + goto integer; default: - (void)m_free(m); - return (ENOPROTOOPT); + error = ENOPROTOOPT; + break; } - *mp = m; - return (0); + return (error); } } Index: kern/uipc_syscalls.c =================================================================== RCS file: /usr/cvs/src/sys/kern/uipc_syscalls.c,v retrieving revision 1.126 diff -u -p -r1.126 uipc_syscalls.c --- kern/uipc_syscalls.c 26 Dec 2007 16:01:37 -0000 1.126 +++ kern/uipc_syscalls.c 29 Dec 2007 15:45:46 -0000 @@ -882,38 +882,42 @@ sys_setsockopt(struct lwp *l, const stru syscallarg(const void *) val; syscallarg(unsigned int) valsize; } */ - struct proc *p; struct file *fp; - struct mbuf *m; - struct socket *so; int error; - unsigned int len; + void *lbuf = NULL; + struct sockopt sopt; + + /* Sanity. */ + if (SCARG(uap, valsize) > MCLBYTES) + return (EINVAL); + + lbuf = kmem_zalloc(MCLBYTES, KM_SLEEP); + + memset(&sopt, 0, sizeof(sopt)); + sopt.sopt_dir = SOPT_SET; + error = copyin(SCARG(uap, val), lbuf, SCARG(uap, valsize)); + if (error) + goto out; + sopt.sopt_level = SCARG(uap, level); + sopt.sopt_name = SCARG(uap, name); + sopt.sopt_lwp = l; + sopt.sopt_waitok = 1; + error = sockopt_set(&sopt, lbuf, SCARG(uap, valsize)); + if (error) + goto out; - p = l->l_proc; - m = NULL; /* getsock() will use the descriptor for us */ - if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) - return (error); - so = (struct socket *)fp->f_data; - len = SCARG(uap, valsize); - if (len > MCLBYTES) { - error = EINVAL; + error = getsock(l->l_proc->p_fd, SCARG(uap, s), &fp); + if (error) goto out; - } - if (SCARG(uap, val)) { - m = getsombuf(so, MT_SOOPTS); - if (len > MLEN) - m_clget(m, M_WAIT); - error = copyin(SCARG(uap, val), mtod(m, void *), len); - if (error) { - (void) m_free(m); - goto out; - } - m->m_len = SCARG(uap, valsize); - } - error = sosetopt(so, SCARG(uap, level), SCARG(uap, name), m); - out: + + error = sosetopt((struct socket *)fp->f_data, &sopt); + FILE_UNUSE(fp, l); + + out: + sockopt_destroy(&sopt); + kmem_free(lbuf, MCLBYTES); return (error); } @@ -929,41 +933,48 @@ sys_getsockopt(struct lwp *l, const stru syscallarg(unsigned int *) avalsize; } */ struct file *fp; - struct mbuf *m; - unsigned int op, i, valsize; int error; - char *val = SCARG(uap, val); + void *lbuf; + unsigned int valsize; + struct sockopt sopt; - m = NULL; /* getsock() will use the descriptor for us */ - if ((error = getsock(l->l_proc->p_fd, SCARG(uap, s), &fp)) != 0) + error = getsock(l->l_proc->p_fd, SCARG(uap, s), &fp); + if (error) return (error); - if (val != NULL) { - error = copyin(SCARG(uap, avalsize), - &valsize, sizeof(valsize)); + + memset(&sopt, 0, sizeof(sopt)); + sopt.sopt_dir = SOPT_GET; + sopt.sopt_level = SCARG(uap, level); + sopt.sopt_name = SCARG(uap, name); + if (SCARG(uap, val) != NULL) { + error = copyin(SCARG(uap, avalsize), &valsize, + sizeof(valsize)); if (error) goto out; } else valsize = 0; - if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level), - SCARG(uap, name), &m)) == 0 && val != NULL && valsize && - m != NULL) { - op = 0; - while (m && !error && op < valsize) { - i = min(m->m_len, (valsize - op)); - error = copyout(mtod(m, void *), val, i); - op += i; - val += i; - m = m_free(m); - } - valsize = op; - if (error == 0) - error = copyout(&valsize, - SCARG(uap, avalsize), sizeof(valsize)); + sopt.sopt_waitok = 1; + sopt.sopt_lwp = l; + + error = sogetopt((struct socket *)fp->f_data, &sopt); + if (error) + goto out; + + lbuf = sopt.sopt_un; + if ((SCARG(uap, val) != NULL) && (valsize != 0)) { + unsigned int copylen = min(valsize, sopt.sopt_size); + + error = copyout(lbuf, SCARG(uap, val), copylen); + if (error) + goto out; + + error = copyout(©len, SCARG(uap, avalsize), + sizeof(copylen)); } - if (m != NULL) - (void) m_freem(m); + out: + sockopt_destroy(&sopt); FILE_UNUSE(fp, l); return (error); } Index: kern/uipc_usrreq.c =================================================================== RCS file: /usr/cvs/src/sys/kern/uipc_usrreq.c,v retrieving revision 1.104 diff -u -p -r1.104 uipc_usrreq.c --- kern/uipc_usrreq.c 5 Jan 2008 19:08:49 -0000 1.104 +++ kern/uipc_usrreq.c 7 Jan 2008 19:31:13 -0000 @@ -451,72 +451,65 @@ release: * Unix domain socket option processing. */ int -uipc_ctloutput(int op, struct socket *so, int level, int optname, - struct mbuf **mp) +uipc_ctloutput(struct socket *so, struct sockopt *sopt) { struct unpcb *unp = sotounpcb(so); - struct mbuf *m = *mp; int optval = 0, error = 0; + void *v; - if (level != 0) { + if (sopt->sopt_level != 0) { error = ENOPROTOOPT; - if (op == PRCO_SETOPT && m) - (void) m_free(m); - } else switch (op) { - - case PRCO_SETOPT: - switch (optname) { + } else switch (sopt->sopt_dir) { + case SOPT_SET: + switch (sopt->sopt_name) { case LOCAL_CREDS: case LOCAL_CONNWAIT: - if (m == NULL || m->m_len != sizeof(int)) + v = sockopt_getintptr(sopt); + if (v == NULL) { error = EINVAL; - else { - optval = *mtod(m, int *); - switch (optname) { + break; + } + optval = *((int *)v); + switch (sopt->sopt_name) { #define OPTSET(bit) \ if (optval) \ unp->unp_flags |= (bit); \ else \ unp->unp_flags &= ~(bit); - case LOCAL_CREDS: - OPTSET(UNP_WANTCRED); - break; - case LOCAL_CONNWAIT: - OPTSET(UNP_CONNWAIT); - break; - } + case LOCAL_CREDS: + OPTSET(UNP_WANTCRED); + break; + case LOCAL_CONNWAIT: + OPTSET(UNP_CONNWAIT); + break; } - break; + break; #undef OPTSET default: error = ENOPROTOOPT; break; } - if (m) - (void) m_free(m); break; - case PRCO_GETOPT: - switch (optname) { + case SOPT_GET: + switch (sopt->sopt_name) { case LOCAL_PEEREID: if (unp->unp_flags & UNP_EIDSVALID) { - *mp = m = m_get(M_WAIT, MT_SOOPTS); - m->m_len = sizeof(struct unpcbid); - *mtod(m, struct unpcbid *) = unp->unp_connid; + struct unpcbid peerid; + + peerid = unp->unp_connid; + error = sockopt_set(sopt, &peerid, sizeof(peerid)); } else { error = EINVAL; } break; case LOCAL_CREDS: - *mp = m = m_get(M_WAIT, MT_SOOPTS); - m->m_len = sizeof(int); - #define OPTBIT(bit) (unp->unp_flags & (bit) ? 1 : 0) optval = OPTBIT(UNP_WANTCRED); - *mtod(m, int *) = optval; + error = sockopt_set(sopt, &optval, sizeof(optval)); break; #undef OPTBIT Index: net/if_gre.c =================================================================== RCS file: /usr/cvs/src/sys/net/if_gre.c,v retrieving revision 1.122 diff -u -p -r1.122 if_gre.c --- net/if_gre.c 20 Dec 2007 18:12:11 -0000 1.122 +++ net/if_gre.c 21 Dec 2007 00:04:04 -0000 @@ -466,6 +466,7 @@ gre_socreate(struct gre_softc *sc, struc struct sockaddr *sa; sa_family_t af; struct socket *so; + int val; GRE_DPRINTF(sc, "%s: enter\n", __func__); @@ -509,19 +510,18 @@ gre_socreate(struct gre_softc *sc, struc } /* XXX convert to a (new) SOL_SOCKET call */ - *mtod(m, int *) = ip_gre_ttl; - m->m_len = sizeof(int); pr = so->so_proto; KASSERT(pr != NULL); - rc = sosetopt(so, IPPROTO_IP, IP_TTL, m); - m = NULL; + rc = so_setsockopt(l, so, IPPROTO_IP, IP_TTL, &ip_gre_ttl, sizeof(ip_gre_ttl)); if (rc != 0) { - GRE_DPRINTF(sc, "%s: sosetopt ttl failed\n", __func__); + GRE_DPRINTF(sc, "%s: so_setsockopt ttl failed\n", __func__); rc = 0; } - rc = sosetopt(so, SOL_SOCKET, SO_NOHEADER, m_intopt(so, 1)); + val = 1; + rc = so_setsockopt(l, so, SOL_SOCKET, SO_NOHEADER, &val, sizeof(val)); if (rc != 0) { - GRE_DPRINTF(sc, "%s: sosetopt SO_NOHEADER failed\n", __func__); + GRE_DPRINTF(sc, "%s: so_setsockopt SO_NOHEADER failed\n", + __func__); rc = 0; } out: @@ -1259,7 +1259,7 @@ gre_ioctl(struct ifnet *ifp, const u_lon case SIOCSLIFPHYADDR: case SIOCDIFPHYADDR: if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE, - KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd, + KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, KAUTH_ARG(cmd), NULL) != 0) return EPERM; break; Index: netbt/hci.h =================================================================== RCS file: /usr/cvs/src/sys/netbt/hci.h,v retrieving revision 1.21 diff -u -p -r1.21 hci.h --- netbt/hci.h 30 Dec 2007 18:26:42 -0000 1.21 +++ netbt/hci.h 2 Jan 2008 12:43:08 -0000 @@ -74,6 +74,7 @@ #ifndef _NETBT_HCI_H_ #define _NETBT_HCI_H_ +#include #include /************************************************************************** @@ -2208,7 +2209,7 @@ void hci_memo_free(struct hci_memo *); /* hci_socket.c */ void hci_drop(void *); int hci_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *, struct lwp *); -int hci_ctloutput(int, struct socket *, int, int, struct mbuf **); +int hci_ctloutput(struct socket *, struct sockopt *); void hci_mtap(struct mbuf *, struct hci_unit *); /* hci_unit.c */ Index: netbt/hci_socket.c =================================================================== RCS file: /usr/cvs/src/sys/netbt/hci_socket.c,v retrieving revision 1.13 diff -u -p -r1.13 hci_socket.c --- netbt/hci_socket.c 30 Dec 2007 18:26:42 -0000 1.13 +++ netbt/hci_socket.c 2 Jan 2008 12:43:08 -0000 @@ -697,14 +697,19 @@ release: * get/set socket options */ int -hci_ctloutput(int req, struct socket *so, int level, - int optname, struct mbuf **opt) +hci_ctloutput(struct socket *so, struct sockopt *sopt) { struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb; - struct mbuf *m; int err = 0; + int req, level, optname, optval; + struct hci_filter *hcifil; + void *v; + + req = sopt->sopt_dir; + level = sopt->sopt_level; + optname = sopt->sopt_name; - DPRINTFN(2, "req %s\n", prcorequests[req]); + DPRINTFN(2, "req %s\n", (req == SOPT_SET) ? "SET" : "GET"); if (pcb == NULL) return EINVAL; @@ -713,51 +718,60 @@ hci_ctloutput(int req, struct socket *so return ENOPROTOOPT; switch(req) { - case PRCO_GETOPT: - m = m_get(M_WAIT, MT_SOOPTS); + case SOPT_GET: switch (optname) { case SO_HCI_EVT_FILTER: - m->m_len = sizeof(struct hci_filter); - memcpy(mtod(m, void *), &pcb->hp_efilter, m->m_len); + err = sockopt_set(sopt, &pcb->hp_efilter, + sizeof(struct hci_filter)); break; case SO_HCI_PKT_FILTER: - m->m_len = sizeof(struct hci_filter); - memcpy(mtod(m, void *), &pcb->hp_pfilter, m->m_len); + err = sockopt_set(sopt, &pcb->hp_pfilter, + sizeof(struct hci_filter)); break; case SO_HCI_DIRECTION: - m->m_len = sizeof(int); if (pcb->hp_flags & HCI_DIRECTION) - *mtod(m, int *) = 1; + optval = 1; else - *mtod(m, int *) = 0; + optval = 0; + err = sockopt_set(sopt, &optval, sizeof(optval)); break; default: err = ENOPROTOOPT; - m_freem(m); - m = NULL; break; } - *opt = m; break; - case PRCO_SETOPT: - m = *opt; - if (m) switch (optname) { + case SOPT_SET: + switch (optname) { case SO_HCI_EVT_FILTER: /* set event filter */ - m->m_len = min(m->m_len, sizeof(struct hci_filter)); - memcpy(&pcb->hp_efilter, mtod(m, void *), m->m_len); + hcifil = sockopt_get(sopt, sizeof(*hcifil)); + if (hcifil == NULL) { + err = EINVAL; + break; + } + memcpy(&pcb->hp_efilter, hcifil, sizeof(*hcifil)); break; case SO_HCI_PKT_FILTER: /* set packet filter */ - m->m_len = min(m->m_len, sizeof(struct hci_filter)); - memcpy(&pcb->hp_pfilter, mtod(m, void *), m->m_len); + hcifil = sockopt_get(sopt, sizeof(*hcifil)); + if (hcifil == NULL) { + err = EINVAL; + break; + } + memcpy(&pcb->hp_pfilter, hcifil, sizeof(*hcifil)); break; case SO_HCI_DIRECTION: /* request direction ctl messages */ - if (*mtod(m, int *)) + v = sockopt_getintptr(sopt); + if (v == NULL) { + err = EINVAL; + break; + } + optval = *((int *)v); + if (optval) pcb->hp_flags |= HCI_DIRECTION; else pcb->hp_flags &= ~HCI_DIRECTION; @@ -767,7 +781,6 @@ hci_ctloutput(int req, struct socket *so err = ENOPROTOOPT; break; } - m_freem(m); break; default: Index: netbt/l2cap.h =================================================================== RCS file: /usr/cvs/src/sys/netbt/l2cap.h,v retrieving revision 1.6 diff -u -p -r1.6 l2cap.h --- netbt/l2cap.h 3 Nov 2007 17:20:17 -0000 1.6 +++ netbt/l2cap.h 21 Dec 2007 00:27:29 -0000 @@ -70,6 +70,7 @@ #define _NETBT_L2CAP_H_ #include +#include /************************************************************************** ************************************************************************** @@ -464,7 +465,7 @@ int l2cap_send_connect_rsp(struct hci_li /* l2cap_socket.c */ int l2cap_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *, struct lwp *); -int l2cap_ctloutput(int, struct socket *, int, int, struct mbuf **); +int l2cap_ctloutput(struct socket *, struct sockopt *); /* l2cap_upper.c */ int l2cap_attach(struct l2cap_channel **, const struct btproto *, void *); @@ -476,8 +477,8 @@ int l2cap_disconnect(struct l2cap_channe int l2cap_detach(struct l2cap_channel **); int l2cap_listen(struct l2cap_channel *); int l2cap_send(struct l2cap_channel *, struct mbuf *); -int l2cap_setopt(struct l2cap_channel *, int, void *); -int l2cap_getopt(struct l2cap_channel *, int, void *); +int l2cap_setopt(struct l2cap_channel *, struct sockopt *); +int l2cap_getopt(struct l2cap_channel *, struct sockopt *); #endif /* _KERNEL */ Index: netbt/l2cap_socket.c =================================================================== RCS file: /usr/cvs/src/sys/netbt/l2cap_socket.c,v retrieving revision 1.7 diff -u -p -r1.7 l2cap_socket.c --- netbt/l2cap_socket.c 21 Apr 2007 06:15:23 -0000 1.7 +++ netbt/l2cap_socket.c 29 Dec 2007 12:41:14 -0000 @@ -259,14 +259,16 @@ release: * "Reconfigure Channel Request" in the L2CAP specification. */ int -l2cap_ctloutput(int req, struct socket *so, int level, - int optname, struct mbuf **opt) +l2cap_ctloutput(struct socket *so, struct sockopt *sopt) { struct l2cap_channel *pcb = so->so_pcb; - struct mbuf *m; int err = 0; + int req, level, len; - DPRINTFN(2, "%s\n", prcorequests[req]); + req = sopt->sopt_dir; + level = sopt->sopt_level; + + DPRINTFN(2, "%s\n", (req == SOPT_SET) ? "SET" : "GET"); if (pcb == NULL) return EINVAL; @@ -275,22 +277,14 @@ l2cap_ctloutput(int req, struct socket * return ENOPROTOOPT; switch(req) { - case PRCO_GETOPT: - m = m_get(M_WAIT, MT_SOOPTS); - m->m_len = l2cap_getopt(pcb, optname, mtod(m, void *)); - if (m->m_len == 0) { - m_freem(m); - m = NULL; + case SOPT_GET: + len = l2cap_getopt(pcb, sopt); + if (len == 0) err = ENOPROTOOPT; - } - *opt = m; break; - case PRCO_SETOPT: - m = *opt; - KASSERT(m != NULL); - err = l2cap_setopt(pcb, optname, mtod(m, void *)); - m_freem(m); + case SOPT_SET: + err = l2cap_setopt(pcb, sopt); break; default: @@ -368,13 +362,24 @@ l2cap_linkmode(void *arg, int new) { struct socket *so = arg; int mode; + struct sockopt sopt; DPRINTF("auth %s, encrypt %s, secure %s\n", (new & L2CAP_LM_AUTH ? "on" : "off"), (new & L2CAP_LM_ENCRYPT ? "on" : "off"), (new & L2CAP_LM_SECURE ? "on" : "off")); - (void)l2cap_getopt(so->so_pcb, SO_L2CAP_LM, &mode); + /* XXX elad - maybe create a function that does this */ + memset(&sopt, 0, sizeof(sopt)); + sopt.sopt_dir = SOPT_GET; + sopt.sopt_level = BTPROTO_L2CAP; + sopt.sopt_name = SO_L2CAP_LM; + sopt.sopt_lwp = NULL; + + (void)l2cap_getopt(so->so_pcb, &sopt); + + mode = *sockopt_getintptr(&sopt); + if (((mode & L2CAP_LM_AUTH) && !(new & L2CAP_LM_AUTH)) || ((mode & L2CAP_LM_ENCRYPT) && !(new & L2CAP_LM_ENCRYPT)) || ((mode & L2CAP_LM_SECURE) && !(new & L2CAP_LM_SECURE))) Index: netbt/l2cap_upper.c =================================================================== RCS file: /usr/cvs/src/sys/netbt/l2cap_upper.c,v retrieving revision 1.8 diff -u -p -r1.8 l2cap_upper.c --- netbt/l2cap_upper.c 29 Apr 2007 20:23:36 -0000 1.8 +++ netbt/l2cap_upper.c 29 Dec 2007 12:41:22 -0000 @@ -420,14 +420,21 @@ l2cap_send(struct l2cap_channel *chan, s * will be made when the change is complete. */ int -l2cap_setopt(struct l2cap_channel *chan, int opt, void *addr) +l2cap_setopt(struct l2cap_channel *chan, struct sockopt *sopt) { int mode, err = 0; uint16_t mtu; + void *v; - switch (opt) { + switch (sopt->sopt_name) { case SO_L2CAP_IMTU: /* set Incoming MTU */ - mtu = *(uint16_t *)addr; + v = sockopt_get(sopt, sizeof(mtu)); + if (v == NULL) { + err = EINVAL; + break; + } + mtu = *((uint16_t *)v); + if (mtu < L2CAP_MTU_MINIMUM) err = EINVAL; else if (chan->lc_state == L2CAP_CLOSED) @@ -438,7 +445,13 @@ l2cap_setopt(struct l2cap_channel *chan, break; case SO_L2CAP_LM: /* set link mode */ - mode = *(int *)addr; + v = sockopt_getintptr(sopt); + if (v == NULL) { + err = EINVAL; + break; + } + mode = *((int *)v); + mode &= (L2CAP_LM_SECURE | L2CAP_LM_ENCRYPT | L2CAP_LM_AUTH); if (mode & L2CAP_LM_SECURE) @@ -470,37 +483,47 @@ l2cap_setopt(struct l2cap_channel *chan, * Return configuration parameters. */ int -l2cap_getopt(struct l2cap_channel *chan, int opt, void *addr) +l2cap_getopt(struct l2cap_channel *chan, struct sockopt *sopt) { + uint16_t ui; - switch (opt) { + switch (sopt->sopt_name) { case SO_L2CAP_IMTU: /* get Incoming MTU */ - *(uint16_t *)addr = chan->lc_imtu; + ui = chan->lc_imtu; + + integer: + if (sockopt_set(sopt, &ui, sizeof(ui)) != 0) + goto bad; return sizeof(uint16_t); case SO_L2CAP_OMTU: /* get Outgoing MTU */ - *(uint16_t *)addr = chan->lc_omtu; - return sizeof(uint16_t); + ui = chan->lc_omtu; + goto integer; case SO_L2CAP_IQOS: /* get Incoming QoS flow spec */ - memcpy(addr, &chan->lc_iqos, sizeof(l2cap_qos_t)); + if (sockopt_set(sopt, &chan->lc_iqos, sizeof(l2cap_qos_t)) != 0) + goto bad; return sizeof(l2cap_qos_t); case SO_L2CAP_OQOS: /* get Outgoing QoS flow spec */ - memcpy(addr, &chan->lc_oqos, sizeof(l2cap_qos_t)); + if (sockopt_set(sopt, &chan->lc_oqos, sizeof(l2cap_qos_t)) != 0) + goto bad; return sizeof(l2cap_qos_t); case SO_L2CAP_FLUSH: /* get Flush Timeout */ - *(uint16_t *)addr = chan->lc_flush; - return sizeof(uint16_t); + ui = chan->lc_flush; + goto integer; case SO_L2CAP_LM: /* get link mode */ - *(int *)addr = chan->lc_mode; + if (sockopt_set(sopt, &chan->lc_mode, sizeof(chan->lc_mode)) != 0) + goto bad; + return sizeof(int); default: break; } + bad: return 0; } Index: netbt/rfcomm.h =================================================================== RCS file: /usr/cvs/src/sys/netbt/rfcomm.h,v retrieving revision 1.6 diff -u -p -r1.6 rfcomm.h --- netbt/rfcomm.h 20 Nov 2007 20:25:58 -0000 1.6 +++ netbt/rfcomm.h 21 Dec 2007 11:18:44 -0000 @@ -63,6 +63,7 @@ #define _NETBT_RFCOMM_H_ #include +#include /************************************************************************* ************************************************************************* @@ -403,7 +404,7 @@ int rfcomm_session_send_mcc(struct rfcom /* rfcomm_socket.c */ int rfcomm_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *, struct lwp *); -int rfcomm_ctloutput(int, struct socket *, int, int, struct mbuf **); +int rfcomm_ctloutput(struct socket *, struct sockopt *); /* rfcomm_upper.c */ int rfcomm_attach(struct rfcomm_dlc **, const struct btproto *, void *); @@ -416,8 +417,8 @@ int rfcomm_detach(struct rfcomm_dlc **); int rfcomm_listen(struct rfcomm_dlc *); int rfcomm_send(struct rfcomm_dlc *, struct mbuf *); int rfcomm_rcvd(struct rfcomm_dlc *, size_t); -int rfcomm_setopt(struct rfcomm_dlc *, int, void *); -int rfcomm_getopt(struct rfcomm_dlc *, int, void *); +int rfcomm_setopt(struct rfcomm_dlc *, struct sockopt *); +int rfcomm_getopt(struct rfcomm_dlc *, struct sockopt *); #endif /* _KERNEL */ Index: netbt/rfcomm_dlc.c =================================================================== RCS file: /usr/cvs/src/sys/netbt/rfcomm_dlc.c,v retrieving revision 1.4 diff -u -p -r1.4 rfcomm_dlc.c --- netbt/rfcomm_dlc.c 3 Nov 2007 17:20:17 -0000 1.4 +++ netbt/rfcomm_dlc.c 18 Dec 2007 21:34:07 -0000 @@ -221,6 +221,7 @@ int rfcomm_dlc_setmode(struct rfcomm_dlc *dlc) { int mode = 0; + struct sockopt sopt; KASSERT(dlc->rd_session != NULL); KASSERT(dlc->rd_session->rs_state == RFCOMM_SESSION_OPEN); @@ -239,7 +240,14 @@ rfcomm_dlc_setmode(struct rfcomm_dlc *dl if (dlc->rd_mode & RFCOMM_LM_SECURE) mode |= L2CAP_LM_SECURE; - return l2cap_setopt(dlc->rd_session->rs_l2cap, SO_L2CAP_LM, &mode); + /* XXX elad - functionize */ + sopt.sopt_dir = SOPT_SET; + sopt.sopt_level = BTPROTO_L2CAP; + sopt.sopt_name = SO_L2CAP_LM; + sockopt_setint(&sopt, mode); + sopt.sopt_lwp = NULL; + + return l2cap_setopt(dlc->rd_session->rs_l2cap, &sopt); } /* Index: netbt/rfcomm_session.c =================================================================== RCS file: /usr/cvs/src/sys/netbt/rfcomm_session.c,v retrieving revision 1.11 diff -u -p -r1.11 rfcomm_session.c --- netbt/rfcomm_session.c 3 Nov 2007 17:20:17 -0000 1.11 +++ netbt/rfcomm_session.c 18 Dec 2007 21:36:42 -0000 @@ -163,6 +163,7 @@ rfcomm_session_alloc(struct rfcomm_sessi { struct rfcomm_session *rs; int err; + struct sockopt sopt; rs = malloc(sizeof(*rs), M_BLUETOOTH, M_NOWAIT | M_ZERO); if (rs == NULL) @@ -182,7 +183,15 @@ rfcomm_session_alloc(struct rfcomm_sessi return NULL; } - (void)l2cap_getopt(rs->rs_l2cap, SO_L2CAP_OMTU, &rs->rs_mtu); + /* XXX elad - functionize */ + sopt.sopt_dir = SOPT_GET; + sopt.sopt_level = BTPROTO_L2CAP; + sopt.sopt_name = SO_L2CAP_OMTU; + sopt.sopt_lwp = NULL; + + (void)l2cap_getopt(rs->rs_l2cap, &sopt); + + rs->rs_mtu = *((uint16_t *)sockopt_get(&sopt, sizeof(rs->rs_mtu))); if (laddr->bt_psm == L2CAP_PSM_ANY) laddr->bt_psm = L2CAP_PSM_RFCOMM; @@ -336,6 +345,7 @@ static void rfcomm_session_connected(void *arg) { struct rfcomm_session *rs = arg; + struct sockopt sopt; DPRINTF("Connected\n"); @@ -348,7 +358,15 @@ rfcomm_session_connected(void *arg) * We must take note of the L2CAP MTU because currently * the L2CAP implementation can only do Basic Mode. */ - l2cap_getopt(rs->rs_l2cap, SO_L2CAP_OMTU, &rs->rs_mtu); + /* XXX elad - functionize */ + sopt.sopt_dir = SOPT_GET; + sopt.sopt_level = BTPROTO_L2CAP; + sopt.sopt_name = SO_L2CAP_OMTU; + sopt.sopt_lwp = NULL; + + l2cap_getopt(rs->rs_l2cap, &sopt); + + rs->rs_mtu = *((uint16_t *)sockopt_get(&sopt, sizeof(rs->rs_mtu))); rs->rs_mtu -= 6; /* (RFCOMM overhead could be this big) */ if (rs->rs_mtu < RFCOMM_MTU_MIN) { Index: netbt/rfcomm_socket.c =================================================================== RCS file: /usr/cvs/src/sys/netbt/rfcomm_socket.c,v retrieving revision 1.8 diff -u -p -r1.8 rfcomm_socket.c --- netbt/rfcomm_socket.c 15 Oct 2007 18:04:34 -0000 1.8 +++ netbt/rfcomm_socket.c 29 Dec 2007 12:40:43 -0000 @@ -260,14 +260,17 @@ release: * */ int -rfcomm_ctloutput(int req, struct socket *so, int level, - int optname, struct mbuf **opt) +rfcomm_ctloutput(struct socket *so, struct sockopt *sopt) { struct rfcomm_dlc *pcb = so->so_pcb; - struct mbuf *m; int err = 0; + int req, level, optname, len; - DPRINTFN(2, "%s\n", prcorequests[req]); + req = sopt->sopt_dir; + level = sopt->sopt_level; + optname = sopt->sopt_name; + + DPRINTFN(2, "%s\n", (req == SOPT_SET) ? "SET" : "GET"); if (pcb == NULL) return EINVAL; @@ -276,22 +279,14 @@ rfcomm_ctloutput(int req, struct socket return ENOPROTOOPT; switch(req) { - case PRCO_GETOPT: - m = m_get(M_WAIT, MT_SOOPTS); - m->m_len = rfcomm_getopt(pcb, optname, mtod(m, void *)); - if (m->m_len == 0) { - m_freem(m); - m = NULL; + case SOPT_GET: + len = rfcomm_getopt(pcb, sopt); + if (len == 0) err = ENOPROTOOPT; - } - *opt = m; break; - case PRCO_SETOPT: - m = *opt; - KASSERT(m != NULL); - err = rfcomm_setopt(pcb, optname, mtod(m, void *)); - m_freem(m); + case SOPT_SET: + err = rfcomm_setopt(pcb, sopt); break; default: @@ -378,13 +373,23 @@ rfcomm_linkmode(void *arg, int new) { struct socket *so = arg; int mode; + struct sockopt sopt; DPRINTF("auth %s, encrypt %s, secure %s\n", (new & RFCOMM_LM_AUTH ? "on" : "off"), (new & RFCOMM_LM_ENCRYPT ? "on" : "off"), (new & RFCOMM_LM_SECURE ? "on" : "off")); - (void)rfcomm_getopt(so->so_pcb, SO_RFCOMM_LM, &mode); + /* XXX elad - functionize */ + sopt.sopt_dir = SOPT_GET; + sopt.sopt_level = BTPROTO_RFCOMM; + sopt.sopt_name = SO_RFCOMM_LM; + sopt.sopt_lwp = NULL; + + (void)rfcomm_getopt(so->so_pcb, &sopt); + + mode = *sockopt_getintptr(&sopt); + if (((mode & RFCOMM_LM_AUTH) && !(new & RFCOMM_LM_AUTH)) || ((mode & RFCOMM_LM_ENCRYPT) && !(new & RFCOMM_LM_ENCRYPT)) || ((mode & RFCOMM_LM_SECURE) && !(new & RFCOMM_LM_SECURE))) Index: netbt/rfcomm_upper.c =================================================================== RCS file: /usr/cvs/src/sys/netbt/rfcomm_upper.c,v retrieving revision 1.10 diff -u -p -r1.10 rfcomm_upper.c --- netbt/rfcomm_upper.c 20 Nov 2007 20:25:57 -0000 1.10 +++ netbt/rfcomm_upper.c 29 Dec 2007 12:40:52 -0000 @@ -439,14 +439,24 @@ rfcomm_rcvd(struct rfcomm_dlc *dlc, size * set DLC options */ int -rfcomm_setopt(struct rfcomm_dlc *dlc, int opt, void *addr) +rfcomm_setopt(struct rfcomm_dlc *dlc, struct sockopt *sopt) { int mode, err = 0; uint16_t mtu; + int opt; + void *v; + + opt = sopt->sopt_name; switch (opt) { case SO_RFCOMM_MTU: - mtu = *(uint16_t *)addr; + v = sockopt_get(sopt, sizeof(mtu)); + if (v == NULL) { + err = EINVAL; + break; + } + mtu = *((uint16_t *)v); + if (mtu < RFCOMM_MTU_MIN || mtu > RFCOMM_MTU_MAX) err = EINVAL; else if (dlc->rd_state == RFCOMM_DLC_CLOSED) @@ -457,7 +467,13 @@ rfcomm_setopt(struct rfcomm_dlc *dlc, in break; case SO_RFCOMM_LM: - mode = *(int *)addr; + v = sockopt_getintptr(sopt); + if (v == NULL) { + err = EINVAL; + break; + } + mode = *((int *)v); + mode &= (RFCOMM_LM_SECURE | RFCOMM_LM_ENCRYPT | RFCOMM_LM_AUTH); if (mode & RFCOMM_LM_SECURE) @@ -486,35 +502,48 @@ rfcomm_setopt(struct rfcomm_dlc *dlc, in * get DLC options */ int -rfcomm_getopt(struct rfcomm_dlc *dlc, int opt, void *addr) +rfcomm_getopt(struct rfcomm_dlc *dlc, struct sockopt *sopt) { - struct rfcomm_fc_info *fc; + struct rfcomm_fc_info fc; + int opt, i, error; + uint16_t ui; + + opt = sopt->sopt_name; switch (opt) { case SO_RFCOMM_MTU: - *(uint16_t *)addr = dlc->rd_mtu; + ui = dlc->rd_mtu; + error = sockopt_set(sopt, &ui, sizeof(ui)); + if (error) + goto bad; return sizeof(uint16_t); case SO_RFCOMM_FC_INFO: - fc = addr; - memset(fc, 0, sizeof(*fc)); - fc->lmodem = dlc->rd_lmodem; - fc->rmodem = dlc->rd_rmodem; - fc->tx_cred = max(dlc->rd_txcred, 0xff); - fc->rx_cred = max(dlc->rd_rxcred, 0xff); + memset(&fc, 0, sizeof(fc)); + fc.lmodem = dlc->rd_lmodem; + fc.rmodem = dlc->rd_rmodem; + fc.tx_cred = max(dlc->rd_txcred, 0xff); + fc.rx_cred = max(dlc->rd_rxcred, 0xff); if (dlc->rd_session && (dlc->rd_session->rs_flags & RFCOMM_SESSION_CFC)) - fc->cfc = 1; + fc.cfc = 1; + error = sockopt_set(sopt, &fc, sizeof(fc)); + if (error) + goto bad; - return sizeof(*fc); + return sizeof(fc); case SO_RFCOMM_LM: - *(int *)addr = dlc->rd_mode; + i = dlc->rd_mode; + error = sockopt_set(sopt, &i, sizeof(i)); + if (error) + goto bad; return sizeof(int); default: break; } + bad: return 0; } Index: netbt/sco.h =================================================================== RCS file: /usr/cvs/src/sys/netbt/sco.h,v retrieving revision 1.2 diff -u -p -r1.2 sco.h --- netbt/sco.h 26 Jul 2006 10:20:56 -0000 1.2 +++ netbt/sco.h 16 Dec 2007 15:35:49 -0000 @@ -65,7 +65,7 @@ extern int sco_sendspace; extern int sco_recvspace; int sco_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *, struct lwp *); -int sco_ctloutput(int, struct socket *, int, int, struct mbuf **); +int sco_ctloutput(struct socket *, struct sockopt *); /* sco_upper.c */ int sco_attach(struct sco_pcb **, const struct btproto *, void *); @@ -77,8 +77,8 @@ int sco_disconnect(struct sco_pcb *, int int sco_detach(struct sco_pcb **); int sco_listen(struct sco_pcb *); int sco_send(struct sco_pcb *, struct mbuf *); -int sco_setopt(struct sco_pcb *, int, void *); -int sco_getopt(struct sco_pcb *, int, void *); +int sco_setopt(struct sco_pcb *, struct sockopt *); +int sco_getopt(struct sco_pcb *, struct sockopt *); #endif /* _KERNEL */ Index: netbt/sco_socket.c =================================================================== RCS file: /usr/cvs/src/sys/netbt/sco_socket.c,v retrieving revision 1.9 diff -u -p -r1.9 sco_socket.c --- netbt/sco_socket.c 21 Apr 2007 06:15:23 -0000 1.9 +++ netbt/sco_socket.c 16 Dec 2007 15:35:49 -0000 @@ -246,14 +246,16 @@ release: * get/set socket options */ int -sco_ctloutput(int req, struct socket *so, int level, - int optname, struct mbuf **opt) +sco_ctloutput(struct socket *so, struct sockopt *sopt) { struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb; - struct mbuf *m; int err = 0; + int req, level, len; - DPRINTFN(2, "req %s\n", prcorequests[req]); + req = sopt->sopt_dir; + level = sopt->sopt_level; + + DPRINTFN(2, "req %s\n", (req == SOPT_SET) ? "SET" : "GET"); if (pcb == NULL) return EINVAL; @@ -263,21 +265,13 @@ sco_ctloutput(int req, struct socket *so switch(req) { case PRCO_GETOPT: - m = m_get(M_WAIT, MT_SOOPTS); - m->m_len = sco_getopt(pcb, optname, mtod(m, uint8_t *)); - if (m->m_len == 0) { - m_freem(m); - m = NULL; + len = sco_getopt(pcb, sopt); + if (len == 0) err = ENOPROTOOPT; - } - *opt = m; break; case PRCO_SETOPT: - m = *opt; - KASSERT(m != NULL); - err = sco_setopt(pcb, optname, mtod(m, uint8_t *)); - m_freem(m); + err = sco_setopt(pcb, sopt); break; default: Index: netbt/sco_upper.c =================================================================== RCS file: /usr/cvs/src/sys/netbt/sco_upper.c,v retrieving revision 1.6 diff -u -p -r1.6 sco_upper.c --- netbt/sco_upper.c 30 Mar 2007 20:47:03 -0000 1.6 +++ netbt/sco_upper.c 21 Dec 2007 22:33:32 -0000 @@ -319,11 +319,11 @@ sco_send(struct sco_pcb *pcb, struct mbu * Set SCO pcb options */ int -sco_setopt(struct sco_pcb *pcb, int opt, void *addr) +sco_setopt(struct sco_pcb *pcb, struct sockopt *sopt) { int err = 0; - switch (opt) { + switch (sopt->sopt_name) { default: err = ENOPROTOOPT; break; @@ -338,23 +338,32 @@ sco_setopt(struct sco_pcb *pcb, int opt, * Get SCO pcb options */ int -sco_getopt(struct sco_pcb *pcb, int opt, void *addr) +sco_getopt(struct sco_pcb *pcb, struct sockopt *sopt) { + uint16_t ui; + int error; - switch (opt) { + switch (sopt->sopt_name) { case SO_SCO_MTU: - *(uint16_t *)addr = pcb->sp_mtu; + ui = pcb->sp_mtu; + + uinteger: + error = sockopt_set(sopt, &ui, sizeof(ui)); + if (error) + goto bad; return sizeof(uint16_t); case SO_SCO_HANDLE: if (pcb->sp_link) { - *(uint16_t *)addr = pcb->sp_link->hl_handle; - return sizeof(uint16_t); + ui = pcb->sp_link->hl_handle; + goto uinteger; } break; default: break; } + + bad: return 0; } Index: netinet/ip_mroute.c =================================================================== RCS file: /usr/cvs/src/sys/netinet/ip_mroute.c,v retrieving revision 1.110 diff -u -p -r1.110 ip_mroute.c --- netinet/ip_mroute.c 21 Dec 2007 02:07:55 -0000 1.110 +++ netinet/ip_mroute.c 29 Dec 2007 12:40:02 -0000 @@ -212,23 +212,19 @@ static const struct protosw vif_protosw 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 get_version(struct mbuf *); -static int set_assert(struct mbuf *); -static int get_assert(struct mbuf *); -static int add_vif(struct mbuf *); -static int del_vif(struct mbuf *); +static int ip_mrouter_init(struct socket *); +static int set_assert(int); +static int add_vif(struct vifctl *); +static int del_vif(vifi_t *); static void update_mfc_params(struct mfc *, struct mfcctl2 *); static void init_mfc_params(struct mfc *, struct mfcctl2 *); static void expire_mfc(struct mfc *); -static int add_mfc(struct mbuf *); +static int add_mfc(struct sockopt *); #ifdef UPCALL_TIMING static void collate(struct timeval *); #endif -static int del_mfc(struct mbuf *); -static int set_api_config(struct mbuf *); /* chose API capabilities */ -static int get_api_support(struct mbuf *); -static int get_api_config(struct mbuf *); +static int del_mfc(struct sockopt *); +static int set_api_config(u_int32_t *); /* chose API capabilities */ static int socket_send(struct socket *, struct mbuf *, struct sockaddr_in *); static void expire_upcalls(void *); #ifdef RSVP_ISI @@ -251,8 +247,8 @@ static int priority(struct vif *, struct * Bandwidth monitoring */ static void free_bw_list(struct bw_meter *); -static int add_bw_upcall(struct mbuf *); -static int del_bw_upcall(struct mbuf *); +static int add_bw_upcall(struct bw_upcall *); +static int del_bw_upcall(struct bw_upcall *); static void bw_meter_receive_packet(struct bw_meter *, int , struct timeval *); static void bw_meter_prepare_upcall(struct bw_meter *, struct timeval *); static void bw_upcalls_send(void); @@ -438,51 +434,97 @@ u_int32_t upcall_data[51]; * Handle MRT setsockopt commands to modify the multicast routing tables. */ int -ip_mrouter_set(struct socket *so, int optname, struct mbuf **m) +ip_mrouter_set(struct socket *so, struct sockopt *sopt) { int error; + int optval; + struct vifctl *vifc; + vifi_t *vifi; + struct bw_upcall *bwuc; + void *v; - if (optname != MRT_INIT && so != ip_mrouter) + if (sopt->sopt_name != MRT_INIT && so != ip_mrouter) error = ENOPROTOOPT; - else - switch (optname) { + else { + switch (sopt->sopt_name) { case MRT_INIT: - error = ip_mrouter_init(so, *m); + v = sockopt_getintptr(sopt); + if (v == NULL) { + error = EINVAL; + break; + } + optval = *((int *)v); + + if (optval != 1) { + error = EINVAL; + break; + } + + error = ip_mrouter_init(so); break; case MRT_DONE: error = ip_mrouter_done(); break; case MRT_ADD_VIF: - error = add_vif(*m); + vifc = sockopt_get(sopt, sizeof(vifc)); + if (vifc == NULL) { + error = EINVAL; + break; + } + error = add_vif(vifc); break; case MRT_DEL_VIF: - error = del_vif(*m); + vifi = sockopt_get(sopt, sizeof(vifi)); + if (vifi == NULL) { + error = EINVAL; + break; + } + error = del_vif(vifi); break; case MRT_ADD_MFC: - error = add_mfc(*m); + error = add_mfc(sopt); break; case MRT_DEL_MFC: - error = del_mfc(*m); + error = del_mfc(sopt); break; case MRT_ASSERT: - error = set_assert(*m); + v = sockopt_getintptr(sopt); + if (v == NULL) { + error = EINVAL; + break; + } + optval = *((int *)v); + error = set_assert(optval); break; case MRT_API_CONFIG: - error = set_api_config(*m); + v = sockopt_get(sopt, sizeof(uint16_t)); + if (v == NULL) { + error = EINVAL; + break; + } + error = set_api_config(v); break; case MRT_ADD_BW_UPCALL: - error = add_bw_upcall(*m); + bwuc = sockopt_get(sopt, sizeof(bwuc)); + if (bwuc == NULL) { + error = EINVAL; + break; + } + error = add_bw_upcall(bwuc); break; case MRT_DEL_BW_UPCALL: - error = del_bw_upcall(*m); + bwuc = sockopt_get(sopt, sizeof(bwuc)); + if (bwuc == NULL) { + error = EINVAL; + break; + } + error = del_bw_upcall(bwuc); break; default: error = ENOPROTOOPT; break; } - - if (*m) - m_free(*m); + } return (error); } @@ -490,38 +532,37 @@ ip_mrouter_set(struct socket *so, int op * Handle MRT getsockopt commands */ int -ip_mrouter_get(struct socket *so, int optname, struct mbuf **m) +ip_mrouter_get(struct socket *so, struct sockopt *sopt) { int error; + int optval; + uint32_t ui; if (so != ip_mrouter) error = ENOPROTOOPT; else { - *m = m_get(M_WAIT, MT_SOOPTS); - MCLAIM(*m, so->so_mowner); - - switch (optname) { + switch (sopt->sopt_name) { case MRT_VERSION: - error = get_version(*m); + optval = 0x0305; /* XXX !!!! */ + error = sockopt_set(sopt, &optval, sizeof(optval)); break; case MRT_ASSERT: - error = get_assert(*m); + optval = pim_assert; + error = sockopt_set(sopt, &optval, sizeof(optval)); break; case MRT_API_SUPPORT: - error = get_api_support(*m); + ui = mrt_api_support; + error = sockopt_set(sopt, &ui, sizeof(ui)); break; case MRT_API_CONFIG: - error = get_api_config(*m); + ui = mrt_api_config; + error = sockopt_set(sopt, &ui, sizeof(ui)); break; default: error = ENOPROTOOPT; break; } - - if (error) - m_free(*m); } - return (error); } @@ -598,10 +639,8 @@ get_vif_cnt(struct sioc_vif_req *req) * Enable multicast routing */ static int -ip_mrouter_init(struct socket *so, struct mbuf *m) +ip_mrouter_init(struct socket *so) { - int *v; - if (mrtdebug) log(LOG_DEBUG, "ip_mrouter_init: so_type = %d, pr_protocol = %d\n", @@ -611,13 +650,6 @@ ip_mrouter_init(struct socket *so, struc so->so_proto->pr_protocol != IPPROTO_IGMP) return (EOPNOTSUPP); - if (m == NULL || m->m_len != sizeof(int)) - return (EINVAL); - - v = mtod(m, int *); - if (*v != 1) - return (EINVAL); - if (ip_mrouter != NULL) return (EADDRINUSE); @@ -733,42 +765,13 @@ ip_mrouter_detach(struct ifnet *ifp) } } -static int -get_version(struct mbuf *m) -{ - int *v = mtod(m, int *); - - *v = 0x0305; /* XXX !!!! */ - m->m_len = sizeof(int); - return (0); -} - /* * Set PIM assert processing global */ static int -set_assert(struct mbuf *m) +set_assert(int i) { - int *i; - - if (m == NULL || m->m_len != sizeof(int)) - return (EINVAL); - - i = mtod(m, int *); - pim_assert = !!*i; - return (0); -} - -/* - * Get PIM assert processing global - */ -static int -get_assert(struct mbuf *m) -{ - int *i = mtod(m, int *); - - *i = pim_assert; - m->m_len = sizeof(int); + pim_assert = !!i; return (0); } @@ -776,15 +779,9 @@ get_assert(struct mbuf *m) * Configure API capabilities */ static int -set_api_config(struct mbuf *m) +set_api_config(u_int32_t *apival) { int i; - u_int32_t *apival; - - if (m == NULL || m->m_len < sizeof(u_int32_t)) - return (EINVAL); - - apival = mtod(m, u_int32_t *); /* * We can set the API capabilities only if it is the first operation @@ -815,48 +812,11 @@ set_api_config(struct mbuf *m) } /* - * Get API capabilities - */ -static int -get_api_support(struct mbuf *m) -{ - u_int32_t *apival; - - if (m == NULL || m->m_len < sizeof(u_int32_t)) - return (EINVAL); - - apival = mtod(m, u_int32_t *); - - *apival = mrt_api_support; - - return (0); -} - -/* - * Get API configured capabilities - */ -static int -get_api_config(struct mbuf *m) -{ - u_int32_t *apival; - - if (m == NULL || m->m_len < sizeof(u_int32_t)) - return (EINVAL); - - apival = mtod(m, u_int32_t *); - - *apival = mrt_api_config; - - return (0); -} - -/* * Add a vif to the vif table */ static int -add_vif(struct mbuf *m) +add_vif(struct vifctl *vifcp) { - struct vifctl *vifcp; struct vif *vifp; struct ifaddr *ifa; struct ifnet *ifp; @@ -864,10 +824,6 @@ add_vif(struct mbuf *m) int error, s; struct sockaddr_in sin; - if (m == NULL || m->m_len < sizeof(struct vifctl)) - return (EINVAL); - - vifcp = mtod(m, struct vifctl *); if (vifcp->vifc_vifi >= MAXVIFS) return (EINVAL); if (in_nullhost(vifcp->vifc_lcl_addr)) @@ -1040,17 +996,12 @@ reset_vif(struct vif *vifp) * Delete a vif from the vif table */ static int -del_vif(struct mbuf *m) +del_vif(vifi_t *vifip) { - vifi_t *vifip; struct vif *vifp; vifi_t vifi; int s; - if (m == NULL || m->m_len < sizeof(vifi_t)) - return (EINVAL); - - vifip = mtod(m, vifi_t *); if (*vifip >= numvifs) return (EINVAL); @@ -1136,7 +1087,7 @@ expire_mfc(struct mfc *rt) * Add an mfc entry */ static int -add_mfc(struct mbuf *m) +add_mfc(struct sockopt *sopt) { struct mfcctl2 mfcctl2; struct mfcctl2 *mfccp; @@ -1150,17 +1101,25 @@ add_mfc(struct mbuf *m) if (mrt_api_config & MRT_API_FLAGS_ALL) mfcctl_size = sizeof(struct mfcctl2); - if (m == NULL || m->m_len < mfcctl_size) - return (EINVAL); - /* * select data size depending on API version. */ if (mrt_api_config & MRT_API_FLAGS_ALL) { - struct mfcctl2 *mp2 = mtod(m, struct mfcctl2 *); + struct mfcctl2 *mp2; + + mfcctl_size = sizeof(*mp2); + mp2 = sockopt_get(sopt, mfcctl_size); + if (mp2 == NULL) + return (EINVAL); + bcopy(mp2, (void *)&mfcctl2, sizeof(*mp2)); } else { - struct mfcctl *mp = mtod(m, struct mfcctl *); + struct mfcctl *mp; + + mfcctl_size = sizeof(*mp); + mp = sockopt_get(sopt, mfcctl_size); + if (mp == NULL) + return (EINVAL); memcpy(&mfcctl2, mp, sizeof(*mp)); memset((char *)&mfcctl2 + sizeof(struct mfcctl), 0, sizeof(mfcctl2) - sizeof(struct mfcctl)); @@ -1306,23 +1265,28 @@ collate(struct timeval *t) * Delete an mfc entry */ static int -del_mfc(struct mbuf *m) +del_mfc(struct sockopt *sopt) { struct mfcctl2 mfcctl2; struct mfcctl2 *mfccp; struct mfc *rt; int s; - int mfcctl_size = sizeof(struct mfcctl); - struct mfcctl *mp = mtod(m, struct mfcctl *); + struct mfcctl *mp; + struct mfcctl *mp2; + + mp = sockopt_get(sopt, sizeof(*mp)); + if (mp == NULL) { + mp2 = sockopt_get(sopt, sizeof(*mp2)); + if (mp2 == NULL) /* XXX elad */ + return (EINVAL); + mp = (struct mfcctl *)mp2; + } /* * XXX: for deleting MFC entries the information in entries * of size "struct mfcctl" is sufficient. */ - if (m == NULL || m->m_len < mfcctl_size) - return (EINVAL); - memcpy(&mfcctl2, mp, sizeof(*mp)); memset((char *)&mfcctl2 + sizeof(struct mfcctl), 0, sizeof(mfcctl2) - sizeof(struct mfcctl)); @@ -2553,7 +2517,7 @@ compute_bw_meter_flags(struct bw_upcall * Add a bw_meter entry */ static int -add_bw_upcall(struct mbuf *m) +add_bw_upcall(struct bw_upcall *req) { int s; struct mfc *mfc; @@ -2562,12 +2526,6 @@ add_bw_upcall(struct mbuf *m) struct timeval now; struct bw_meter *x; uint32_t flags; - struct bw_upcall *req; - - if (m == NULL || m->m_len < sizeof(struct bw_upcall)) - return EINVAL; - - req = mtod(m, struct bw_upcall *); if (!(mrt_api_config & MRT_MFC_BW_UPCALL)) return EOPNOTSUPP; @@ -2652,17 +2610,11 @@ free_bw_list(struct bw_meter *list) * Delete one or multiple bw_meter entries */ static int -del_bw_upcall(struct mbuf *m) +del_bw_upcall(struct bw_upcall *req) { int s; struct mfc *mfc; struct bw_meter *x; - struct bw_upcall *req; - - if (m == NULL || m->m_len < sizeof(struct bw_upcall)) - return EINVAL; - - req = mtod(m, struct bw_upcall *); if (!(mrt_api_config & MRT_MFC_BW_UPCALL)) return EOPNOTSUPP; Index: netinet/ip_mroute.h =================================================================== RCS file: /usr/cvs/src/sys/netinet/ip_mroute.h,v retrieving revision 1.29 diff -u -p -r1.29 ip_mroute.h --- netinet/ip_mroute.h 25 Dec 2007 18:33:46 -0000 1.29 +++ netinet/ip_mroute.h 26 Dec 2007 22:33:45 -0000 @@ -332,8 +332,8 @@ struct bw_meter { struct timeval bm_start_time; /* abs. time */ }; -int ip_mrouter_set(struct socket *, int, struct mbuf **); -int ip_mrouter_get(struct socket *, int, struct mbuf **); +int ip_mrouter_set(struct socket *, struct sockopt *); +int ip_mrouter_get(struct socket *, struct sockopt *); int mrt_ioctl(struct socket *, u_long, void *); int ip_mrouter_done(void); void ip_mrouter_detach(struct ifnet *); Index: netinet/ip_output.c =================================================================== RCS file: /usr/cvs/src/sys/netinet/ip_output.c,v retrieving revision 1.191 diff -u -p -r1.191 ip_output.c --- netinet/ip_output.c 14 Jan 2008 04:19:09 -0000 1.191 +++ netinet/ip_output.c 15 Jan 2008 11:55:33 -0000 @@ -157,7 +157,6 @@ static struct mbuf *ip_insertoptions(str static struct ifnet *ip_multicast_if(struct in_addr *, int *); static void ip_mloopback(struct ifnet *, struct mbuf *, const struct sockaddr_in *); -static int ip_getoptval(struct mbuf *, u_int8_t *, u_int); #ifdef PFIL_HOOKS extern struct pfil_head inet_pfil_hook; /* XXX */ @@ -1197,36 +1196,46 @@ ip_optcopy(struct ip *ip, struct ip *jp) * IP socket option processing. */ int -ip_ctloutput(int op, struct socket *so, int level, int optname, - struct mbuf **mp) +ip_ctloutput(struct socket *so, struct sockopt *sopt) { struct inpcb *inp = sotoinpcb(so); - struct mbuf *m = *mp; int optval = 0; int error = 0; -#if defined(IPSEC) || defined(FAST_IPSEC) - struct lwp *l = curlwp; /*XXX*/ -#endif + int op, level; + void *v; + + op = sopt->sopt_dir; + level = sopt->sopt_level; if (level != IPPROTO_IP) { - if (op == PRCO_SETOPT && *mp) - (void) m_free(*mp); - if (level == SOL_SOCKET && optname == SO_NOHEADER) + if (level == SOL_SOCKET && sopt->sopt_name == SO_NOHEADER) return 0; return ENOPROTOOPT; } switch (op) { - - case PRCO_SETOPT: - switch (optname) { + 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; + + m = sockopt_getmbuf(sopt); + if (m == NULL) { + error = ENOBUFS; + break; + } + + error = ip_pcbopts(&inp->inp_options, sopt->sopt_name, m); + if (!error) + error = sockopt_setmbuf(sopt, m); + + return (error); + } case IP_TOS: case IP_TTL: @@ -1234,43 +1243,44 @@ ip_ctloutput(int op, struct socket *so, case IP_RECVRETOPTS: case IP_RECVDSTADDR: case IP_RECVIF: - if (m == NULL || m->m_len != sizeof(int)) + v = sockopt_getintptr(sopt); + if (v == NULL) { error = EINVAL; - else { - optval = *mtod(m, int *); - switch (optname) { - - case IP_TOS: - inp->inp_ip.ip_tos = optval; - break; - - case IP_TTL: - inp->inp_ip.ip_ttl = optval; - break; + break; + } + optval = *((int *)v); + + switch (sopt->sopt_name) { + case IP_TOS: + inp->inp_ip.ip_tos = optval; + break; + + case IP_TTL: + inp->inp_ip.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_RECVRETOPTS: - OPTSET(INP_RECVRETOPTS); - break; - - case IP_RECVDSTADDR: - OPTSET(INP_RECVDSTADDR); - break; - - case IP_RECVIF: - OPTSET(INP_RECVIF); - break; - } + case IP_RECVOPTS: + OPTSET(INP_RECVOPTS); + break; + + case IP_RECVRETOPTS: + OPTSET(INP_RECVRETOPTS); + break; + + case IP_RECVDSTADDR: + OPTSET(INP_RECVDSTADDR); + break; + + case IP_RECVIF: + OPTSET(INP_RECVIF); + break; } - break; + break; #undef OPTSET case IP_MULTICAST_IF: @@ -1278,31 +1288,33 @@ ip_ctloutput(int op, struct socket *so, case IP_MULTICAST_LOOP: case IP_ADD_MEMBERSHIP: case IP_DROP_MEMBERSHIP: - error = ip_setmoptions(optname, &inp->inp_moptions, m); + error = ip_setmoptions(&inp->inp_moptions, sopt); break; case IP_PORTRANGE: - if (m == 0 || m->m_len != sizeof(int)) + v = sockopt_getintptr(sopt); + if (v == NULL) { error = EINVAL; - else { - optval = *mtod(m, int *); + break; + } + optval = *((int *)v); - switch (optval) { + /* INP_LOCK(inp); */ + switch (optval) { + case IP_PORTRANGE_DEFAULT: + case IP_PORTRANGE_HIGH: + inp->inp_flags &= ~(INP_LOWPORT); + break; - case IP_PORTRANGE_DEFAULT: - case IP_PORTRANGE_HIGH: - inp->inp_flags &= ~(INP_LOWPORT); - break; - - case IP_PORTRANGE_LOW: - inp->inp_flags |= INP_LOWPORT; - break; - - default: - error = EINVAL; - break; - } + case IP_PORTRANGE_LOW: + inp->inp_flags |= INP_LOWPORT; + break; + + default: + error = EINVAL; + break; } + /* INP_UNLOCK(inp); */ break; #if defined(IPSEC) || defined(FAST_IPSEC) @@ -1311,9 +1323,12 @@ ip_ctloutput(int op, struct socket *so, void *req = NULL; size_t len = 0; int priv = 0; + struct mbuf *m; + int optname; #ifdef __NetBSD__ - if (l == 0 || kauth_authorize_generic(l->l_cred, + if (sopt->sopt_lwp == NULL || + kauth_authorize_generic(sopt->sopt_lwp->l_cred, KAUTH_GENERIC_ISSUSER, NULL)) priv = 0; else @@ -1321,11 +1336,20 @@ ip_ctloutput(int op, struct socket *so, #else priv = (in6p->in6p_socket->so_state & SS_PRIV); #endif - if (m) { - req = mtod(m, void *); - len = m->m_len; + + m = sockopt_getmbuf(sopt); + if (m == NULL) { + error = ENOBUFS; + break; } + req = mtod(m, void *); + len = m->m_len; + optname = sopt->sopt_name; error = ipsec4_set_policy(inp, optname, req, len, priv); + m_freem(m); + if (!error) + error = sockopt_setmbuf(sopt, m); + break; } #endif /*IPSEC*/ @@ -1334,22 +1358,18 @@ ip_ctloutput(int op, struct socket *so, 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); - MCLAIM(m, so->so_mowner); if (inp->inp_options) { - m->m_len = inp->inp_options->m_len; - bcopy(mtod(inp->inp_options, void *), - mtod(m, void *), (unsigned)m->m_len); + error = sockopt_set(sopt, + mtod(inp->inp_options, void *), + inp->inp_options->m_len); } else - m->m_len = 0; + sopt->sopt_size = 0; break; case IP_TOS: @@ -1359,10 +1379,7 @@ ip_ctloutput(int op, struct socket *so, case IP_RECVDSTADDR: case IP_RECVIF: case IP_ERRORMTU: - *mp = m = m_get(M_WAIT, MT_SOOPTS); - MCLAIM(m, so->so_mowner); - m->m_len = sizeof(int); - switch (optname) { + switch (sopt->sopt_name) { case IP_TOS: optval = inp->inp_ip.ip_tos; @@ -1394,7 +1411,7 @@ ip_ctloutput(int op, struct socket *so, optval = OPTBIT(INP_RECVIF); break; } - *mtod(m, int *) = optval; + error = sockopt_set(sopt, &optval, sizeof(optval)); break; #if 0 /* defined(IPSEC) || defined(FAST_IPSEC) */ @@ -1403,12 +1420,17 @@ ip_ctloutput(int op, struct socket *so, { void *req = NULL; size_t len = 0; + struct mbuf *m = NULL; if (m) { req = mtod(m, void *); len = m->m_len; } error = ipsec4_get_policy(inp, req, len, mp); + if (!error) + error = soopt_mcopyout(sopt, m); /* XXX */ + if (!error) + m_freem(m); break; } #endif /*IPSEC*/ @@ -1418,22 +1440,17 @@ ip_ctloutput(int op, struct socket *so, case IP_MULTICAST_LOOP: case IP_ADD_MEMBERSHIP: case IP_DROP_MEMBERSHIP: - error = ip_getmoptions(optname, inp->inp_moptions, mp); - if (*mp) - MCLAIM(*mp, so->so_mowner); + error = ip_getmoptions(inp->inp_moptions, sopt); break; case IP_PORTRANGE: - *mp = m = m_get(M_WAIT, MT_SOOPTS); - MCLAIM(m, so->so_mowner); - m->m_len = sizeof(int); - if (inp->inp_flags & INP_LOWPORT) optval = IP_PORTRANGE_LOW; else optval = IP_PORTRANGE_DEFAULT; - *mtod(m, int *) = optval; + error = sockopt_set(sopt, &optval, sizeof(optval)); + break; default: @@ -1451,11 +1468,7 @@ ip_ctloutput(int op, struct socket *so, * with destination address if source routed. */ int -#ifdef notyet -ip_pcbopts(int optname, struct mbuf **pcbopt, struct mbuf *m) -#else -ip_pcbopts(struct mbuf **pcbopt, struct mbuf *m) -#endif +ip_pcbopts(struct mbuf **pcbopt, int optname, struct mbuf *m) { int cnt, optlen; u_char *cp; @@ -1584,19 +1597,19 @@ ip_multicast_if(struct in_addr *a, int * } static int -ip_getoptval(struct mbuf *m, u_int8_t *val, u_int maxval) +ip_getoptval(struct sockopt *sopt, u_int8_t *val, u_int maxval) { u_int tval; - if (m == NULL) + if (sopt == NULL) return EINVAL; - switch (m->m_len) { + switch (sopt->sopt_size) { case sizeof(u_char): - tval = *(mtod(m, u_char *)); + tval = *((u_int8_t *)sockopt_get(sopt, sizeof(u_int8_t))); break; case sizeof(u_int): - tval = *(mtod(m, u_int *)); + tval = *((u_int *)sockopt_get(sopt, sizeof(u_int))); break; default: return EINVAL; @@ -1613,7 +1626,7 @@ ip_getoptval(struct mbuf *m, u_int8_t *v * Set the IP multicast options in response to user setsockopt(). */ int -ip_setmoptions(int optname, struct ip_moptions **imop, struct mbuf *m) +ip_setmoptions(struct ip_moptions **imop, struct sockopt *sopt) { int error = 0; int i; @@ -1622,6 +1635,7 @@ ip_setmoptions(int optname, struct ip_mo struct ifnet *ifp; struct ip_moptions *imo = *imop; int ifindex; + void *v; if (imo == NULL) { /* @@ -1641,17 +1655,18 @@ ip_setmoptions(int optname, struct ip_mo imo->imo_num_memberships = 0; } - switch (optname) { - + switch (sopt->sopt_name) { case IP_MULTICAST_IF: /* * Select the interface for outgoing multicast packets. */ - if (m == NULL || m->m_len != sizeof(struct in_addr)) { + v = sockopt_get(sopt, sizeof(addr)); + if (v == NULL) { error = EINVAL; break; } - addr = *(mtod(m, struct in_addr *)); + addr = *((struct in_addr *)v); + /* * INADDR_ANY is used to remove a previous selection. * When no interface is selected, a default one is @@ -1682,7 +1697,7 @@ ip_setmoptions(int optname, struct ip_mo /* * Set the IP time-to-live for outgoing multicast packets. */ - error = ip_getoptval(m, &imo->imo_multicast_ttl, MAXTTL); + error = ip_getoptval(sopt, &imo->imo_multicast_ttl, MAXTTL); break; case IP_MULTICAST_LOOP: @@ -1690,7 +1705,7 @@ ip_setmoptions(int optname, struct ip_mo * Set the loopback flag for outgoing multicast packets. * Must be zero or one. */ - error = ip_getoptval(m, &imo->imo_multicast_loop, 1); + error = ip_getoptval(sopt, &imo->imo_multicast_loop, 1); break; case IP_ADD_MEMBERSHIP: @@ -1698,11 +1713,12 @@ ip_setmoptions(int optname, struct ip_mo * Add a multicast group membership. * Group must be a valid IP multicast address. */ - if (m == NULL || m->m_len != sizeof(struct ip_mreq)) { + mreq = sockopt_get(sopt, sizeof(*mreq)); + if (mreq == NULL) { error = EINVAL; break; } - mreq = mtod(m, struct ip_mreq *); + if (!IN_MULTICAST(mreq->imr_multiaddr.s_addr)) { error = EINVAL; break; @@ -1772,11 +1788,12 @@ ip_setmoptions(int optname, struct ip_mo * Drop a multicast group membership. * Group must be a valid IP multicast address. */ - if (m == NULL || m->m_len != sizeof(struct ip_mreq)) { + mreq = sockopt_get(sopt, sizeof(*mreq)); + if (mreq == NULL) { error = EINVAL; break; } - mreq = mtod(m, struct ip_mreq *); + if (!IN_MULTICAST(mreq->imr_multiaddr.s_addr)) { error = EINVAL; break; @@ -1844,48 +1861,58 @@ ip_setmoptions(int optname, struct ip_mo * Return the IP multicast options in response to user getsockopt(). */ int -ip_getmoptions(int optname, struct ip_moptions *imo, struct mbuf **mp) +ip_getmoptions(struct ip_moptions *imo, struct sockopt *sopt) { - u_char *ttl; - u_char *loop; - struct in_addr *addr; + struct in_addr addr; struct in_ifaddr *ia; + u_char coptval; + int error, optval; - *mp = m_get(M_WAIT, MT_SOOPTS); - - switch (optname) { + error = 0; + switch (sopt->sopt_name) { 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 = zeroin_addr; + addr = zeroin_addr; else if (imo->imo_multicast_addr.s_addr) { /* return the value user has set */ - *addr = imo->imo_multicast_addr; + addr = imo->imo_multicast_addr; } else { IFP_TO_IA(imo->imo_multicast_ifp, ia); - *addr = ia ? ia->ia_addr.sin_addr : zeroin_addr; + addr = ia ? ia->ia_addr.sin_addr : zeroin_addr; } - return (0); + error = sockopt_set(sopt, &addr, sizeof(addr)); + break; case IP_MULTICAST_TTL: - ttl = mtod(*mp, u_char *); - (*mp)->m_len = 1; - *ttl = imo ? imo->imo_multicast_ttl - : IP_DEFAULT_MULTICAST_TTL; - return (0); + if (imo != NULL) + optval = coptval = imo->imo_multicast_ttl; + else + optval = coptval = IP_DEFAULT_MULTICAST_TTL; + + if (sopt->sopt_size == sizeof(u_char)) + error = sockopt_set(sopt, &coptval, sizeof(u_char)); + else + error = sockopt_set(sopt, &optval, sizeof(int)); + break; case IP_MULTICAST_LOOP: - loop = mtod(*mp, u_char *); - (*mp)->m_len = 1; - *loop = imo ? imo->imo_multicast_loop - : IP_DEFAULT_MULTICAST_LOOP; - return (0); + if (imo != NULL) + optval = coptval = imo->imo_multicast_loop; + else + optval = coptval = IP_DEFAULT_MULTICAST_LOOP; + + if (sopt->sopt_size == sizeof(u_char)) + error = sockopt_set(sopt, &coptval, sizeof(u_char)); + else + error = sockopt_set(sopt, &optval, sizeof(int)); + break; default: - return (EOPNOTSUPP); + error = EOPNOTSUPP; } + + return (error); } /* Index: netinet/ip_var.h =================================================================== RCS file: /usr/cvs/src/sys/netinet/ip_var.h,v retrieving revision 1.83 diff -u -p -r1.83 ip_var.h --- netinet/ip_var.h 25 Dec 2007 18:33:47 -0000 1.83 +++ netinet/ip_var.h 26 Dec 2007 22:33:45 -0000 @@ -218,34 +218,35 @@ extern int ip_hashsize; extern struct pool inmulti_pool; extern struct pool ipqent_pool; struct inpcb; +struct sockopt; -int ip_ctloutput(int, struct socket *, int, int, struct mbuf **); +int ip_ctloutput(struct socket *, struct sockopt *); int ip_dooptions(struct mbuf *); void ip_drain(void); void ip_forward(struct mbuf *, int); void ip_freef(struct ipq *); void ip_freemoptions(struct ip_moptions *); -int ip_getmoptions(int, struct ip_moptions *, struct mbuf **); +int ip_getmoptions(struct ip_moptions *, struct sockopt *); void ip_init(void); int ip_optcopy(struct ip *, struct ip *); u_int ip_optlen(struct inpcb *); int ip_output(struct mbuf *, ...); int ip_fragment(struct mbuf *, struct ifnet *, u_long); -int ip_pcbopts(struct mbuf **, struct mbuf *); +int ip_pcbopts(struct mbuf **, int, struct mbuf *); struct mbuf * ip_reass(struct ipqent *, struct ipq *, struct ipqhead *); struct in_ifaddr * ip_rtaddr(struct in_addr); void ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *, struct mbuf *); -int ip_setmoptions(int, struct ip_moptions **, struct mbuf *); +int ip_setmoptions(struct ip_moptions **, struct sockopt *); void ip_slowtimo(void); struct mbuf * ip_srcroute(void); int ip_sysctl(int *, u_int, void *, size_t *, void *, size_t); void ipintr(void); void * rip_ctlinput(int, const struct sockaddr *, void *); -int rip_ctloutput(int, struct socket *, int, int, struct mbuf **); +int rip_ctloutput(struct socket *, struct sockopt *); void rip_init(void); void rip_input(struct mbuf *, ...); int rip_output(struct mbuf *, ...); Index: netinet/raw_ip.c =================================================================== RCS file: /usr/cvs/src/sys/netinet/raw_ip.c,v retrieving revision 1.102 diff -u -p -r1.102 raw_ip.c --- netinet/raw_ip.c 21 Dec 2007 02:07:55 -0000 1.102 +++ netinet/raw_ip.c 29 Dec 2007 12:39:25 -0000 @@ -373,40 +373,50 @@ rip_output(struct mbuf *m, ...) * Raw IP socket option processing. */ int -rip_ctloutput(int op, struct socket *so, int level, int optname, - struct mbuf **m) +rip_ctloutput(struct socket *so, struct sockopt *sopt) { struct inpcb *inp = sotoinpcb(so); int error = 0; + int optval; + void *v; - if (level == SOL_SOCKET && optname == SO_NOHEADER) { - if (op == PRCO_GETOPT) { - *m = m_intopt(so, - (inp->inp_flags & INP_NOHEADER) ? 1 : 0); - return 0; - } else if (*m == NULL || (*m)->m_len != sizeof(int)) - error = EINVAL; - else if (*mtod(*m, int *)) { - inp->inp_flags &= ~INP_HDRINCL; - inp->inp_flags |= INP_NOHEADER; - } else - inp->inp_flags &= ~INP_NOHEADER; - goto free_m; - } else if (level != IPPROTO_IP) - return ip_ctloutput(op, so, level, optname, m); + if (sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_NOHEADER) { + if (sopt->sopt_dir == SOPT_GET) { + optval = (inp->inp_flags & INP_NOHEADER) ? 1 : 0; + error = sockopt_set(sopt, &optval, sizeof(optval)); + } else if (sopt->sopt_dir == SOPT_SET) { + v = sockopt_getintptr(sopt); + if (v == NULL) { + error = EINVAL; + goto out; + } + optval = *((int *)v); + if (optval) { + inp->inp_flags &= ~INP_HDRINCL; + inp->inp_flags |= INP_NOHEADER; + } else + inp->inp_flags &= ~INP_NOHEADER; + } + goto out; + } else if (sopt->sopt_level != IPPROTO_IP) + return ip_ctloutput(so, sopt); - switch (op) { + switch (sopt->sopt_dir) { - case PRCO_SETOPT: - switch (optname) { + case SOPT_SET: + switch (sopt->sopt_name) { case IP_HDRINCL: - if (*m == NULL || (*m)->m_len != sizeof(int)) + v = sockopt_getintptr(sopt); + if (v == NULL) { error = EINVAL; - else if (*mtod(*m, int *)) + break; + } + optval = *((int *)v); + if (optval) inp->inp_flags |= INP_HDRINCL; else inp->inp_flags &= ~INP_HDRINCL; - goto free_m; + break; #ifdef MROUTING case MRT_INIT: @@ -419,20 +429,21 @@ rip_ctloutput(int op, struct socket *so, case MRT_API_CONFIG: case MRT_ADD_BW_UPCALL: case MRT_DEL_BW_UPCALL: - error = ip_mrouter_set(so, optname, m); + error = ip_mrouter_set(so, sopt); break; #endif default: - error = ip_ctloutput(op, so, level, optname, m); + error = ip_ctloutput(so, sopt); break; } break; - case PRCO_GETOPT: - switch (optname) { + case SOPT_GET: + switch (sopt->sopt_name) { case IP_HDRINCL: - *m = m_intopt(so, inp->inp_flags & INP_HDRINCL ? 1 : 0); + optval = inp->inp_flags & INP_HDRINCL; + error = sockopt_set(sopt, &optval, sizeof(optval)); break; #ifdef MROUTING @@ -440,20 +451,17 @@ rip_ctloutput(int op, struct socket *so, case MRT_ASSERT: case MRT_API_SUPPORT: case MRT_API_CONFIG: - error = ip_mrouter_get(so, optname, m); + error = ip_mrouter_get(so, sopt); break; #endif default: - error = ip_ctloutput(op, so, level, optname, m); + error = ip_ctloutput(so, sopt); break; } break; } - return error; -free_m: - if (op == PRCO_SETOPT && *m != NULL) - (void)m_free(*m); + out: return error; } Index: netinet/tcp_usrreq.c =================================================================== RCS file: /usr/cvs/src/sys/netinet/tcp_usrreq.c,v retrieving revision 1.140 diff -u -p -r1.140 tcp_usrreq.c --- netinet/tcp_usrreq.c 16 Dec 2007 14:12:35 -0000 1.140 +++ netinet/tcp_usrreq.c 29 Dec 2007 12:39:15 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: tcp_usrreq.c,v 1.140 2007/12/16 14:12:35 elad Exp $ */ +/* $NetBSD: tcp_usrreq.c,v 1.139 2007/11/27 22:45:30 christos Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -102,7 +102,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: tcp_usrreq.c,v 1.140 2007/12/16 14:12:35 elad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: tcp_usrreq.c,v 1.139 2007/11/27 22:45:30 christos Exp $"); #include "opt_inet.h" #include "opt_ipsec.h" @@ -639,8 +639,7 @@ change_keepalive(struct socket *so, stru int -tcp_ctloutput(int op, struct socket *so, int level, int optname, - struct mbuf **mp) +tcp_ctloutput(struct socket *so, struct sockopt *sopt) { int error = 0, s; struct inpcb *inp; @@ -648,10 +647,17 @@ tcp_ctloutput(int op, struct socket *so, struct in6pcb *in6p; #endif struct tcpcb *tp; - struct mbuf *m; - int i; u_int ui; int family; /* family of the socket */ + int op, level, optname, optval; +#ifdef notyet /* XXX tcp_congctl_select() */ + char name[TCPCC_MAXLEN]; +#endif + void *v; + + op = sopt->sopt_dir; + level = sopt->sopt_level; + optname = sopt->sopt_name; family = so->so_proto->pr_domain->dom_family; @@ -682,20 +688,18 @@ tcp_ctloutput(int op, struct socket *so, #endif { splx(s); - if (op == PRCO_SETOPT && *mp) - (void) m_free(*mp); return (ECONNRESET); } if (level != IPPROTO_TCP) { switch (family) { #ifdef INET case PF_INET: - error = ip_ctloutput(op, so, level, optname, mp); + error = ip_ctloutput(so, sopt); break; #endif #ifdef INET6 case PF_INET6: - error = ip6_ctloutput(op, so, level, optname, mp); + error = ip6_ctloutput(so, sopt); break; #endif } @@ -712,18 +716,17 @@ tcp_ctloutput(int op, struct socket *so, tp = NULL; switch (op) { - - case PRCO_SETOPT: - m = *mp; + case SOPT_SET: switch (optname) { - #ifdef TCP_SIGNATURE case TCP_MD5SIG: - if (m == NULL || m->m_len != sizeof(int)) + v = sockopt_getintptr(sopt); + if (v == NULL) { error = EINVAL; - if (error) break; - if (*mtod(m, int *) > 0) + } + optval = *((int *)v); + if (optval > 0) tp->t_flags |= TF_SIGNATURE; else tp->t_flags &= ~TF_SIGNATURE; @@ -731,33 +734,50 @@ tcp_ctloutput(int op, struct socket *so, #endif /* TCP_SIGNATURE */ case TCP_NODELAY: - if (m == NULL || m->m_len != sizeof(int)) + v = sockopt_getintptr(sopt); + if (v == NULL) { error = EINVAL; - else if (*mtod(m, int *)) + break; + } + optval = *((int *)v); + if (optval) tp->t_flags |= TF_NODELAY; else tp->t_flags &= ~TF_NODELAY; break; case TCP_MAXSEG: - if (m && m->m_len == sizeof(int) && - (i = *mtod(m, int *)) > 0 && - i <= tp->t_peermss) - tp->t_peermss = i; /* limit on send size */ + v = sockopt_getintptr(sopt); + if (v == NULL) { + error = EINVAL; + break; + } + optval = *((int *)v); + if (optval > 0 && optval <= tp->t_peermss) + tp->t_peermss = optval; /* limit on send size */ else error = EINVAL; break; #ifdef notyet case TCP_CONGCTL: - if (m == NULL) + v = sockopt_getintptr(sopt); + if (v == NULL) { error = EINVAL; - error = tcp_congctl_select(tp, mtod(m, char *)); + break; + } + optval = *((int *)v); + error = tcp_congctl_select(tp, name); #endif break; case TCP_KEEPIDLE: - if (m && m->m_len == sizeof(u_int) && - (ui = *mtod(m, u_int *)) > 0) { + v = sockopt_get(sopt, sizeof(ui)); + if (v == NULL) { + error = EINVAL; + break; + } + ui = *((u_int *)v); + if (ui > 0) { tp->t_keepidle = ui; change_keepalive(so, tp); } else @@ -765,8 +785,13 @@ tcp_ctloutput(int op, struct socket *so, break; case TCP_KEEPINTVL: - if (m && m->m_len == sizeof(u_int) && - (ui = *mtod(m, u_int *)) > 0) { + v = sockopt_get(sopt, sizeof(ui)); + if (v == NULL) { + error = EINVAL; + break; + } + ui = *((u_int *)v); + if (ui > 0) { tp->t_keepintvl = ui; change_keepalive(so, tp); } else @@ -774,8 +799,13 @@ tcp_ctloutput(int op, struct socket *so, break; case TCP_KEEPCNT: - if (m && m->m_len == sizeof(u_int) && - (ui = *mtod(m, u_int *)) > 0) { + v = sockopt_get(sopt, sizeof(ui)); + if (v == NULL) { + error = EINVAL; + break; + } + ui = *((u_int *)v); + if (ui > 0) { tp->t_keepcnt = ui; change_keepalive(so, tp); } else @@ -783,8 +813,13 @@ tcp_ctloutput(int op, struct socket *so, break; case TCP_KEEPINIT: - if (m && m->m_len == sizeof(u_int) && - (ui = *mtod(m, u_int *)) > 0) { + v = sockopt_get(sopt, sizeof(ui)); + if (v == NULL) { + error = EINVAL; + break; + } + ui = *((u_int *)v); + if (ui > 0) { tp->t_keepinit = ui; change_keepalive(so, tp); } else @@ -795,24 +830,23 @@ tcp_ctloutput(int op, struct socket *so, error = ENOPROTOOPT; break; } - if (m) - (void) m_free(m); break; - case PRCO_GETOPT: - *mp = m = m_intopt(so, 0); - + case SOPT_GET: switch (optname) { #ifdef TCP_SIGNATURE case TCP_MD5SIG: - *mtod(m, int *) = (tp->t_flags & TF_SIGNATURE) ? 1 : 0; + optval = (tp->t_flags & TF_SIGNATURE) ? 1 : 0; + error = sockopt_set(sopt, &optval, sizeof(optval)); break; #endif case TCP_NODELAY: - *mtod(m, int *) = tp->t_flags & TF_NODELAY; + optval = tp->t_flags & TF_NODELAY; + error = sockopt_set(sopt, &optval, sizeof(optval)); break; case TCP_MAXSEG: - *mtod(m, int *) = tp->t_peermss; + optval = tp->t_peermss; + error = sockopt_set(sopt, &optval, sizeof(optval)); break; #ifdef notyet case TCP_CONGCTL: Index: netinet/tcp_var.h =================================================================== RCS file: /usr/cvs/src/sys/netinet/tcp_var.h,v retrieving revision 1.151 diff -u -p -r1.151 tcp_var.h --- netinet/tcp_var.h 25 Dec 2007 18:33:47 -0000 1.151 +++ netinet/tcp_var.h 26 Dec 2007 22:33:46 -0000 @@ -844,7 +844,7 @@ int tcp_isdead(struct tcpcb *); void tcp6_ctlinput(int, const struct sockaddr *, void *); #endif void *tcp_ctlinput(int, const struct sockaddr *, void *); -int tcp_ctloutput(int, struct socket *, int, int, struct mbuf **); +int tcp_ctloutput(struct socket *, struct sockopt *); struct tcpcb * tcp_disconnect(struct tcpcb *); struct tcpcb * Index: netinet/udp_usrreq.c =================================================================== RCS file: /usr/cvs/src/sys/netinet/udp_usrreq.c,v retrieving revision 1.163 diff -u -p -r1.163 udp_usrreq.c --- netinet/udp_usrreq.c 27 Nov 2007 22:45:30 -0000 1.163 +++ netinet/udp_usrreq.c 29 Dec 2007 12:40:21 -0000 @@ -987,14 +987,14 @@ udp_ctlinput(int cmd, const struct socka } int -udp_ctloutput(int op, struct socket *so, int level, int optname, - struct mbuf **mp) +udp_ctloutput(struct socket *so, struct sockopt *sopt) { int s; int error = 0; - struct mbuf *m; struct inpcb *inp; int family; + int optval; + void *v; family = so->so_proto->pr_domain->dom_family; @@ -1002,16 +1002,16 @@ udp_ctloutput(int op, struct socket *so, switch (family) { #ifdef INET case PF_INET: - if (level != IPPROTO_UDP) { - error = ip_ctloutput(op, so, level, optname, mp); + if (sopt->sopt_level != IPPROTO_UDP) { + error = ip_ctloutput(so, sopt); goto end; } break; #endif #ifdef INET6 case PF_INET6: - if (level != IPPROTO_UDP) { - error = ip6_ctloutput(op, so, level, optname, mp); + if (sopt->sopt_level != IPPROTO_UDP) { + error = ip6_ctloutput(so, sopt); goto end; } break; @@ -1022,19 +1022,20 @@ udp_ctloutput(int op, struct socket *so, } - switch (op) { - case PRCO_SETOPT: - m = *mp; + switch (sopt->sopt_dir) { + case SOPT_SET: inp = sotoinpcb(so); - switch (optname) { + switch (sopt->sopt_name) { case UDP_ENCAP: - if (m == NULL || m->m_len != sizeof(int)) { + v = sockopt_getintptr(sopt); + if (v == NULL) { error = EINVAL; break; } + optval = *((int *)v); - switch(*mtod(m, int *)) { + switch(optval) { #ifdef IPSEC_NAT_T case 0: inp->inp_flags &= ~INP_ESPINUDP_ALL; @@ -1060,9 +1061,6 @@ udp_ctloutput(int op, struct socket *so, error = ENOPROTOOPT; break; } - if (m != NULL) { - m_free(m); - } break; default: Index: netinet/udp_var.h =================================================================== RCS file: /usr/cvs/src/sys/netinet/udp_var.h,v retrieving revision 1.33 diff -u -p -r1.33 udp_var.h --- netinet/udp_var.h 25 Dec 2007 18:33:47 -0000 1.33 +++ netinet/udp_var.h 26 Dec 2007 22:33:46 -0000 @@ -95,7 +95,7 @@ extern struct udpstat udpstat; #endif void *udp_ctlinput(int, const struct sockaddr *, void *); -int udp_ctloutput(int, struct socket *, int, int, struct mbuf **); +int udp_ctloutput(struct socket *, struct sockopt *); void udp_init(void); void udp_input(struct mbuf *, ...); int udp_output(struct mbuf *, ...); Index: netinet6/icmp6.c =================================================================== RCS file: /usr/cvs/src/sys/netinet6/icmp6.c,v retrieving revision 1.141 diff -u -p -r1.141 icmp6.c --- netinet6/icmp6.c 4 Dec 2007 10:27:33 -0000 1.141 +++ netinet6/icmp6.c 22 Dec 2007 16:09:13 -0000 @@ -2553,32 +2553,23 @@ fail: * ICMPv6 socket option processing. */ int -icmp6_ctloutput(int op, struct socket *so, int level, - int optname, struct mbuf **mp) +icmp6_ctloutput(struct socket *so, struct sockopt *sopt) { int error = 0; - int optlen; struct in6pcb *in6p = sotoin6pcb(so); - struct mbuf *m = *mp; - optlen = m ? m->m_len : 0; + if (sopt->sopt_level != IPPROTO_ICMPV6) + return rip6_ctloutput(so, sopt); - if (level != IPPROTO_ICMPV6) - return rip6_ctloutput(op, so, level, optname, mp); - - switch (op) { - case PRCO_SETOPT: - switch (optname) { + switch (sopt->sopt_dir) { + case SOPT_SET: + switch (sopt->sopt_name) { case ICMP6_FILTER: { struct icmp6_filter *p; - if (optlen != sizeof(*p)) { - error = EMSGSIZE; - break; - } - p = mtod(m, struct icmp6_filter *); - if (!p || !in6p->in6p_icmp6filt) { + p = sockopt_get(sopt, sizeof(*p)); + if (p == NULL) { error = EINVAL; break; } @@ -2592,26 +2583,18 @@ icmp6_ctloutput(int op, struct socket *s error = ENOPROTOOPT; break; } - if (m) - (void)m_freem(m); break; - case PRCO_GETOPT: - switch (optname) { + case SOPT_GET: + switch (sopt->sopt_name) { case ICMP6_FILTER: { - struct icmp6_filter *p; - - if (!in6p->in6p_icmp6filt) { + if (in6p->in6p_icmp6filt == NULL) { error = EINVAL; break; } - *mp = m = m_get(M_WAIT, MT_SOOPTS); - m->m_len = sizeof(struct icmp6_filter); - p = mtod(m, struct icmp6_filter *); - bcopy(in6p->in6p_icmp6filt, p, - sizeof(struct icmp6_filter)); - error = 0; + error = sockopt_set(sopt, in6p->in6p_icmp6filt, + sizeof(struct icmp6_filter)); break; } Index: netinet6/ip6_mroute.c =================================================================== RCS file: /usr/cvs/src/sys/netinet6/ip6_mroute.c,v retrieving revision 1.86 diff -u -p -r1.86 ip6_mroute.c --- netinet6/ip6_mroute.c 27 Nov 2007 22:45:30 -0000 1.86 +++ netinet6/ip6_mroute.c 29 Dec 2007 12:39:42 -0000 @@ -159,7 +159,6 @@ static int ip6_mdq(struct mbuf *, struct static void phyint_send(struct ip6_hdr *, struct mif6 *, struct mbuf *); static int set_pim6(int *); -static int get_pim6(struct mbuf *); static int socket_send(struct socket *, struct mbuf *, struct sockaddr_in6 *); static int register_send(struct ip6_hdr *, struct mif6 *, struct mbuf *); @@ -296,65 +295,98 @@ static callout_t expire_upcalls_ch; * Handle MRT setsockopt commands to modify the multicast routing tables. */ int -ip6_mrouter_set(int cmd, struct socket *so, struct mbuf *m) +ip6_mrouter_set(struct socket *so, struct sockopt *sopt) { - if (cmd != MRT6_INIT && so != ip6_mrouter) + int error, optval; + struct mif6ctl *mifc; + struct mf6cctl *mfcc; + mifi_t *mifi; + void *v; + + if (sopt->sopt_name != MRT6_INIT && so != ip6_mrouter) return (EACCES); - switch (cmd) { + error = 0; + + switch (sopt->sopt_name) { #ifdef MRT6_OINIT case MRT6_OINIT: #endif case MRT6_INIT: - if (m == NULL || m->m_len != sizeof(int)) - return (EINVAL); - return (ip6_mrouter_init(so, *mtod(m, int *), cmd)); + v = sockopt_getintptr(sopt); + if (v == NULL) { + error = EINVAL; + break; + } + optval = *((int *)v); + return (ip6_mrouter_init(so, optval, sopt->sopt_name)); case MRT6_DONE: return (ip6_mrouter_done()); case MRT6_ADD_MIF: - if (m == NULL || m->m_len != sizeof(struct mif6ctl)) - return (EINVAL); - return (add_m6if(mtod(m, struct mif6ctl *))); + mifc = sockopt_get(sopt, sizeof(*mifc)); + if (mifc == NULL) { + error = EINVAL; + break; + } + return (add_m6if(mifc)); case MRT6_DEL_MIF: - if (m == NULL || m->m_len != sizeof(mifi_t)) - return (EINVAL); - return (del_m6if(mtod(m, mifi_t *))); + mifi = sockopt_get(sopt, sizeof(*mifi)); + if (mifi == NULL) { + error = EINVAL; + break; + } + return (del_m6if(mifi)); case MRT6_ADD_MFC: - if (m == NULL || m->m_len != sizeof(struct mf6cctl)) - return (EINVAL); - return (add_m6fc(mtod(m, struct mf6cctl *))); + mfcc = sockopt_get(sopt, sizeof(*mfcc)); + if (mfcc == NULL) { + error = EINVAL; + break; + } + return (add_m6fc(mfcc)); case MRT6_DEL_MFC: - if (m == NULL || m->m_len != sizeof(struct mf6cctl)) - return (EINVAL); - return (del_m6fc(mtod(m, struct mf6cctl *))); + mfcc = sockopt_get(sopt, sizeof(*mfcc)); + if (mfcc == NULL) { + error = EINVAL; + break; + } + return (del_m6fc(mfcc)); case MRT6_PIM: - if (m == NULL || m->m_len != sizeof(int)) - return (EINVAL); - return (set_pim6(mtod(m, int *))); + v = sockopt_getintptr(sopt); + if (v == NULL) { + error = EINVAL; + break; + } + optval = *((int *)v); + return (set_pim6(&optval)); default: - return (EOPNOTSUPP); + error = EOPNOTSUPP; } + + return (error); } /* * Handle MRT getsockopt commands */ int -ip6_mrouter_get(int cmd, struct socket *so, struct mbuf **m) +ip6_mrouter_get(struct socket *so, struct sockopt *sopt) { - struct mbuf *mb; + int error; if (so != ip6_mrouter) return EACCES; - *m = mb = m_get(M_WAIT, MT_SOOPTS); + error = 0; - switch (cmd) { + switch (sopt->sopt_name) { case MRT6_PIM: - return get_pim6(mb); + error = sockopt_set(sopt, &pim6, sizeof(pim6)); + break; default: - m_free(mb); - return EOPNOTSUPP; + error = EOPNOTSUPP; + break; } + + return (error); } /* @@ -418,21 +450,6 @@ get_mif6_cnt(struct sioc_mif_req6 *req) return 0; } -/* - * Get PIM processiong global - */ -static int -get_pim6(struct mbuf *m) -{ - int *i; - - i = mtod(m, int *); - - *i = pim6; - - return 0; -} - static int set_pim6(int *i) { Index: netinet6/ip6_mroute.h =================================================================== RCS file: /usr/cvs/src/sys/netinet6/ip6_mroute.h,v retrieving revision 1.13 diff -u -p -r1.13 ip6_mroute.h --- netinet6/ip6_mroute.h 1 Nov 2007 20:33:57 -0000 1.13 +++ netinet6/ip6_mroute.h 13 Dec 2007 19:45:23 -0000 @@ -267,8 +267,8 @@ struct rtdetq { /* XXX: rtdetq is also #define MAX_UPQ6 4 /* max. no of pkts in upcall Q */ -int ip6_mrouter_set(int, struct socket *, struct mbuf *); -int ip6_mrouter_get(int, struct socket *, struct mbuf **); +int ip6_mrouter_set(struct socket *, struct sockopt *); +int ip6_mrouter_get(struct socket *, struct sockopt *); int ip6_mrouter_done(void); void ip6_mrouter_detach(struct ifnet *); int mrt6_ioctl(int, void *); Index: netinet6/ip6_output.c =================================================================== RCS file: /usr/cvs/src/sys/netinet6/ip6_output.c,v retrieving revision 1.126 diff -u -p -r1.126 ip6_output.c --- netinet6/ip6_output.c 14 Jan 2008 04:16:45 -0000 1.126 +++ netinet6/ip6_output.c 15 Jan 2008 11:55:34 -0000 @@ -127,7 +127,7 @@ struct ip6_exthdrs { static int ip6_pcbopt(int, u_char *, int, struct ip6_pktopts **, int, int); -static int ip6_getpcbopt(struct ip6_pktopts *, int, struct mbuf **); +static int ip6_getpcbopt(struct ip6_pktopts *, int, struct sockopt *); static int ip6_setpktopt(int, u_char *, int, struct ip6_pktopts *, int, int, int, int); static int ip6_setmoptions(int, struct ip6_moptions **, struct mbuf *); @@ -143,7 +143,7 @@ static int copypktopts(struct ip6_pktopt #ifdef RFC2292 static int ip6_pcbopts(struct ip6_pktopts **, struct mbuf *, - struct socket *); + struct socket *, struct sockopt *); #endif #define IN6_NEED_CHECKSUM(ifp, csum_flags) \ @@ -1463,37 +1463,50 @@ ip6_getpmtu(struct route *ro_pmtu, struc * IP6 socket option processing. */ int -ip6_ctloutput(int op, struct socket *so, int level, int optname, - struct mbuf **mp) +ip6_ctloutput(struct socket *so, struct sockopt *sopt) { int privileged, optdatalen, uproto; void *optdata; struct in6pcb *in6p = sotoin6pcb(so); - struct mbuf *m = *mp; int error, optval; - int optlen; - struct lwp *l = curlwp; /* XXX */ + struct lwp *l; + int level, op, optname; + void *v; + + KASSERT(sopt != NULL); + + level = sopt->sopt_level; + op = sopt->sopt_dir; + optname = sopt->sopt_name; + l = sopt->sopt_lwp; - optlen = m ? m->m_len : 0; error = optval = 0; privileged = (l == 0 || kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL)) ? 0 : 1; uproto = (int)so->so_proto->pr_protocol; if (level != IPPROTO_IPV6) { - if (op == PRCO_SETOPT && *mp) - (void)m_free(*mp); return ENOPROTOOPT; } switch (op) { - case PRCO_SETOPT: + case SOPT_SET: switch (optname) { #ifdef RFC2292 - case IPV6_2292PKTOPTIONS: + case IPV6_2292PKTOPTIONS: { + struct mbuf *m; + + m = sockopt_getmbuf(sopt); /* XXX */ + /* m is freed in ip6_pcbopts */ error = ip6_pcbopts(&in6p->in6p_outputopts, - m, so); + m, so, sopt); + if (!error) + error = sockopt_setmbuf(sopt, m); + + m_free(m); /* XXX */ + break; + } #endif /* @@ -1527,13 +1540,13 @@ ip6_ctloutput(int op, struct socket *so, case IPV6_RECVPATHMTU: case IPV6_RECVTCLASS: case IPV6_V6ONLY: - if (optlen != sizeof(int)) { + v = sockopt_getintptr(sopt); + if (v == NULL) { error = EINVAL; break; } - optval = *mtod(m, int *); + optval = *((int *)v); switch (optname) { - case IPV6_UNICAST_HOPS: if (optval < -1 || optval >= 256) error = EINVAL; @@ -1701,11 +1714,12 @@ else \ struct ip6_pktopts **optp; u_int8_t tclass; - if (optlen != sizeof(tclass)) { + v = sockopt_get(sopt, sizeof(tclass)); + if (v == NULL) { error = EINVAL; break; } - tclass = *mtod(m, u_int8_t *); + tclass = *((u_int8_t *)v); optp = &in6p->in6p_outputopts; error = ip6_pcbopt(optname, (u_char *)&tclass, @@ -1718,11 +1732,12 @@ else \ case IPV6_TCLASS: case IPV6_DONTFRAG: case IPV6_USE_MIN_MTU: - if (optlen != sizeof(optval)) { + v = sockopt_getintptr(sopt); + if (v == NULL) { error = EINVAL; break; } - optval = *mtod(m, int *); + optval = *((int *)v); { struct ip6_pktopts **optp; optp = &in6p->in6p_outputopts; @@ -1741,11 +1756,13 @@ else \ case IPV6_2292DSTOPTS: case IPV6_2292RTHDR: /* RFC 2292 */ - if (optlen != sizeof(int)) { + v = sockopt_getintptr(sopt); + if (v == NULL) { error = EINVAL; break; } - optval = *mtod(m, int *); + optval = *((int *)v); + switch (optname) { case IPV6_2292PKTINFO: OPTSET2292(IN6P_PKTINFO); @@ -1778,16 +1795,11 @@ else \ case IPV6_RTHDR: case IPV6_DSTOPTS: case IPV6_RTHDRDSTOPTS: - case IPV6_NEXTHOP: - { + case IPV6_NEXTHOP: { /* new advanced API (RFC3542) */ - u_char *optbuf; + void *optbuf; int optbuflen; struct ip6_pktopts **optp; - if (!m) { - error = EINVAL; - break; - } #ifdef RFC2292 /* cannot mix with RFC2292 */ @@ -1797,35 +1809,40 @@ else \ } #endif - if (m && m->m_next) { - error = EINVAL; /* XXX */ - break; - } - - optbuf = mtod(m, u_char *); - optbuflen = m->m_len; + optbuflen = sopt->sopt_size; + optbuf = sockopt_get(sopt, optbuflen); optp = &in6p->in6p_outputopts; error = ip6_pcbopt(optname, optbuf, optbuflen, optp, privileged, uproto); break; - } + } #undef OPTSET case IPV6_MULTICAST_IF: case IPV6_MULTICAST_HOPS: case IPV6_MULTICAST_LOOP: case IPV6_JOIN_GROUP: - case IPV6_LEAVE_GROUP: + case IPV6_LEAVE_GROUP: { + struct mbuf *m; + + m = sockopt_getmbuf(sopt); + if (m == NULL) + return (ENOMEM); error = ip6_setmoptions(optname, &in6p->in6p_moptions, m); + if (!error) + error = sockopt_setmbuf(sopt, m); + break; + } case IPV6_PORTRANGE: - if (!m) { + v = sockopt_getintptr(sopt); + if (v == NULL) { error = EINVAL; break; } - optval = *mtod(m, int *); + optval = *((int *)v); switch (optval) { case IPV6_PORTRANGE_DEFAULT: @@ -1855,12 +1872,19 @@ else \ { void *req = NULL; size_t len = 0; - if (m) { + struct mbuf *m; + + m = sockopt_getmbuf(sopt); + if (m != NULL) { req = mtod(m, void *); len = m->m_len; } error = ipsec6_set_policy(in6p, optname, req, len, privileged); + if (!error) + error = sockopt_setmbuf(sopt, m); + + m_free(m); } break; #endif /* IPSEC */ @@ -1869,11 +1893,9 @@ else \ error = ENOPROTOOPT; break; } - if (m) - (void)m_free(m); break; - case PRCO_GETOPT: + case SOPT_GET: switch (optname) { #ifdef RFC2292 case IPV6_2292PKTOPTIONS: @@ -1886,8 +1908,6 @@ else \ * to simplify this part by always returning * empty data. */ - *mp = m_get(M_WAIT, MT_SOOPTS); - (*mp)->m_len = 0; break; #endif @@ -1965,9 +1985,7 @@ else \ } if (error) break; - *mp = m = m_get(M_WAIT, MT_SOOPTS); - m->m_len = sizeof(int); - *mtod(m, int *) = optval; + error = sockopt_set(sopt, &optval, sizeof(optval)); break; case IPV6_PATHMTU: @@ -1996,11 +2014,7 @@ else \ optdatalen = sizeof(mtuinfo); if (optdatalen > MCLBYTES) return (EMSGSIZE); /* XXX */ - *mp = m = m_get(M_WAIT, MT_SOOPTS); - if (optdatalen > MLEN) - MCLGET(m, M_WAIT); - m->m_len = optdatalen; - memcpy(mtod(m, void *), optdata, optdatalen); + error = sockopt_set(sopt, optdata, optdatalen); break; } @@ -2027,9 +2041,7 @@ else \ optval = OPTBIT(IN6P_DSTOPTS|IN6P_RTHDRDSTOPTS); break; } - *mp = m = m_get(M_WAIT, MT_SOOPTS); - m->m_len = sizeof(int); - *mtod(m, int *) = optval; + error = sockopt_set(sopt, &optval, sizeof(optval)); break; #endif case IPV6_PKTINFO: @@ -2043,30 +2055,43 @@ else \ case IPV6_DONTFRAG: case IPV6_USE_MIN_MTU: error = ip6_getpcbopt(in6p->in6p_outputopts, - optname, mp); + optname, sopt); break; case IPV6_MULTICAST_IF: case IPV6_MULTICAST_HOPS: case IPV6_MULTICAST_LOOP: case IPV6_JOIN_GROUP: - case IPV6_LEAVE_GROUP: + case IPV6_LEAVE_GROUP: { + struct mbuf *m; + error = ip6_getmoptions(optname, - in6p->in6p_moptions, mp); + in6p->in6p_moptions, &m); + if (!error) + error = sockopt_set(sopt, mtod(m, void *), + m->m_len); + m_free(m); break; + } #if defined(IPSEC) || defined(FAST_IPSEC) - case IPV6_IPSEC_POLICY: - { + case IPV6_IPSEC_POLICY: { + struct mbuf *m = NULL; void *req = NULL; size_t len = 0; - if (m) { + + m = sockopt_getmbuf(sopt); + if (m != NULL) { req = mtod(m, void *); len = m->m_len; } - error = ipsec6_get_policy(in6p, req, len, mp); + + error = ipsec6_get_policy(in6p, req, len, &m); + if (!error) + error = sockopt_setmbuf(sopt, m); + break; - } + } #endif /* IPSEC */ @@ -2082,19 +2107,21 @@ else \ } int -ip6_raw_ctloutput(int op, struct socket *so, int level, int optname, - struct mbuf **mp) +ip6_raw_ctloutput(struct socket *so, struct sockopt *sopt) { - int error = 0, optval, optlen; + int error = 0, optval; const int icmp6off = offsetof(struct icmp6_hdr, icmp6_cksum); struct in6pcb *in6p = sotoin6pcb(so); - struct mbuf *m = *mp; + int op, level, optname; + void *v; + + KASSERT(sopt != NULL); - optlen = m ? m->m_len : 0; + op = sopt->sopt_dir; + level = sopt->sopt_level; + optname = sopt->sopt_name; if (level != IPPROTO_IPV6) { - if (op == PRCO_SETOPT && *mp) - (void)m_free(*mp); return ENOPROTOOPT; } @@ -2109,12 +2136,13 @@ ip6_raw_ctloutput(int op, struct socket * behavior does not meet RFC3542. */ switch (op) { - case PRCO_SETOPT: - if (optlen != sizeof(int)) { + case SOPT_SET: + v = sockopt_getintptr(sopt); + if (v == NULL) { error = EINVAL; break; } - optval = *mtod(m, int *); + optval = *((int *)v); if ((optval % 2) != 0) { /* the API assumes even offset values */ error = EINVAL; @@ -2126,15 +2154,13 @@ ip6_raw_ctloutput(int op, struct socket in6p->in6p_cksum = optval; break; - case PRCO_GETOPT: + case SOPT_GET: if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) optval = icmp6off; else optval = in6p->in6p_cksum; - *mp = m = m_get(M_WAIT, MT_SOOPTS); - m->m_len = sizeof(int); - *mtod(m, int *) = optval; + error = sockopt_set(sopt, &optval, sizeof(optval)); break; default: @@ -2148,9 +2174,6 @@ ip6_raw_ctloutput(int op, struct socket break; } - if (op == PRCO_SETOPT && m) - (void)m_free(m); - return (error); } @@ -2160,7 +2183,8 @@ ip6_raw_ctloutput(int op, struct socket * specifying behavior of outgoing packets. */ static int -ip6_pcbopts(struct ip6_pktopts **pktopt, struct mbuf *m, struct socket *so) +ip6_pcbopts(struct ip6_pktopts **pktopt, struct mbuf *m, struct socket *so, + struct sockopt *sopt) { struct ip6_pktopts *opt = *pktopt; int error = 0; @@ -2236,7 +2260,7 @@ ip6_pcbopt(int optname, u_char *buf, int } static int -ip6_getpcbopt(struct ip6_pktopts *pktopt, int optname, struct mbuf **mp) +ip6_getpcbopt(struct ip6_pktopts *pktopt, int optname, struct sockopt *sopt) { void *optdata = NULL; int optdatalen = 0; @@ -2245,7 +2269,6 @@ ip6_getpcbopt(struct ip6_pktopts *pktopt struct in6_pktinfo null_pktinfo; int deftclass = 0, on; int defminmtu = IP6PO_MINMTU_MCASTONLY; - struct mbuf *m; switch (optname) { case IPV6_PKTINFO: @@ -2324,14 +2347,7 @@ ip6_getpcbopt(struct ip6_pktopts *pktopt return (ENOPROTOOPT); } - if (optdatalen > MCLBYTES) - return (EMSGSIZE); /* XXX */ - *mp = m = m_get(M_WAIT, MT_SOOPTS); - if (optdatalen > MLEN) - MCLGET(m, M_WAIT); - m->m_len = optdatalen; - if (optdatalen) - memcpy(mtod(m, void *), optdata, optdatalen); + error = sockopt_set(sopt, optdata, optdatalen); return (error); } Index: netinet6/ip6_var.h =================================================================== RCS file: /usr/cvs/src/sys/netinet6/ip6_var.h,v retrieving revision 1.46 diff -u -p -r1.46 ip6_var.h --- netinet6/ip6_var.h 29 Oct 2007 16:54:43 -0000 1.46 +++ netinet6/ip6_var.h 13 Dec 2007 15:42:15 -0000 @@ -64,6 +64,7 @@ #ifndef _NETINET6_IP6_VAR_H_ #define _NETINET6_IP6_VAR_H_ +#include #include /* @@ -311,7 +312,7 @@ extern int ip6_hashsize; /* size of has struct in6pcb; -int icmp6_ctloutput(int, struct socket *, int, int, struct mbuf **); +int icmp6_ctloutput(struct socket *, struct sockopt *); void ip6_init(void); void ip6intr(void); @@ -345,8 +346,8 @@ int ip6_output(struct mbuf *, struct ip6 struct route *, int, struct ip6_moptions *, struct socket *, struct ifnet **); -int ip6_ctloutput(int, struct socket *, int, int, struct mbuf **); -int ip6_raw_ctloutput(int, struct socket *, int, int, struct mbuf **); +int ip6_ctloutput(struct socket *, struct sockopt *); +int ip6_raw_ctloutput(struct socket *, struct sockopt *); void ip6_initpktopts(struct ip6_pktopts *); int ip6_setpktopts(struct mbuf *, struct ip6_pktopts *, struct ip6_pktopts *, int, int); @@ -370,7 +371,7 @@ int ip6flow_invalidate_all(int); void rip6_init(void); int rip6_input(struct mbuf **, int *, int); void rip6_ctlinput(int, const struct sockaddr *, void *); -int rip6_ctloutput(int, struct socket *, int, int, struct mbuf **); +int rip6_ctloutput(struct socket *, struct sockopt *); int rip6_output(struct mbuf *, struct socket *, struct sockaddr_in6 *, struct mbuf *); int rip6_usrreq(struct socket *, Index: netinet6/ip6protosw.h =================================================================== RCS file: /usr/cvs/src/sys/netinet6/ip6protosw.h,v retrieving revision 1.19 diff -u -p -r1.19 ip6protosw.h --- netinet6/ip6protosw.h 19 Jul 2007 20:48:57 -0000 1.19 +++ netinet6/ip6protosw.h 13 Dec 2007 22:35:44 -0000 @@ -126,7 +126,7 @@ struct ip6protosw { void (*pr_ctlinput) /* control input (from below) */ (int, const struct sockaddr *, void *); int (*pr_ctloutput) /* control output (from above) */ - (int, struct socket *, int, int, struct mbuf **); + (struct socket *, struct sockopt *); /* user-protocol hook */ int (*pr_usrreq) /* user request: see list below */ Index: netinet6/raw_ip6.c =================================================================== RCS file: /usr/cvs/src/sys/netinet6/raw_ip6.c,v retrieving revision 1.91 diff -u -p -r1.91 raw_ip6.c --- netinet6/raw_ip6.c 27 Nov 2007 22:45:30 -0000 1.91 +++ netinet6/raw_ip6.c 29 Dec 2007 12:40:33 -0000 @@ -552,25 +552,35 @@ rip6_output(struct mbuf *m, struct socke * Raw IPv6 socket option processing. */ int -rip6_ctloutput(int op, struct socket *so, int level, int optname, - struct mbuf **mp) +rip6_ctloutput(struct socket *so, struct sockopt *sopt) { int error = 0; - if (level == SOL_SOCKET && optname == SO_NOHEADER) { + if (sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_NOHEADER) { + int optval; + /* need to fiddle w/ opt(IPPROTO_IPV6, IPV6_CHECKSUM)? */ - if (op == PRCO_GETOPT) { - *mp = m_intopt(so, 1); - return 0; - } else if (*mp == NULL || (*mp)->m_len != sizeof(int)) - error = EINVAL; - else if (*mtod(*mp, int *) == 0) - error = EINVAL; - goto free_m; - } else if (level != IPPROTO_IPV6) - return ip6_ctloutput(op, so, level, optname, mp); + if (sopt->sopt_dir == SOPT_GET) { + optval = 1; + error = sockopt_set(sopt, &optval, sizeof(optval)); + } else if (sopt->sopt_dir == SOPT_SET) { + void *v; + + v = sockopt_getintptr(sopt); + if (v == NULL) { + error = EINVAL; + goto out; + } + optval = *((int *)v); + if (optval == 0) + error = EINVAL; + } + + goto out; + } else if (sopt->sopt_level != IPPROTO_IPV6) + return ip6_ctloutput(so, sopt); - switch (optname) { + switch (sopt->sopt_name) { case MRT6_INIT: case MRT6_DONE: case MRT6_ADD_MIF: @@ -578,21 +588,19 @@ rip6_ctloutput(int op, struct socket *so case MRT6_ADD_MFC: case MRT6_DEL_MFC: case MRT6_PIM: - if (op == PRCO_SETOPT) - error = ip6_mrouter_set(optname, so, *mp); - else if (op == PRCO_GETOPT) - error = ip6_mrouter_get(optname, so, mp); + if (sopt->sopt_dir == SOPT_SET) + error = ip6_mrouter_set(so, sopt); + else if (sopt->sopt_dir == SOPT_GET) + error = ip6_mrouter_get(so, sopt); else error = EINVAL; break; case IPV6_CHECKSUM: - return ip6_raw_ctloutput(op, so, level, optname, mp); + return ip6_raw_ctloutput(so, sopt); default: - return ip6_ctloutput(op, so, level, optname, mp); + return ip6_ctloutput(so, sopt); } -free_m: - if (op == PRCO_SETOPT && *mp != NULL) - m_free(*mp); + out: return error; } Index: netiso/clnp.h =================================================================== RCS file: /usr/cvs/src/sys/netiso/clnp.h,v retrieving revision 1.25 diff -u -p -r1.25 clnp.h --- netiso/clnp.h 25 Dec 2007 18:33:48 -0000 1.25 +++ netiso/clnp.h 26 Dec 2007 22:33:49 -0000 @@ -513,7 +513,7 @@ void clnp_ctloutput (void); /* clnp_raw.c */ void rclnp_input (struct mbuf *, ...); int rclnp_output (struct mbuf *, ...); -int rclnp_ctloutput (int, struct socket *, int, int, struct mbuf **); +int rclnp_ctloutput (struct socket *, struct sockopt *); int clnp_usrreq (struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *, struct lwp *); Index: netiso/clnp_raw.c =================================================================== RCS file: /usr/cvs/src/sys/netiso/clnp_raw.c,v retrieving revision 1.28 diff -u -p -r1.28 clnp_raw.c --- netiso/clnp_raw.c 2 May 2007 20:40:28 -0000 1.28 +++ netiso/clnp_raw.c 26 Dec 2007 20:31:07 -0000 @@ -197,60 +197,66 @@ rclnp_output(struct mbuf *m0, ...) */ int rclnp_ctloutput( - int op, /* type of operation */ struct socket *so, /* ptr to socket */ - int level, /* level of option */ - int optname,/* name of option */ - struct mbuf **m) /* ptr to ptr to option data */ + struct sockopt *sopt) /* socket options */ { int error = 0; struct rawisopcb *rp = sotorawisopcb(so); /* raw cb ptr */ + struct mbuf *m; + + m = sockopt_getmbuf(sopt); + if (m == NULL) + return (ENOBUFS); #ifdef ARGO_DEBUG if (argo_debug[D_CTLOUTPUT]) { printf("rclnp_ctloutput: op = x%x, level = x%x, name = x%x\n", - op, level, optname); - if (*m != NULL) { - printf("rclnp_ctloutput: %d bytes of mbuf data\n", (*m)->m_len); - dump_buf(mtod((*m), void *), (*m)->m_len); + sopt->sopt_dir, sopt->sopt_level, sopt->sopt_name); + if (m != NULL) { + printf("rclnp_ctloutput: %d bytes of mbuf data\n", (m)->m_len); + dump_buf(mtod((m), void *), (m)->m_len); } } #endif #ifdef SOL_NETWORK - if (level != SOL_NETWORK) + if (sopt->sopt_level != SOL_NETWORK) error = EINVAL; else - switch (op) { + switch (sopt->sopt_dir) { #else - switch (op) { + switch (sopt->sopt_dir) { #endif /* SOL_NETWORK */ - case PRCO_SETOPT: - switch (optname) { + case SOPT_SET: + switch (sopt->sopt_name) { case CLNPOPT_FLAGS:{ - u_short usr_flags; - /* - * Insure that the data passed has exactly - * one short in it - */ - if ((*m == NULL) || ((*m)->m_len != sizeof(short))) { - error = EINVAL; - break; - } - /* - * Don't allow invalid flags to be set - */ - usr_flags = (*mtod((*m), short *)); - - if ((usr_flags & (CLNP_VFLAGS)) != usr_flags) { - error = EINVAL; - } else - rp->risop_flags |= usr_flags; + u_short usr_flags; + + /* + * Insure that the data passed has exactly + * one short in it + */ + m = sockopt_getmbuf(sopt); + if (m == NULL) { + error = ENOBUFS; + break; + } + + usr_flags = (*mtod(m, short *)); - } break; + /* + * Don't allow invalid flags to be set + */ + if ((usr_flags & (CLNP_VFLAGS)) != usr_flags) { + error = EINVAL; + } else + rp->risop_flags |= usr_flags; - case CLNPOPT_OPTS: - error = clnp_set_opts(&rp->risop_isop.isop_options, m); + break; + } + + case CLNPOPT_OPTS: { + error = clnp_set_opts(&rp->risop_isop.isop_options, &m); if (error) break; rp->risop_isop.isop_optindex = m_get(M_WAIT, MT_SOOPTS); @@ -260,13 +266,14 @@ rclnp_ctloutput( mtod(rp->risop_isop.isop_optindex, struct clnp_optidx *)); break; + } } break; - case PRCO_GETOPT: + case SOPT_GET: #ifdef notdef /* commented out to keep hi C quiet */ - switch (optname) { + switch (sopt->sopt_name) { default: error = EINVAL; break; @@ -277,11 +284,6 @@ rclnp_ctloutput( error = EINVAL; break; } - if (op == PRCO_SETOPT) { - /* note: m_freem does not barf is *m is NULL */ - m_freem(*m); - *m = NULL; - } return error; } Index: netiso/iso.c =================================================================== RCS file: /usr/cvs/src/sys/netiso/iso.c,v retrieving revision 1.48 diff -u -p -r1.48 iso.c --- netiso/iso.c 6 Dec 2007 00:28:36 -0000 1.48 +++ netiso/iso.c 7 Dec 2007 17:07:07 -0000 @@ -512,7 +512,7 @@ iso_control(struct socket *so, u_long cm if (l == 0 || kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE, KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd, - NULL)) + ifr)) return (EPERM); if (ifp == 0) Index: netiso/iso_pcb.c =================================================================== RCS file: /usr/cvs/src/sys/netiso/iso_pcb.c,v retrieving revision 1.42 diff -u -p -r1.42 iso_pcb.c --- netiso/iso_pcb.c 14 Jan 2008 04:17:35 -0000 1.42 +++ netiso/iso_pcb.c 15 Jan 2008 11:55:36 -0000 @@ -223,8 +223,8 @@ iso_pcbbind(void *v, struct mbuf *nam, s bcopy(TSEL(siso), suf.data, sizeof(suf.data)); suf.s = ntohs(suf.s); if (suf.s < ISO_PORT_RESERVED && - (l == NULL || kauth_authorize_generic(l->l_cred, - KAUTH_GENERIC_ISSUSER, NULL))) + kauth_authorize_generic(l->l_cred, + KAUTH_GENERIC_ISSUSER, NULL)) return EACCES; } else { char *cp; @@ -351,8 +351,7 @@ iso_pcbconnect(void *v, struct mbuf *nam const void *oldtsel; siso = isop->isop_laddr; if (siso == 0 || siso->siso_tlen == 0) - (void) iso_pcbbind(isop, (struct mbuf *)0, - (struct lwp *)0); + (void) iso_pcbbind(isop, (struct mbuf *)0, l); /* * Here we have problem of squezeing in a definite network address * into an existing sockaddr_iso, which in fact may not have room Index: netiso/tp_output.c =================================================================== RCS file: /usr/cvs/src/sys/netiso/tp_output.c,v retrieving revision 1.34 diff -u -p -r1.34 tp_output.c --- netiso/tp_output.c 9 Nov 2007 21:00:06 -0000 1.34 +++ netiso/tp_output.c 26 Dec 2007 20:36:16 -0000 @@ -386,8 +386,7 @@ done: * NOTES: */ int -tp_ctloutput(int cmd, struct socket *so, int level, int optname, - struct mbuf **mp) +tp_ctloutput(struct socket *so, struct sockopt *sopt) { struct lwp *l = curlwp; /* XXX */ struct tp_pcb *tpcb = sototpcb(so); @@ -395,36 +394,33 @@ tp_ctloutput(int cmd, struct socket *so void * value; unsigned val_len; int error = 0; + int cmd, level, optname; + struct mbuf *m; + + cmd = sopt->sopt_dir; + level = sopt->sopt_level; + optname = sopt->sopt_name; + m = sockopt_getmbuf(sopt); + if (m == NULL) + return (ENOBUFS); #ifdef TPPT if (tp_traceflags[D_REQUEST]) { tptrace(TPPTmisc, "tp_ctloutput cmd so optname mp", - cmd, so, optname, mp); + cmd, so, optname); } #endif #ifdef ARGO_DEBUG if (argo_debug[D_REQUEST]) { printf( - "tp_ctloutput so %p cmd 0x%x optname 0x%x, mp %p *mp %p tpcb %p\n", - so, cmd, optname, mp, mp ? *mp : 0, tpcb); + "tp_ctloutput so %p cmd 0x%x optname 0x%x, tpcb %p\n", + so, cmd, optname, tpcb); } #endif if (tpcb == (struct tp_pcb *) 0) { error = ENOTSOCK; goto done; } - if (mp && *mp == NULL) { - struct mbuf *m; - - MGET(m, M_DONTWAIT, TPMT_SONAME); /* does off, type, next */ - if (m == NULL) { - splx(s); - return ENOBUFS; - } - m->m_len = 0; - m->m_nextpkt = 0; - *mp = m; - } /* * Hook so one can set network options via a tp socket. */ @@ -435,10 +431,10 @@ tp_ctloutput(int cmd, struct socket *so error = EOPNOTSUPP; else return ((tpcb->tp_nlproto->nlp_ctloutput) (cmd, optname, - tpcb->tp_npcb, *mp)); + tpcb->tp_npcb, m)); goto done; } else if (level == SOL_SOCKET) { - if (optname == SO_RCVBUF && cmd == PRCO_SETOPT) { + if (optname == SO_RCVBUF && cmd == SOPT_SET) { u_long old_credit = tpcb->tp_maxlcredit; tp_rsyset(tpcb); if (tpcb->tp_rhiwat != so->so_rcv.sb_hiwat && @@ -453,7 +449,7 @@ tp_ctloutput(int cmd, struct socket *so error = EOPNOTSUPP; goto done; } - if (cmd != PRCO_GETOPT && cmd != PRCO_SETOPT) { + if (cmd != SOPT_GET && cmd != SOPT_SET) { error = EOPNOTSUPP; goto done; } @@ -467,7 +463,7 @@ tp_ctloutput(int cmd, struct socket *so */ if (((so->so_state & SS_ISCONNECTING) || (so->so_state & SS_ISCONNECTED)) && - (cmd == PRCO_SETOPT && + (cmd == SOPT_SET && optname != TPOPT_DISC_DATA && optname != TPOPT_CFRM_DATA && optname != TPOPT_PERF_MEAS && @@ -491,12 +487,11 @@ tp_ctloutput(int cmd, struct socket *so goto done; } } - value = mtod(*mp, void *); /* it's aligned, don't worry, but + value = mtod(m, void *); /* it's aligned, don't worry, but * lint complains about it */ - val_len = (*mp)->m_len; + val_len = (m)->m_len; switch (optname) { - case TPOPT_INTERCEPT: #define INA(t) (((struct inpcb *)(t->tp_npcb))->inp_laddr.s_addr) #define ISOA(t) (((struct isopcb *)(t->tp_npcb))->isop_laddr->siso_addr) @@ -504,7 +499,7 @@ tp_ctloutput(int cmd, struct socket *so if (l == 0 || (error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL))) { error = EPERM; - } else if (cmd != PRCO_SETOPT || tpcb->tp_state != TP_CLOSED || + } else if (cmd != SOPT_SET || tpcb->tp_state != TP_CLOSED || (tpcb->tp_flags & TPF_GENERAL_ADDR) || tpcb->tp_next == 0) error = EINVAL; @@ -542,14 +537,14 @@ tp_ctloutput(int cmd, struct socket *so break; case TPOPT_MY_TSEL: - if (cmd == PRCO_GETOPT) { + if (cmd == SOPT_GET) { ASSERT(tpcb->tp_lsuffixlen <= MAX_TSAP_SEL_LEN); bcopy((void *) tpcb->tp_lsuffix, value, tpcb->tp_lsuffixlen); - (*mp)->m_len = tpcb->tp_lsuffixlen; - } else { /* cmd == PRCO_SETOPT */ + (m)->m_len = tpcb->tp_lsuffixlen; + } else { /* cmd == SOPT_SET */ if ((val_len > MAX_TSAP_SEL_LEN) || (val_len <= 0)) { - printf("val_len 0x%x (*mp)->m_len %p\n", - val_len, (*mp)); + printf("val_len 0x%x (m)->m_len %p\n", + val_len, (m)); error = EINVAL; } else { bcopy(value, (void *) tpcb->tp_lsuffix, val_len); @@ -559,14 +554,14 @@ tp_ctloutput(int cmd, struct socket *so break; case TPOPT_PEER_TSEL: - if (cmd == PRCO_GETOPT) { + if (cmd == SOPT_GET) { ASSERT(tpcb->tp_fsuffixlen <= MAX_TSAP_SEL_LEN); bcopy((void *) tpcb->tp_fsuffix, value, tpcb->tp_fsuffixlen); - (*mp)->m_len = tpcb->tp_fsuffixlen; - } else { /* cmd == PRCO_SETOPT */ + (m)->m_len = tpcb->tp_fsuffixlen; + } else { /* cmd == SOPT_SET */ if ((val_len > MAX_TSAP_SEL_LEN) || (val_len <= 0)) { - printf("val_len 0x%x (*mp)->m_len %p\n", - val_len, (*mp)); + printf("val_len 0x%x (m)->m_len %p\n", + val_len, (m)); error = EINVAL; } else { bcopy(value, (void *) tpcb->tp_fsuffix, val_len); @@ -579,17 +574,17 @@ tp_ctloutput(int cmd, struct socket *so #ifdef ARGO_DEBUG if (argo_debug[D_REQUEST]) { printf("%s TPOPT_FLAGS value %p *value 0x%x, flags 0x%x \n", - cmd == PRCO_GETOPT ? "GET" : "SET", + cmd == SOPT_GET ? "GET" : "SET", value, *(unsigned char *)value, tpcb->tp_flags); } #endif - if (cmd == PRCO_GETOPT) { + if (cmd == SOPT_GET) { *(int *) value = (int) tpcb->tp_flags; - (*mp)->m_len = sizeof(u_int); - } else { /* cmd == PRCO_SETOPT */ + (m)->m_len = sizeof(u_int); + } else { /* cmd == SOPT_SET */ error = EINVAL; goto done; } @@ -605,20 +600,20 @@ tp_ctloutput(int cmd, struct socket *so #ifdef ARGO_DEBUG if (argo_debug[D_SETPARAMS]) { printf("TPOPT_PARAMS value %p, cmd %s \n", value, - cmd == PRCO_GETOPT ? "GET" : "SET"); + cmd == SOPT_GET ? "GET" : "SET"); } #endif #ifdef ARGO_DEBUG if (argo_debug[D_REQUEST]) { printf("TPOPT_PARAMS value %p, cmd %s \n", value, - cmd == PRCO_GETOPT ? "GET" : "SET"); + cmd == SOPT_GET ? "GET" : "SET"); } #endif - if (cmd == PRCO_GETOPT) { + if (cmd == SOPT_GET) { *(struct tp_conn_param *) value = tpcb->_tp_param; - (*mp)->m_len = sizeof(tpcb->_tp_param); - } else { /* cmd == PRCO_SETOPT */ + (m)->m_len = sizeof(tpcb->_tp_param); + } else { /* cmd == SOPT_SET */ if ((error = tp_consistency(tpcb, TP_STRICT | TP_FORCE, (struct tp_conn_param *) value)) == 0) { @@ -627,24 +622,24 @@ tp_ctloutput(int cmd, struct socket *so * of params */ tpcb->_tp_param = *(struct tp_conn_param *) value; - (*mp)->m_len = sizeof(tpcb->_tp_param); + (m)->m_len = sizeof(tpcb->_tp_param); } } break; case TPOPT_PSTATISTICS: #ifdef TP_PERF_MEAS - if (cmd == PRCO_SETOPT) { + if (cmd == SOPT_SET) { error = EINVAL; goto done; } if (tpcb->tp_perf_on) { - m_clget(*mp, M_WAIT); - if (((*mp)->m_flags & M_EXT) == 0) { + m_clget(m, M_WAIT); + if (((m)->m_flags & M_EXT) == 0) { error = ENOBUFS; goto done; } - (*mp)->m_len = sizeof(struct tp_pmeas); - bcopy(tpcb->tp_p_meas, mtod(*mp), sizeof(struct tp_pmeas)); + (m)->m_len = sizeof(struct tp_pmeas); + bcopy(tpcb->tp_p_meas, mtod(m), sizeof(struct tp_pmeas)); } else { error = EINVAL; @@ -657,7 +652,7 @@ tp_ctloutput(int cmd, struct socket *so #endif /* TP_PERF_MEAS */ case TPOPT_CDDATA_CLEAR: - if (cmd == PRCO_GETOPT) { + if (cmd == SOPT_GET) { error = EINVAL; } else { if (tpcb->tp_ucddata) { @@ -678,11 +673,11 @@ tp_ctloutput(int cmd, struct socket *so if (argo_debug[D_REQUEST]) { printf("%s\n", optname == TPOPT_DISC_DATA ? "DISC data" : "CONN data"); printf("m_len 0x%x, vallen 0x%x so_snd.cc 0x%lx\n", - (*mp)->m_len, val_len, so->so_snd.sb_cc); + (m)->m_len, val_len, so->so_snd.sb_cc); dump_mbuf(so->so_snd.sb_mb, "tp_ctloutput: sosnd "); } #endif - if (cmd == PRCO_SETOPT) { + if (cmd == SOPT_SET) { int len = tpcb->tp_ucddata ? tpcb->tp_ucddata->m_len : 0; /* can append connect data in several calls */ if (len + val_len > @@ -690,12 +685,12 @@ tp_ctloutput(int cmd, struct socket *so error = EMSGSIZE; goto done; } - (*mp)->m_next = NULL; - (*mp)->m_nextpkt = 0; + (m)->m_next = NULL; + (m)->m_nextpkt = 0; if (tpcb->tp_ucddata) - m_cat(tpcb->tp_ucddata, *mp); + m_cat(tpcb->tp_ucddata, m); else - tpcb->tp_ucddata = *mp; + tpcb->tp_ucddata = m; #ifdef ARGO_DEBUG if (argo_debug[D_REQUEST]) { dump_mbuf(tpcb->tp_ucddata, "tp_ctloutput after CONN_DATA"); @@ -707,7 +702,7 @@ tp_ctloutput(int cmd, struct socket *so tpcb->tp_flags, so->so_snd.sb_cc, val_len, 0); } #endif - *mp = NULL; + m = NULL; if (optname == TPOPT_CFRM_DATA && (so->so_state & SS_ISCONFIRMING)) (void) tp_confirm(tpcb); } @@ -715,11 +710,11 @@ tp_ctloutput(int cmd, struct socket *so case TPOPT_PERF_MEAS: #ifdef TP_PERF_MEAS - if (cmd == PRCO_GETOPT) { + if (cmd == SOPT_GET) { *value = (u_int) tpcb->tp_perf_on; - (*mp)->m_len = sizeof(u_int); - } else if (cmd == PRCO_SETOPT) { - (*mp)->m_len = 0; + (m)->m_len = sizeof(u_int); + } else if (cmd == SOPT_SET) { + (m)->m_len = 0; if ((*value) != 0 && (*value) != 1) error = EINVAL; else @@ -740,24 +735,24 @@ done: #ifdef ARGO_DEBUG if (argo_debug[D_REQUEST]) { dump_mbuf(so->so_snd.sb_mb, "tp_ctloutput sosnd at end"); - dump_mbuf(*mp, "tp_ctloutput *mp"); + dump_mbuf(m, "tp_ctloutput m"); } #endif /* * sigh: getsockopt looks only at m_len : all output data must reside * in the first mbuf */ - if (*mp) { - if (cmd == PRCO_SETOPT) { - m_freem(*mp); - *mp = NULL; + if (m) { + if (cmd == SOPT_SET) { + m_freem(m); + m = NULL; } else { - ASSERT(m_compress(*mp, mp) <= MLEN); + ASSERT(m_compress(m, &m) <= MLEN); if (error) - (*mp)->m_len = 0; + (m)->m_len = 0; #ifdef ARGO_DEBUG if (argo_debug[D_REQUEST]) { - dump_mbuf(*mp, "tp_ctloutput *mp after compress"); + dump_mbuf(m, "tp_ctloutput m after compress"); } #endif } Index: netiso/tp_pcb.c =================================================================== RCS file: /usr/cvs/src/sys/netiso/tp_pcb.c,v retrieving revision 1.35 diff -u -p -r1.35 tp_pcb.c --- netiso/tp_pcb.c 9 Nov 2007 21:00:06 -0000 1.35 +++ netiso/tp_pcb.c 13 Dec 2007 14:52:52 -0000 @@ -82,6 +82,7 @@ __KERNEL_RCSID(0, "$NetBSD: tp_pcb.c,v 1 #include #include #include +#include #include #include Index: netiso/tp_usrreq.c =================================================================== RCS file: /usr/cvs/src/sys/netiso/tp_usrreq.c,v retrieving revision 1.33 diff -u -p -r1.33 tp_usrreq.c --- netiso/tp_usrreq.c 9 Nov 2007 21:00:06 -0000 1.33 +++ netiso/tp_usrreq.c 26 Dec 2007 20:57:38 -0000 @@ -484,8 +484,7 @@ tp_usrreq(struct socket *so, int req, st } #endif if (tpcb->tp_lsuffixlen == 0) { - error = tp_pcbbind(tpcb, (struct mbuf *)0, - (struct lwp *)0); + error = tp_pcbbind(tpcb, (struct mbuf *)0, l); if (error) { #ifdef ARGO_DEBUG if (argo_debug[D_CONN]) { @@ -796,11 +795,19 @@ tp_snd_control(struct mbuf *m, struct so int error = 0; if (m && m->m_len) { + struct sockopt sopt; + ch = mtod(m, struct cmsghdr *); m->m_len -= sizeof(*ch); m->m_data += sizeof(*ch); - error = tp_ctloutput(PRCO_SETOPT, - so, ch->cmsg_level, ch->cmsg_type, &m); + + memset(&sopt, 0, sizeof(sopt)); + sopt.sopt_dir = SOPT_SET; + sopt.sopt_level = ch->cmsg_level; + sopt.sopt_name = ch->cmsg_type; + sockopt_set(&sopt, mtod(m, void *), m->m_len); + sopt.sopt_waitok = 1; + error = tp_ctloutput(so, &sopt); if (ch->cmsg_type == TPOPT_DISC_DATA) { if (data && *data) { m_freem(*data); Index: netiso/tp_var.h =================================================================== RCS file: /usr/cvs/src/sys/netiso/tp_var.h,v retrieving revision 1.15 diff -u -p -r1.15 tp_var.h --- netiso/tp_var.h 4 Mar 2007 06:03:33 -0000 1.15 +++ netiso/tp_var.h 22 Dec 2007 21:14:34 -0000 @@ -118,7 +118,7 @@ void Tpmeas (u_int, u_int, struct timeva /* tp_output.c */ int tp_consistency (struct tp_pcb *, u_int, struct tp_conn_param *); -int tp_ctloutput (int, struct socket *, int, int, struct mbuf **); +int tp_ctloutput (struct socket *, struct sockopt *); /* tp_pcb.c */ void tp_init (void); Index: netsmb/smb_trantcp.c =================================================================== RCS file: /usr/cvs/src/sys/netsmb/smb_trantcp.c,v retrieving revision 1.31 diff -u -p -r1.31 smb_trantcp.c --- netsmb/smb_trantcp.c 10 Jul 2007 21:05:03 -0000 1.31 +++ netsmb/smb_trantcp.c 22 Dec 2007 21:14:42 -0000 @@ -94,7 +94,7 @@ static int nb_setsockopt_int(struct socket *so, int level, int name, int val) { #ifdef __NetBSD__ - return sosetopt(so, level, name, NULL); /* XXX */ + return so_setsockopt(NULL, so, level, name, &val, sizeof(val)); #else struct sockopt sopt; Index: nfs/nfs_boot.c =================================================================== RCS file: /usr/cvs/src/sys/nfs/nfs_boot.c,v retrieving revision 1.69 diff -u -p -r1.69 nfs_boot.c --- nfs/nfs_boot.c 31 Aug 2007 22:02:58 -0000 1.69 +++ nfs/nfs_boot.c 16 Dec 2007 18:12:18 -0000 @@ -342,29 +342,24 @@ int nfs_boot_setrecvtimo(so) struct socket *so; { - struct mbuf *m; - struct timeval *tv; + struct timeval tv; + + tv.tv_sec = 1; + tv.tv_usec = 0; - m = m_get(M_WAIT, MT_SOOPTS); - tv = mtod(m, struct timeval *); - m->m_len = sizeof(*tv); - tv->tv_sec = 1; - tv->tv_usec = 0; - return (sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m)); + return (so_setsockopt(NULL, so, SOL_SOCKET, SO_RCVTIMEO, &tv, + sizeof(tv))); } int nfs_boot_enbroadcast(so) struct socket *so; { - struct mbuf *m; - int32_t *on; + int32_t on; - m = m_get(M_WAIT, MT_SOOPTS); - on = mtod(m, int32_t *); - m->m_len = sizeof(*on); - *on = 1; - return (sosetopt(so, SOL_SOCKET, SO_BROADCAST, m)); + on = 1; + return (so_setsockopt(NULL, so, SOL_SOCKET, SO_BROADCAST, &on, + sizeof(on))); } int Index: nfs/nfs_bootdhcp.c =================================================================== RCS file: /usr/cvs/src/sys/nfs/nfs_bootdhcp.c,v retrieving revision 1.37 diff -u -p -r1.37 nfs_bootdhcp.c --- nfs/nfs_bootdhcp.c 20 Dec 2007 16:19:38 -0000 1.37 +++ nfs/nfs_bootdhcp.c 21 Dec 2007 00:04:09 -0000 @@ -498,13 +498,11 @@ bootpc_call(nd, lwp) * interface (why?) and then fails because broadcast * is not supported on that interface... */ - { int32_t *opt; - m = m_get(M_WAIT, MT_SOOPTS); - opt = mtod(m, int32_t *); - m->m_len = sizeof(*opt); - *opt = 1; - error = sosetopt(so, SOL_SOCKET, SO_DONTROUTE, m); - m = NULL; /* was consumed */ + { int32_t opt; + + opt = 1; + error = so_setsockopt(NULL, so, SOL_SOCKET, SO_DONTROUTE, &opt, + sizeof(opt)); } if (error) { DPRINTF(("bootpc_call: SO_DONTROUTE failed %d\n", error)); @@ -524,13 +522,11 @@ bootpc_call(nd, lwp) * The "helper-address" feature of some popular router vendor seems * to do simple IP forwarding and drops packets with (ip_ttl == 1). */ - { u_char *opt; - m = m_get(M_WAIT, MT_SOOPTS); - opt = mtod(m, u_char *); - m->m_len = sizeof(*opt); - *opt = 7; - error = sosetopt(so, IPPROTO_IP, IP_MULTICAST_TTL, m); - m = NULL; /* was consumed */ + { u_char opt; + + opt = 7; + error = so_setsockopt(NULL, so, IPPROTO_IP, IP_MULTICAST_TTL, + &opt, sizeof(opt)); } if (error) { DPRINTF(("bootpc_call: IP_MULTICAST_TTL failed %d\n", error)); Index: nfs/nfs_socket.c =================================================================== RCS file: /usr/cvs/src/sys/nfs/nfs_socket.c,v retrieving revision 1.167 diff -u -p -r1.167 nfs_socket.c --- nfs/nfs_socket.c 2 Jan 2008 19:26:46 -0000 1.167 +++ nfs/nfs_socket.c 7 Jan 2008 19:31:32 -0000 @@ -199,6 +199,7 @@ nfs_connect(nmp, rep, l) struct sockaddr_in6 *sin6; #endif struct mbuf *m; + int val; nmp->nm_so = (struct socket *)0; saddr = mtod(nmp->nm_nam, struct sockaddr *); @@ -218,11 +219,10 @@ nfs_connect(nmp, rep, l) * Some servers require that the client port be a reserved port number. */ if (saddr->sa_family == AF_INET && (nmp->nm_flag & NFSMNT_RESVPORT)) { - m = m_get(M_WAIT, MT_SOOPTS); - MCLAIM(m, so->so_mowner); - *mtod(m, int32_t *) = IP_PORTRANGE_LOW; - m->m_len = sizeof(int32_t); - if ((error = sosetopt(so, IPPROTO_IP, IP_PORTRANGE, m))) + val = IP_PORTRANGE_LOW; + + if ((error = so_setsockopt(NULL, so, IPPROTO_IP, IP_PORTRANGE, + &val, sizeof(val)))) goto bad; m = m_get(M_WAIT, MT_SONAME); MCLAIM(m, so->so_mowner); @@ -238,11 +238,10 @@ nfs_connect(nmp, rep, l) } #ifdef INET6 if (saddr->sa_family == AF_INET6 && (nmp->nm_flag & NFSMNT_RESVPORT)) { - m = m_get(M_WAIT, MT_SOOPTS); - MCLAIM(m, so->so_mowner); - *mtod(m, int32_t *) = IPV6_PORTRANGE_LOW; - m->m_len = sizeof(int32_t); - if ((error = sosetopt(so, IPPROTO_IPV6, IPV6_PORTRANGE, m))) + val = IPV6_PORTRANGE_LOW; + + if ((error = so_setsockopt(NULL, so, IPPROTO_IPV6, + IPV6_PORTRANGE, &val, sizeof(val)))) goto bad; m = m_get(M_WAIT, MT_SONAME); MCLAIM(m, so->so_mowner); @@ -320,18 +319,14 @@ nfs_connect(nmp, rep, l) if (nmp->nm_sotype != SOCK_STREAM) panic("nfscon sotype"); if (so->so_proto->pr_flags & PR_CONNREQUIRED) { - m = m_get(M_WAIT, MT_SOOPTS); - MCLAIM(m, so->so_mowner); - *mtod(m, int32_t *) = 1; - m->m_len = sizeof(int32_t); - sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m); + val = 1; + so_setsockopt(NULL, so, SOL_SOCKET, SO_KEEPALIVE, &val, + sizeof(val)); } if (so->so_proto->pr_protocol == IPPROTO_TCP) { - m = m_get(M_WAIT, MT_SOOPTS); - MCLAIM(m, so->so_mowner); - *mtod(m, int32_t *) = 1; - m->m_len = sizeof(int32_t); - sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m); + val = 1; + so_setsockopt(NULL, so, IPPROTO_TCP, TCP_NODELAY, &val, + sizeof(val)); } sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR + sizeof (u_int32_t)) * 2; Index: nfs/nfs_syscalls.c =================================================================== RCS file: /usr/cvs/src/sys/nfs/nfs_syscalls.c,v retrieving revision 1.130 diff -u -p -r1.130 nfs_syscalls.c --- nfs/nfs_syscalls.c 2 Jan 2008 19:26:46 -0000 1.130 +++ nfs/nfs_syscalls.c 7 Jan 2008 19:31:32 -0000 @@ -388,12 +388,12 @@ nfssvc_addsock(fp, mynam) struct file *fp; struct mbuf *mynam; { - struct mbuf *m; int siz; struct nfssvc_sock *slp; struct socket *so; struct nfssvc_sock *tslp; int error, s; + int val; so = (struct socket *)fp->f_data; tslp = (struct nfssvc_sock *)0; @@ -436,11 +436,9 @@ nfssvc_addsock(fp, mynam) * repeatedly for the same socket, but that isn't harmful. */ if (so->so_type == SOCK_STREAM) { - m = m_get(M_WAIT, MT_SOOPTS); - MCLAIM(m, &nfs_mowner); - *mtod(m, int32_t *) = 1; - m->m_len = sizeof(int32_t); - sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m); + val = 1; + so_setsockopt(NULL, so, SOL_SOCKET, SO_KEEPALIVE, &val, + sizeof(val)); } if ((so->so_proto->pr_domain->