Skip to content

Commit 8faccb2

Browse files
Jonathan T. Leightongregkh
authored andcommitted
ipv6: Handle IPv4-mapped src to in6addr_any dst.
[ Upstream commit 052d2369d1b479cdbbe020fdd6d057d3c342db74 ] 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> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <alexander.levin@verizon.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 10a7629 commit 8faccb2

3 files changed

Lines changed: 21 additions & 8 deletions

File tree

net/ipv6/datagram.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,22 @@ static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int a
7676
}
7777
}
7878

79-
addr_type = ipv6_addr_type(&usin->sin6_addr);
80-
81-
if (addr_type == IPV6_ADDR_ANY) {
79+
if (ipv6_addr_any(&usin->sin6_addr)) {
8280
/*
8381
* connect to self
8482
*/
85-
usin->sin6_addr.s6_addr[15] = 0x01;
83+
if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr))
84+
ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
85+
&usin->sin6_addr);
86+
else
87+
usin->sin6_addr = in6addr_loopback;
8688
}
8789

90+
addr_type = ipv6_addr_type(&usin->sin6_addr);
91+
8892
daddr = &usin->sin6_addr;
8993

90-
if (addr_type == IPV6_ADDR_MAPPED) {
94+
if (addr_type & IPV6_ADDR_MAPPED) {
9195
struct sockaddr_in sin;
9296

9397
if (__ipv6_only_sock(sk)) {

net/ipv6/tcp_ipv6.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,13 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
149149
* connect() to INADDR_ANY means loopback (BSD'ism).
150150
*/
151151

152-
if (ipv6_addr_any(&usin->sin6_addr))
153-
usin->sin6_addr.s6_addr[15] = 0x1;
152+
if (ipv6_addr_any(&usin->sin6_addr)) {
153+
if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr))
154+
ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
155+
&usin->sin6_addr);
156+
else
157+
usin->sin6_addr = in6addr_loopback;
158+
}
154159

155160
addr_type = ipv6_addr_type(&usin->sin6_addr);
156161

@@ -189,7 +194,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
189194
* TCP over IPv4
190195
*/
191196

192-
if (addr_type == IPV6_ADDR_MAPPED) {
197+
if (addr_type & IPV6_ADDR_MAPPED) {
193198
u32 exthdrlen = icsk->icsk_ext_hdr_len;
194199
struct sockaddr_in sin;
195200

net/ipv6/udp.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,10 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
11361136
if (addr_len < SIN6_LEN_RFC2133)
11371137
return -EINVAL;
11381138
daddr = &sin6->sin6_addr;
1139+
if (ipv6_addr_any(daddr) &&
1140+
ipv6_addr_v4mapped(&np->saddr))
1141+
ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
1142+
daddr);
11391143
break;
11401144
case AF_INET:
11411145
goto do_udp_sendmsg;

0 commit comments

Comments
 (0)