Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 052d2369 authored by Jonathan T. Leighton's avatar Jonathan T. Leighton Committed by David S. Miller
Browse files

ipv6: Handle IPv4-mapped src to in6addr_any dst.



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: default avatarJonathan T. Leighton <jtleight@udel.edu>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ec5e3b0a
Loading
Loading
Loading
Loading
+9 −5
Original line number Original line Diff line number Diff line
@@ -167,18 +167,22 @@ int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr,
	if (np->sndflow)
	if (np->sndflow)
		fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
		fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;


	addr_type = ipv6_addr_type(&usin->sin6_addr);
	if (ipv6_addr_any(&usin->sin6_addr)) {

	if (addr_type == IPV6_ADDR_ANY) {
		/*
		/*
		 *	connect to self
		 *	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;
	daddr = &usin->sin6_addr;


	if (addr_type == IPV6_ADDR_MAPPED) {
	if (addr_type & IPV6_ADDR_MAPPED) {
		struct sockaddr_in sin;
		struct sockaddr_in sin;


		if (__ipv6_only_sock(sk)) {
		if (__ipv6_only_sock(sk)) {
+8 −3
Original line number Original line Diff line number Diff line
@@ -148,8 +148,13 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
	 *	connect() to INADDR_ANY means loopback (BSD'ism).
	 *	connect() to INADDR_ANY means loopback (BSD'ism).
	 */
	 */


	if (ipv6_addr_any(&usin->sin6_addr))
	if (ipv6_addr_any(&usin->sin6_addr)) {
		usin->sin6_addr.s6_addr[15] = 0x1;
		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);
	addr_type = ipv6_addr_type(&usin->sin6_addr);


@@ -188,7 +193,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
	 *	TCP over IPv4
	 *	TCP over IPv4
	 */
	 */


	if (addr_type == IPV6_ADDR_MAPPED) {
	if (addr_type & IPV6_ADDR_MAPPED) {
		u32 exthdrlen = icsk->icsk_ext_hdr_len;
		u32 exthdrlen = icsk->icsk_ext_hdr_len;
		struct sockaddr_in sin;
		struct sockaddr_in sin;


+4 −0
Original line number Original line Diff line number Diff line
@@ -1033,6 +1033,10 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
			if (addr_len < SIN6_LEN_RFC2133)
			if (addr_len < SIN6_LEN_RFC2133)
				return -EINVAL;
				return -EINVAL;
			daddr = &sin6->sin6_addr;
			daddr = &sin6->sin6_addr;
			if (ipv6_addr_any(daddr) &&
			    ipv6_addr_v4mapped(&np->saddr))
				ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
						       daddr);
			break;
			break;
		case AF_INET:
		case AF_INET:
			goto do_udp_sendmsg;
			goto do_udp_sendmsg;