diff options
author | Jonathan T. Leighton <jtleight@udel.edu> | 2017-02-12 17:26:07 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-02-14 12:13:51 -0500 |
commit | 052d2369d1b479cdbbe020fdd6d057d3c342db74 (patch) | |
tree | 16f83a2393edec2827eac68eac1d1e739dcb862f /net/ipv6/datagram.c | |
parent | ec5e3b0a1d41fbda0cc33a45bc9e54e91d9d12c7 (diff) | |
download | talos-op-linux-052d2369d1b479cdbbe020fdd6d057d3c342db74.tar.gz talos-op-linux-052d2369d1b479cdbbe020fdd6d057d3c342db74.zip |
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: Jonathan T. Leighton <jtleight@udel.edu>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/datagram.c')
-rw-r--r-- | net/ipv6/datagram.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index a3eaafd87100..eec27f87efac 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)) { |