Index: udp_usrreq.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/udp_usrreq.c,v retrieving revision 1.202 diff -u -r1.202 udp_usrreq.c --- udp_usrreq.c 20 Feb 2007 10:20:02 -0000 1.202 +++ udp_usrreq.c 23 Feb 2007 04:06:48 -0000 @@ -648,7 +648,8 @@ for (i = 0; i < n; i++) { inp = inp_list[i]; INP_LOCK(inp); - if (inp->inp_gencnt <= gencnt) { + if ((inp->inp_gencnt <= gencnt) && + !(inp->inp_vflag & INP_DROPPED)) { struct xinpcb xi; bzero(&xi, sizeof(xi)); xi.xi_len = sizeof xi; @@ -701,7 +702,12 @@ INP_INFO_RLOCK(&udbinfo); inp = in_pcblookup_hash(&udbinfo, addrs[1].sin_addr, addrs[1].sin_port, addrs[0].sin_addr, addrs[0].sin_port, 1, NULL); - if (inp == NULL || inp->inp_socket == NULL) { + if (inp == NULL) { + error = ENOENT; + goto out; + } + INP_LOCK(inp); + if (inp->inp_socket == NULL || (inp->inp_vflag & INP_DROPPED)) { error = ENOENT; goto out; } @@ -710,6 +716,8 @@ goto out; cru2x(inp->inp_socket->so_cred, &xuc); out: + if (inp != NULL) + INP_UNLOCK(inp); INP_INFO_RUNLOCK(&udbinfo); if (error == 0) error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred)); @@ -803,6 +811,10 @@ } else unlock_udbinfo = 0; INP_LOCK(inp); + if (inp->inp_vflag & INP_DROPPED) { + error = EINVAL; + goto release; + } #ifdef MAC mac_create_mbuf_from_inpcb(inp, m); @@ -963,9 +975,10 @@ INP_LOCK(inp); if (inp->inp_faddr.s_addr != INADDR_ANY) { in_pcbdisconnect(inp); - inp->inp_laddr.s_addr = INADDR_ANY; soisdisconnected(so); } + in_pcbdrop(inp); + inp->inp_laddr.s_addr = INADDR_ANY; INP_UNLOCK(inp); INP_INFO_WUNLOCK(&udbinfo); } @@ -1006,7 +1019,10 @@ KASSERT(inp != NULL, ("udp_bind: inp == NULL")); INP_INFO_WLOCK(&udbinfo); INP_LOCK(inp); - error = in_pcbbind(inp, nam, td->td_ucred); + if (inp->inp_vflag & INP_DROPPED) + error = EINVAL; + else + error = in_pcbbind(inp, nam, td->td_ucred); INP_UNLOCK(inp); INP_INFO_WUNLOCK(&udbinfo); return (error); @@ -1026,6 +1042,8 @@ inp->inp_laddr.s_addr = INADDR_ANY; soisdisconnected(so); } + in_pcbdrop(inp); + inp->inp_laddr.s_addr = INADDR_ANY; INP_UNLOCK(inp); INP_INFO_WUNLOCK(&udbinfo); } @@ -1041,10 +1059,13 @@ KASSERT(inp != NULL, ("udp_connect: inp == NULL")); INP_INFO_WLOCK(&udbinfo); INP_LOCK(inp); + if (inp->inp_vflag & INP_DROPPED) { + error = EINVAL; + goto out; + } if (inp->inp_faddr.s_addr != INADDR_ANY) { - INP_UNLOCK(inp); - INP_INFO_WUNLOCK(&udbinfo); - return (EISCONN); + error = EISCONN; + goto out; } sin = (struct sockaddr_in *)nam; if (jailed(td->td_ucred)) @@ -1052,6 +1073,7 @@ error = in_pcbconnect(inp, nam, td->td_ucred); if (error == 0) soisconnected(so); +out: INP_UNLOCK(inp); INP_INFO_WUNLOCK(&udbinfo); return (error); @@ -1066,6 +1088,7 @@ KASSERT(inp != NULL, ("udp_detach: inp == NULL")); KASSERT(inp->inp_faddr.s_addr == INADDR_ANY, ("udp_detach: not disconnected")); + KASSERT(inp->inp_vflag & INP_DROPPED, ("udp_detach: not dropped")); INP_INFO_WLOCK(&udbinfo); INP_LOCK(inp); in_pcbdetach(inp); @@ -1077,25 +1100,31 @@ udp_disconnect(struct socket *so) { struct inpcb *inp; + int error; + error = 0; inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_disconnect: inp == NULL")); INP_INFO_WLOCK(&udbinfo); INP_LOCK(inp); + if (inp->inp_vflag & INP_DROPPED) { + error = EINVAL; + goto out; + } if (inp->inp_faddr.s_addr == INADDR_ANY) { - INP_INFO_WUNLOCK(&udbinfo); - INP_UNLOCK(inp); - return (ENOTCONN); + error = ENOTCONN; + goto out; } - in_pcbdisconnect(inp); + in_pcbdrop(inp); inp->inp_laddr.s_addr = INADDR_ANY; SOCK_LOCK(so); so->so_state &= ~SS_ISCONNECTED; /* XXX */ SOCK_UNLOCK(so); +out: INP_UNLOCK(inp); INP_INFO_WUNLOCK(&udbinfo); - return (0); + return (error); } static int @@ -1113,11 +1142,18 @@ udp_shutdown(struct socket *so) { struct inpcb *inp; + int error; + error = 0; inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_shutdown: inp == NULL")); INP_LOCK(inp); + if (inp->inp_vflag & INP_DROPPED) { + error = EINVAL; + goto out; + } socantsendmore(so); +out: INP_UNLOCK(inp); return (0); }