patch-2.4.21 linux-2.4.21/net/ipv6/udp.c
Next file: linux-2.4.21/net/irda/ircomm/ircomm_core.c
Previous file: linux-2.4.21/net/ipv6/tcp_ipv6.c
Back to the patch index
Back to the overall index
- Lines: 80
- Date:
2003-06-13 07:51:39.000000000 -0700
- Orig file:
linux-2.4.20/net/ipv6/udp.c
- Orig date:
2002-11-28 15:53:15.000000000 -0800
diff -urN linux-2.4.20/net/ipv6/udp.c linux-2.4.21/net/ipv6/udp.c
@@ -11,6 +11,9 @@
*
* Fixes:
* Hideaki YOSHIFUJI : sin6_scope_id support
+ * YOSHIFUJI Hideaki @USAGI and: Support IPV6_V6ONLY socket option, which
+ * Alexey Kuznetsov 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;
@@ -831,6 +850,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 = udh.uh.dest;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)