Attaching a PCB to a socket is currently done via PRU_ATTACH but in most cases this does not need the network / socket lock since no packets can be received or sent over this socket (needs a bind or connect first) It also cleans up a few other ugly things like how the proto is passed.
This diff works for me but I did not test each and every protocol (TCP, UDP, ICMP, AF_UNIX work). Also not sure if I should renumber the PRU_* defines... in a way this can be solved in a second step. -- :wq Claudio Index: kern/uipc_proto.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_proto.c,v retrieving revision 1.12 diff -u -p -r1.12 uipc_proto.c --- kern/uipc_proto.c 22 Feb 2017 19:34:42 -0000 1.12 +++ kern/uipc_proto.c 26 Feb 2017 08:06:34 -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.177 diff -u -p -r1.177 uipc_socket.c --- kern/uipc_socket.c 14 Feb 2017 09:46:21 -0000 1.177 +++ kern/uipc_socket.c 26 Feb 2017 08:07:15 -0000 @@ -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.37 diff -u -p -r1.37 pfkey.c --- net/pfkey.c 22 Feb 2017 19:34:42 -0000 1.37 +++ net/pfkey.c 26 Feb 2017 08:29:12 -0000 @@ -188,31 +188,34 @@ 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 (!(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; + so->so_options |= SO_USELOOPBACK; if ((rval = - pfkey_versions[socket->so_proto->pr_protocol]->create(socket)) != 0) + pfkey_versions[so->so_proto->pr_protocol]->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); } @@ -242,9 +245,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)); @@ -271,7 +271,8 @@ static struct protosw pfkey_protosw_temp .pr_protocol = -1, .pr_flags = PR_ATOMIC | PR_ADDR, .pr_output = (void *) 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.28 diff -u -p -r1.28 raw_usrreq.c --- net/raw_usrreq.c 23 Jan 2017 16:31:24 -0000 1.28 +++ net/raw_usrreq.c 25 Jan 2017 23:01:28 -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.223 diff -u -p -r1.223 rtsock.c --- net/rtsock.c 22 Feb 2017 19:34:42 -0000 1.223 +++ net/rtsock.c 26 Feb 2017 08:09:30 -0000 @@ -157,46 +157,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; @@ -233,6 +193,59 @@ 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(); + + rp = sotorawcb(so); + + /* + * 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, 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) { @@ -1661,6 +1674,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.73 diff -u -p -r1.73 in_proto.c --- netinet/in_proto.c 22 Feb 2017 19:34:42 -0000 1.73 +++ netinet/in_proto.c 26 Feb 2017 08:28:06 -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.68 diff -u -p -r1.68 ip_var.h --- netinet/ip_var.h 1 Feb 2017 20:59:47 -0000 1.68 +++ netinet/ip_var.h 25 Feb 2017 18:51:02 -0000 @@ -256,6 +256,7 @@ int rip_input(struct mbuf **, int *, in int rip_output(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.95 diff -u -p -r1.95 raw_ip.c --- netinet/raw_ip.c 1 Feb 2017 20:59:47 -0000 1.95 +++ netinet/raw_ip.c 25 Feb 2017 18:51:02 -0000 @@ -410,32 +410,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; @@ -566,4 +547,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.89 diff -u -p -r1.89 in6_proto.c --- netinet6/in6_proto.c 22 Feb 2017 19:34:42 -0000 1.89 +++ netinet6/in6_proto.c 26 Feb 2017 08:26:48 -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.68 diff -u -p -r1.68 ip6_var.h --- netinet6/ip6_var.h 8 Feb 2017 12:37:43 -0000 1.68 +++ netinet6/ip6_var.h 25 Feb 2017 18:51:02 -0000 @@ -348,6 +348,7 @@ int rip6_ctloutput(int, struct socket *, int rip6_output(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.106 diff -u -p -r1.106 raw_ip6.c --- netinet6/raw_ip6.c 9 Feb 2017 15:23:35 -0000 1.106 +++ netinet6/raw_ip6.c 26 Feb 2017 08:11:08 -0000 @@ -578,35 +578,6 @@ rip6_usrreq(struct socket *so, int req, (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; @@ -766,6 +737,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: netmpls/mpls_proto.c =================================================================== RCS file: /cvs/src/sys/netmpls/mpls_proto.c,v retrieving revision 1.14 diff -u -p -r1.14 mpls_proto.c --- netmpls/mpls_proto.c 3 Dec 2015 21:57:59 -0000 1.14 +++ netmpls/mpls_proto.c 26 Jan 2017 01:59:51 -0000 @@ -48,18 +48,18 @@ struct protosw mplssw[] = { { 0, &mplsdomain, 0, 0, 0, 0, 0, 0, - 0, + 0, NULL, mpls_init, 0, 0, 0, mpls_sysctl }, { SOCK_DGRAM, &mplsdomain, 0, PR_ATOMIC|PR_ADDR, 0, 0, 0, 0, - mpls_raw_usrreq, + mpls_raw_usrreq, NULL, 0, 0, 0, 0, mpls_sysctl, }, /* raw wildcard */ { SOCK_RAW, &mplsdomain, 0, PR_ATOMIC|PR_ADDR, 0, 0, 0, 0, - mpls_raw_usrreq, + mpls_raw_usrreq, NULL, 0, 0, 0, 0, mpls_sysctl, }, }; Index: netmpls/mpls_raw.c =================================================================== RCS file: /cvs/src/sys/netmpls/mpls_raw.c,v retrieving revision 1.14 diff -u -p -r1.14 mpls_raw.c --- netmpls/mpls_raw.c 15 Nov 2016 13:44:03 -0000 1.14 +++ netmpls/mpls_raw.c 26 Jan 2017 02:00:09 -0000 @@ -74,15 +74,6 @@ mpls_raw_usrreq(struct socket *so, int r return (EOPNOTSUPP); switch (req) { - case PRU_ATTACH: - if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { - error = soreserve(so, mpls_raw_sendspace, - mpls_raw_recvspace); - if (error) - break; - } - break; - case PRU_DETACH: case PRU_BIND: case PRU_LISTEN: Index: sys/protosw.h =================================================================== RCS file: /cvs/src/sys/sys/protosw.h,v retrieving revision 1.22 diff -u -p -r1.22 protosw.h --- sys/protosw.h 1 Feb 2017 20:59:47 -0000 1.22 +++ sys/protosw.h 26 Feb 2017 09:49:58 -0000 @@ -82,6 +82,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) */ @@ -120,7 +122,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 */ @@ -148,7 +149,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 *);