Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 4 Jul 2013 22:03:47 +0300
From:      Mikolaj Golub <trociny@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   Re: svn commit: r252710 - in head/sys: netinet netinet6
Message-ID:  <20130704190345.GA12450@gmail.com>
In-Reply-To: <201307041838.r64Ic1Ld099772@svn.freebsd.org>
References:  <201307041838.r64Ic1Ld099772@svn.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--9jxsPFA5p3P2qPhR
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

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

--9jxsPFA5p3P2qPhR
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: inline; filename="pr179901.2.1.patch"

commit 7cf3a6a95d74ae91c80350fc1ae8e96fe59c3c65
Author: Mikolaj Golub <trociny@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;

--9jxsPFA5p3P2qPhR--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130704190345.GA12450>