netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC 0/2] ipv6: IPv4-mapped on wire, :: dst address issue
@ 2017-02-02 18:27 Jonathan T. Leighton
  2017-02-02 18:27 ` [PATCH RFC 1/2] ipv6: Inhibit IPv4-mapped src address on the wire Jonathan T. Leighton
  2017-02-02 18:27 ` [PATCH RFC 2/2] ipv6: Handle IPv4-mapped src to in6addr_any dst Jonathan T. Leighton
  0 siblings, 2 replies; 3+ messages in thread
From: Jonathan T. Leighton @ 2017-02-02 18:27 UTC (permalink / raw)
  To: netdev; +Cc: Jonathan T. Leighton

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.

Jon

Jonathan T. Leighton (2):
  ipv6: Inhibit IPv4-mapped src address on the wire.
  ipv6: Handle IPv4-mapped src to in6addr_any dst.

 net/ipv6/datagram.c   | 14 +++++++++-----
 net/ipv6/ip6_output.c |  3 +++
 net/ipv6/tcp_ipv6.c   | 11 ++++++++---
 net/ipv6/udp.c        |  4 ++++
 4 files changed, 24 insertions(+), 8 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH RFC 1/2] ipv6: Inhibit IPv4-mapped src address on the wire.
  2017-02-02 18:27 [PATCH RFC 0/2] ipv6: IPv4-mapped on wire, :: dst address issue Jonathan T. Leighton
@ 2017-02-02 18:27 ` Jonathan T. Leighton
  2017-02-02 18:27 ` [PATCH RFC 2/2] ipv6: Handle IPv4-mapped src to in6addr_any dst Jonathan T. Leighton
  1 sibling, 0 replies; 3+ messages in thread
From: Jonathan T. Leighton @ 2017-02-02 18:27 UTC (permalink / raw)
  To: netdev; +Cc: Jonathan T. Leighton

This patch adds a check for the problematic case of an IPv4-mapped IPv6
source address and a destination address that is neither an IPv4-mapped
IPv6 address nor in6addr_any, and returns an appropriate error. The
check in done before returning from looking up the route.

Signed-off-by: Jonathan T. Leighton <jtleight@udel.edu>
---
 net/ipv6/ip6_output.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 38122d0..7969c1e 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1021,6 +1021,9 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk,
 		}
 	}
 #endif
+	if (ipv6_addr_v4mapped(&fl6->saddr) &&
+	    !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr)))
+		return -EAFNOSUPPORT;
 
 	return 0;
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH RFC 2/2] ipv6: Handle IPv4-mapped src to in6addr_any dst.
  2017-02-02 18:27 [PATCH RFC 0/2] ipv6: IPv4-mapped on wire, :: dst address issue Jonathan T. Leighton
  2017-02-02 18:27 ` [PATCH RFC 1/2] ipv6: Inhibit IPv4-mapped src address on the wire Jonathan T. Leighton
@ 2017-02-02 18:27 ` Jonathan T. Leighton
  1 sibling, 0 replies; 3+ messages in thread
From: Jonathan T. Leighton @ 2017-02-02 18:27 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..678a84e 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(ntohl(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 228965d..9e91da4 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(ntohl(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 4d5c4ee..bbdf7de 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1033,6 +1033,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(ntohl(INADDR_LOOPBACK),
+						       daddr);
 			break;
 		case AF_INET:
 			goto do_udp_sendmsg;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2017-02-02 18:28 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-02-02 18:27 [PATCH RFC 0/2] ipv6: IPv4-mapped on wire, :: dst address issue Jonathan T. Leighton
2017-02-02 18:27 ` [PATCH RFC 1/2] ipv6: Inhibit IPv4-mapped src address on the wire Jonathan T. Leighton
2017-02-02 18:27 ` [PATCH RFC 2/2] ipv6: Handle IPv4-mapped src to in6addr_any dst Jonathan T. Leighton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).