netdev
[Top] [All Lists]

Re: [PATCH] IPV6_V6ONLY Support, v2 (is Re: [PATCH] IPv6: Allow Both IPv

To: Kyle C Quest <kquest@xxxxxxxxxx>
Subject: Re: [PATCH] IPV6_V6ONLY Support, v2 (is Re: [PATCH] IPv6: Allow Both IPv6 and IPv4 Sockets on the Same Port)
From: Pekka Savola <pekkas@xxxxxxxxxx>
Date: Wed, 23 Oct 2002 19:06:08 +0300 (EEST)
Cc: yoshfuji@xxxxxxxxxxxxxx, <netdev@xxxxxxxxxxx>
In-reply-to: <01b901c27aac$4bab0d20$0506330a@leachlap5328>
Sender: netdev-bounce@xxxxxxxxxxx
On Wed, 23 Oct 2002, Kyle C Quest wrote:
> I'm just curious... what happened to the generic option, SO_ONEFAMILY, that
> would replace
> the need for IPV6_V6ONLY?

This kind of thing is only applicable to IPv4 and IPv6 (and badly even 
there), there is no use trying to generalize it -- the idea was discarded.

> > In article <200210031552.TAA29921@xxxxxxxxxxxxx> (at Thu, 3 Oct 2002
> 19:52:40 +0400 (MSD)), kuznet@xxxxxxxxxxxxx says:
> >
> > > Actually, it would be great if you said what is wrong in that my patch?
> > > It looks so simple that I am not ready to agree that real one should be
> > > so complicated. :-)
> >
> > Well, I've refered alexey's patch and simplified many if-clauses.
> > Here's the new patch and test results.  seems ok.
> >
> > --------------------
> > Linux IPv6 stack provides the ability for IPv6 applications to
> > interoperate with IPv4 applications.  Port space for TCP (or UDP) is
> > shared by IPv6 and IPv4.  This conforms to RFC2553.
> > However, some kind of applications may want to restrict their use of
> > an IPv6 socket to IPv6 communication only.  IPV6_V6ONLY socket option is
> > defined for such applications in RFC2553bis, which is successor of
> RFC2553.
> > This patch allows to bind both IPv6 and IPv4 sockets with the single
> > port number at the same time if IPV6_V6ONLY socket options is set to
> > the IPv6 socket.
> >
> > Packet delivery strategy is similar to one before, but we prefer
> > IPv4 a bit.
> >
> > Test results and patch against 2.4.20-pre11 follows.
> >
> > *** Test for bind(2) ***
> >
> > [SOCK_DGRAM w/o IPV6_V6ONLY]
> > 0 :: 127.1 ::1
> > 0 x x x x
> > :: x x x x
> > 127.1 x x x o
> > ::1 x x o x
> >
> > ==> OK
> >
> > [SOCK_DGRAM w/ IPV6_V6ONLY]
> > 0 :: 127.1 ::1
> > 0 x o x o
> > :: o x o x
> > 127.1 x o x o
> > ::1 o x o x
> >
> > ==> OK
> >
> > [SOCK_DGRAM w/ SO_REUSEADDR w/o IPV6_V6ONLY]
> > 0 :: 127.1 ::1
> > 0 o o o o
> > :: o o o o
> > 127.1 o o o o
> > ::1 o o o o
> >
> > ==> OK
> >
> > [SOCK_DGRAM w/ SO_REUSEADDR w IPV6_V6ONLY]
> > 0 :: 127.1 ::1
> > 0 o o o o
> > :: o o o o
> > 127.1 o o o o
> > ::1 o o o o
> >
> > ==> OK
> >
> > [SOCK_STREAM w/o IPV6_V6ONLY]
> > 0 :: 127.1 ::1
> > 0 x x x x
> > :: x x x x
> > 127.1 x x x o
> > ::1 x x o x
> >
> > ==> OK
> >
> > [SOCK_STREAM w/ IPV6_V6ONLY]
> > 0 :: 127.1 ::1
> > 0 x o x o
> > :: o x o x
> > 127.1 x o x o
> > ::1 o x o x
> >
> > ==> OK
> >
> > [SOCK_STREAM w/ SO_REUSEADDR w/o IPV6_V6ONLY]
> > 0 :: 127.1 ::1
> > 0 o o o o
> > :: o o o o
> > 127.1 o o o o
> > ::1 o o o o
> >
> > ==> OK
> >
> > [SOCK_STREAM w/ SO_REUSEADDR w IPV6_V6ONLY]
> > 0 :: 127.1 ::1
> > 0 o o o o
> > :: o o o o
> > 127.1 o o o o
> > ::1 o o o o
> >
> > ==> OK
> >
> > *** Test for Receiver ***
> >
> > [IPv6]
> > 1a. :: <- ::1
> > received from ::1
> >
> > 1b. :: w/IPV6_V6ONLY <- ::1
> > received from ::1
> >
> > 2a. :: <- 127.0.0.1
> > received from ::1
> >
> > 2b. :: w/IPV6_V6ONLY <- 127.0.0.1
> > none received
> >
> > 3a. :: <- ff02::1
> > received from fe80::EUI64
> >
> > 3b. :: w/IPV6_V6ONLY <- ff02::1
> > received from fe80::EUI64
> >
> > 4a. :: <- 224.0.0.1
> > received from ::ffff:ipv4addr
> >
> > 4b. :: w/IPV6_V6ONLY <- 224.0.0.1
> > none received
> >
> > ==> OK
> >
> > [IPv4]
> > 1. 0.0.0.0 <- ::1
> > none received
> >
> > 2. 0.0.0.0 <- 127.0.0.1
> > received from 127.0.0.1
> >
> > 3. 0.0.0.0 <- ff02::1
> > none received
> >
> > 4. 0.0.0.0 <- 224.0.0.1
> > received from ipv4addr
> >
> > ==> OK
> >
> > [IPv6 vs IPv4]
> > 5. :: w/IPV6_V6ONLY vs 0.0.0.0 <- ::1
> > ipv6 received from ::1
> >
> > 6. :: w/IPV6_V6ONLY vs 0.0.0.0 <- 127.0.0.1
> > ipv4 received from 127.0.0.1
> >
> > 7. :: w/IPV6_V6ONLY vs 0.0.0.0 <- ff02::1
> > ipv6 received from fe80::EUI64
> >
> > 8. :: w/IPV6_V6ONLY vs 0.0.0.0 <- 224.0.0.1
> > ipv4 received from ipv4addra
> >
> > ==> OK
> >
> > -------------------------------------------------------------------
> > Patch-Name: Allow Both IPv6 and IPv4 Sockets on the Same Port Number
> (IPV6_V6ONLY Support) - Rev.2
> > Patch-Id: FIX_2_4_20_pre11_DOUBLEBIND-20021023
> > Patch-Author: YOSHIFUJI Hideaki / USAGI Project <yoshfuji@xxxxxxxxxxxxxx>
> > Credit: YOSHIFUJI Hideaki / USAGI Project <yoshfuji@xxxxxxxxxxxxxx>
> > Reference: RFC2553bis
> > -------------------------------------------------------------------
> > Index: Documentation/networking/ip-sysctl.txt
> > ===================================================================
> > RCS file:
> /cvsroot/usagi/usagi-backport/linux24/Documentation/networking/ip-sysctl.txt
> ,v
> > retrieving revision 1.1.1.1
> > retrieving revision 1.1.1.1.42.1
> > diff -u -r1.1.1.1 -r1.1.1.1.42.1
> > --- Documentation/networking/ip-sysctl.txt 20 Aug 2002 09:48:10 -0000
> 1.1.1.1
> > +++ Documentation/networking/ip-sysctl.txt 22 Oct 2002 19:19:48 -0000
> 1.1.1.1.42.1
> > @@ -462,6 +462,15 @@
> >  IPv6 has no global variables such as tcp_*.  tcp_* settings under ipv4/
> also
> >  apply to IPv6 [XXX?].
> >
> > +bindv6only - BOOLEAN
> > + Default value for IPV6_V6ONLY socket option,
> > + which restricts use of the IPv6 socket to IPv6 communication
> > + only.
> > + TRUE: disable IPv4-mapped address feature
> > + FALSE: enable IPv4-mapped address feature
> > +
> > + Default: FALSE (as specified in RFC2553bis)
> > +
> >  conf/default/*:
> >   Change the interface-specific default settings.
> >
> > Index: include/linux/in6.h
> > ===================================================================
> > RCS file: /cvsroot/usagi/usagi-backport/linux24/include/linux/in6.h,v
> > retrieving revision 1.1.1.1
> > retrieving revision 1.1.1.1.40.1
> > diff -u -r1.1.1.1 -r1.1.1.1.40.1
> > --- include/linux/in6.h 20 Aug 2002 09:46:34 -0000 1.1.1.1
> > +++ include/linux/in6.h 22 Oct 2002 19:19:48 -0000 1.1.1.1.40.1
> > @@ -156,6 +156,7 @@
> >  #define IPV6_MTU_DISCOVER 23
> >  #define IPV6_MTU 24
> >  #define IPV6_RECVERR 25
> > +#define IPV6_V6ONLY 26
> >
> >  /* IPV6_MTU_DISCOVER values */
> >  #define IPV6_PMTUDISC_DONT 0
> > Index: include/linux/sysctl.h
> > ===================================================================
> > RCS file: /cvsroot/usagi/usagi-backport/linux24/include/linux/sysctl.h,v
> > retrieving revision 1.1.1.2
> > retrieving revision 1.1.1.2.16.1
> > diff -u -r1.1.1.2 -r1.1.1.2.16.1
> > --- include/linux/sysctl.h 9 Oct 2002 01:35:37 -0000 1.1.1.2
> > +++ include/linux/sysctl.h 22 Oct 2002 19:19:48 -0000 1.1.1.2.16.1
> > @@ -345,7 +345,8 @@
> >  enum {
> >   NET_IPV6_CONF=16,
> >   NET_IPV6_NEIGH=17,
> > - NET_IPV6_ROUTE=18
> > + NET_IPV6_ROUTE=18,
> > + NET_IPV6_BINDV6ONLY=20,
> >  };
> >
> >  enum {
> > Index: include/net/ipv6.h
> > ===================================================================
> > RCS file: /cvsroot/usagi/usagi-backport/linux24/include/net/ipv6.h,v
> > retrieving revision 1.1.1.1
> > retrieving revision 1.1.1.1.38.1
> > diff -u -r1.1.1.1 -r1.1.1.1.38.1
> > --- include/net/ipv6.h 20 Aug 2002 09:46:45 -0000 1.1.1.1
> > +++ include/net/ipv6.h 22 Oct 2002 19:19:48 -0000 1.1.1.1.38.1
> > @@ -88,6 +88,9 @@
> >
> >  #include <net/sock.h>
> >
> > +/* sysctls */
> > +extern int sysctl_ipv6_bindv6only;
> > +
> >  extern struct ipv6_mib ipv6_statistics[NR_CPUS*2];
> >  #define IP6_INC_STATS(field) SNMP_INC_STATS(ipv6_statistics, field)
> >  #define IP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(ipv6_statistics, field)
> > Index: include/net/sock.h
> > ===================================================================
> > RCS file: /cvsroot/usagi/usagi-backport/linux24/include/net/sock.h,v
> > retrieving revision 1.1.1.1
> > retrieving revision 1.1.1.1.40.1
> > diff -u -r1.1.1.1 -r1.1.1.1.40.1
> > --- include/net/sock.h 20 Aug 2002 09:46:45 -0000 1.1.1.1
> > +++ include/net/sock.h 22 Oct 2002 19:19:48 -0000 1.1.1.1.40.1
> > @@ -171,7 +171,8 @@
> >   __u8 mc_loop:1,
> >                           recverr:1,
> >                           sndflow:1,
> > -                         pmtudisc:2;
> > +                         pmtudisc:2,
> > + ipv6only:1;
> >
> >   struct ipv6_mc_socklist *ipv6_mc_list;
> >   struct ipv6_fl_socklist *ipv6_fl_list;
> > @@ -188,6 +189,12 @@
> >   struct icmp6_filter filter;
> >  };
> >
> > +#define __ipv6_only_sock(sk) ((sk)->net_pinfo.af_inet6.ipv6only)
> > +#define ipv6_only_sock(sk) ((sk)->family == PF_INET6 && \
> > + (sk)->net_pinfo.af_inet6.ipv6only)
> > +#else
> > +#define __ipv6_only_sock(sk) 0
> > +#define ipv6_only_sock(sk) 0
> >  #endif /* IPV6 */
> >
> >  #if defined(CONFIG_INET) || defined(CONFIG_INET_MODULE)
> > Index: net/ipv4/tcp_ipv4.c
> > ===================================================================
> > RCS file: /cvsroot/usagi/usagi-backport/linux24/net/ipv4/tcp_ipv4.c,v
> > retrieving revision 1.1.1.2
> > retrieving revision 1.1.1.2.16.2
> > diff -u -r1.1.1.2 -r1.1.1.2.16.2
> > --- net/ipv4/tcp_ipv4.c 9 Oct 2002 01:35:52 -0000 1.1.1.2
> > +++ net/ipv4/tcp_ipv4.c 22 Oct 2002 19:40:48 -0000 1.1.1.2.16.2
> > @@ -45,9 +45,13 @@
> >   * Vitaly E. Lavrov : Transparent proxy revived after year coma.
> >   * Andi Kleen : Fix new listen.
> >   * Andi Kleen : Fix accept error reporting.
> > + * YOSHIFUJI Hideaki @USAGI: Support IPV6_V6ONLY socket option, which
> > + * allow both IPv4 and IPv6 sockets to bind
> > + * a single port at the same time.
> >   */
> >
> >  #include <linux/config.h>
> > +
> >  #include <linux/types.h>
> >  #include <linux/fcntl.h>
> >  #include <linux/random.h>
> > @@ -182,6 +186,7 @@
> >   for( ; sk2 != NULL; sk2 = sk2->bind_next) {
> >   if (sk != sk2 &&
> >       sk2->reuse <= 1 &&
> > +     !ipv6_only_sock(sk2) &&
> >       sk->bound_dev_if == sk2->bound_dev_if) {
> >   if (!sk_reuse ||
> >       !sk2->reuse ||
> > @@ -418,23 +423,27 @@
> >   struct sock *result = NULL;
> >   int score, hiscore;
> >
> > - hiscore=0;
> > + hiscore=-1;
> >   for(; sk; sk = sk->next) {
> > - if(sk->num == hnum) {
> > + if(sk->num == hnum && !ipv6_only_sock(sk)) {
> >   __u32 rcv_saddr = sk->rcv_saddr;
> >
> > +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
> > + score = sk->family == PF_INET ? 1 : 0;
> > +#else
> >   score = 1;
> > +#endif
> >   if(rcv_saddr) {
> >   if (rcv_saddr != daddr)
> >   continue;
> > - score++;
> > + score+=2;
> >   }
> >   if (sk->bound_dev_if) {
> >   if (sk->bound_dev_if != dif)
> >   continue;
> > - score++;
> > + score+=2;
> >   }
> > - if (score == 3)
> > + if (score == 5)
> >   return sk;
> >   if (score > hiscore) {
> >   hiscore = score;
> > @@ -456,6 +465,7 @@
> >   if (sk->num == hnum &&
> >       sk->next == NULL &&
> >       (!sk->rcv_saddr || sk->rcv_saddr == daddr) &&
> > +     (sk->family == PF_INET || !ipv6_only_sock(sk)) &&
> >       !sk->bound_dev_if)
> >   goto sherry_cache;
> >   sk = __tcp_v4_lookup_listener(sk, daddr, hnum, dif);
> > Index: net/ipv4/udp.c
> > ===================================================================
> > RCS file: /cvsroot/usagi/usagi-backport/linux24/net/ipv4/udp.c,v
> > retrieving revision 1.1.1.1
> > retrieving revision 1.1.1.1.40.1
> > diff -u -r1.1.1.1 -r1.1.1.1.40.1
> > --- net/ipv4/udp.c 20 Aug 2002 09:47:02 -0000 1.1.1.1
> > +++ net/ipv4/udp.c 22 Oct 2002 19:19:48 -0000 1.1.1.1.40.1
> > @@ -61,6 +61,9 @@
> >   * return ENOTCONN for unconnected sockets (POSIX)
> >   * Janos Farkas : don't deliver multi/broadcasts to a different
> >   * bound-to-device socket
> > + * YOSHIFUJI Hideaki @USAGI: Support IPV6_V6ONLY socket option, which
> > + * allow both IPv4 and IPv6 sockets to bind
> > + * a single port at the same time.
> >   *
> >   *
> >   * This program is free software; you can redistribute it and/or
> > @@ -85,6 +88,7 @@
> >  #include <linux/netdevice.h>
> >  #include <net/snmp.h>
> >  #include <net/ip.h>
> > +#include <net/ipv6.h>
> >  #include <net/protocol.h>
> >  #include <linux/skbuff.h>
> >  #include <net/sock.h>
> > @@ -159,6 +163,7 @@
> >        sk2 = sk2->next) {
> >   if (sk2->num == snum &&
> >       sk2 != sk &&
> > +     !ipv6_only_sock(sk2) &&
> >       sk2->bound_dev_if == sk->bound_dev_if &&
> >       (!sk2->rcv_saddr ||
> >        !sk->rcv_saddr ||
> > @@ -215,29 +220,34 @@
> >   int badness = -1;
> >
> >   for(sk = udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]; sk != NULL; sk =
> sk->next) {
> > - if(sk->num == hnum) {
> > - int score = 0;
> > + if(sk->num == hnum && !ipv6_only_sock(sk)) {
> > + int score;
> > +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
> > + score = sk->family == PF_INET ? 1 : 0;
> > +#else
> > + score = 1;
> > +#endif
> >   if(sk->rcv_saddr) {
> >   if(sk->rcv_saddr != daddr)
> >   continue;
> > - score++;
> > + score+=2;
> >   }
> >   if(sk->daddr) {
> >   if(sk->daddr != saddr)
> >   continue;
> > - score++;
> > + score+=2;
> >   }
> >   if(sk->dport) {
> >   if(sk->dport != sport)
> >   continue;
> > - score++;
> > + score+=2;
> >   }
> >   if(sk->bound_dev_if) {
> >   if(sk->bound_dev_if != dif)
> >   continue;
> > - score++;
> > + score+=2;
> >   }
> > - if(score == 4) {
> > + if(score == 9) {
> >   result = sk;
> >   break;
> >   } else if(score > badness) {
> > @@ -273,6 +283,7 @@
> >       (s->daddr && s->daddr!=rmt_addr) ||
> >       (s->dport != rmt_port && s->dport != 0) ||
> >       (s->rcv_saddr  && s->rcv_saddr != loc_addr) ||
> > +     ipv6_only_sock(s) ||
> >       (s->bound_dev_if && s->bound_dev_if != dif))
> >   continue;
> >   break;
> > Index: net/ipv6/af_inet6.c
> > ===================================================================
> > RCS file: /cvsroot/usagi/usagi-backport/linux24/net/ipv6/af_inet6.c,v
> > retrieving revision 1.1.1.1
> > retrieving revision 1.1.1.1.36.1
> > diff -u -r1.1.1.1 -r1.1.1.1.36.1
> > --- net/ipv6/af_inet6.c 20 Aug 2002 09:47:02 -0000 1.1.1.1
> > +++ net/ipv6/af_inet6.c 22 Oct 2002 19:19:48 -0000 1.1.1.1.36.1
> > @@ -88,6 +88,8 @@
> >  extern void ipv6_sysctl_unregister(void);
> >  #endif
> >
> > +int sysctl_ipv6_bindv6only;
> > +
> >  #ifdef INET_REFCNT_DEBUG
> >  atomic_t inet6_sock_nr;
> >  #endif
> > @@ -173,6 +175,8 @@
> >   sk->net_pinfo.af_inet6.mc_loop   = 1;
> >   sk->net_pinfo.af_inet6.pmtudisc   = IPV6_PMTUDISC_WANT;
> >
> > + sk->net_pinfo.af_inet6.ipv6only = sysctl_ipv6_bindv6only;
> > +
> >   /* Init the ipv4 part of the socket since we can have sockets
> >   * using v6 API for ipv4.
> >   */
> > Index: net/ipv6/ipv6_sockglue.c
> > ===================================================================
> > RCS file: /cvsroot/usagi/usagi-backport/linux24/net/ipv6/ipv6_sockglue.c,v
> > retrieving revision 1.1.1.1
> > retrieving revision 1.1.1.1.36.1
> > diff -u -r1.1.1.1 -r1.1.1.1.36.1
> > --- net/ipv6/ipv6_sockglue.c 20 Aug 2002 09:47:02 -0000 1.1.1.1
> > +++ net/ipv6/ipv6_sockglue.c 22 Oct 2002 19:19:48 -0000 1.1.1.1.36.1
> > @@ -157,7 +157,8 @@
> >   break;
> >   }
> >
> > - if (!(ipv6_addr_type(&np->daddr) & IPV6_ADDR_MAPPED)) {
> > + if (ipv6_only_sock(sk) ||
> > +     !(ipv6_addr_type(&np->daddr) & IPV6_ADDR_MAPPED)) {
> >   retv = -EADDRNOTAVAIL;
> >   break;
> >   }
> > @@ -203,6 +204,13 @@
> >   }
> >   goto e_inval;
> >
> > + case IPV6_V6ONLY:
> > + if (sk->num)
> > + goto e_inval;
> > + np->ipv6only = valbool;
> > + retv = 0;
> > + break;
> > +
> >   case IPV6_PKTINFO:
> >   np->rxopt.bits.rxinfo = valbool;
> >   retv = 0;
> > @@ -465,6 +473,10 @@
> >   return -ENOTCONN;
> >   break;
> >   }
> > +
> > + case IPV6_V6ONLY:
> > + val = np->ipv6only;
> > + break;
> >
> >   case IPV6_PKTINFO:
> >   val = np->rxopt.bits.rxinfo;
> > Index: net/ipv6/sysctl_net_ipv6.c
> > ===================================================================
> > RCS file:
> /cvsroot/usagi/usagi-backport/linux24/net/ipv6/sysctl_net_ipv6.c,v
> > retrieving revision 1.1.1.1
> > retrieving revision 1.1.1.1.40.1
> > diff -u -r1.1.1.1 -r1.1.1.1.40.1
> > --- net/ipv6/sysctl_net_ipv6.c 20 Aug 2002 09:47:02 -0000 1.1.1.1
> > +++ net/ipv6/sysctl_net_ipv6.c 22 Oct 2002 19:19:48 -0000 1.1.1.1.40.1
> > @@ -17,6 +17,8 @@
> >
> >  ctl_table ipv6_table[] = {
> >   {NET_IPV6_ROUTE, "route", NULL, 0, 0555, ipv6_route_table},
> > + {NET_IPV6_BINDV6ONLY, "bindv6only",
> > + &sysctl_ipv6_bindv6only, sizeof(int), 0644, NULL, &proc_dointvec},
> >   {0}
> >  };
> >
> > Index: net/ipv6/tcp_ipv6.c
> > ===================================================================
> > RCS file: /cvsroot/usagi/usagi-backport/linux24/net/ipv6/tcp_ipv6.c,v
> > retrieving revision 1.1.1.2
> > retrieving revision 1.1.1.2.16.1
> > diff -u -r1.1.1.2 -r1.1.1.2.16.1
> > --- net/ipv6/tcp_ipv6.c 9 Oct 2002 01:35:53 -0000 1.1.1.2
> > +++ net/ipv6/tcp_ipv6.c 22 Oct 2002 19:19:48 -0000 1.1.1.2.16.1
> > @@ -14,6 +14,9 @@
> >   *
> >   * Fixes:
> >   * Hideaki YOSHIFUJI : sin6_scope_id support
> > + * YOSHIFUJI Hideaki @USAGI: Support IPV6_V6ONLY socket option, which
> > + * allow both IPv4 and IPv6 sockets to bind
> > + * a single port at the same time.
> >   *
> >   * This program is free software; you can redistribute it and/or
> >   *      modify it under the terms of the GNU General Public License
> > @@ -148,14 +151,23 @@
> >       !sk2->reuse ||
> >       sk2->state == TCP_LISTEN) {
> >   /* NOTE: IPv6 tw bucket have different format */
> > - if (!sk2->rcv_saddr ||
> > -     addr_type == IPV6_ADDR_ANY ||
> > -     !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr,
> > -    sk2->state != TCP_TIME_WAIT ?
> > -    &sk2->net_pinfo.af_inet6.rcv_saddr :
> > -    &((struct tcp_tw_bucket*)sk)->v6_rcv_saddr) ||
> > -     (addr_type==IPV6_ADDR_MAPPED && sk2->family==AF_INET &&
> > -      sk->rcv_saddr==sk2->rcv_saddr))
> > + if ((!sk2->rcv_saddr && !ipv6_only_sock(sk)) ||
> > +     (sk2->family == AF_INET6 &&
> > +      ipv6_addr_any(&sk2->net_pinfo.af_inet6.rcv_saddr) &&
> > +      !(ipv6_only_sock(sk2) && addr_type == IPV6_ADDR_MAPPED)) ||
> > +     (addr_type == IPV6_ADDR_ANY &&
> > +      (!ipv6_only_sock(sk) ||
> > +       !(sk2->family == AF_INET6 ?
> ipv6_addr_type(&sk2->net_pinfo.af_inet6.rcv_saddr) == IPV6_ADDR_MAPPED :
> 1))) ||
> > +     (sk2->family == AF_INET6 &&
> > +      !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr,
> > +     sk2->state != TCP_TIME_WAIT ?
> > +     &sk2->net_pinfo.af_inet6.rcv_saddr :
> > +     &((struct tcp_tw_bucket*)sk)->v6_rcv_saddr)) ||
> > +     (addr_type == IPV6_ADDR_MAPPED &&
> > +      !ipv6_only_sock(sk2) &&
> > +      (!sk2->rcv_saddr ||
> > +       !sk->rcv_saddr ||
> > +       sk->rcv_saddr == sk2->rcv_saddr)))
> >   break;
> >   }
> >   }
> > @@ -601,6 +613,9 @@
> >   struct sockaddr_in sin;
> >
> >   SOCK_DEBUG(sk, "connect: ipv4 mapped\n");
> > +
> > + if (__ipv6_only_sock(sk))
> > + return -ENETUNREACH;
> >
> >   sin.sin_family = AF_INET;
> >   sin.sin_port = usin->sin6_port;
> > Index: net/ipv6/udp.c
> > ===================================================================
> > RCS file: /cvsroot/usagi/usagi-backport/linux24/net/ipv6/udp.c,v
> > retrieving revision 1.1.1.2
> > retrieving revision 1.1.1.2.16.1
> > diff -u -r1.1.1.2 -r1.1.1.2.16.1
> > --- net/ipv6/udp.c 9 Oct 2002 01:35:53 -0000 1.1.1.2
> > +++ net/ipv6/udp.c 22 Oct 2002 19:19:48 -0000 1.1.1.2.16.1
> > @@ -11,6 +11,9 @@
> >   *
> >   * Fixes:
> >   * Hideaki YOSHIFUJI : sin6_scope_id support
> > + * YOSHIFUJI Hideaki @USAGI: Support IPV6_V6ONLY socket option, which
> > + * allow both IPv4 and IPv6 sockets to bind
> > + * a single port at the same time.
> >   *
> >   * This program is free software; you can redistribute it and/or
> >   *      modify it under the terms of the GNU General Public License
> > @@ -106,13 +109,21 @@
> >   if (sk2->num == snum &&
> >       sk2 != sk &&
> >       sk2->bound_dev_if == sk->bound_dev_if &&
> > -     (!sk2->rcv_saddr ||
> > -      addr_type == IPV6_ADDR_ANY ||
> > -      !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr,
> > -     &sk2->net_pinfo.af_inet6.rcv_saddr) ||
> > +     ((!sk2->rcv_saddr && !ipv6_only_sock(sk)) ||
> > +      (sk2->family == AF_INET6 &&
> > +       ipv6_addr_any(&sk2->net_pinfo.af_inet6.rcv_saddr) &&
> > +       !(ipv6_only_sock(sk2) && addr_type == IPV6_ADDR_MAPPED)) ||
> > +      (addr_type == IPV6_ADDR_ANY &&
> > +       (!ipv6_only_sock(sk) ||
> > +        !(sk2->family == AF_INET6 ?
> (ipv6_addr_type(&sk2->net_pinfo.af_inet6.rcv_saddr) == IPV6_ADDR_MAPPED) :
> 1))) ||
> > +      (sk2->family == AF_INET6 &&
> > +       !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr,
> > +      &sk2->net_pinfo.af_inet6.rcv_saddr)) ||
> >        (addr_type == IPV6_ADDR_MAPPED &&
> > -       sk2->family == AF_INET &&
> > -       sk->rcv_saddr == sk2->rcv_saddr)) &&
> > +       !ipv6_only_sock(sk2) &&
> > +       (!sk2->rcv_saddr ||
> > +        !sk->rcv_saddr ||
> > +        sk->rcv_saddr == sk2->rcv_saddr))) &&
> >       (!sk2->reuse || !sk->reuse))
> >   goto fail;
> >   }
> > @@ -221,6 +232,8 @@
> >   int err;
> >
> >   if (usin->sin6_family == AF_INET) {
> > + if (__ipv6_only_sock(sk))
> > + return -EAFNOSUPPORT;
> >   err = udp_connect(sk, uaddr, addr_len);
> >   goto ipv4_connected;
> >   }
> > @@ -256,6 +269,9 @@
> >   if (addr_type == IPV6_ADDR_MAPPED) {
> >   struct sockaddr_in sin;
> >
> > + if (__ipv6_only_sock(sk))
> > + return -ENETUNREACH;
> > +
> >   sin.sin_family = AF_INET;
> >   sin.sin_addr.s_addr = daddr->s6_addr32[3];
> >   sin.sin_port = usin->sin6_port;
> > @@ -783,8 +799,11 @@
> >   fl.oif = 0;
> >
> >   if (sin6) {
> > - if (sin6->sin6_family == AF_INET)
> > + if (sin6->sin6_family == AF_INET) {
> > + if (__ipv6_only_sock(sk))
> > + return -ENETUNREACH;
> >   return udp_sendmsg(sk, msg, ulen);
> > + }
> >
> >   if (addr_len < SIN6_LEN_RFC2133)
> >   return -EINVAL;
> > @@ -830,6 +849,9 @@
> >
> >   if (addr_type == IPV6_ADDR_MAPPED) {
> >   struct sockaddr_in sin;
> > +
> > + if (__ipv6_only_sock(sk))
> > + return -ENETUNREACH;
> >
> >   sin.sin_family = AF_INET;
> >   sin.sin_addr.s_addr = daddr->s6_addr32[3];
> >
> >
> 
> 

-- 
Pekka Savola                 "Tell me of difficulties surmounted,
Netcore Oy                   not those you stumble over and fall"
Systems. Networks. Security.  -- Robert Jordan: A Crown of Swords


<Prev in Thread] Current Thread [Next in Thread>