The regression test in regress/sys/netinet6/autoport is failing because
my merge of in_pcbbind() and in6_pcbbind() introduced a bug. Long story
short, if nam == NULL, then you skip the part where you check if the socket
is already bound based on inp_laddr/inp_laddr6. Also INPLOOKUP_IPV6 is not
set when dealing with INET6 sockets.

The diff below fixes that by moving the 'if (nam){}' inside the
'switch (sotopf(so)){}'.

Ok ?

Index: in_pcb.c
===================================================================
RCS file: /cvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.200
diff -u -p -r1.200 in_pcb.c
--- in_pcb.c    5 Apr 2016 21:21:41 -0000       1.200
+++ in_pcb.c    6 Apr 2016 15:03:50 -0000
@@ -297,35 +297,36 @@ in_pcbbind(struct inpcb *inp, struct mbu
             (so->so_options & SO_ACCEPTCONN) == 0))
                wild = INPLOOKUP_WILDCARD;
 
-       if (nam) {
-               switch (sotopf(so)) {
+       switch (sotopf(so)) {
 #ifdef INET6
-               case PF_INET6: {
-                       struct sockaddr_in6 *sin6;
-                       if (TAILQ_EMPTY(&in6_ifaddr))
-                               return (EADDRNOTAVAIL);
-                       if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6))
-                               return (EINVAL);
+       case PF_INET6:
+               if (TAILQ_EMPTY(&in6_ifaddr))
+                       return (EADDRNOTAVAIL);
+               if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6))
+                       return (EINVAL);
+               wild |= INPLOOKUP_IPV6;
 
+               if (nam) {
+                       struct sockaddr_in6 *sin6;
                        sin6 = mtod(nam, struct sockaddr_in6 *);
                        if (nam->m_len != sizeof(struct sockaddr_in6))
                                return (EINVAL);
                        if (sin6->sin6_family != AF_INET6)
                                return (EAFNOSUPPORT);
 
-                       wild |= INPLOOKUP_IPV6;
                        if ((error = in6_pcbaddrisavail(inp, sin6, wild, p)))
                                return (error);
                        laddr = &sin6->sin6_addr;
                        lport = sin6->sin6_port;
-                       break;
                }
+               break;
 #endif
-               case PF_INET: {
-                       struct sockaddr_in *sin;
-                       if (inp->inp_laddr.s_addr != INADDR_ANY)
-                               return (EINVAL);
+       case PF_INET:
+               if (inp->inp_laddr.s_addr != INADDR_ANY)
+                       return (EINVAL);
 
+               if (nam) {
+                       struct sockaddr_in *sin;
                        sin = mtod(nam, struct sockaddr_in *);
                        if (nam->m_len != sizeof(*sin))
                                return (EINVAL);
@@ -336,11 +337,10 @@ in_pcbbind(struct inpcb *inp, struct mbu
                                return (error);
                        laddr = &sin->sin_addr;
                        lport = sin->sin_port;
-                       break;
-               }
-               default:
-                       return (EINVAL);
                }
+               break;
+       default:
+               return (EINVAL);
        }
 
        if (lport == 0) {

Reply via email to