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);
 }
