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) {