diff options
author | wollman <wollman@FreeBSD.org> | 1997-04-27 20:01:29 +0000 |
---|---|---|
committer | wollman <wollman@FreeBSD.org> | 1997-04-27 20:01:29 +0000 |
commit | 6afbf203bd570424ecf3f9d9d9ced17f82c81adc (patch) | |
tree | 41103dcf8addc8e73880fc79975713ce1e6ba14c /sys/net | |
parent | ced78602fea5284de7f4cb1673405ad3f3ad57ce (diff) | |
download | FreeBSD-src-6afbf203bd570424ecf3f9d9d9ced17f82c81adc.zip FreeBSD-src-6afbf203bd570424ecf3f9d9d9ced17f82c81adc.tar.gz |
The long-awaited mega-massive-network-code- cleanup. Part I.
This commit includes the following changes:
1) Old-style (pr_usrreq()) protocols are no longer supported, the compatibility
glue for them is deleted, and the kernel will panic on boot if any are compiled
in.
2) Certain protocol entry points are modified to take a process structure,
so they they can easily tell whether or not it is possible to sleep, and
also to access credentials.
3) SS_PRIV is no more, and with it goes the SO_PRIVSTATE setsockopt()
call. Protocols should use the process pointer they are now passed.
4) The PF_LOCAL and PF_ROUTE families have been updated to use the new
style, as has the `raw' skeleton family.
5) PF_LOCAL sockets now obey the process's umask when creating a socket
in the filesystem.
As a result, LINT is now broken. I'm hoping that some enterprising hacker
with a bit more time will either make the broken bits work (should be
easy for netipx) or dike them out.
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if.c | 4 | ||||
-rw-r--r-- | sys/net/raw_cb.c | 2 | ||||
-rw-r--r-- | sys/net/raw_cb.h | 6 | ||||
-rw-r--r-- | sys/net/raw_usrreq.c | 306 | ||||
-rw-r--r-- | sys/net/rtsock.c | 227 |
5 files changed, 336 insertions, 209 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index b1f7087..115cd64 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)if.c 8.3 (Berkeley) 1/4/94 - * $Id: if.c,v 1.45 1997/02/14 15:30:54 wollman Exp $ + * $Id: if.c,v 1.46 1997/03/24 11:33:08 bde Exp $ */ #include <sys/param.h> @@ -640,7 +640,7 @@ ifioctl(so, cmd, data, p) error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, - ifp)); + ifp, p)); switch (ocmd) { case OSIOCGIFADDR: diff --git a/sys/net/raw_cb.c b/sys/net/raw_cb.c index 5b39bc0..9db18a3 100644 --- a/sys/net/raw_cb.c +++ b/sys/net/raw_cb.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)raw_cb.c 8.1 (Berkeley) 6/10/93 - * $Id: raw_cb.c,v 1.10 1997/02/22 09:41:13 peter Exp $ + * $Id: raw_cb.c,v 1.11 1997/04/14 18:23:22 phk Exp $ */ #include <sys/param.h> diff --git a/sys/net/raw_cb.h b/sys/net/raw_cb.h index bff3989..2cc5ccc 100644 --- a/sys/net/raw_cb.h +++ b/sys/net/raw_cb.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)raw_cb.h 8.1 (Berkeley) 6/10/93 - * $Id: raw_cb.h,v 1.7 1997/02/22 09:41:13 peter Exp $ + * $Id: raw_cb.h,v 1.8 1997/04/14 18:23:23 phk Exp $ */ #ifndef _NET_RAW_CB_H_ @@ -67,8 +67,8 @@ void raw_disconnect __P((struct rawcb *)); void raw_init __P((void)); void raw_input __P((struct mbuf *, struct sockproto *, struct sockaddr *, struct sockaddr *)); -int raw_usrreq __P((struct socket *, - int, struct mbuf *, struct mbuf *, struct mbuf *)); + +extern struct pr_usrreqs raw_usrreqs; #endif #endif diff --git a/sys/net/raw_usrreq.c b/sys/net/raw_usrreq.c index ae7729f..9ec02fb 100644 --- a/sys/net/raw_usrreq.c +++ b/sys/net/raw_usrreq.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93 - * $Id: raw_usrreq.c,v 1.10 1997/02/22 09:41:14 peter Exp $ + * $Id: raw_usrreq.c,v 1.11 1997/04/14 18:23:25 phk Exp $ */ #include <sys/param.h> @@ -39,6 +39,7 @@ #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/domain.h> +#include <sys/proc.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> @@ -140,175 +141,172 @@ raw_ctlinput(cmd, arg, dummy) /* INCOMPLETE */ } -/*ARGSUSED*/ -int -raw_usrreq(so, req, m, nam, control) - struct socket *so; - int req; - struct mbuf *m, *nam, *control; +static int +raw_uabort(struct socket *so) { - register struct rawcb *rp = sotorawcb(so); - register int error = 0; - int len; + struct rawcb *rp = sotorawcb(so); - if (req == PRU_CONTROL) - return (EOPNOTSUPP); - if (control && control->m_len) { - error = EOPNOTSUPP; - goto release; + if (rp == 0) + return EINVAL; + raw_disconnect(rp); + sofree(so); + soisdisconnected(so); + return 0; +} + +/* pru_accept is EOPNOTSUPP */ + +static int +raw_uattach(struct socket *so, int proto, struct proc *p) +{ + struct rawcb *rp = sotorawcb(so); + int error; + + if (rp == 0) + return EINVAL; + if (p && (error = suser(p->p_ucred, &p->p_acflag)) != 0) + return error; + return raw_attach(so, proto); +} + +static int +raw_ubind(struct socket *so, struct mbuf *nam, struct proc *p) +{ + return EINVAL; +} + +static int +raw_uconnect(struct socket *so, struct mbuf *nam, struct proc *p) +{ + return EINVAL; +} + +/* pru_connect2 is EOPNOTSUPP */ +/* pru_control is EOPNOTSUPP */ + +static int +raw_udetach(struct socket *so) +{ + struct rawcb *rp = sotorawcb(so); + + if (rp == 0) + return EINVAL; + + raw_detach(rp); + return 0; +} + +static int +raw_udisconnect(struct socket *so) +{ + struct rawcb *rp = sotorawcb(so); + + if (rp == 0) + return EINVAL; + if (rp->rcb_faddr == 0) { + return ENOTCONN; + } + raw_disconnect(rp); + soisdisconnected(so); + return 0; +} + +/* pru_listen is EOPNOTSUPP */ + +static int +raw_upeeraddr(struct socket *so, struct mbuf *nam) +{ + struct rawcb *rp = sotorawcb(so); + unsigned len; + + if (rp == 0) + return EINVAL; + if (rp->rcb_faddr == 0) { + return ENOTCONN; } + len = rp->rcb_faddr->sa_len; + bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), len); + nam->m_len = len; + return 0; +} + +/* pru_rcvd is EOPNOTSUPP */ +/* pru_rcvoob is EOPNOTSUPP */ + +static int +raw_usend(struct socket *so, int flags, struct mbuf *m, + struct mbuf *nam, struct mbuf *control, struct proc *p) +{ + int error; + struct rawcb *rp = sotorawcb(so); + if (rp == 0) { error = EINVAL; goto release; } - switch (req) { - - /* - * Allocate a raw control block and fill in the - * necessary info to allow packets to be routed to - * the appropriate raw interface routine. - */ - case PRU_ATTACH: - if ((so->so_state & SS_PRIV) == 0) { - error = EACCES; - break; - } - error = raw_attach(so, (int)nam); - break; - - /* - * Destroy state just before socket deallocation. - * Flush data or not depending on the options. - */ - case PRU_DETACH: - if (rp == 0) { - error = ENOTCONN; - break; - } - raw_detach(rp); - break; - - /* - * If a socket isn't bound to a single address, - * the raw input routine will hand it anything - * within that protocol family (assuming there's - * nothing else around it should go to). - */ - case PRU_CONNECT: - error = EINVAL; -#if 0 - if (rp->rcb_faddr) { - error = EISCONN; - break; - } - nam = m_copym(nam, 0, M_COPYALL, M_WAIT); - rp->rcb_faddr = mtod(nam, struct sockaddr *); - soisconnected(so); -#endif - break; - - case PRU_BIND: - error = EINVAL; -#if 0 - if (rp->rcb_laddr) { - error = EINVAL; /* XXX */ - break; - } - error = raw_bind(so, nam); -#endif - break; - case PRU_CONNECT2: + if (flags & PRUS_OOB) { error = EOPNOTSUPP; goto release; + } - case PRU_DISCONNECT: - if (rp->rcb_faddr == 0) { - error = ENOTCONN; - break; - } - raw_disconnect(rp); - soisdisconnected(so); - break; - - /* - * Mark the connection as being incapable of further input. - */ - case PRU_SHUTDOWN: - socantsendmore(so); - break; - - /* - * Ship a packet out. The appropriate raw output - * routine handles any massaging necessary. - */ - case PRU_SEND: - if (nam) { - if (rp->rcb_faddr) { - error = EISCONN; - break; - } - rp->rcb_faddr = mtod(nam, struct sockaddr *); - } else if (rp->rcb_faddr == 0) { - error = ENOTCONN; - break; - } - error = (*so->so_proto->pr_output)(m, so); - m = NULL; - if (nam) - rp->rcb_faddr = 0; - break; - - case PRU_ABORT: - raw_disconnect(rp); - sofree(so); - soisdisconnected(so); - break; - - case PRU_SENSE: - /* - * stat: don't bother with a blocksize. - */ - return (0); - - /* - * Not supported. - */ - case PRU_RCVOOB: - case PRU_RCVD: - return(EOPNOTSUPP); - - case PRU_LISTEN: - case PRU_ACCEPT: - case PRU_SENDOOB: + if (control && control->m_len) { error = EOPNOTSUPP; - break; - - case PRU_SOCKADDR: - if (rp->rcb_laddr == 0) { - error = EINVAL; - break; - } - len = rp->rcb_laddr->sa_len; - bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len); - nam->m_len = len; - break; - - case PRU_PEERADDR: - if (rp->rcb_faddr == 0) { - error = ENOTCONN; - break; + goto release; + } + if (nam) { + if (rp->rcb_faddr) { + error = EISCONN; + goto release; } - len = rp->rcb_faddr->sa_len; - bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len); - nam->m_len = len; - break; - - default: - panic("raw_usrreq"); + rp->rcb_faddr = mtod(nam, struct sockaddr *); + } else if (rp->rcb_faddr == 0) { + error = ENOTCONN; + goto release; } + error = (*so->so_proto->pr_output)(m, so); + m = NULL; + if (nam) + rp->rcb_faddr = 0; release: if (m != NULL) m_freem(m); return (error); } + +/* pru_sense is null */ + +static int +raw_ushutdown(struct socket *so) +{ + struct rawcb *rp = sotorawcb(so); + + if (rp == 0) + return EINVAL; + socantsendmore(so); + return 0; +} + +static int +raw_usockaddr(struct socket *so, struct mbuf *nam) +{ + struct rawcb *rp = sotorawcb(so); + unsigned len; + + if (rp == 0) + return EINVAL; + if (rp->rcb_laddr == 0) + return EINVAL; + len = rp->rcb_laddr->sa_len; + bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), len); + nam->m_len = len; + return 0; +} + +struct pr_usrreqs raw_usrreqs = { + raw_uabort, pru_accept_notsupp, raw_uattach, raw_ubind, raw_uconnect, + pru_connect2_notsupp, pru_control_notsupp, raw_udetach, + raw_udisconnect, pru_listen_notsupp, raw_upeeraddr, pru_rcvd_notsupp, + pru_rcvoob_notsupp, raw_usend, pru_sense_null, raw_ushutdown, + raw_usockaddr, sosend, soreceive, soselect +}; diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 36afca9..ae1a900 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -31,9 +31,10 @@ * SUCH DAMAGE. * * @(#)rtsock.c 8.5 (Berkeley) 11/2/94 - * $Id$ + * $Id: rtsock.c,v 1.26 1997/02/22 09:41:15 peter Exp $ */ + #include <sys/param.h> #include <sys/queue.h> #include <sys/systm.h> @@ -69,8 +70,6 @@ static void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); static int sysctl_dumpentry __P((struct radix_node *rn, void *vw)); static int sysctl_iflist __P((int af, struct walkarg *w)); static int route_output __P((struct mbuf *, struct socket *)); -static int route_usrreq __P((struct socket *, - int, struct mbuf *, struct mbuf *, struct mbuf *)); static void rt_setmetrics __P((u_long, struct rt_metrics *, struct rt_metrics *)); /* Sleazy use of local variables throughout file, warning!!!! */ @@ -82,62 +81,191 @@ static void rt_setmetrics __P((u_long, struct rt_metrics *, struct rt_metrics * #define ifaaddr info.rti_info[RTAX_IFA] #define brdaddr info.rti_info[RTAX_BRD] -/*ARGSUSED*/ +/* + * It really doesn't make any sense at all for this code to share much + * with raw_usrreq.c, since its functionality is so restricted. XXX + */ +static int +rts_abort(struct socket *so) +{ + int s, error; + s = splnet(); + error = raw_usrreqs.pru_abort(so); + splx(s); + return error; +} + +/* pru_accept is EOPNOTSUPP */ + static int -route_usrreq(so, req, m, nam, control) - register struct socket *so; - int req; - struct mbuf *m, *nam, *control; +rts_attach(struct socket *so, int proto, struct proc *p) { - register int error = 0; - register struct rawcb *rp = sotorawcb(so); - int s; - - if (req == PRU_ATTACH) { - MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK); - so->so_pcb = (caddr_t)rp; - if (so->so_pcb) - bzero(so->so_pcb, sizeof(*rp)); + struct rawcb *rp; + int s, error; + + if (sotorawcb(so) != 0) + return EISCONN; /* XXX panic? */ + MALLOC(rp, struct rawcb *, sizeof *rp, M_PCB, M_WAITOK); /* XXX */ + if (rp == 0) + return ENOBUFS; + bzero(rp, sizeof *rp); + + /* + * The splnet() is necessary to block protocols from sending + * error notifications (like RTM_REDIRECT or RTM_LOSING) while + * this PCB is extant but incompletely initialized. + * Probably we should try to do more of this work beforehand and + * eliminate the spl. + */ + s = splnet(); + so->so_pcb = (caddr_t)rp; + error = raw_usrreqs.pru_attach(so, proto, p); + rp = sotorawcb(so); + if (error) { + splx(s); + free(rp, M_PCB); + return error; + } + switch(rp->rcb_proto.sp_protocol) { + case AF_INET: + route_cb.ip_count++; + break; + case AF_IPX: + route_cb.ipx_count++; + break; + case AF_NS: + route_cb.ns_count++; + break; + case AF_ISO: + route_cb.iso_count++; + break; } - if (req == PRU_DETACH && rp) { - int af = rp->rcb_proto.sp_protocol; - if (af == AF_INET) + rp->rcb_faddr = &route_src; + route_cb.any_count++; + soisconnected(so); + so->so_options |= SO_USELOOPBACK; + splx(s); + return 0; +} + +static int +rts_bind(struct socket *so, struct mbuf *nam, struct proc *p) +{ + int s, error; + s = splnet(); + error = raw_usrreqs.pru_bind(so, nam, p); /* xxx just EINVAL */ + splx(s); + return error; +} + +static int +rts_connect(struct socket *so, struct mbuf *nam, struct proc *p) +{ + int s, error; + s = splnet(); + error = raw_usrreqs.pru_connect(so, nam, p); /* XXX just EINVAL */ + splx(s); + return error; +} + +/* pru_connect2 is EOPNOTSUPP */ +/* pru_control is EOPNOTSUPP */ + +static int +rts_detach(struct socket *so) +{ + struct rawcb *rp = sotorawcb(so); + int s, error; + + s = splnet(); + if (rp != 0) { + switch(rp->rcb_proto.sp_protocol) { + case AF_INET: route_cb.ip_count--; - else if (af == AF_IPX) + break; + case AF_IPX: route_cb.ipx_count--; - else if (af == AF_NS) + break; + case AF_NS: route_cb.ns_count--; - else if (af == AF_ISO) + break; + case AF_ISO: route_cb.iso_count--; + break; + } route_cb.any_count--; } + error = raw_usrreqs.pru_detach(so); + splx(s); + return error; +} + +static int +rts_disconnect(struct socket *so) +{ + int s, error; s = splnet(); - error = raw_usrreq(so, req, m, nam, control); - rp = sotorawcb(so); - if (req == PRU_ATTACH && rp) { - int af = rp->rcb_proto.sp_protocol; - if (error) { - free((caddr_t)rp, M_PCB); - splx(s); - return (error); - } - if (af == AF_INET) - route_cb.ip_count++; - else if (af == AF_IPX) - route_cb.ipx_count++; - else if (af == AF_NS) - route_cb.ns_count++; - else if (af == AF_ISO) - route_cb.iso_count++; - rp->rcb_faddr = &route_src; - route_cb.any_count++; - soisconnected(so); - so->so_options |= SO_USELOOPBACK; - } + error = raw_usrreqs.pru_disconnect(so); splx(s); - return (error); + return error; } +/* pru_listen is EOPNOTSUPP */ + +static int +rts_peeraddr(struct socket *so, struct mbuf *nam) +{ + int s, error; + s = splnet(); + error = raw_usrreqs.pru_peeraddr(so, nam); + splx(s); + return error; +} + +/* pru_rcvd is EOPNOTSUPP */ +/* pru_rcvoob is EOPNOTSUPP */ + +static int +rts_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *nam, + struct mbuf *control, struct proc *p) +{ + int s, error; + s = splnet(); + error = raw_usrreqs.pru_send(so, flags, m, nam, control, p); + splx(s); + return error; +} + +/* pru_sense is null */ + +static int +rts_shutdown(struct socket *so) +{ + int s, error; + s = splnet(); + error = raw_usrreqs.pru_shutdown(so); + splx(s); + return error; +} + +static int +rts_sockaddr(struct socket *so, struct mbuf *nam) +{ + int s, error; + s = splnet(); + error = raw_usrreqs.pru_sockaddr(so, nam); + splx(s); + return error; +} + +static struct pr_usrreqs route_usrreqs = { + rts_abort, pru_accept_notsupp, rts_attach, rts_bind, rts_connect, + pru_connect2_notsupp, pru_control_notsupp, rts_detach, rts_disconnect, + pru_listen_notsupp, rts_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp, + rts_send, pru_sense_null, rts_shutdown, rts_sockaddr, + sosend, soreceive, soselect +}; + /*ARGSUSED*/ static int route_output(m, so) @@ -811,7 +939,7 @@ sysctl_rtsock SYSCTL_HANDLER_ARGS return (error); } -SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock,""); +SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock, ""); /* * Definitions of protocols supported in the ROUTE domain. @@ -822,8 +950,9 @@ extern struct domain routedomain; /* or at least forward */ static struct protosw routesw[] = { { SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR, 0, route_output, raw_ctlinput, 0, - route_usrreq, - raw_init + 0, + raw_init, 0, 0, 0, + &route_usrreqs } }; |