diff options
author | Brian Haley <Brian.Haley@hp.com> | 2008-04-11 00:38:24 -0400 |
---|---|---|
committer | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2008-04-12 00:43:27 -0400 |
commit | 876c7f41961dc5172b03cbf2dca65f05003f28a0 (patch) | |
tree | 3b5644d172edf0b9d2eecfc5f6c96d41b31c9a2a | |
parent | 6ac7eb0868ccc9a2c597d6fd0b1ea09dcdc396ed (diff) |
[IPv6]: Change IPv6 unspecified destination address to ::1 for raw and un-connected sockets
This patch fixes a difference between IPv4 and IPv6 when sending packets
to the unspecified address (either 0.0.0.0 or ::) when using raw or
un-connected UDP sockets. There are two cases where IPv6 either fails
to send anything, or sends with the destination address set to ::. For
example:
--> ping -c1 0.0.0.0
PING 0.0.0.0 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.032 ms
--> ping6 -c1 ::
PING ::(::) 56 data bytes
ping: sendmsg: Invalid argument
Doing a sendto("0.0.0.0") reveals:
10:55:01.495090 IP localhost.32780 > localhost.7639: UDP, length 100
Doing a sendto("::") reveals:
10:56:13.262478 IP6 fe80::217:8ff:fe7d:4718.32779 > ::.7639: UDP, length 100
If you issue a connect() first in the UDP case, it will be sent to ::1,
similar to what happens with TCP.
This restores the BSD-ism.
Signed-off-by: Brian Haley <brian.haley@hp.com>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
-rw-r--r-- | net/ipv6/raw.c | 14 | ||||
-rw-r--r-- | net/ipv6/udp.c | 5 |
2 files changed, 8 insertions, 11 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 088b80b4ce74..059298baa1dd 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -805,15 +805,6 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
805 | fl.fl6_flowlabel = np->flow_label; | 805 | fl.fl6_flowlabel = np->flow_label; |
806 | } | 806 | } |
807 | 807 | ||
808 | if (ipv6_addr_any(daddr)) { | ||
809 | /* | ||
810 | * unspecified destination address | ||
811 | * treated as error... is this correct ? | ||
812 | */ | ||
813 | fl6_sock_release(flowlabel); | ||
814 | return(-EINVAL); | ||
815 | } | ||
816 | |||
817 | if (fl.oif == 0) | 808 | if (fl.oif == 0) |
818 | fl.oif = sk->sk_bound_dev_if; | 809 | fl.oif = sk->sk_bound_dev_if; |
819 | 810 | ||
@@ -846,7 +837,10 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
846 | if (err) | 837 | if (err) |
847 | goto out; | 838 | goto out; |
848 | 839 | ||
849 | ipv6_addr_copy(&fl.fl6_dst, daddr); | 840 | if (!ipv6_addr_any(daddr)) |
841 | ipv6_addr_copy(&fl.fl6_dst, daddr); | ||
842 | else | ||
843 | fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ | ||
850 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) | 844 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) |
851 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 845 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
852 | 846 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 30ef7dc5d403..1fd784f3e2ec 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -752,7 +752,10 @@ do_udp_sendmsg: | |||
752 | opt = ipv6_fixup_options(&opt_space, opt); | 752 | opt = ipv6_fixup_options(&opt_space, opt); |
753 | 753 | ||
754 | fl.proto = sk->sk_protocol; | 754 | fl.proto = sk->sk_protocol; |
755 | ipv6_addr_copy(&fl.fl6_dst, daddr); | 755 | if (!ipv6_addr_any(daddr)) |
756 | ipv6_addr_copy(&fl.fl6_dst, daddr); | ||
757 | else | ||
758 | fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */ | ||
756 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) | 759 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) |
757 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 760 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
758 | fl.fl_ip_sport = inet->sport; | 761 | fl.fl_ip_sport = inet->sport; |