On 02/11/17(Thu) 09:06, Florian Obser wrote: > this moves PRU_DETACH out of pr_usrreq into per proto pr_detach > functions, like what claudio did to pr_attach. > > Intentionally mostly mechanical. There might be some cleanup here and > there in the functions themselves.
I like it, comments inline. > diff --git kern/uipc_socket.c kern/uipc_socket.c > index 615da029414..df08096a9ee 100644 > --- kern/uipc_socket.c > +++ kern/uipc_socket.c > @@ -266,8 +266,13 @@ soclose(struct socket *so) > } > drop: > if (so->so_pcb) { > - int error2 = (*so->so_proto->pr_usrreq)(so, PRU_DETACH, NULL, > - NULL, NULL, curproc); > + int error2; > + > + if (so->so_proto->pr_detach == NULL) > + panic("soclose pr_detach == NULL: so %p, so_type %d", > + so, so->so_type); Since we're now enforcing the existence of pr_detach, a KASSERT() is enough. > + > + error2 = (*so->so_proto->pr_detach)(so); > if (error == 0) > error = error2; > } > diff --git kern/uipc_usrreq.c kern/uipc_usrreq.c > index 07e032ca0a3..35871b7cf54 100644 > --- kern/uipc_usrreq.c > +++ kern/uipc_usrreq.c > @@ -126,10 +126,6 @@ uipc_usrreq(struct socket *so, int req, struct mbuf *m, > struct mbuf *nam, > > switch (req) { > > - case PRU_DETACH: > - unp_detach(unp); > - break; > - > case PRU_BIND: > error = unp_bind(unp, nam, p); > break; > @@ -378,6 +374,21 @@ uipc_attach(struct socket *so, int proto) > return (0); > } > > +int > +uipc_detach(struct socket *so) > +{ > + struct unpcb *unp = sotounpcb(so); > + > + if (unp == NULL) > + return (EINVAL); > + > + NET_ASSERT_UNLOCKED(); > + > + unp_detach(unp); > + > + return (0); > +} > + > void > unp_detach(struct unpcb *unp) > { > diff --git net/pfkeyv2.c net/pfkeyv2.c > index ac593e4d5f1..f52ec9d3692 100644 > --- net/pfkeyv2.c > +++ net/pfkeyv2.c > @@ -159,7 +159,7 @@ static int npromisc = 0; > void pfkey_init(void); > > int pfkeyv2_attach(struct socket *, int); > -int pfkeyv2_detach(struct socket *, struct proc *); > +int pfkeyv2_detach(struct socket *); > int pfkeyv2_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, > struct mbuf *, struct proc *); > int pfkeyv2_output(struct mbuf *, struct socket *, struct sockaddr *, > @@ -192,6 +192,7 @@ static struct protosw pfkeysw[] = { > .pr_output = pfkeyv2_output, > .pr_usrreq = pfkeyv2_usrreq, > .pr_attach = pfkeyv2_attach, > + .pr_detach = pfkeyv2_detach, > .pr_sysctl = pfkeyv2_sysctl, > } > }; > @@ -255,7 +256,7 @@ pfkeyv2_attach(struct socket *so, int proto) > * Close a PF_KEYv2 socket. > */ > int > -pfkeyv2_detach(struct socket *so, struct proc *p) > +pfkeyv2_detach(struct socket *so) > { > struct keycb *kp; > > @@ -276,7 +277,7 @@ pfkeyv2_detach(struct socket *so, struct proc *p) > mtx_leave(&pfkeyv2_mtx); > } > > - raw_detach(&kp->rcb); > + raw_do_detach(&kp->rcb); Claudio suggested merging the content of the raw functions in pfkey and rtsock. It doesn't make much sense to keep a function for calling sofree(). So I'd get rid of raw_detach() and inline it here. A next step could be to get rid of net/raw_cb.c > return (0); > } > > @@ -284,12 +285,7 @@ int > pfkeyv2_usrreq(struct socket *so, int req, struct mbuf *mbuf, > struct mbuf *nam, struct mbuf *control, struct proc *p) > { > - switch (req) { > - case PRU_DETACH: > - return (pfkeyv2_detach(so, p)); > - default: > - return (raw_usrreq(so, req, mbuf, nam, control, p)); > - } > + return (raw_usrreq(so, req, mbuf, nam, control, p)); > } > > int > diff --git net/raw_cb.c net/raw_cb.c > index e77da50b039..55c3fd21d2f 100644 > --- net/raw_cb.c > +++ net/raw_cb.c > @@ -76,12 +76,27 @@ raw_attach(struct socket *so, int proto) > return (0); > } > > +int > +raw_detach(struct socket *so) > +{ > + struct rawcb *rp = sotorawcb(so); > + > + soassertlocked(so); > + > + if (rp == NULL) > + return (EINVAL); > + > + raw_do_detach(rp); > + > + return (0); > +} > + > /* > * Detach the raw connection block and discard > * socket resources. > */ > void > -raw_detach(struct rawcb *rp) > +raw_do_detach(struct rawcb *rp) > { > struct socket *so = rp->rcb_socket; > > @@ -97,5 +112,5 @@ void > raw_disconnect(struct rawcb *rp) > { > if (rp->rcb_socket->so_state & SS_NOFDREF) > - raw_detach(rp); > + raw_do_detach(rp); > } > diff --git net/raw_cb.h net/raw_cb.h > index 00c3d30f98a..a3e964d807f 100644 > --- net/raw_cb.h > +++ net/raw_cb.h > @@ -56,7 +56,8 @@ struct rawcb { > > #define sotorawcb(so) ((struct rawcb *)(so)->so_pcb) > int raw_attach(struct socket *, int); > -void raw_detach(struct rawcb *); > +int raw_detach(struct socket *); > +void raw_do_detach(struct rawcb *); > void raw_disconnect(struct rawcb *); > void raw_init(void); > int raw_usrreq(struct socket *, > diff --git net/raw_usrreq.c net/raw_usrreq.c > index d72f242c892..0300ab65e1b 100644 > --- net/raw_usrreq.c > +++ net/raw_usrreq.c > @@ -67,14 +67,6 @@ raw_usrreq(struct socket *so, int req, struct mbuf *m, > struct mbuf *nam, > return (EINVAL); > } > switch (req) { > - /* > - * Destroy state just before socket deallocation. > - * Flush data or not depending on the options. > - */ > - case PRU_DETACH: > - raw_detach(rp); > - break; > - > case PRU_CONNECT: > case PRU_BIND: > case PRU_CONNECT2: > diff --git net/rtsock.c net/rtsock.c > index dc77a2411b3..08cef9d14a8 100644 > --- net/rtsock.c > +++ net/rtsock.c > @@ -174,7 +174,6 @@ route_usrreq(struct socket *so, int req, struct mbuf *m, > struct mbuf *nam, > struct mbuf *control, struct proc *p) > { > struct routecb *rop; > - int af; > int error = 0; > > soassertlocked(so); > @@ -198,20 +197,6 @@ route_usrreq(struct socket *so, int req, struct mbuf *m, > struct mbuf *nam, > rop->flags &= ~ROUTECB_FLAG_FLUSH; > break; > > - case PRU_DETACH: > - timeout_del(&rop->timeout); > - af = rop->rcb.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 > - route_cb.any_count--; > - LIST_REMOVE(rop, rcb_list); > - /* FALLTHROUGH */ > default: > error = raw_usrreq(so, req, m, nam, control, p); > } > @@ -270,6 +255,33 @@ route_attach(struct socket *so, int proto) > return (0); > } > > +int > +route_detach(struct socket *so) > +{ > + struct routecb *rop; > + int af; > + > + soassertlocked(so); > + > + rop = sotoroutecb(so); > + if (rop == NULL) > + return (EINVAL); > + > + timeout_del(&rop->timeout); > + af = rop->rcb.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 > + route_cb.any_count--; > + LIST_REMOVE(rop, rcb_list); > + return (raw_detach(so)); > +} > + > int > route_ctloutput(int op, struct socket *so, int level, int optname, > struct mbuf *m) > @@ -1922,6 +1934,7 @@ struct protosw routesw[] = { > .pr_ctloutput = route_ctloutput, > .pr_usrreq = route_usrreq, > .pr_attach = route_attach, > + .pr_detach = route_detach, > .pr_init = route_prinit, > .pr_sysctl = sysctl_rtable > } > diff --git netinet/in_proto.c netinet/in_proto.c > index 2c3dbec3ed2..3a006cefcc7 100644 > --- netinet/in_proto.c > +++ netinet/in_proto.c > @@ -192,6 +192,7 @@ struct protosw inetsw[] = { > .pr_ctloutput = ip_ctloutput, > .pr_usrreq = udp_usrreq, > .pr_attach = udp_attach, > + .pr_detach = udp_detach, > .pr_init = udp_init, > .pr_sysctl = udp_sysctl > }, > @@ -205,6 +206,7 @@ struct protosw inetsw[] = { > .pr_ctloutput = tcp_ctloutput, > .pr_usrreq = tcp_usrreq, > .pr_attach = tcp_attach, > + .pr_detach = tcp_detach, > .pr_init = tcp_init, > .pr_slowtimo = tcp_slowtimo, > .pr_sysctl = tcp_sysctl > @@ -217,7 +219,8 @@ struct protosw inetsw[] = { > .pr_input = rip_input, > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > - .pr_attach = rip_attach > + .pr_attach = rip_attach, > + .pr_detach = rip_detach, > }, > { > .pr_type = SOCK_RAW, > @@ -228,6 +231,7 @@ struct protosw inetsw[] = { > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > .pr_attach = rip_attach, > + .pr_detach = rip_detach, > .pr_init = icmp_init, > .pr_sysctl = icmp_sysctl > }, > @@ -244,6 +248,7 @@ struct protosw inetsw[] = { > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > .pr_attach = rip_attach, > + .pr_detach = rip_detach, > .pr_sysctl = ipip_sysctl, > .pr_init = ipip_init > }, > @@ -260,7 +265,8 @@ struct protosw inetsw[] = { > #endif > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, /* XXX */ > - .pr_attach = rip_attach > + .pr_attach = rip_attach, > + .pr_detach = rip_detach, > }, > #endif > #if NGIF > 0 > @@ -273,6 +279,7 @@ struct protosw inetsw[] = { > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > .pr_attach = rip_attach, > + .pr_detach = rip_detach, > .pr_sysctl = etherip_sysctl > }, > #endif /* NGIF */ > @@ -284,7 +291,8 @@ struct protosw inetsw[] = { > .pr_flags = PR_ATOMIC|PR_ADDR, > .pr_input = etherip_input, > .pr_usrreq = rip_usrreq, > - .pr_attach = rip_attach > + .pr_attach = rip_attach, > + .pr_detach = rip_detach, > }, > #endif /* MPLS && GIF */ > { > @@ -296,6 +304,7 @@ struct protosw inetsw[] = { > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > .pr_attach = rip_attach, > + .pr_detach = rip_detach, > .pr_init = igmp_init, > .pr_fasttimo = igmp_fasttimo, > .pr_slowtimo = igmp_slowtimo, > @@ -312,6 +321,7 @@ struct protosw inetsw[] = { > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > .pr_attach = rip_attach, > + .pr_detach = rip_detach, > .pr_sysctl = ah_sysctl > }, > { > @@ -324,6 +334,7 @@ struct protosw inetsw[] = { > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > .pr_attach = rip_attach, > + .pr_detach = rip_detach, > .pr_sysctl = esp_sysctl > }, > { > @@ -335,6 +346,7 @@ struct protosw inetsw[] = { > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > .pr_attach = rip_attach, > + .pr_detach = rip_detach, > .pr_sysctl = ipcomp_sysctl > }, > #endif /* IPSEC */ > @@ -348,6 +360,7 @@ struct protosw inetsw[] = { > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = gre_usrreq, > .pr_attach = rip_attach, > + .pr_detach = rip_detach, > .pr_sysctl = gre_sysctl > }, > { > @@ -359,6 +372,7 @@ struct protosw inetsw[] = { > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > .pr_attach = rip_attach, > + .pr_detach = rip_detach, > .pr_sysctl = ipmobile_sysctl > }, > #endif /* NGRE > 0 */ > @@ -372,6 +386,7 @@ struct protosw inetsw[] = { > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > .pr_attach = rip_attach, > + .pr_detach = rip_detach, > .pr_sysctl = carp_sysctl > }, > #endif /* NCARP > 0 */ > @@ -385,6 +400,7 @@ struct protosw inetsw[] = { > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > .pr_attach = rip_attach, > + .pr_detach = rip_detach, > .pr_sysctl = pfsync_sysctl > }, > #endif /* NPFSYNC > 0 */ > @@ -397,6 +413,7 @@ struct protosw inetsw[] = { > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = divert_usrreq, > .pr_attach = divert_attach, > + .pr_detach = divert_detach, > .pr_init = divert_init, > .pr_sysctl = divert_sysctl > }, > @@ -411,6 +428,7 @@ struct protosw inetsw[] = { > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > .pr_attach = rip_attach, > + .pr_detach = rip_detach, > .pr_sysctl = ip_etherip_sysctl > }, > #endif /* NETHERIP */ > @@ -423,6 +441,7 @@ struct protosw inetsw[] = { > .pr_ctloutput = rip_ctloutput, > .pr_usrreq = rip_usrreq, > .pr_attach = rip_attach, > + .pr_detach = rip_detach, > .pr_init = rip_init > } > }; > diff --git netinet/ip_divert.c netinet/ip_divert.c > index 6f1bc3e55ee..5ecd8c6189b 100644 > --- netinet/ip_divert.c > +++ netinet/ip_divert.c > @@ -254,10 +254,6 @@ divert_usrreq(struct socket *so, int req, struct mbuf > *m, struct mbuf *addr, > } > switch (req) { > > - case PRU_DETACH: > - in_pcbdetach(inp); > - break; > - > case PRU_BIND: > error = in_pcbbind(inp, addr, p); > break; > @@ -334,6 +330,20 @@ divert_attach(struct socket *so, int proto) > return (0); > } > > +int > +divert_detach(struct socket *so) > +{ > + struct inpcb *inp = sotoinpcb(so); > + > + soassertlocked(so); > + > + if (inp == NULL) > + return (EINVAL); > + > + in_pcbdetach(inp); > + return (0); > +} > + > int > divert_sysctl_divstat(void *oldp, size_t *oldlenp, void *newp) > { > diff --git netinet/ip_divert.h netinet/ip_divert.h > index 31cdc0c09f8..2912921f30d 100644 > --- netinet/ip_divert.h > +++ netinet/ip_divert.h > @@ -78,6 +78,6 @@ 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); > - > +int divert_detach(struct socket *); > #endif /* _KERNEL */ > #endif /* _IP_DIVERT_H_ */ > diff --git netinet/ip_var.h netinet/ip_var.h > index 23f824b5ed6..9fe65aad3f4 100644 > --- netinet/ip_var.h > +++ netinet/ip_var.h > @@ -253,7 +253,7 @@ int rip_output(struct mbuf *, struct socket *, > struct sockaddr *, > int rip_usrreq(struct socket *, > int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *); > int rip_attach(struct socket *, int); > - > +int rip_detach(struct socket *); > #ifdef MROUTING > extern struct socket *ip_mrouter[]; /* multicast routing daemon */ > #endif > diff --git netinet/raw_ip.c netinet/raw_ip.c > index 3e4af999eea..8e815964705 100644 > --- netinet/raw_ip.c > +++ netinet/raw_ip.c > @@ -382,10 +382,8 @@ rip_usrreq(struct socket *so, int req, struct mbuf *m, > struct mbuf *nam, > /* FALLTHROUGH */ > case PRU_ABORT: > soisdisconnected(so); > - /* FALLTHROUGH */ > - case PRU_DETACH: > if (inp == NULL) > - panic("rip_detach"); > + panic("rip_abort"); > #ifdef MROUTING > if (so == ip_mrouter[inp->inp_rtableid]) > ip_mrouter_done(so); > @@ -522,3 +520,22 @@ rip_attach(struct socket *so, int proto) > inp->inp_ip.ip_p = proto; > return 0; > } > + > +int > +rip_detach(struct socket *so) > +{ > + struct inpcb *inp = sotoinpcb(so); > + > + soassertlocked(so); > + > + if (inp == NULL) > + return (EINVAL); > + > +#ifdef MROUTING > + if (so == ip_mrouter[inp->inp_rtableid]) > + ip_mrouter_done(so); > +#endif > + in_pcbdetach(inp); > + > + return (0); > +} > diff --git netinet/tcp_usrreq.c netinet/tcp_usrreq.c > index b4333507447..61ea6cdc6d5 100644 > --- netinet/tcp_usrreq.c > +++ netinet/tcp_usrreq.c > @@ -181,17 +181,6 @@ tcp_usrreq(struct socket *so, int req, struct mbuf *m, > struct mbuf *nam, > ostate = 0; > switch (req) { > > - /* > - * 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, > - * which may finish later; embryonic TCB's can just > - * be discarded here. > - */ > - case PRU_DETACH: > - tp = tcp_disconnect(tp); > - break; > - > /* > * Give the socket an address. > */ > @@ -618,6 +607,54 @@ tcp_attach(struct socket *so, int proto) > return (0); > } > > +int > +tcp_detach(struct socket *so) > +{ > + struct inpcb *inp; > + struct tcpcb *tp = NULL; > + int error = 0; > + short ostate; > + > + soassertlocked(so); > + > + inp = sotoinpcb(so); > + /* > + * When a TCP is attached to a socket, then there will be > + * a (struct inpcb) pointed at by the socket, and this > + * structure will point at a subsidiary (struct tcpcb). > + */ > + if (inp == NULL) { > + error = so->so_error; > + if (error == 0) > + error = EINVAL; > + > + return (error); > + } > + if (inp) { > + tp = intotcpcb(inp); > + /* tp might get 0 when using socket splicing */ > + if (tp == NULL) { > + return (0); > + } > +#ifdef KPROF > + tcp_acounts[tp->t_state][req]++; > +#endif > + ostate = tp->t_state; > + } else > + ostate = 0; > + > + /* > + * Detache 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, > + * which may finish later; embryonic TCB's can just > + * be discarded here. > + */ > + tcp_disconnect(tp); > + > + return (error); > +} > + > /* > * Initiate (or continue) disconnect. > * If embryonic state, just send reset (once). > diff --git netinet/tcp_var.h netinet/tcp_var.h > index 54e8aecc262..f2f398fc61c 100644 > --- netinet/tcp_var.h > +++ netinet/tcp_var.h > @@ -751,6 +751,7 @@ 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); > +int tcp_detach(struct socket *); > void tcp_xmit_timer(struct tcpcb *, int); > void tcpdropoldhalfopen(struct tcpcb *, u_int16_t); > void tcp_sack_option(struct tcpcb *,struct tcphdr *,u_char *,int); > diff --git netinet/udp_usrreq.c netinet/udp_usrreq.c > index 95b093bee58..a5c4b52896b 100644 > --- netinet/udp_usrreq.c > +++ netinet/udp_usrreq.c > @@ -1085,10 +1085,6 @@ udp_usrreq(struct socket *so, int req, struct mbuf *m, > struct mbuf *addr, > */ > switch (req) { > > - case PRU_DETACH: > - in_pcbdetach(inp); > - break; > - > case PRU_BIND: > error = in_pcbbind(inp, addr, p); > break; > @@ -1270,6 +1266,22 @@ udp_attach(struct socket *so, int proto) > return 0; > } > > +int > +udp_detach(struct socket *so) > +{ > + struct inpcb *inp; > + > + soassertlocked(so); > + > + ^ Extra line. > + inp = sotoinpcb(so); > + if (inp == NULL) > + return (EINVAL); > + > + in_pcbdetach(inp); > + return (0); > +} > + > /* > * Sysctl for udp variables. > */ > diff --git netinet/udp_var.h netinet/udp_var.h > index 7a511e7b05b..ba405d30b20 100644 > --- netinet/udp_var.h > +++ netinet/udp_var.h > @@ -150,5 +150,6 @@ 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); > +int udp_detach(struct socket *); > #endif /* _KERNEL */ > #endif /* _NETINET_UDP_VAR_H_ */ > diff --git netinet6/in6_proto.c netinet6/in6_proto.c > index 2a653e0286e..3cc11abbb7b 100644 > --- netinet6/in6_proto.c > +++ netinet6/in6_proto.c > @@ -140,6 +140,7 @@ struct protosw inet6sw[] = { > .pr_ctloutput = ip6_ctloutput, > .pr_usrreq = udp_usrreq, > .pr_attach = udp_attach, > + .pr_detach = udp_detach, > .pr_sysctl = udp_sysctl > }, > { > @@ -152,6 +153,7 @@ struct protosw inet6sw[] = { > .pr_ctloutput = tcp_ctloutput, > .pr_usrreq = tcp_usrreq, > .pr_attach = tcp_attach, > + .pr_detach = tcp_detach, > .pr_sysctl = tcp_sysctl > }, > { > @@ -164,6 +166,7 @@ struct protosw inet6sw[] = { > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > .pr_attach = rip6_attach, > + .pr_detach = rip6_detach, > .pr_sysctl = rip6_sysctl > }, > { > @@ -176,6 +179,7 @@ struct protosw inet6sw[] = { > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > .pr_attach = rip6_attach, > + .pr_detach = rip6_detach, > .pr_init = icmp6_init, > .pr_fasttimo = icmp6_fasttimo, > .pr_sysctl = icmp6_sysctl > @@ -211,6 +215,7 @@ struct protosw inet6sw[] = { > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > .pr_attach = rip6_attach, > + .pr_detach = rip6_detach, > .pr_sysctl = ah_sysctl > }, > { > @@ -222,6 +227,7 @@ struct protosw inet6sw[] = { > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > .pr_attach = rip6_attach, > + .pr_detach = rip6_detach, > .pr_sysctl = esp_sysctl > }, > { > @@ -233,6 +239,7 @@ struct protosw inet6sw[] = { > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > .pr_attach = rip6_attach, > + .pr_detach = rip6_detach, > .pr_sysctl = ipcomp_sysctl > }, > #endif /* IPSEC */ > @@ -248,7 +255,8 @@ struct protosw inet6sw[] = { > #endif > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, /* XXX */ > - .pr_attach = rip6_attach > + .pr_attach = rip6_attach, > + .pr_detach = rip6_detach, > }, > { > .pr_type = SOCK_RAW, > @@ -263,6 +271,7 @@ struct protosw inet6sw[] = { > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, /* XXX */ > .pr_attach = rip6_attach, > + .pr_detach = rip6_detach, > }, > #if NGIF > 0 > { > @@ -274,6 +283,7 @@ struct protosw inet6sw[] = { > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > .pr_attach = rip6_attach, > + .pr_detach = rip6_detach, > .pr_sysctl = etherip_sysctl > }, > #endif /* NGIF */ > @@ -287,6 +297,7 @@ struct protosw inet6sw[] = { > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > .pr_attach = rip6_attach, > + .pr_detach = rip6_detach, > .pr_sysctl = carp_sysctl > }, > #endif /* NCARP */ > @@ -299,6 +310,7 @@ struct protosw inet6sw[] = { > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = divert6_usrreq, > .pr_attach = divert6_attach, > + .pr_detach = divert6_detach, > .pr_init = divert6_init, > .pr_sysctl = divert6_sysctl > }, > @@ -313,6 +325,7 @@ struct protosw inet6sw[] = { > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > .pr_attach = rip6_attach, > + .pr_detach = rip6_detach, > .pr_sysctl = ip_etherip_sysctl > }, > #endif /* NETHERIP */ > @@ -325,6 +338,7 @@ struct protosw inet6sw[] = { > .pr_ctloutput = rip6_ctloutput, > .pr_usrreq = rip6_usrreq, > .pr_attach = rip6_attach, > + .pr_detach = rip6_detach, > .pr_init = rip6_init > } > }; > diff --git netinet6/ip6_divert.c netinet6/ip6_divert.c > index 1f20dc64d83..c8b91c3298e 100644 > --- netinet6/ip6_divert.c > +++ netinet6/ip6_divert.c > @@ -257,10 +257,6 @@ divert6_usrreq(struct socket *so, int req, struct mbuf > *m, struct mbuf *addr, > } > switch (req) { > > - case PRU_DETACH: > - in_pcbdetach(inp); > - break; > - > case PRU_BIND: > error = in_pcbbind(inp, addr, p); > break; > @@ -337,6 +333,21 @@ divert6_attach(struct socket *so, int proto) > return (0); > } > > +int > +divert6_detach(struct socket *so) > +{ > + struct inpcb *inp = sotoinpcb(so); > + > + soassertlocked(so); > + > + if (inp == NULL) > + return (EINVAL); > + > + in_pcbdetach(inp); > + > + return (0); > +} > + > int > divert6_sysctl_div6stat(void *oldp, size_t *oldlenp, void *newp) > { > diff --git netinet6/ip6_divert.h netinet6/ip6_divert.h > index bbda15b4061..4e8daaca779 100644 > --- netinet6/ip6_divert.h > +++ netinet6/ip6_divert.h > @@ -78,6 +78,7 @@ 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); > +int divert6_detach(struct socket *); > #endif /* _KERNEL */ > > #endif /* _IP6_DIVERT_H_ */ > diff --git netinet6/ip6_var.h netinet6/ip6_var.h > index da11f5a1ee5..216392c6660 100644 > --- netinet6/ip6_var.h > +++ netinet6/ip6_var.h > @@ -345,6 +345,7 @@ int rip6_output(struct mbuf *, struct socket *, > struct sockaddr *, > int rip6_usrreq(struct socket *, > int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *); > int rip6_attach(struct socket *, int); > +int rip6_detach(struct socket *); > int rip6_sysctl(int *, u_int, void *, size_t *, void *, size_t); > > int dest6_input(struct mbuf **, int *, int, int); > diff --git netinet6/raw_ip6.c netinet6/raw_ip6.c > index c201852c69e..507d65539d0 100644 > --- netinet6/raw_ip6.c > +++ netinet6/raw_ip6.c > @@ -558,8 +558,6 @@ rip6_usrreq(struct socket *so, int req, struct mbuf *m, > struct mbuf *nam, > > case PRU_ABORT: > soisdisconnected(so); > - /* FALLTHROUGH */ > - case PRU_DETACH: > if (in6p == NULL) > panic("rip6_detach"); > #ifdef MROUTING > @@ -715,6 +713,27 @@ rip6_attach(struct socket *so, int proto) > return 0; > } > > +int > +rip6_detach(struct socket *so) > +{ > + struct inpcb *in6p = sotoinpcb(so); > + > + soassertlocked(so); > + > + if (in6p == NULL) > + panic("rip6_detach"); This should really be turned into an EINVAL like the others routine, it's a different issue. > +#ifdef MROUTING > + if (so == ip6_mrouter[in6p->inp_rtableid]) > + ip6_mrouter_done(so); > +#endif > + free(in6p->inp_icmp6filt, M_PCB, sizeof(struct icmp6_filter)); > + in6p->inp_icmp6filt = NULL; > + > + in_pcbdetach(in6p); > + > + return (0); > +} > + > int > rip6_sysctl_rip6stat(void *oldp, size_t *oldplen, void *newp) > { > diff --git sys/protosw.h sys/protosw.h > index ccb2e004c22..e525f8b3f93 100644 > --- sys/protosw.h > +++ sys/protosw.h > @@ -84,6 +84,7 @@ struct protosw { > struct mbuf *, struct mbuf *, struct proc *); > > int (*pr_attach)(struct socket *, int); > + int (*pr_detach)(struct socket *); > > /* utility hooks */ > void (*pr_init)(void); /* initialization hook */ > @@ -123,7 +124,6 @@ struct protosw { > * A non-zero return from usrreq gives an > * UNIX error number which should be passed to higher level software. > */ > -#define PRU_DETACH 1 /* detach protocol from up */ > #define PRU_BIND 2 /* bind socket to address */ > #define PRU_LISTEN 3 /* listen for connection */ > #define PRU_CONNECT 4 /* establish connection to peer > */ > diff --git sys/unpcb.h sys/unpcb.h > index cae4f5af505..1733dea26ef 100644 > --- sys/unpcb.h > +++ sys/unpcb.h > @@ -94,6 +94,7 @@ struct fdpass { > int uipc_usrreq(struct socket *, int , struct mbuf *, > struct mbuf *, struct mbuf *, struct proc *); > int uipc_attach(struct socket *, int); > +int uipc_detach(struct socket *); > > int unp_bind(struct unpcb *, struct mbuf *, struct proc *); > int unp_connect(struct socket *, struct mbuf *, struct proc *); > > > -- > I'm not entirely sure you are real. >