diff options
Diffstat (limited to 'sys/netinet/udp_usrreq.c')
-rw-r--r-- | sys/netinet/udp_usrreq.c | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 7fff2b6..695a7e1 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -959,9 +959,12 @@ udp_abort(struct socket *so) KASSERT(inp != NULL, ("udp_abort: inp == NULL")); INP_INFO_WLOCK(&udbinfo); INP_LOCK(inp); - soisdisconnected(so); - in_pcbdetach(inp); - in_pcbfree(inp); + if (inp->inp_faddr.s_addr != INADDR_ANY) { + in_pcbdisconnect(inp); + inp->inp_laddr.s_addr = INADDR_ANY; + soisdisconnected(so); + } + INP_UNLOCK(inp); INP_INFO_WUNLOCK(&udbinfo); } @@ -1007,6 +1010,24 @@ udp_bind(struct socket *so, struct sockaddr *nam, struct thread *td) return error; } +static void +udp_close(struct socket *so) +{ + struct inpcb *inp; + + inp = sotoinpcb(so); + KASSERT(inp != NULL, ("udp_close: inp == NULL")); + INP_INFO_WLOCK(&udbinfo); + INP_LOCK(inp); + if (inp->inp_faddr.s_addr != INADDR_ANY) { + in_pcbdisconnect(inp); + inp->inp_laddr.s_addr = INADDR_ANY; + soisdisconnected(so); + } + INP_UNLOCK(inp); + INP_INFO_WUNLOCK(&udbinfo); +} + static int udp_connect(struct socket *so, struct sockaddr *nam, struct thread *td) { @@ -1041,6 +1062,8 @@ udp_detach(struct socket *so) inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_detach: inp == NULL")); + KASSERT(inp->inp_faddr.s_addr == INADDR_ANY, + ("udp_detach: not disconnected")); INP_INFO_WLOCK(&udbinfo); INP_LOCK(inp); in_pcbdetach(inp); @@ -1131,5 +1154,6 @@ struct pr_usrreqs udp_usrreqs = { .pru_sosend = sosend_dgram, .pru_shutdown = udp_shutdown, .pru_sockaddr = udp_sockaddr, - .pru_sosetlabel = in_pcbsosetlabel + .pru_sosetlabel = in_pcbsosetlabel, + .pru_close = udp_close, }; |