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
|