diff options
author | David Howells <dhowells@redhat.com> | 2017-08-29 10:18:37 +0100 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2017-08-29 10:55:20 +0100 |
commit | 7b674e390e513ea443c5a0f27ec95e93fb8a94fa (patch) | |
tree | 21ed0fb6ec3d190608bf72cbf9e3776d7e296fbe /net/rxrpc/peer_event.c | |
parent | 0a3785855edcdb326ebf052c4f92ebc2710614c6 (diff) |
rxrpc: Fix IPv6 support
Fix IPv6 support in AF_RXRPC in the following ways:
(1) When extracting the address from a received IPv4 packet, if the local
transport socket is open for IPv6 then fill out the sockaddr_rxrpc
struct for an IPv4-mapped-to-IPv6 AF_INET6 transport address instead
of an AF_INET one.
(2) When sending CHALLENGE or RESPONSE packets, the transport length needs
to be set from the sockaddr_rxrpc::transport_len field rather than
sizeof() on the IPv4 transport address.
(3) When processing an IPv4 ICMP packet received by an IPv6 socket, set up
the address correctly before searching for the affected peer.
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net/rxrpc/peer_event.c')
-rw-r--r-- | net/rxrpc/peer_event.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/net/rxrpc/peer_event.c b/net/rxrpc/peer_event.c index 1ed9c0c2e94f..7f749505e699 100644 --- a/net/rxrpc/peer_event.c +++ b/net/rxrpc/peer_event.c @@ -37,6 +37,7 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local, memset(&srx, 0, sizeof(srx)); srx.transport_type = local->srx.transport_type; + srx.transport_len = local->srx.transport_len; srx.transport.family = local->srx.transport.family; /* Can we see an ICMP4 packet on an ICMP6 listening socket? and vice @@ -45,7 +46,6 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local, switch (srx.transport.family) { case AF_INET: srx.transport.sin.sin_port = serr->port; - srx.transport_len = sizeof(struct sockaddr_in); switch (serr->ee.ee_origin) { case SO_EE_ORIGIN_ICMP: _net("Rx ICMP"); @@ -69,7 +69,6 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local, #ifdef CONFIG_AF_RXRPC_IPV6 case AF_INET6: srx.transport.sin6.sin6_port = serr->port; - srx.transport_len = sizeof(struct sockaddr_in6); switch (serr->ee.ee_origin) { case SO_EE_ORIGIN_ICMP6: _net("Rx ICMP6"); @@ -79,6 +78,9 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local, break; case SO_EE_ORIGIN_ICMP: _net("Rx ICMP on v6 sock"); + srx.transport.sin6.sin6_addr.s6_addr32[0] = 0; + srx.transport.sin6.sin6_addr.s6_addr32[1] = 0; + srx.transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff); memcpy(srx.transport.sin6.sin6_addr.s6_addr + 12, skb_network_header(skb) + serr->addr_offset, sizeof(struct in_addr)); |