On Thu, Jul 04, 2013 at 06:38:01PM +0000, Mikolaj Golub wrote:
> Author: trociny
> Date: Thu Jul  4 18:38:00 2013
> New Revision: 252710
> URL: http://svnweb.freebsd.org/changeset/base/252710
> 
> Log:
>   In r227207, to fix the issue with possible NULL inp_socket pointer
>   dereferencing, when checking for SO_REUSEPORT option (and SO_REUSEADDR
>   for multicast), INP_REUSEPORT flag was introduced to cache the socket
>   option.  It was decided then that one flag would be enough to cache
>   both SO_REUSEPORT and SO_REUSEADDR: when processing SO_REUSEADDR
>   setsockopt(2), it was checked if it was called for a multicast address
>   and INP_REUSEPORT was set accordingly.
>   
>   Unfortunately that approach does not work when setsockopt(2) is called
>   before binding to a multicast address: the multicast check fails and
>   INP_REUSEPORT is not set.
>   
>   Fix this by adding INP_REUSEADDR flag to unconditionally cache
>   SO_REUSEADDR.
>   
>   PR:         179901
>   Submitted by:       Michael Gmelin freebsd grem.de (initial version)
>   Reviewed by:        rwatson
>   MFC after:  1 week

Also, in this PR another issue is reported by Michael: if SO_REUSEADDR
is set for the first multicast bound socket and one tries to bind a
socket to the same address:port with SO_REUSEPORT, it fails, although
for multicast there should not be difference between SO_REUSEPORT and
SO_REUSEADDR. This is an old issue (observed on FreeBSD7 too), but I
would like to fix it. Below is a patch I am going to commit to HEAD.
Though I am not going to MFC it before 9.2 unless I have strong
support from people.

-- 
Mikolaj Golub
commit 7cf3a6a95d74ae91c80350fc1ae8e96fe59c3c65
Author: Mikolaj Golub <troc...@freebsd.org>
Date:   Sun Jun 30 00:09:20 2013 +0300

    A complete duplication of binding should be allowed if on both new and
    duplicated sockets a multicast address is bound and either
    SO_REUSEPORT or SO_REUSEADDR is set.
    
    But actually it works for the following combinations:
    
     * SO_REUSEPORT is set for the fist socket and SO_REUSEPORT for the new;
     * SO_REUSEADDR is set for the fist socket and SO_REUSEADDR for the new;
     * SO_REUSEPORT is set for the fist socket and SO_REUSEADDR for the new;
    
    and fails for this:
    
     * SO_REUSEADDR is set for the fist socket and SO_REUSEPORT for the new.
    
    Fix the last case.
    
    PR:		179901

diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 3506b74..eb15a38 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -554,7 +554,7 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
 			 * and a multicast address is bound on both
 			 * new and duplicated sockets.
 			 */
-			if (so->so_options & SO_REUSEADDR)
+			if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) != 0)
 				reuseport = SO_REUSEADDR|SO_REUSEPORT;
 		} else if (sin->sin_addr.s_addr != INADDR_ANY) {
 			sin->sin_port = 0;		/* yech... */
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index a0a6874..fb84279 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -156,7 +156,7 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
 			 * and a multicast address is bound on both
 			 * new and duplicated sockets.
 			 */
-			if (so->so_options & SO_REUSEADDR)
+			if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) != 0)
 				reuseport = SO_REUSEADDR|SO_REUSEPORT;
 		} else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
 			struct ifaddr *ifa;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to