Only enter wildcard sockets into the wildcard hash table.
authorJeffrey Hsu <hsu@dragonflybsd.org>
Wed, 31 Mar 2004 00:43:09 +0000 (00:43 +0000)
committerJeffrey Hsu <hsu@dragonflybsd.org>
Wed, 31 Mar 2004 00:43:09 +0000 (00:43 +0000)
sys/netinet/in_pcb.c
sys/netinet/in_pcb.h
sys/netinet/ip_divert.c
sys/netinet/raw_ip.c
sys/netinet/tcp_subr.c
sys/netinet/tcp_usrreq.c
sys/netinet/udp_usrreq.c
sys/netinet6/in6_pcb.c
sys/netinet6/udp6_usrreq.c

index d144db4..69f50cf 100644 (file)
@@ -33,7 +33,7 @@
  *
  *     @(#)in_pcb.c    8.4 (Berkeley) 5/24/95
  * $FreeBSD: src/sys/netinet/in_pcb.c,v 1.59.2.27 2004/01/02 04:06:42 ambrisko Exp $
- * $DragonFly: src/sys/netinet/in_pcb.c,v 1.15 2004/03/21 07:15:36 hsu Exp $
+ * $DragonFly: src/sys/netinet/in_pcb.c,v 1.16 2004/03/31 00:43:09 hsu Exp $
  */
 
 #include "opt_ipsec.h"
@@ -367,7 +367,6 @@ in_pcbbind(struct inpcb *inp, struct sockaddr *nam, struct thread *td)
                inp->inp_lport = 0;
                return (EAGAIN);
        }
-       in_pcbinsbindhash(inp);
        return (0);
 }
 
@@ -539,7 +538,7 @@ in_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct thread *td)
        }
        inp->inp_faddr = sin->sin_addr;
        inp->inp_fport = sin->sin_port;
-       in_pcbrehash(inp, INP_CONNECTED);
+       in_pcbinsconnhash(inp);
        return (0);
 }
 
@@ -868,8 +867,8 @@ in_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard, ifp)
                struct inpcb *local_wild_mapped = NULL;
 #endif
 
-               head = &pcbinfo->bindhashbase[INP_PCBBINDHASH(lport,
-                   pcbinfo->bindhashmask)];
+               head = &pcbinfo->wildcardhashbase[INP_PCBWILDCARDHASH(lport,
+                   pcbinfo->wildcardhashmask)];
                LIST_FOREACH(inp, head, inp_hash) {
 #ifdef INET6
                        if (!(inp->inp_vflag & INP_IPV4))
@@ -927,6 +926,8 @@ in_pcbinsconnhash(struct inpcb *inp)
        }
 #endif
 
+       KASSERT(!(inp->inp_flags & (INP_WILDCARD | INP_CONNECTED)),
+           ("already on hash list"));
        inp->inp_flags |= INP_CONNECTED;
 
        /*
@@ -987,50 +988,41 @@ in_pcbinsporthash(struct inpcb *inp)
 }
 
 /*
- * Insert PCB into bind hash table.
+ * Insert PCB into wildcard hash table.
  */
 void
-in_pcbinsbindhash(struct inpcb *inp)
+in_pcbinswildcardhash(struct inpcb *inp)
 {
        struct inpcbhead *bucket;
+       struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 
-       bucket = &inp->inp_pcbinfo->bindhashbase[INP_PCBBINDHASH(inp->inp_lport,
-           inp->inp_pcbinfo->porthashmask)];
+       bucket = &pcbinfo->wildcardhashbase[
+           INP_PCBWILDCARDHASH(inp->inp_lport, pcbinfo->wildcardhashmask)];
 
-       inp->inp_flags |= INP_BOUND;
+       inp->inp_flags |= INP_WILDCARD;
        LIST_INSERT_HEAD(bucket, inp, inp_hash);
 }
 
 /*
- * Remove PCB from bind hash table.
+ * Remove PCB from wildcard hash table.
  */
 void
-in_pcbrembindhash(struct inpcb *inp)
+in_pcbremwildcardhash(struct inpcb *inp)
 {
-       KASSERT(inp->inp_flags & INP_BOUND, ("inp not bound"));
+       KASSERT(inp->inp_flags & INP_WILDCARD, ("inp not wildcard"));
        LIST_REMOVE(inp, inp_hash);
-       inp->inp_flags &= ~INP_BOUND;
+       inp->inp_flags &= ~INP_WILDCARD;
 }
 
 static void
 in_pcbremhash(struct inpcb *inp)
 {
-       if (inp->inp_flags & (INP_BOUND | INP_CONNECTED)) {
+       if (inp->inp_flags & (INP_WILDCARD | INP_CONNECTED)) {
                LIST_REMOVE(inp, inp_hash);
-               inp->inp_flags &= ~(INP_BOUND | INP_CONNECTED);
+               inp->inp_flags &= ~(INP_WILDCARD | INP_CONNECTED);
        }
 }
 
-void
-in_pcbrehash(struct inpcb *inp, int state)
-{
-       in_pcbremhash(inp);
-       if (state == INP_BOUND)
-               in_pcbinsbindhash(inp);
-       else
-               in_pcbinsconnhash(inp);
-}
-
 /*
  * Remove PCB from various lists.
  */
index d34e2bb..480caea 100644 (file)
@@ -33,7 +33,7 @@
  *
  *     @(#)in_pcb.h    8.1 (Berkeley) 6/10/93
  * $FreeBSD: src/sys/netinet/in_pcb.h,v 1.32.2.7 2003/01/24 05:11:34 sam Exp $
- * $DragonFly: src/sys/netinet/in_pcb.h,v 1.8 2004/03/06 05:00:41 hsu Exp $
+ * $DragonFly: src/sys/netinet/in_pcb.h,v 1.9 2004/03/31 00:43:09 hsu Exp $
  */
 
 #ifndef _NETINET_IN_PCB_H_
@@ -239,8 +239,8 @@ struct inpcbinfo {          /* XXX documentation, prefixes */
        u_long  hashmask;
        struct  inpcbporthead *porthashbase;
        u_long  porthashmask;
-       struct  inpcbhead *bindhashbase;
-       u_long  bindhashmask;
+       struct  inpcbhead *wildcardhashbase;
+       u_long  wildcardhashmask;
        struct  inpcbhead listhead;     /* head of queue of active pcb's */
        u_short lastport;
        u_short lastlow;
@@ -251,12 +251,12 @@ struct inpcbinfo {                /* XXX documentation, prefixes */
 };
 
 
-#define INP_PCBCONNHASH(faddr, fport, laddr, lport, mask)              \
+#define        INP_PCBCONNHASH(faddr, fport, laddr, lport, mask)               \
     (((faddr) ^ ((faddr) >> 16) ^ (laddr) ^ ntohs((lport) ^ (fport))) & (mask))
 
-#define INP_PCBPORTHASH(lport, mask)   (ntohs(lport) & (mask))
+#define        INP_PCBPORTHASH(lport, mask)            (ntohs(lport) & (mask))
 
-#define INP_PCBBINDHASH(lport, mask)   (ntohs(lport) & (mask))
+#define        INP_PCBWILDCARDHASH(lport, mask)        (ntohs(lport) & (mask))
 
 /* flags in inp_flags: */
 #define        INP_RECVOPTS            0x01    /* receive incoming IP options */
@@ -269,8 +269,9 @@ struct inpcbinfo {          /* XXX documentation, prefixes */
 #define        INP_RECVIF              0x80    /* receive incoming interface */
 #define        INP_MTUDISC             0x100   /* user can do MTU discovery */
 #define        INP_FAITH               0x200   /* accept FAITH'ed connections */
-#define        INP_BOUND               0x400
-#define        INP_CONNECTED           0x800
+#define        INP_WILDCARD            0x400   /* wildcard match */
+#define        INP_CONNECTED           0x800   /* exact match */
+#define        INP_WASBOUND_NOTANY     0x1000  /* was bound to non-null laddr */
 
 #define IN6P_IPV6_V6ONLY       0x008000 /* restrict AF_INET6 socket for v6 */
 
@@ -327,7 +328,7 @@ int in_pcbbind (struct inpcb *, struct sockaddr *, struct thread *);
 int    in_pcbconnect (struct inpcb *, struct sockaddr *, struct thread *);
 void   in_pcbdetach (struct inpcb *);
 void   in_pcbdisconnect (struct inpcb *);
-void   in_pcbinsbindhash(struct inpcb *inp);
+void   in_pcbinswildcardhash(struct inpcb *inp);
 void   in_pcbinsconnhash(struct inpcb *inp);
 int    in_pcbinsporthash (struct inpcb *);
 int    in_pcbladdr (struct inpcb *, struct sockaddr *,
@@ -341,10 +342,9 @@ struct inpcb *
                               int, struct ifnet *);
 void   in_pcbnotifyall (struct inpcbhead *, struct in_addr,
            int, void (*)(struct inpcb *, int));
-void   in_pcbrehash(struct inpcb *, int);
 int    in_setpeeraddr (struct socket *so, struct sockaddr **nam);
 int    in_setsockaddr (struct socket *so, struct sockaddr **nam);
-void   in_pcbrembindhash(struct inpcb *inp);
+void   in_pcbremwildcardhash(struct inpcb *inp);
 void   in_pcbremconnhash(struct inpcb *inp);
 void   in_pcbremlists (struct inpcb *inp);
 int    prison_xinpcb (struct thread *p, struct inpcb *inp);
index bafcbe2..1d1a93d 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/netinet/ip_divert.c,v 1.42.2.6 2003/01/23 21:06:45 sam Exp $
- * $DragonFly: src/sys/netinet/ip_divert.c,v 1.10 2004/03/06 05:00:41 hsu Exp $
+ * $DragonFly: src/sys/netinet/ip_divert.c,v 1.11 2004/03/31 00:43:09 hsu Exp $
  */
 
 #include "opt_inet.h"
@@ -124,7 +124,8 @@ div_init(void)
         */
        divcbinfo.hashbase = hashinit(1, M_PCB, &divcbinfo.hashmask);
        divcbinfo.porthashbase = hashinit(1, M_PCB, &divcbinfo.porthashmask);
-       divcbinfo.bindhashbase = hashinit(1, M_PCB, &divcbinfo.bindhashmask);
+       divcbinfo.wildcardhashbase = hashinit(1, M_PCB,
+                                             &divcbinfo.wildcardhashmask);
        divcbinfo.ipi_zone = zinit("divcb", sizeof(struct inpcb),
                                   maxsockets, ZONE_INTERRUPT, 0);
 }
index 38fb98b..4247087 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)raw_ip.c    8.7 (Berkeley) 5/15/95
  * $FreeBSD: src/sys/netinet/raw_ip.c,v 1.64.2.16 2003/08/24 08:24:38 hsu Exp $
- * $DragonFly: src/sys/netinet/raw_ip.c,v 1.11 2004/03/06 05:00:41 hsu Exp $
+ * $DragonFly: src/sys/netinet/raw_ip.c,v 1.12 2004/03/31 00:43:09 hsu Exp $
  */
 
 #include "opt_inet6.h"
@@ -127,7 +127,8 @@ rip_init(void)
         */
        ripcbinfo.hashbase = hashinit(1, M_PCB, &ripcbinfo.hashmask);
        ripcbinfo.porthashbase = hashinit(1, M_PCB, &ripcbinfo.porthashmask);
-       ripcbinfo.bindhashbase = hashinit(1, M_PCB, &ripcbinfo.bindhashmask);
+       ripcbinfo.wildcardhashbase = hashinit(1, M_PCB,
+                                             &ripcbinfo.wildcardhashmask);
        ripcbinfo.ipi_zone = zinit("ripcb", sizeof(struct inpcb),
                                   maxsockets, ZONE_INTERRUPT, 0);
 }
index e285cdb..a034fd7 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)tcp_subr.c  8.2 (Berkeley) 5/24/95
  * $FreeBSD: src/sys/netinet/tcp_subr.c,v 1.73.2.31 2003/01/24 05:11:34 sam Exp $
- * $DragonFly: src/sys/netinet/tcp_subr.c,v 1.17 2004/03/14 08:26:31 hsu Exp $
+ * $DragonFly: src/sys/netinet/tcp_subr.c,v 1.18 2004/03/31 00:43:09 hsu Exp $
  */
 
 #include "opt_compat.h"
@@ -225,8 +225,8 @@ tcp_init()
 {
        struct inpcbporthead *porthashbase;
        u_long porthashmask;
-       struct inpcbhead *bindhashbase;
-       u_long bindhashmask;
+       struct inpcbhead *wildcardhashbase;
+       u_long wildcardhashmask;
        struct vm_zone *ipi_zone;
        int hashsize = TCBHASHSIZE;
        int cpu;
@@ -250,7 +250,7 @@ tcp_init()
        }
        tcp_tcbhashsize = hashsize;
        porthashbase = hashinit(hashsize, M_PCB, &porthashmask);
-       bindhashbase = hashinit(hashsize, M_PCB, &bindhashmask);
+       wildcardhashbase = hashinit(hashsize, M_PCB, &wildcardhashmask);
        ipi_zone = zinit("tcpcb", sizeof(struct inp_tp), maxsockets,
                         ZONE_INTERRUPT, 0);
 
@@ -260,8 +260,8 @@ tcp_init()
                    &tcbinfo[cpu].hashmask);
                tcbinfo[cpu].porthashbase = porthashbase;
                tcbinfo[cpu].porthashmask = porthashmask;
-               tcbinfo[cpu].bindhashbase = bindhashbase;
-               tcbinfo[cpu].bindhashmask = bindhashmask;
+               tcbinfo[cpu].wildcardhashbase = wildcardhashbase;
+               tcbinfo[cpu].wildcardhashmask = wildcardhashmask;
                tcbinfo[cpu].ipi_zone = ipi_zone;
        }
 
index 200a956..ed562f5 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     From: @(#)tcp_usrreq.c  8.2 (Berkeley) 1/3/94
  * $FreeBSD: src/sys/netinet/tcp_usrreq.c,v 1.51.2.17 2002/10/11 11:46:44 ume Exp $
- * $DragonFly: src/sys/netinet/tcp_usrreq.c,v 1.8 2004/03/08 19:44:32 hsu Exp $
+ * $DragonFly: src/sys/netinet/tcp_usrreq.c,v 1.9 2004/03/31 00:43:09 hsu Exp $
  */
 
 #include "opt_ipsec.h"
@@ -278,6 +278,7 @@ tcp_usr_listen(struct socket *so, struct thread *td)
                error = in_pcbbind(inp, (struct sockaddr *)0, td);
        if (error == 0)
                tp->t_state = TCPS_LISTEN;
+       in_pcbinswildcardhash(inp);
        COMMON_END(PRU_LISTEN);
 }
 
@@ -746,7 +747,6 @@ tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
                inp->inp_laddr = if_sin->sin_addr;
        inp->inp_faddr = sin->sin_addr;
        inp->inp_fport = sin->sin_port;
-       in_pcbrembindhash(inp);
        in_pcbinsconnhash(inp);
 
        /* Compute window scaling to request.  */
@@ -830,7 +830,6 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
        inp->inp_fport = sin6->sin6_port;
        if ((sin6->sin6_flowinfo & IPV6_FLOWINFO_MASK) != NULL)
                inp->in6p_flowinfo = sin6->sin6_flowinfo;
-       in_pcbrembindhash(inp);
        in_pcbinsconnhash(inp);
 
        /* Compute window scaling to request.  */
index eec87a4..86f5bed 100644 (file)
@@ -33,7 +33,7 @@
  *
  *     @(#)udp_usrreq.c        8.6 (Berkeley) 5/23/95
  * $FreeBSD: src/sys/netinet/udp_usrreq.c,v 1.64.2.18 2003/01/24 05:11:34 sam Exp $
- * $DragonFly: src/sys/netinet/udp_usrreq.c,v 1.18 2004/03/27 11:48:48 hsu Exp $
+ * $DragonFly: src/sys/netinet/udp_usrreq.c,v 1.19 2004/03/31 00:43:09 hsu Exp $
  */
 
 #include "opt_ipsec.h"
@@ -149,8 +149,8 @@ udp_init()
        udbinfo.hashbase = hashinit(UDBHASHSIZE, M_PCB, &udbinfo.hashmask);
        udbinfo.porthashbase = hashinit(UDBHASHSIZE, M_PCB,
                                        &udbinfo.porthashmask);
-       udbinfo.bindhashbase = hashinit(UDBHASHSIZE, M_PCB,
-                                       &udbinfo.bindhashmask);
+       udbinfo.wildcardhashbase = hashinit(UDBHASHSIZE, M_PCB,
+                                           &udbinfo.wildcardhashmask);
        udbinfo.ipi_zone = zinit("udpcb", sizeof(struct inpcb), maxsockets,
                                 ZONE_INTERRUPT, 0);
        udp_thread_init();
@@ -897,6 +897,7 @@ udp_attach(struct socket *so, int proto, struct pru_attach_info *ai)
 static int
 udp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
 {
+       struct sockaddr_in *sin = (struct sockaddr_in *)nam;
        struct inpcb *inp;
        int s, error;
 
@@ -906,6 +907,9 @@ udp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
        s = splnet();
        error = in_pcbbind(inp, nam, td);
        splx(s);
+       if (sin->sin_addr.s_addr != INADDR_ANY)
+               inp->inp_flags |= INP_WASBOUND_NOTANY;
+       in_pcbinswildcardhash(inp);
        return error;
 }
 
@@ -923,19 +927,30 @@ udp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
                return EISCONN;
        error = 0;
        s = splnet();
-       if (inp->inp_laddr.s_addr == INADDR_ANY && 
-           td->td_proc &&
-           td->td_proc->p_ucred->cr_prison != NULL) {
+       if (td->td_proc && td->td_proc->p_ucred->cr_prison != NULL &&
+           inp->inp_laddr.s_addr == INADDR_ANY) {
                error = in_pcbbind(inp, NULL, td);
        }
        if (error == 0) {
                sin = (struct sockaddr_in *)nam;
                prison_remote_ip(td, 0, &sin->sin_addr.s_addr);
+               if (inp->inp_flags & INP_WILDCARD)
+                       in_pcbremwildcardhash(inp);
                error = in_pcbconnect(inp, nam, td);
        }
        splx(s);
        if (error == 0)
                soisconnected(so);
+       else if (error == EAFNOSUPPORT) {       /* connection dissolved */
+               /*
+                * Follow traditional BSD behavior and retain
+                * the local port binding.  But, fix the old misbehavior
+                * of overwriting any previously bound local address.
+                */
+               if (!(inp->inp_flags & INP_WASBOUND_NOTANY))
+                       inp->inp_laddr.s_addr = INADDR_ANY;
+               in_pcbinswildcardhash(inp);
+       }
        return error;
 }
 
@@ -968,8 +983,6 @@ udp_disconnect(struct socket *so)
 
        s = splnet();
        in_pcbdisconnect(inp);
-       inp->inp_laddr.s_addr = INADDR_ANY;
-       in_pcbinsbindhash(inp);
        splx(s);
        so->so_state &= ~SS_ISCONNECTED;                /* XXX */
        return 0;
index 7496591..bfb399a 100644 (file)
@@ -1,5 +1,5 @@
 /*     $FreeBSD: src/sys/netinet6/in6_pcb.c,v 1.10.2.9 2003/01/24 05:11:35 sam Exp $   */
-/*     $DragonFly: src/sys/netinet6/in6_pcb.c,v 1.11 2004/03/04 01:02:06 hsu Exp $     */
+/*     $DragonFly: src/sys/netinet6/in6_pcb.c,v 1.12 2004/03/31 00:43:09 hsu Exp $     */
 /*     $KAME: in6_pcb.c,v 1.31 2001/05/21 05:45:10 jinmei Exp $        */
   
 /*
@@ -258,7 +258,6 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr *nam, struct thread *td)
                        return (EAGAIN);
                }
        }
-       in_pcbinsbindhash(inp);
        return(0);
 }
 
@@ -373,7 +372,7 @@ in6_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct thread *td)
                inp->in6p_flowinfo |=
                    (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
 
-       in_pcbrehash(inp, INP_CONNECTED);
+       in_pcbinsconnhash(inp);
        return (0);
 }
 
@@ -1043,8 +1042,8 @@ in6_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard, ifp)
        if (wildcard) {
                struct inpcb *local_wild = NULL;
 
-               head = &pcbinfo->hashbase[INP_PCBBINDHASH(lport,
-                   pcbinfo->hashmask)];
+               head = &pcbinfo->wildcardhashbase[INP_PCBWILDCARDHASH(lport,
+                   pcbinfo->wildcardhashmask)];
                LIST_FOREACH(inp, head, inp_hash) {
                        if ((inp->inp_vflag & INP_IPV6) == 0)
                                continue;
index aadefc2..98c67f5 100644 (file)
@@ -1,5 +1,5 @@
 /*     $FreeBSD: src/sys/netinet6/udp6_usrreq.c,v 1.6.2.13 2003/01/24 05:11:35 sam Exp $       */
-/*     $DragonFly: src/sys/netinet6/udp6_usrreq.c,v 1.11 2004/03/06 05:00:41 hsu Exp $ */
+/*     $DragonFly: src/sys/netinet6/udp6_usrreq.c,v 1.12 2004/03/31 00:43:09 hsu Exp $ */
 /*     $KAME: udp6_usrreq.c,v 1.27 2001/05/21 05:45:10 jinmei Exp $    */
 
 /*
@@ -581,6 +581,7 @@ udp6_attach(struct socket *so, int proto, struct pru_attach_info *ai)
 static int
 udp6_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
 {
+       struct sockaddr_in6 *sin6_p = (struct sockaddr_in6 *)nam;
        struct inpcb *inp;
        int s, error;
 
@@ -591,10 +592,6 @@ udp6_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
        inp->inp_vflag &= ~INP_IPV4;
        inp->inp_vflag |= INP_IPV6;
        if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
-               struct sockaddr_in6 *sin6_p;
-
-               sin6_p = (struct sockaddr_in6 *)nam;
-
                if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr))
                        inp->inp_vflag |= INP_IPV4;
                else if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
@@ -613,6 +610,9 @@ udp6_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
        s = splnet();
        error = in6_pcbbind(inp, nam, td);
        splx(s);
+       if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr))
+               inp->inp_flags |= INP_WASBOUND_NOTANY;
+       in_pcbinswildcardhash(inp);
        return error;
 }
 
@@ -649,6 +649,8 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
        }
        if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
                return EISCONN;
+       if (inp->inp_flags & INP_WILDCARD)
+               in_pcbremwildcardhash(inp);
        s = splnet();
        error = in6_pcbconnect(inp, nam, td);
        splx(s);
@@ -658,6 +660,15 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
                        inp->inp_vflag |= INP_IPV6;
                }
                soisconnected(so);
+       } else if (error == EAFNOSUPPORT) {     /* connection dissolved */
+               /*
+                * Follow traditional BSD behavior and retain
+                * the local port binding.  But, fix the old misbehavior
+                * of overwriting any previously bound local address.
+                */
+               if (!(inp->inp_flags & INP_WASBOUND_NOTANY))
+                       inp->in6p_laddr = in6addr_any;
+               in_pcbinswildcardhash(inp);
        }
        return error;
 }
@@ -699,7 +710,6 @@ udp6_disconnect(struct socket *so)
 
        s = splnet();
        in6_pcbdisconnect(inp);
-       inp->in6p_laddr = in6addr_any;
        splx(s);
        so->so_state &= ~SS_ISCONNECTED;                /* XXX */
        return 0;