* [PATCH 2/2] ipv6: Handle IPv4-mapped src to in6addr_any dst.
2017-02-12 22:26 [PATCH 0/2] IPv4-mapped on wire, :: dst address issue Jonathan T. Leighton
2017-02-12 22:26 ` [PATCH 1/2] ipv6: Inhibit IPv4-mapped src address on the wire Jonathan T. Leighton
@ 2017-02-12 22:26 ` Jonathan T. Leighton
2017-02-14 17:14 ` [PATCH 0/2] IPv4-mapped on wire, :: dst address issue David Miller
2 siblings, 0 replies; 4+ messages in thread
From: Jonathan T. Leighton @ 2017-02-12 22:26 UTC (permalink / raw)
To: netdev; +Cc: Jonathan T. Leighton
This patch adds a check on the type of the source address for the case
where the destination address is in6addr_any. If the source is an
IPv4-mapped IPv6 source address, the destination is changed to
::ffff:127.0.0.1, and otherwise the destination is changed to ::1. This
is done in three locations to handle UDP calls to either connect() or
sendmsg() and TCP calls to connect(). Note that udpv6_sendmsg() delays
handling an in6addr_any destination until very late, so the patch only
needs to handle the case where the source is an IPv4-mapped IPv6
address.
Signed-off-by: Jonathan T. Leighton <jtleight@udel.edu>
---
net/ipv6/datagram.c | 14 +++++++++-----
net/ipv6/tcp_ipv6.c | 11 ++++++++---
net/ipv6/udp.c | 4 ++++
3 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index a3eaafd..eec27f8 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -167,18 +167,22 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr,
if (np->sndflow)
fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
- addr_type = ipv6_addr_type(&usin->sin6_addr);
-
- if (addr_type == IPV6_ADDR_ANY) {
+ if (ipv6_addr_any(&usin->sin6_addr)) {
/*
* connect to self
*/
- usin->sin6_addr.s6_addr[15] = 0x01;
+ if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr))
+ ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
+ &usin->sin6_addr);
+ else
+ usin->sin6_addr = in6addr_loopback;
}
+ addr_type = ipv6_addr_type(&usin->sin6_addr);
+
daddr = &usin->sin6_addr;
- if (addr_type == IPV6_ADDR_MAPPED) {
+ if (addr_type & IPV6_ADDR_MAPPED) {
struct sockaddr_in sin;
if (__ipv6_only_sock(sk)) {
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index b5d2721..21c7199 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -149,8 +149,13 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
* connect() to INADDR_ANY means loopback (BSD'ism).
*/
- if (ipv6_addr_any(&usin->sin6_addr))
- usin->sin6_addr.s6_addr[15] = 0x1;
+ if (ipv6_addr_any(&usin->sin6_addr)) {
+ if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr))
+ ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
+ &usin->sin6_addr);
+ else
+ usin->sin6_addr = in6addr_loopback;
+ }
addr_type = ipv6_addr_type(&usin->sin6_addr);
@@ -189,7 +194,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
* TCP over IPv4
*/
- if (addr_type == IPV6_ADDR_MAPPED) {
+ if (addr_type & IPV6_ADDR_MAPPED) {
u32 exthdrlen = icsk->icsk_ext_hdr_len;
struct sockaddr_in sin;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index df71ba0..4e4c401 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1046,6 +1046,10 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
if (addr_len < SIN6_LEN_RFC2133)
return -EINVAL;
daddr = &sin6->sin6_addr;
+ if (ipv6_addr_any(daddr) &&
+ ipv6_addr_v4mapped(&np->saddr))
+ ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
+ daddr);
break;
case AF_INET:
goto do_udp_sendmsg;
--
2.7.4
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH 0/2] IPv4-mapped on wire, :: dst address issue
2017-02-12 22:26 [PATCH 0/2] IPv4-mapped on wire, :: dst address issue Jonathan T. Leighton
2017-02-12 22:26 ` [PATCH 1/2] ipv6: Inhibit IPv4-mapped src address on the wire Jonathan T. Leighton
2017-02-12 22:26 ` [PATCH 2/2] ipv6: Handle IPv4-mapped src to in6addr_any dst Jonathan T. Leighton
@ 2017-02-14 17:14 ` David Miller
2 siblings, 0 replies; 4+ messages in thread
From: David Miller @ 2017-02-14 17:14 UTC (permalink / raw)
To: jtleight; +Cc: netdev
From: "Jonathan T. Leighton" <jtleight@udel.edu>
Date: Sun, 12 Feb 2017 17:26:05 -0500
> Under some circumstances IPv6 datagrams are sent with IPv4-mapped IPv6
> addresses as the source. Given an IPv6 socket bound to an IPv4-mapped
> IPv6 address, and an IPv6 destination address, both TCP and UDP will
> will send packets using the IPv4-mapped IPv6 address as the source. Per
> RFC 6890 (Table 20), IPv4-mapped IPv6 source addresses are not allowed
> in an IP datagram. The problem can be observed by attempting to
> connect() either a TCP or UDP socket, or by using sendmsg() with a UDP
> socket. The patch is intended to correct this issue for all socket
> types.
>
> linux follows the BSD convention that an IPv6 destination address
> specified as in6addr_any is converted to the loopback address.
> Currently, neither TCP nor UDP consider the possibility that the source
> address is an IPv4-mapped IPv6 address, and assume that the appropriate
> loopback address is ::1. The patch adds a check on whether or not the
> source address is an IPv4-mapped IPv6 address and then sets the
> destination address to either ::ffff:127.0.0.1 or ::1, as appropriate.
Series applied, thanks.
^ permalink raw reply [flat|nested] 4+ messages in thread