On Sun, Mar 05, 2017 at 10:54:39AM +0100, Claudio Jeker wrote: > Here is an updated version of the PRU_ATTACH diff. I looked at the pfkey > code and decided to only do the minimum now. I will go in afterwards and > kill the dynamic fiddling in there. There is no reason for all this > complication since we only support one and only one version of pfkey.
This diff is not minimal. By changing socket->so_proto->pr_protocol to proto you broke socket(AF_KEY,0x3<SOCK_RAW>,0). ipsecctl(9) uses socket(AF_KEY,0x3<SOCK_RAW>,0x2) so this is not noticed. Such a diff may not change user land semantics. > I would like to commit this version and then do the pfkey cleanup on top > of this. Yes please. I took me a while to understand that something broke. > Any OKs? Do not do unnecessary changes in pfkey_attach() to keep review simple. The route_usrreq() chunk does not apply anymore after mpi@'s commit. Everything else is OK bluhm@ > -- > :wq Claudio > > Index: kern/uipc_proto.c > =================================================================== > RCS file: /cvs/src/sys/kern/uipc_proto.c,v > retrieving revision 1.13 > diff -u -p -r1.13 uipc_proto.c > --- kern/uipc_proto.c 2 Mar 2017 08:58:24 -0000 1.13 > +++ kern/uipc_proto.c 5 Mar 2017 09:23:04 -0000 > @@ -55,6 +55,7 @@ struct protosw unixsw[] = { > .pr_protocol = PF_LOCAL, > .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_RIGHTS, > .pr_usrreq = uipc_usrreq, > + .pr_attach = uipc_attach, > }, > { > .pr_type = SOCK_SEQPACKET, > @@ -62,6 +63,7 @@ struct protosw unixsw[] = { > .pr_protocol = PF_LOCAL, > .pr_flags = PR_ATOMIC|PR_CONNREQUIRED|PR_WANTRCVD|PR_RIGHTS, > .pr_usrreq = uipc_usrreq, > + .pr_attach = uipc_attach, > }, > { > .pr_type = SOCK_DGRAM, > @@ -69,6 +71,7 @@ struct protosw unixsw[] = { > .pr_protocol = PF_LOCAL, > .pr_flags = PR_ATOMIC|PR_ADDR|PR_RIGHTS, > .pr_usrreq = uipc_usrreq, > + .pr_attach = uipc_attach, > } > }; > > Index: kern/uipc_socket.c > =================================================================== > RCS file: /cvs/src/sys/kern/uipc_socket.c,v > retrieving revision 1.178 > diff -u -p -r1.178 uipc_socket.c > --- kern/uipc_socket.c 3 Mar 2017 09:41:20 -0000 1.178 > +++ kern/uipc_socket.c 5 Mar 2017 09:39:34 -0000 > @@ -119,7 +119,7 @@ socreate(int dom, struct socket **aso, i > prp = pffindproto(dom, proto, type); > else > prp = pffindtype(dom, type); > - if (prp == NULL || prp->pr_usrreq == 0) > + if (prp == NULL || prp->pr_attach == NULL) > return (EPROTONOSUPPORT); > if (prp->pr_type != type) > return (EPROTOTYPE); > @@ -135,9 +135,9 @@ socreate(int dom, struct socket **aso, i > so->so_egid = p->p_ucred->cr_gid; > so->so_cpid = p->p_p->ps_pid; > so->so_proto = prp; > + > s = solock(so); > - error = (*prp->pr_usrreq)(so, PRU_ATTACH, NULL, > - (struct mbuf *)(long)proto, NULL, p); > + error = (*prp->pr_attach)(so, proto); > if (error) { > so->so_state |= SS_NOFDREF; > sofree(so); > Index: kern/uipc_socket2.c > =================================================================== > RCS file: /cvs/src/sys/kern/uipc_socket2.c,v > retrieving revision 1.72 > diff -u -p -r1.72 uipc_socket2.c > --- kern/uipc_socket2.c 14 Feb 2017 09:46:21 -0000 1.72 > +++ kern/uipc_socket2.c 25 Feb 2017 18:51:02 -0000 > @@ -187,8 +187,7 @@ sonewconn(struct socket *head, int conns > so->so_rcv.sb_timeo = head->so_rcv.sb_timeo; > > soqinsque(head, so, soqueue); > - if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH, NULL, NULL, NULL, > - curproc)) { > + if ((*so->so_proto->pr_attach)(so, 0)) { > (void) soqremque(so, soqueue); > pool_put(&socket_pool, so); > return (NULL); > Index: kern/uipc_usrreq.c > =================================================================== > RCS file: /cvs/src/sys/kern/uipc_usrreq.c,v > retrieving revision 1.116 > diff -u -p -r1.116 uipc_usrreq.c > --- kern/uipc_usrreq.c 14 Feb 2017 09:46:21 -0000 1.116 > +++ kern/uipc_usrreq.c 26 Feb 2017 08:03:29 -0000 > @@ -117,7 +117,7 @@ uipc_usrreq(struct socket *so, int req, > error = EOPNOTSUPP; > goto release; > } > - if (unp == NULL && req != PRU_ATTACH) { > + if (unp == NULL) { > error = EINVAL; > goto release; > } > @@ -126,14 +126,6 @@ uipc_usrreq(struct socket *so, int req, > > switch (req) { > > - case PRU_ATTACH: > - if (unp) { > - error = EISCONN; > - break; > - } > - error = unp_attach(so); > - break; > - > case PRU_DETACH: > unp_detach(unp); > break; > @@ -351,11 +343,13 @@ u_long unpdg_recvspace = 4*1024; > int unp_rights; /* file descriptors in flight */ > > int > -unp_attach(struct socket *so) > +uipc_attach(struct socket *so, int proto) > { > struct unpcb *unp; > int error; > > + if (so->so_pcb) > + return EISCONN; > if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { > switch (so->so_type) { > > Index: net/pfkey.c > =================================================================== > RCS file: /cvs/src/sys/net/pfkey.c,v > retrieving revision 1.39 > diff -u -p -r1.39 pfkey.c > --- net/pfkey.c 3 Mar 2017 15:48:02 -0000 1.39 > +++ net/pfkey.c 5 Mar 2017 09:46:15 -0000 > @@ -189,31 +189,37 @@ ret: > return (error); > } > > -static int > -pfkey_attach(struct socket *socket, struct mbuf *proto, struct proc *p) > +int > +pfkey_attach(struct socket *so, int proto) > { > int rval; > > - if (!(socket->so_pcb = malloc(sizeof(struct rawcb), > + if ((so->so_state & SS_PRIV) == 0) > + return EACCES; > + > + if ((proto > PFKEY_PROTOCOL_MAX) || (proto < 0) || > + !pfkey_versions[proto]) > + return (EPROTONOSUPPORT); > + > + if (!(so->so_pcb = malloc(sizeof(struct rawcb), > M_PCB, M_DONTWAIT | M_ZERO))) > return (ENOMEM); > > - rval = raw_usrreq(socket, PRU_ATTACH, NULL, proto, NULL, p); > + rval = raw_attach(so, proto); > if (rval) > goto ret; > > - ((struct rawcb *)socket->so_pcb)->rcb_faddr = &pfkey_addr; > - soisconnected(socket); > + ((struct rawcb *)so->so_pcb)->rcb_faddr = &pfkey_addr; > + soisconnected(so); > > - socket->so_options |= SO_USELOOPBACK; > - if ((rval = > - pfkey_versions[socket->so_proto->pr_protocol]->create(socket)) != 0) > + so->so_options |= SO_USELOOPBACK; > + if ((rval = pfkey_versions[proto]->create(so)) != 0) > goto ret; > > return (0); > > ret: > - free(socket->so_pcb, M_PCB, sizeof(struct rawcb)); > + free(so->so_pcb, M_PCB, sizeof(struct rawcb)); > return (rval); > } > > @@ -243,9 +249,6 @@ pfkey_usrreq(struct socket *socket, int > return (EPROTONOSUPPORT); > > switch (req) { > - case PRU_ATTACH: > - return (pfkey_attach(socket, nam, p)); > - > case PRU_DETACH: > return (pfkey_detach(socket, p)); > > @@ -268,7 +271,8 @@ static struct protosw pfkey_protosw_temp > .pr_protocol = -1, > .pr_flags = PR_ATOMIC | PR_ADDR, > .pr_output = pfkey_output, > - .pr_usrreq = pfkey_usrreq > + .pr_usrreq = pfkey_usrreq, > + .pr_attach = pfkey_attach, > }; > > int > Index: net/raw_usrreq.c > =================================================================== > RCS file: /cvs/src/sys/net/raw_usrreq.c,v > retrieving revision 1.29 > diff -u -p -r1.29 raw_usrreq.c > --- net/raw_usrreq.c 3 Mar 2017 15:48:02 -0000 1.29 > +++ net/raw_usrreq.c 5 Mar 2017 09:25:55 -0000 > @@ -76,20 +76,6 @@ raw_usrreq(struct socket *so, int req, s > return (EINVAL); > } > 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)(long)nam); > - break; > - > /* > * Destroy state just before socket deallocation. > * Flush data or not depending on the options. > Index: net/rtsock.c > =================================================================== > RCS file: /cvs/src/sys/net/rtsock.c,v > retrieving revision 1.228 > diff -u -p -r1.228 rtsock.c > --- net/rtsock.c 3 Mar 2017 15:48:02 -0000 1.228 > +++ net/rtsock.c 5 Mar 2017 09:25:55 -0000 > @@ -161,46 +161,6 @@ route_usrreq(struct socket *so, int req, > rp = sotorawcb(so); > > switch (req) { > - case PRU_ATTACH: > - /* > - * use the rawcb but allocate a routecb, this > - * code does not care about the additional fields > - * and works directly on the raw socket. > - */ > - rop = malloc(sizeof(struct routecb), M_PCB, M_WAITOK|M_ZERO); > - rp = &rop->rcb; > - so->so_pcb = rp; > - /* Init the timeout structure */ > - timeout_set(&((struct routecb *)rp)->timeout, rt_senddesync, > rp); > - /* > - * Don't call raw_usrreq() in the attach case, because > - * we want to allow non-privileged processes to listen > - * on and send "safe" commands to the routing socket. > - */ > - if (curproc == 0) > - error = EACCES; > - else > - error = raw_attach(so, (int)(long)nam); > - if (error) { > - free(rop, M_PCB, sizeof(struct routecb)); > - return (error); > - } > - rop->rtableid = curproc->p_p->ps_rtableid; > - af = rp->rcb_proto.sp_protocol; > - if (af == AF_INET) > - route_cb.ip_count++; > - else if (af == AF_INET6) > - route_cb.ip6_count++; > -#ifdef MPLS > - else if (af == AF_MPLS) > - route_cb.mpls_count++; > -#endif > - rp->rcb_faddr = &route_src; > - route_cb.any_count++; > - soisconnected(so); > - so->so_options |= SO_USELOOPBACK; > - break; > - > case PRU_RCVD: > rop = (struct routecb *)rp; > > @@ -237,6 +197,53 @@ route_usrreq(struct socket *so, int req, > } > > int > +route_attach(struct socket *so, int proto) > +{ > + struct rawcb *rp; > + struct routecb *rop; > + int af; > + int error = 0; > + > + NET_ASSERT_LOCKED(); > + > + /* > + * use the rawcb but allocate a routecb, this > + * code does not care about the additional fields > + * and works directly on the raw socket. > + */ > + rop = malloc(sizeof(struct routecb), M_PCB, M_WAITOK|M_ZERO); > + rp = &rop->rcb; > + so->so_pcb = rp; > + /* Init the timeout structure */ > + timeout_set(&rop->timeout, rt_senddesync, rp); > + > + if (curproc == NULL) > + error = EACCES; > + else > + error = raw_attach(so, proto); > + if (error) { > + free(rop, M_PCB, sizeof(struct routecb)); > + return (error); > + } > + rop->rtableid = curproc->p_p->ps_rtableid; > + af = rp->rcb_proto.sp_protocol; > + if (af == AF_INET) > + route_cb.ip_count++; > + else if (af == AF_INET6) > + route_cb.ip6_count++; > +#ifdef MPLS > + else if (af == AF_MPLS) > + route_cb.mpls_count++; > +#endif > + rp->rcb_faddr = &route_src; > + route_cb.any_count++; > + soisconnected(so); > + so->so_options |= SO_USELOOPBACK; > + > + return (error); > +} > + > +int > route_ctloutput(int op, struct socket *so, int level, int optname, > struct mbuf *m) > { > @@ -1738,6 +1745,7 @@ struct protosw routesw[] = { > .pr_output = route_output, > .pr_ctloutput = route_ctloutput, > .pr_usrreq = route_usrreq, > + .pr_attach = route_attach, > .pr_init = raw_init, > .pr_sysctl = sysctl_rtable > } > Index: netinet/in_proto.c > =================================================================== > RCS file: /cvs/src/sys/netinet/in_proto.c,v > retrieving revision 1.74 > diff -u -p -r1.74 in_proto.c > --- netinet/in_proto.c 2 Mar 2017 08:58:24 -0000 1.74 > +++ netinet/in_proto.c 5 Mar 2017 09:23:04 -0000 > @@ -191,6 +191,7 @@ struct protosw inetsw[] = { > .pr_ctlinput = udp_ctlinput, > .pr_ctloutput = ip_ctloutput, > .pr_usrreq = udp_usrreq, > + .pr_attach = udp_attach, > .pr_init = udp_init, > .pr_sysctl = udp_sysctl > }, > @@ -203,6 +204,7 @@ struct protosw inetsw[] = { > .pr_ctlinput = tcp_ctlinput, > .pr_ctloutput = tcp_ctloutput, > .pr_usrreq = tcp_usrreq, > + .pr_attach = tcp_attach, > .pr_init = tcp_init, > .pr_slowtimo = tcp_slowtimo, > .pr_sysctl = tcp_sysctl > @@ -215,7 +217,8 @@ struct protosw inetsw[] = { > .pr_input = rip_input, > .pr_output = rip_output, > .pr_ctloutput = rip_ctloutput, > - .pr_usrreq = rip_usrreq > + .pr_usrreq = rip_usrreq, > + .pr_attach = rip_attach > }, > { > .pr_type = SOCK_RAW, > @@ -226,6 +229,7 @@ struct protosw inetsw[] = { > .pr_output = rip_output, > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > + .pr_attach = rip_attach, > .pr_init = icmp_init, > .pr_sysctl = icmp_sysctl > }, > @@ -239,6 +243,7 @@ struct protosw inetsw[] = { > .pr_output = rip_output, > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > + .pr_attach = rip_attach, > .pr_sysctl = ipip_sysctl > }, > { > @@ -250,6 +255,7 @@ struct protosw inetsw[] = { > .pr_output = rip_output, > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > + .pr_attach = rip_attach, > .pr_sysctl = etherip_sysctl > }, > #ifdef INET6 > @@ -260,7 +266,8 @@ struct protosw inetsw[] = { > .pr_flags = PR_ATOMIC|PR_ADDR, > .pr_input = in_gif_input, > .pr_output = rip_output, > - .pr_usrreq = rip_usrreq /* XXX */ > + .pr_usrreq = rip_usrreq, /* XXX */ > + .pr_attach = rip_attach > }, > #endif > #ifdef MPLS > @@ -271,7 +278,8 @@ struct protosw inetsw[] = { > .pr_flags = PR_ATOMIC|PR_ADDR, > .pr_input = etherip_input, > .pr_output = rip_output, > - .pr_usrreq = rip_usrreq > + .pr_usrreq = rip_usrreq, > + .pr_attach = rip_attach > }, > #endif > #else /* NGIF */ > @@ -284,6 +292,7 @@ struct protosw inetsw[] = { > .pr_output = rip_output, > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > + .pr_attach = rip_attach, > .pr_sysctl = ipip_sysctl > }, > #ifdef INET6 > @@ -295,7 +304,8 @@ struct protosw inetsw[] = { > .pr_input = ip4_input, > .pr_output = rip_output, > .pr_ctloutput = rip_ctloutput, > - .pr_usrreq = rip_usrreq /* XXX */ > + .pr_usrreq = rip_usrreq, /* XXX */ > + .pr_attach = rip_attach > }, > #endif > #endif /*NGIF*/ > @@ -308,6 +318,7 @@ struct protosw inetsw[] = { > .pr_output = rip_output, > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > + .pr_attach = rip_attach, > .pr_init = igmp_init, > .pr_fasttimo = igmp_fasttimo, > .pr_slowtimo = igmp_slowtimo, > @@ -324,6 +335,7 @@ struct protosw inetsw[] = { > .pr_ctlinput = ah4_ctlinput, > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > + .pr_attach = rip_attach, > .pr_sysctl = ah_sysctl > }, > { > @@ -336,6 +348,7 @@ struct protosw inetsw[] = { > .pr_ctlinput = esp4_ctlinput, > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > + .pr_attach = rip_attach, > .pr_sysctl = esp_sysctl > }, > { > @@ -347,6 +360,7 @@ struct protosw inetsw[] = { > .pr_output = rip_output, > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > + .pr_attach = rip_attach, > .pr_sysctl = ipcomp_sysctl > }, > #endif /* IPSEC */ > @@ -360,6 +374,7 @@ struct protosw inetsw[] = { > .pr_output = rip_output, > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = gre_usrreq, > + .pr_attach = rip_attach, > .pr_sysctl = gre_sysctl > }, > { > @@ -371,6 +386,7 @@ struct protosw inetsw[] = { > .pr_output = rip_output, > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > + .pr_attach = rip_attach, > .pr_sysctl = ipmobile_sysctl > }, > #endif /* NGRE > 0 */ > @@ -384,6 +400,7 @@ struct protosw inetsw[] = { > .pr_output = rip_output, > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > + .pr_attach = rip_attach, > .pr_sysctl = carp_sysctl > }, > #endif /* NCARP > 0 */ > @@ -397,6 +414,7 @@ struct protosw inetsw[] = { > .pr_output = rip_output, > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > + .pr_attach = rip_attach, > .pr_sysctl = pfsync_sysctl > }, > #endif /* NPFSYNC > 0 */ > @@ -408,6 +426,7 @@ struct protosw inetsw[] = { > .pr_flags = PR_ATOMIC|PR_ADDR, > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = divert_usrreq, > + .pr_attach = divert_attach, > .pr_init = divert_init, > .pr_sysctl = divert_sysctl > }, > @@ -422,6 +441,7 @@ struct protosw inetsw[] = { > .pr_output = rip_output, > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > + .pr_attach = rip_attach, > .pr_sysctl = ip_etherip_sysctl > }, > #endif /* NETHERIP */ > @@ -434,6 +454,7 @@ struct protosw inetsw[] = { > .pr_output = rip_output, > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > + .pr_attach = rip_attach, > .pr_init = rip_init > } > }; > Index: netinet/ip_divert.c > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_divert.c,v > retrieving revision 1.44 > diff -u -p -r1.44 ip_divert.c > --- netinet/ip_divert.c 9 Feb 2017 15:32:56 -0000 1.44 > +++ netinet/ip_divert.c 26 Feb 2017 08:10:15 -0000 > @@ -249,31 +249,12 @@ divert_usrreq(struct socket *so, int req > return (in_control(so, (u_long)m, (caddr_t)addr, > (struct ifnet *)control)); > } > - if (inp == NULL && req != PRU_ATTACH) { > + if (inp == NULL) { > error = EINVAL; > goto release; > } > switch (req) { > > - case PRU_ATTACH: > - if (inp != NULL) { > - error = EINVAL; > - break; > - } > - if ((so->so_state & SS_PRIV) == 0) { > - error = EACCES; > - break; > - } > - error = in_pcballoc(so, &divbtable); > - if (error) > - break; > - > - error = soreserve(so, divert_sendspace, divert_recvspace); > - if (error) > - break; > - sotoinpcb(so)->inp_flags |= INP_HDRINCL; > - break; > - > case PRU_DETACH: > in_pcbdetach(inp); > break; > @@ -330,6 +311,28 @@ release: > m_freem(control); > m_freem(m); > return (error); > +} > + > +int > +divert_attach(struct socket *so, int proto) > +{ > + int error; > + > + if (so->so_pcb != NULL) > + return EINVAL; > + if ((so->so_state & SS_PRIV) == 0) > + return EACCES; > + > + error = in_pcballoc(so, &divbtable); > + if (error) > + return error; > + > + error = soreserve(so, divert_sendspace, divert_recvspace); > + if (error) > + return error; > + > + sotoinpcb(so)->inp_flags |= INP_HDRINCL; > + return (0); > } > > int > Index: netinet/ip_divert.h > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_divert.h,v > retrieving revision 1.8 > diff -u -p -r1.8 ip_divert.h > --- netinet/ip_divert.h 9 Feb 2017 15:32:56 -0000 1.8 > +++ netinet/ip_divert.h 25 Feb 2017 18:51:02 -0000 > @@ -78,6 +78,7 @@ int divert_packet(struct mbuf *, int, u > int divert_sysctl(int *, u_int, void *, size_t *, void *, size_t); > int divert_usrreq(struct socket *, > int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *); > +int divert_attach(struct socket *, int); > > #endif /* _KERNEL */ > #endif /* _IP_DIVERT_H_ */ > Index: netinet/ip_var.h > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_var.h,v > retrieving revision 1.69 > diff -u -p -r1.69 ip_var.h > --- netinet/ip_var.h 3 Mar 2017 15:48:02 -0000 1.69 > +++ netinet/ip_var.h 5 Mar 2017 09:25:55 -0000 > @@ -257,6 +257,7 @@ int rip_output(struct mbuf *, struct so > struct mbuf *); > int rip_usrreq(struct socket *, > int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *); > +int rip_attach(struct socket *, int); > > #endif /* _KERNEL */ > #endif /* _NETINET_IP_VAR_H_ */ > Index: netinet/raw_ip.c > =================================================================== > RCS file: /cvs/src/sys/netinet/raw_ip.c,v > retrieving revision 1.96 > diff -u -p -r1.96 raw_ip.c > --- netinet/raw_ip.c 3 Mar 2017 15:48:02 -0000 1.96 > +++ netinet/raw_ip.c 5 Mar 2017 09:25:55 -0000 > @@ -403,32 +403,13 @@ rip_usrreq(struct socket *so, int req, s > return (in_control(so, (u_long)m, (caddr_t)nam, > (struct ifnet *)control)); > > - if (inp == NULL && req != PRU_ATTACH) { > + if (inp == NULL) { > error = EINVAL; > goto release; > } > > switch (req) { > > - case PRU_ATTACH: > - if (inp) > - panic("rip_attach"); > - if ((so->so_state & SS_PRIV) == 0) { > - error = EACCES; > - break; > - } > - if ((long)nam < 0 || (long)nam >= IPPROTO_MAX) { > - error = EPROTONOSUPPORT; > - break; > - } > - if ((error = soreserve(so, rip_sendspace, rip_recvspace)) || > - (error = in_pcballoc(so, &rawcbtable))) { > - break; > - } > - inp = sotoinpcb(so); > - inp->inp_ip.ip_p = (long)nam; > - break; > - > case PRU_DISCONNECT: > if ((so->so_state & SS_ISCONNECTED) == 0) { > error = ENOTCONN; > @@ -563,4 +544,26 @@ rip_usrreq(struct socket *so, int req, s > release: > m_freem(m); > return (error); > +} > + > +int > +rip_attach(struct socket *so, int proto) > +{ > + struct inpcb *inp; > + int error; > + > + if (so->so_pcb) > + panic("rip_attach"); > + if ((so->so_state & SS_PRIV) == 0) > + return EACCES; > + if (proto < 0 || proto >= IPPROTO_MAX) > + return EPROTONOSUPPORT; > + > + if ((error = soreserve(so, rip_sendspace, rip_recvspace)) || > + (error = in_pcballoc(so, &rawcbtable))) { > + return error; > + } > + inp = sotoinpcb(so); > + inp->inp_ip.ip_p = proto; > + return 0; > } > Index: netinet/tcp_usrreq.c > =================================================================== > RCS file: /cvs/src/sys/netinet/tcp_usrreq.c,v > retrieving revision 1.144 > diff -u -p -r1.144 tcp_usrreq.c > --- netinet/tcp_usrreq.c 9 Feb 2017 15:19:32 -0000 1.144 > +++ netinet/tcp_usrreq.c 25 Feb 2017 18:51:02 -0000 > @@ -157,7 +157,7 @@ tcp_usrreq(struct socket *so, int req, s > * a (struct inpcb) pointed at by the socket, and this > * structure will point at a subsidiary (struct tcpcb). > */ > - if (inp == NULL && req != PRU_ATTACH) { > + if (inp == NULL) { > error = so->so_error; > if (error == 0) > error = EINVAL; > @@ -184,23 +184,6 @@ tcp_usrreq(struct socket *so, int req, s > switch (req) { > > /* > - * TCP attaches to socket via PRU_ATTACH, reserving space, > - * and an internet control block. > - */ > - case PRU_ATTACH: > - if (inp) { > - error = EISCONN; > - break; > - } > - error = tcp_attach(so); > - if (error) > - break; > - if ((so->so_options & SO_LINGER) && so->so_linger == 0) > - so->so_linger = TCP_LINGERTIME; > - tp = sototcpcb(so); > - break; > - > - /* > * PRU_DETACH detaches the TCP protocol from the socket. > * If the protocol state is non-embryonic, then can't > * do this directly: have to initiate a PRU_DISCONNECT, > @@ -608,12 +591,14 @@ tcp_ctloutput(int op, struct socket *so, > * bufer space, and entering LISTEN state if to accept connections. > */ > int > -tcp_attach(struct socket *so) > +tcp_attach(struct socket *so, int proto) > { > struct tcpcb *tp; > struct inpcb *inp; > int error; > > + if (so->so_pcb) > + return EISCONN; > if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0 || > sbcheckreserve(so->so_snd.sb_wat, tcp_sendspace) || > sbcheckreserve(so->so_rcv.sb_wat, tcp_recvspace)) { > @@ -645,6 +630,11 @@ tcp_attach(struct socket *so) > #else > tp->pf = PF_INET; > #endif > + if ((so->so_options & SO_LINGER) && so->so_linger == 0) > + so->so_linger = TCP_LINGERTIME; > + > + if (tp && (so->so_options & SO_DEBUG)) > + tcp_trace(TA_USER, 0, tp, (caddr_t)0, 0 /* XXX */, 0); > return (0); > } > > Index: netinet/tcp_var.h > =================================================================== > RCS file: /cvs/src/sys/netinet/tcp_var.h,v > retrieving revision 1.122 > diff -u -p -r1.122 tcp_var.h > --- netinet/tcp_var.h 9 Feb 2017 15:19:32 -0000 1.122 > +++ netinet/tcp_var.h 25 Feb 2017 18:51:02 -0000 > @@ -716,7 +716,6 @@ extern int tcp_syn_use_limit; /* numbe > extern struct syn_cache_set tcp_syn_cache[]; > extern int tcp_syn_cache_active; /* active syn cache, may be 0 or 1 */ > > -int tcp_attach(struct socket *); > void tcp_canceltimers(struct tcpcb *); > struct tcpcb * > tcp_close(struct tcpcb *); > @@ -765,6 +764,7 @@ struct tcpcb * > int tcp_sysctl(int *, u_int, void *, size_t *, void *, size_t); > int tcp_usrreq(struct socket *, > int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *); > +int tcp_attach(struct socket *, int); > void tcp_xmit_timer(struct tcpcb *, int); > void tcpdropoldhalfopen(struct tcpcb *, u_int16_t); > #ifdef TCP_SACK > Index: netinet/udp_usrreq.c > =================================================================== > RCS file: /cvs/src/sys/netinet/udp_usrreq.c,v > retrieving revision 1.231 > diff -u -p -r1.231 udp_usrreq.c > --- netinet/udp_usrreq.c 5 Feb 2017 16:23:38 -0000 1.231 > +++ netinet/udp_usrreq.c 25 Feb 2017 18:51:02 -0000 > @@ -1115,7 +1115,7 @@ udp_usrreq(struct socket *so, int req, s > } > > inp = sotoinpcb(so); > - if (inp == NULL && req != PRU_ATTACH) { > + if (inp == NULL) { > error = EINVAL; > goto release; > } > @@ -1126,22 +1126,6 @@ udp_usrreq(struct socket *so, int req, s > */ > switch (req) { > > - case PRU_ATTACH: > - if (inp != NULL) { > - error = EINVAL; > - break; > - } > - if ((error = soreserve(so, udp_sendspace, udp_recvspace)) || > - (error = in_pcballoc(so, &udbtable))) > - break; > -#ifdef INET6 > - if (sotoinpcb(so)->inp_flags & INP_IPV6) > - sotoinpcb(so)->inp_ipv6.ip6_hlim = ip6_defhlim; > - else > -#endif /* INET6 */ > - sotoinpcb(so)->inp_ip.ip_ttl = ip_defttl; > - break; > - > case PRU_DETACH: > in_pcbdetach(inp); > break; > @@ -1305,6 +1289,26 @@ release: > m_freem(control); > m_freem(m); > return (error); > +} > + > +int > +udp_attach(struct socket *so, int proto) > +{ > + int error; > + > + if (so->so_pcb != NULL) > + return EINVAL; > + > + if ((error = soreserve(so, udp_sendspace, udp_recvspace)) || > + (error = in_pcballoc(so, &udbtable))) > + return error; > +#ifdef INET6 > + if (sotoinpcb(so)->inp_flags & INP_IPV6) > + sotoinpcb(so)->inp_ipv6.ip6_hlim = ip6_defhlim; > + else > +#endif /* INET6 */ > + sotoinpcb(so)->inp_ip.ip_ttl = ip_defttl; > + return 0; > } > > /* > Index: netinet/udp_var.h > =================================================================== > RCS file: /cvs/src/sys/netinet/udp_var.h,v > retrieving revision 1.31 > diff -u -p -r1.31 udp_var.h > --- netinet/udp_var.h 29 Jan 2017 19:58:47 -0000 1.31 > +++ netinet/udp_var.h 25 Feb 2017 18:51:02 -0000 > @@ -149,5 +149,6 @@ int udp6_output(struct inpcb *, struct > int udp_sysctl(int *, u_int, void *, size_t *, void *, size_t); > int udp_usrreq(struct socket *, > int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *); > +int udp_attach(struct socket *, int); > #endif /* _KERNEL */ > #endif /* _NETINET_UDP_VAR_H_ */ > Index: netinet6/in6_proto.c > =================================================================== > RCS file: /cvs/src/sys/netinet6/in6_proto.c,v > retrieving revision 1.90 > diff -u -p -r1.90 in6_proto.c > --- netinet6/in6_proto.c 2 Mar 2017 08:58:24 -0000 1.90 > +++ netinet6/in6_proto.c 5 Mar 2017 09:23:04 -0000 > @@ -139,6 +139,7 @@ struct protosw inet6sw[] = { > .pr_ctlinput = udp6_ctlinput, > .pr_ctloutput = ip6_ctloutput, > .pr_usrreq = udp_usrreq, > + .pr_attach = udp_attach, > .pr_sysctl = udp_sysctl > }, > { > @@ -150,6 +151,7 @@ struct protosw inet6sw[] = { > .pr_ctlinput = tcp6_ctlinput, > .pr_ctloutput = tcp_ctloutput, > .pr_usrreq = tcp_usrreq, > + .pr_attach = tcp_attach, > .pr_sysctl = tcp_sysctl > }, > { > @@ -162,6 +164,7 @@ struct protosw inet6sw[] = { > .pr_ctlinput = rip6_ctlinput, > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > + .pr_attach = rip6_attach, > .pr_sysctl = rip6_sysctl > }, > { > @@ -174,6 +177,7 @@ struct protosw inet6sw[] = { > .pr_ctlinput = rip6_ctlinput, > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > + .pr_attach = rip6_attach, > .pr_init = icmp6_init, > .pr_fasttimo = icmp6_fasttimo, > .pr_sysctl = icmp6_sysctl > @@ -209,6 +213,7 @@ struct protosw inet6sw[] = { > .pr_output = rip6_output, > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > + .pr_attach = rip6_attach, > .pr_sysctl = ah_sysctl > }, > { > @@ -220,6 +225,7 @@ struct protosw inet6sw[] = { > .pr_output = rip6_output, > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > + .pr_attach = rip6_attach, > .pr_sysctl = esp_sysctl > }, > { > @@ -231,6 +237,7 @@ struct protosw inet6sw[] = { > .pr_output = rip6_output, > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > + .pr_attach = rip6_attach, > .pr_sysctl = ipcomp_sysctl > }, > #endif /* IPSEC */ > @@ -244,6 +251,7 @@ struct protosw inet6sw[] = { > .pr_output = rip6_output, > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > + .pr_attach = rip6_attach, > .pr_sysctl = etherip_sysctl > }, > { > @@ -254,7 +262,8 @@ struct protosw inet6sw[] = { > .pr_input = in6_gif_input, > .pr_output = rip6_output, > .pr_ctloutput = rip6_ctloutput, > - .pr_usrreq = rip6_usrreq /* XXX */ > + .pr_usrreq = rip6_usrreq, /* XXX */ > + .pr_attach = rip6_attach > }, > { > .pr_type = SOCK_RAW, > @@ -264,7 +273,8 @@ struct protosw inet6sw[] = { > .pr_input = in6_gif_input, > .pr_output = rip6_output, > .pr_ctloutput = rip6_ctloutput, > - .pr_usrreq = rip6_usrreq /* XXX */ > + .pr_usrreq = rip6_usrreq, /* XXX */ > + .pr_attach = rip6_attach > }, > #else /* NGIF */ > { > @@ -276,6 +286,7 @@ struct protosw inet6sw[] = { > .pr_output = rip6_output, > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, /* XXX */ > + .pr_attach = rip6_attach, > .pr_sysctl = ipip_sysctl > }, > { > @@ -286,7 +297,8 @@ struct protosw inet6sw[] = { > .pr_input = ip4_input, > .pr_output = rip6_output, > .pr_ctloutput = rip6_ctloutput, > - .pr_usrreq = rip6_usrreq /* XXX */ > + .pr_usrreq = rip6_usrreq, /* XXX */ > + .pr_attach = rip6_attach > }, > #endif /* GIF */ > #if NCARP > 0 > @@ -299,6 +311,7 @@ struct protosw inet6sw[] = { > .pr_output = rip6_output, > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > + .pr_attach = rip6_attach, > .pr_sysctl = carp_sysctl > }, > #endif /* NCARP */ > @@ -310,6 +323,7 @@ struct protosw inet6sw[] = { > .pr_flags = PR_ATOMIC|PR_ADDR, > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = divert6_usrreq, > + .pr_attach = divert6_attach, > .pr_init = divert6_init, > .pr_sysctl = divert6_sysctl > }, > @@ -324,6 +338,7 @@ struct protosw inet6sw[] = { > .pr_output = rip6_output, > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > + .pr_attach = rip6_attach, > .pr_sysctl = ip_etherip_sysctl > }, > #endif /* NETHERIP */ > @@ -336,6 +351,7 @@ struct protosw inet6sw[] = { > .pr_output = rip6_output, > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > + .pr_attach = rip6_attach, > .pr_init = rip6_init > } > }; > Index: netinet6/ip6_divert.c > =================================================================== > RCS file: /cvs/src/sys/netinet6/ip6_divert.c,v > retrieving revision 1.45 > diff -u -p -r1.45 ip6_divert.c > --- netinet6/ip6_divert.c 9 Feb 2017 15:32:56 -0000 1.45 > +++ netinet6/ip6_divert.c 26 Feb 2017 08:10:47 -0000 > @@ -250,31 +250,12 @@ divert6_usrreq(struct socket *so, int re > return (in6_control(so, (u_long)m, (caddr_t)addr, > (struct ifnet *)control)); > } > - if (inp == NULL && req != PRU_ATTACH) { > + if (inp == NULL) { > error = EINVAL; > goto release; > } > switch (req) { > > - case PRU_ATTACH: > - if (inp != NULL) { > - error = EINVAL; > - break; > - } > - if ((so->so_state & SS_PRIV) == 0) { > - error = EACCES; > - break; > - } > - error = in_pcballoc(so, &divb6table); > - if (error) > - break; > - > - error = soreserve(so, divert6_sendspace, divert6_recvspace); > - if (error) > - break; > - sotoinpcb(so)->inp_flags |= INP_HDRINCL; > - break; > - > case PRU_DETACH: > in_pcbdetach(inp); > break; > @@ -331,6 +312,28 @@ release: > m_freem(control); > m_freem(m); > return (error); > +} > + > +int > +divert6_attach(struct socket *so, int proto) > +{ > + int error; > + > + if (so->so_pcb != NULL) > + return EINVAL; > + > + if ((so->so_state & SS_PRIV) == 0) > + return EACCES; > + > + error = in_pcballoc(so, &divb6table); > + if (error) > + return (error); > + > + error = soreserve(so, divert6_sendspace, divert6_recvspace); > + if (error) > + return (error); > + sotoinpcb(so)->inp_flags |= INP_HDRINCL; > + return (0); > } > > int > Index: netinet6/ip6_divert.h > =================================================================== > RCS file: /cvs/src/sys/netinet6/ip6_divert.h,v > retrieving revision 1.6 > diff -u -p -r1.6 ip6_divert.h > --- netinet6/ip6_divert.h 9 Feb 2017 15:32:56 -0000 1.6 > +++ netinet6/ip6_divert.h 25 Feb 2017 18:51:02 -0000 > @@ -78,6 +78,7 @@ int divert6_packet(struct mbuf *, int, > int divert6_sysctl(int *, u_int, void *, size_t *, void *, size_t); > int divert6_usrreq(struct socket *, > int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *); > +int divert6_attach(struct socket *, int); > #endif /* _KERNEL */ > > #endif /* _IP6_DIVERT_H_ */ > Index: netinet6/ip6_var.h > =================================================================== > RCS file: /cvs/src/sys/netinet6/ip6_var.h,v > retrieving revision 1.70 > diff -u -p -r1.70 ip6_var.h > --- netinet6/ip6_var.h 3 Mar 2017 15:48:02 -0000 1.70 > +++ netinet6/ip6_var.h 5 Mar 2017 09:25:55 -0000 > @@ -349,6 +349,7 @@ int rip6_output(struct mbuf *, struct so > struct mbuf *); > int rip6_usrreq(struct socket *, > int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *); > +int rip6_attach(struct socket *, int); > int rip6_sysctl(int *, u_int, void *, size_t *, void *, size_t); > > int dest6_input(struct mbuf **, int *, int); > Index: netinet6/raw_ip6.c > =================================================================== > RCS file: /cvs/src/sys/netinet6/raw_ip6.c,v > retrieving revision 1.107 > diff -u -p -r1.107 raw_ip6.c > --- netinet6/raw_ip6.c 3 Mar 2017 15:48:02 -0000 1.107 > +++ netinet6/raw_ip6.c 5 Mar 2017 09:25:55 -0000 > @@ -556,48 +556,14 @@ rip6_usrreq(struct socket *so, int req, > { > struct inpcb *in6p = sotoinpcb(so); > int error = 0; > - int priv; > > NET_ASSERT_LOCKED(); > > - priv = 0; > - if ((so->so_state & SS_PRIV) != 0) > - priv++; > - > if (req == PRU_CONTROL) > return (in6_control(so, (u_long)m, (caddr_t)nam, > (struct ifnet *)control)); > > switch (req) { > - case PRU_ATTACH: > - if (in6p) > - panic("rip6_attach"); > - if (!priv) { > - error = EACCES; > - break; > - } > - if ((long)nam < 0 || (long)nam >= IPPROTO_MAX) { > - error = EPROTONOSUPPORT; > - break; > - } > - if ((error = soreserve(so, rip6_sendspace, rip6_recvspace)) || > - (error = in_pcballoc(so, &rawin6pcbtable))) { > - break; > - } > - in6p = sotoinpcb(so); > - in6p->inp_ipv6.ip6_nxt = (long)nam; > - in6p->inp_cksum6 = -1; > - > - in6p->inp_icmp6filt = malloc(sizeof(struct icmp6_filter), > - M_PCB, M_NOWAIT); > - if (in6p->inp_icmp6filt == NULL) { > - in_pcbdetach(in6p); > - error = ENOMEM; > - break; > - } > - ICMP6_FILTER_SETPASSALL(in6p->inp_icmp6filt); > - break; > - > case PRU_DISCONNECT: > if ((so->so_state & SS_ISCONNECTED) == 0) { > error = ENOTCONN; > @@ -757,6 +723,37 @@ rip6_usrreq(struct socket *so, int req, > } > m_freem(m); > return (error); > +} > + > +int > +rip6_attach(struct socket *so, int proto) > +{ > + struct inpcb *in6p; > + int error; > + > + if (so->so_pcb) > + panic("rip6_attach"); > + if ((so->so_state & SS_PRIV) == 0) > + return (EACCES); > + if (proto < 0 || proto >= IPPROTO_MAX) > + return EPROTONOSUPPORT; > + > + if ((error = soreserve(so, rip6_sendspace, rip6_recvspace)) || > + (error = in_pcballoc(so, &rawin6pcbtable))) > + return error; > + > + in6p = sotoinpcb(so); > + in6p->inp_ipv6.ip6_nxt = proto; > + in6p->inp_cksum6 = -1; > + > + in6p->inp_icmp6filt = malloc(sizeof(struct icmp6_filter), > + M_PCB, M_NOWAIT); > + if (in6p->inp_icmp6filt == NULL) { > + in_pcbdetach(in6p); > + return ENOMEM; > + } > + ICMP6_FILTER_SETPASSALL(in6p->inp_icmp6filt); > + return 0; > } > > int > Index: sys/protosw.h > =================================================================== > RCS file: /cvs/src/sys/sys/protosw.h,v > retrieving revision 1.23 > diff -u -p -r1.23 protosw.h > --- sys/protosw.h 3 Mar 2017 15:48:02 -0000 1.23 > +++ sys/protosw.h 5 Mar 2017 09:25:55 -0000 > @@ -83,6 +83,8 @@ struct protosw { > int (*pr_usrreq)(struct socket *, int, struct mbuf *, > struct mbuf *, struct mbuf *, struct proc *); > > + int (*pr_attach)(struct socket *, int); > + > /* utility hooks */ > void (*pr_init)(void); /* initialization hook */ > void (*pr_fasttimo)(void); /* fast timeout (200ms) */ > @@ -121,7 +123,6 @@ struct protosw { > * A non-zero return from usrreq gives an > * UNIX error number which should be passed to higher level software. > */ > -#define PRU_ATTACH 0 /* attach protocol to up */ > #define PRU_DETACH 1 /* detach protocol from up */ > #define PRU_BIND 2 /* bind socket to address */ > #define PRU_LISTEN 3 /* listen for connection */ > @@ -149,7 +150,7 @@ struct protosw { > > #ifdef PRUREQUESTS > char *prurequests[] = { > - "ATTACH", "DETACH", "BIND", "LISTEN", > + "", "DETACH", "BIND", "LISTEN", > "CONNECT", "ACCEPT", "DISCONNECT", "SHUTDOWN", > "RCVD", "SEND", "ABORT", "CONTROL", > "SENSE", "RCVOOB", "SENDOOB", "SOCKADDR", > Index: sys/socketvar.h > =================================================================== > RCS file: /cvs/src/sys/sys/socketvar.h,v > retrieving revision 1.68 > diff -u -p -r1.68 socketvar.h > --- sys/socketvar.h 14 Feb 2017 09:46:21 -0000 1.68 > +++ sys/socketvar.h 26 Feb 2017 08:05:05 -0000 > @@ -258,8 +258,6 @@ int soo_poll(struct file *fp, int events > int soo_kqfilter(struct file *fp, struct knote *kn); > int soo_close(struct file *fp, struct proc *p); > int soo_stat(struct file *, struct stat *, struct proc *); > -int uipc_usrreq(struct socket *, int , struct mbuf *, > - struct mbuf *, struct mbuf *, struct proc *); > void sbappend(struct sockbuf *sb, struct mbuf *m); > void sbappendstream(struct sockbuf *sb, struct mbuf *m); > int sbappendaddr(struct sockbuf *sb, struct sockaddr *asa, > Index: sys/unpcb.h > =================================================================== > RCS file: /cvs/src/sys/sys/unpcb.h,v > retrieving revision 1.14 > diff -u -p -r1.14 unpcb.h > --- sys/unpcb.h 27 Jan 2017 20:31:42 -0000 1.14 > +++ sys/unpcb.h 26 Feb 2017 08:05:45 -0000 > @@ -91,7 +91,10 @@ struct fdpass { > int flags; > }; > > -int unp_attach(struct socket *); > +int uipc_usrreq(struct socket *, int , struct mbuf *, > + struct mbuf *, struct mbuf *, struct proc *); > +int uipc_attach(struct socket *, int); > + > int unp_bind(struct unpcb *, struct mbuf *, struct proc *); > int unp_connect(struct socket *, struct mbuf *, struct proc *); > int unp_connect2(struct socket *, struct socket *);