On Wed, Apr 06, 2016 at 05:20:32PM +0200, Vincent Gross wrote:
> 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 ?
OK bluhm@
>
> 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) {