The following reply was made to PR kern/179901; it has been noted by GNATS.

From: Mikolaj Golub <troc...@freebsd.org>
To: Michael Gmelin <free...@grem.de>
Cc: bug-follo...@freebsd.org
Subject: Re: kern/179901: [netinet] [patch] Multicast SO_REUSEADDR handled
 incorrectly
Date: Tue, 25 Jun 2013 18:24:55 +0300

 --tThc/1wpZn/ma/RB
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 On Tue, Jun 25, 2013 at 01:39:38PM +0200, Michael Gmelin wrote:
 
 > Yes, but it seems like your patch is fixing the not all places in
 > in6_pcb.c, I think you should modify the code at line 246 as well:
 > 
 >                         } else if (t && (reuseport == 0 ||
 >                             (t->inp_flags2 & INP_REUSEPORT) == 0)) {
 >                                 return (EADDRINUSE);
 >                         }
 > 
 > so it says
 >                         } else if (t &&
 >                             (reuseport & inp_so_options(t)) == 0) {
 >              
 
 Good catch! I missed this because I was preparing the patch using
 r227207 as a reference, but this had been missed there too (fixed
 later in r233272 by glebius).
 
 > Once 1) has been resolved I can test on a machine running 9.1-RELEASE
 > later (the patch is small enough to apply it manually). I will run the
 > "unit test" code from multicast.c I sent earlier and add IPv6 test
 > cases to it as well.
 
 The updated patch is attached. Thanks.
 
 -- 
 Mikolaj Golub
 
 --tThc/1wpZn/ma/RB
 Content-Type: text/x-diff; charset=us-ascii
 Content-Disposition: attachment; filename="pr179901.2.patch"
 
 Index: sys/netinet/in_pcb.c
 ===================================================================
 --- sys/netinet/in_pcb.c       (revision 251760)
 +++ sys/netinet/in_pcb.c       (working copy)
 @@ -467,6 +467,23 @@ in_pcb_lport(struct inpcb *inp, struct in_addr *la
  
        return (0);
  }
 +
 +/*
 + * Return cached socket options.
 + */
 +int
 +inp_so_options(const struct inpcb *inp)
 +{
 +   int so_options;
 +
 +   so_options = 0;
 +
 +   if ((inp->inp_flags2 & INP_REUSEPORT) != 0)
 +         so_options |= SO_REUSEPORT;
 +   if ((inp->inp_flags2 & INP_REUSEADDR) != 0)
 +         so_options |= SO_REUSEADDR;
 +   return (so_options);
 +}
  #endif /* INET || INET6 */
  
  #ifdef INET
 @@ -595,8 +612,7 @@ in_pcbbind_setup(struct inpcb *inp, struct sockadd
                                if (tw == NULL ||
                                    (reuseport & tw->tw_so_options) == 0)
                                        return (EADDRINUSE);
 -                      } else if (t && (reuseport == 0 ||
 -                          (t->inp_flags2 & INP_REUSEPORT) == 0)) {
 +                      } else if (t && (reuseport & inp_so_options(t)) == 0) {
  #ifdef INET6
                                if (ntohl(sin->sin_addr.s_addr) !=
                                    INADDR_ANY ||
 Index: sys/netinet/in_pcb.h
 ===================================================================
 --- sys/netinet/in_pcb.h       (revision 251760)
 +++ sys/netinet/in_pcb.h       (working copy)
 @@ -442,6 +442,7 @@ struct tcpcb *
        inp_inpcbtotcpcb(struct inpcb *inp);
  void  inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp,
                uint32_t *faddr, uint16_t *fp);
 +int   inp_so_options(const struct inpcb *inp);
  
  #endif /* _KERNEL */
  
 @@ -543,6 +544,7 @@ void       inp_4tuple_get(struct inpcb *inp, uint32_t *
  #define       INP_PCBGROUPWILD        0x00000004 /* in pcbgroup wildcard list 
*/
  #define       INP_REUSEPORT           0x00000008 /* SO_REUSEPORT option is 
set */
  #define       INP_FREED               0x00000010 /* inp itself is not valid */
 +#define       INP_REUSEADDR           0x00000020 /* SO_REUSEADDR option is 
set */
  
  /*
   * Flags passed to in_pcblookup*() functions.
 Index: sys/netinet/ip_output.c
 ===================================================================
 --- sys/netinet/ip_output.c    (revision 251760)
 +++ sys/netinet/ip_output.c    (working copy)
 @@ -900,13 +900,10 @@ ip_ctloutput(struct socket *so, struct sockopt *so
                        switch (sopt->sopt_name) {
                        case SO_REUSEADDR:
                                INP_WLOCK(inp);
 -                              if (IN_MULTICAST(ntohl(inp->inp_laddr.s_addr))) 
{
 -                                      if ((so->so_options &
 -                                          (SO_REUSEADDR | SO_REUSEPORT)) != 0)
 -                                              inp->inp_flags2 |= 
INP_REUSEPORT;
 -                                      else
 -                                              inp->inp_flags2 &= 
~INP_REUSEPORT;
 -                              }
 +                              if ((so->so_options & SO_REUSEADDR) != 0)
 +                                      inp->inp_flags2 |= INP_REUSEADDR;
 +                              else
 +                                      inp->inp_flags2 &= ~INP_REUSEADDR;
                                INP_WUNLOCK(inp);
                                error = 0;
                                break;
 Index: sys/netinet6/in6_pcb.c
 ===================================================================
 --- sys/netinet6/in6_pcb.c     (revision 251760)
 +++ sys/netinet6/in6_pcb.c     (working copy)
 @@ -243,8 +243,7 @@ in6_pcbbind(register struct inpcb *inp, struct soc
                                if (tw == NULL ||
                                    (reuseport & tw->tw_so_options) == 0)
                                        return (EADDRINUSE);
 -                      } else if (t && (reuseport == 0 ||
 -                          (t->inp_flags2 & INP_REUSEPORT) == 0)) {
 +                      } else if (t && (reuseport & inp_so_options(t)) == 0) {
                                return (EADDRINUSE);
                        }
  #ifdef INET
 @@ -265,8 +264,8 @@ in6_pcbbind(register struct inpcb *inp, struct soc
                                             INP_IPV6PROTO) ==
                                             (t->inp_vflag & INP_IPV6PROTO))))
                                                return (EADDRINUSE);
 -                              } else if (t && (reuseport == 0 ||
 -                                  (t->inp_flags2 & INP_REUSEPORT) == 0) &&
 +                              } else if (t &&
 +                                  (reuseport & inp_so_options(t)) == 0 &&
                                    (ntohl(t->inp_laddr.s_addr) != INADDR_ANY ||
                                    (t->inp_vflag & INP_IPV6PROTO) != 0))
                                        return (EADDRINUSE);
 Index: sys/netinet6/ip6_output.c
 ===================================================================
 --- sys/netinet6/ip6_output.c  (revision 251760)
 +++ sys/netinet6/ip6_output.c  (working copy)
 @@ -1477,13 +1477,10 @@ ip6_ctloutput(struct socket *so, struct sockopt *s
                        switch (sopt->sopt_name) {
                        case SO_REUSEADDR:
                                INP_WLOCK(in6p);
 -                              if 
(IN_MULTICAST(ntohl(in6p->inp_laddr.s_addr))) {
 -                                      if ((so->so_options &
 -                                          (SO_REUSEADDR | SO_REUSEPORT)) != 0)
 -                                              in6p->inp_flags2 |= 
INP_REUSEPORT;
 -                                      else
 -                                              in6p->inp_flags2 &= 
~INP_REUSEPORT;
 -                              }
 +                              if ((so->so_options & SO_REUSEADDR) != 0)
 +                                      in6p->inp_flags2 |= INP_REUSEADDR;
 +                              else
 +                                      in6p->inp_flags2 &= ~INP_REUSEADDR;
                                INP_WUNLOCK(in6p);
                                error = 0;
                                break;
 
 --tThc/1wpZn/ma/RB--
_______________________________________________
freebsd-net@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "freebsd-net-unsubscr...@freebsd.org"

Reply via email to