This diff is similar to the one that has been committed to handle the SOCK_RAW binding. I'd like to stop using in_iawithaddr() *and* in_broadcast(). Since these functions are just doing an iteration on all the addresses present in the RB-tree (or equivalent), let's use ifa_ifwithaddr() instead.
This diff should not introduce any behavior change concerning SOCK_DGRAM and binding to multicast addresses. Ok? Index: netinet/in_pcb.c =================================================================== RCS file: /home/ncvs/src/sys/netinet/in_pcb.c,v retrieving revision 1.155 diff -u -p -r1.155 in_pcb.c --- netinet/in_pcb.c 7 May 2014 08:26:38 -0000 1.155 +++ netinet/in_pcb.c 2 Jun 2014 13:37:59 -0000 @@ -261,14 +261,19 @@ in_pcbbind(struct inpcb *inp, struct mbu reuseport = SO_REUSEADDR|SO_REUSEPORT; } else if (sin->sin_addr.s_addr != INADDR_ANY) { sin->sin_port = 0; /* yech... */ - if (!(so->so_options & SO_BINDANY) && - in_iawithaddr(sin->sin_addr, - inp->inp_rtableid) == NULL) + if (!((so->so_options & SO_BINDANY) || + (sin->sin_addr.s_addr == INADDR_BROADCAST && + so->so_type == SOCK_DGRAM))) { + struct in_ifaddr *ia; + + ia = ifatoia(ifa_ifwithaddr(sintosa(sin), + inp->inp_rtableid)); /* SOCK_RAW does not use in_pcbbind() */ - if (!(so->so_type == SOCK_DGRAM && - in_broadcast(sin->sin_addr, NULL, - inp->inp_rtableid))) - return (EADDRNOTAVAIL); + if (ia == NULL || (sin->sin_addr.s_addr == + ia->ia_broadaddr.sin_addr.s_addr && + so->so_type != SOCK_DGRAM)) + return (EADDRNOTAVAIL); + } } if (lport) { struct inpcb *t;