diff options
author | David Howells <dhowells@redhat.com> | 2018-10-04 04:32:28 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2018-10-04 04:32:28 -0400 |
commit | 46894a13599a977ac35411b536fb3e0b2feefa95 (patch) | |
tree | 7900ce31700b2b9c23528fd844f65c10c6010bb6 /net/rxrpc | |
parent | 66be646bd9a7d50961afbf48c1d0df148e37d416 (diff) |
rxrpc: Use IPv4 addresses throught the IPv6
AF_RXRPC opens an IPv6 socket through which to send and receive network
packets, both IPv6 and IPv4. It currently turns AF_INET addresses into
AF_INET-as-AF_INET6 addresses based on an assumption that this was
necessary; on further inspection of the code, however, it turns out that
the IPv6 code just farms packets aimed at AF_INET addresses out to the IPv4
code.
Fix AF_RXRPC to use AF_INET addresses directly when given them.
Fixes: 7b674e390e51 ("rxrpc: Fix IPv6 support")
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net/rxrpc')
-rw-r--r-- | net/rxrpc/af_rxrpc.c | 3 | ||||
-rw-r--r-- | net/rxrpc/conn_object.c | 5 | ||||
-rw-r--r-- | net/rxrpc/peer_event.c | 12 | ||||
-rw-r--r-- | net/rxrpc/utils.c | 19 |
4 files changed, 17 insertions, 22 deletions
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index ac44d8afffb1..2fdd276f6842 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
@@ -97,7 +97,8 @@ static int rxrpc_validate_address(struct rxrpc_sock *rx, | |||
97 | srx->transport_len > len) | 97 | srx->transport_len > len) |
98 | return -EINVAL; | 98 | return -EINVAL; |
99 | 99 | ||
100 | if (srx->transport.family != rx->family) | 100 | if (srx->transport.family != rx->family && |
101 | srx->transport.family == AF_INET && rx->family != AF_INET6) | ||
101 | return -EAFNOSUPPORT; | 102 | return -EAFNOSUPPORT; |
102 | 103 | ||
103 | switch (srx->transport.family) { | 104 | switch (srx->transport.family) { |
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c index 885dae829f4a..fb856a1ccda8 100644 --- a/net/rxrpc/conn_object.c +++ b/net/rxrpc/conn_object.c | |||
@@ -89,8 +89,9 @@ struct rxrpc_connection *rxrpc_find_connection_rcu(struct rxrpc_local *local, | |||
89 | if (rxrpc_extract_addr_from_skb(local, &srx, skb) < 0) | 89 | if (rxrpc_extract_addr_from_skb(local, &srx, skb) < 0) |
90 | goto not_found; | 90 | goto not_found; |
91 | 91 | ||
92 | /* We may have to handle mixing IPv4 and IPv6 */ | 92 | if (srx.transport.family != local->srx.transport.family && |
93 | if (srx.transport.family != local->srx.transport.family) { | 93 | (srx.transport.family == AF_INET && |
94 | local->srx.transport.family != AF_INET6)) { | ||
94 | pr_warn_ratelimited("AF_RXRPC: Protocol mismatch %u not %u\n", | 95 | pr_warn_ratelimited("AF_RXRPC: Protocol mismatch %u not %u\n", |
95 | srx.transport.family, | 96 | srx.transport.family, |
96 | local->srx.transport.family); | 97 | local->srx.transport.family); |
diff --git a/net/rxrpc/peer_event.c b/net/rxrpc/peer_event.c index f3e6fc670da2..81a7869325a6 100644 --- a/net/rxrpc/peer_event.c +++ b/net/rxrpc/peer_event.c | |||
@@ -47,6 +47,8 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local, | |||
47 | */ | 47 | */ |
48 | switch (srx->transport.family) { | 48 | switch (srx->transport.family) { |
49 | case AF_INET: | 49 | case AF_INET: |
50 | srx->transport_len = sizeof(srx->transport.sin); | ||
51 | srx->transport.family = AF_INET; | ||
50 | srx->transport.sin.sin_port = serr->port; | 52 | srx->transport.sin.sin_port = serr->port; |
51 | switch (serr->ee.ee_origin) { | 53 | switch (serr->ee.ee_origin) { |
52 | case SO_EE_ORIGIN_ICMP: | 54 | case SO_EE_ORIGIN_ICMP: |
@@ -70,20 +72,20 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local, | |||
70 | 72 | ||
71 | #ifdef CONFIG_AF_RXRPC_IPV6 | 73 | #ifdef CONFIG_AF_RXRPC_IPV6 |
72 | case AF_INET6: | 74 | case AF_INET6: |
73 | srx->transport.sin6.sin6_port = serr->port; | ||
74 | switch (serr->ee.ee_origin) { | 75 | switch (serr->ee.ee_origin) { |
75 | case SO_EE_ORIGIN_ICMP6: | 76 | case SO_EE_ORIGIN_ICMP6: |
76 | _net("Rx ICMP6"); | 77 | _net("Rx ICMP6"); |
78 | srx->transport.sin6.sin6_port = serr->port; | ||
77 | memcpy(&srx->transport.sin6.sin6_addr, | 79 | memcpy(&srx->transport.sin6.sin6_addr, |
78 | skb_network_header(skb) + serr->addr_offset, | 80 | skb_network_header(skb) + serr->addr_offset, |
79 | sizeof(struct in6_addr)); | 81 | sizeof(struct in6_addr)); |
80 | break; | 82 | break; |
81 | case SO_EE_ORIGIN_ICMP: | 83 | case SO_EE_ORIGIN_ICMP: |
82 | _net("Rx ICMP on v6 sock"); | 84 | _net("Rx ICMP on v6 sock"); |
83 | srx->transport.sin6.sin6_addr.s6_addr32[0] = 0; | 85 | srx->transport_len = sizeof(srx->transport.sin); |
84 | srx->transport.sin6.sin6_addr.s6_addr32[1] = 0; | 86 | srx->transport.family = AF_INET; |
85 | srx->transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff); | 87 | srx->transport.sin.sin_port = serr->port; |
86 | memcpy(srx->transport.sin6.sin6_addr.s6_addr + 12, | 88 | memcpy(&srx->transport.sin.sin_addr, |
87 | skb_network_header(skb) + serr->addr_offset, | 89 | skb_network_header(skb) + serr->addr_offset, |
88 | sizeof(struct in_addr)); | 90 | sizeof(struct in_addr)); |
89 | break; | 91 | break; |
diff --git a/net/rxrpc/utils.c b/net/rxrpc/utils.c index e801171fa351..017adaa54e90 100644 --- a/net/rxrpc/utils.c +++ b/net/rxrpc/utils.c | |||
@@ -25,20 +25,11 @@ int rxrpc_extract_addr_from_skb(struct rxrpc_local *local, | |||
25 | 25 | ||
26 | switch (ntohs(skb->protocol)) { | 26 | switch (ntohs(skb->protocol)) { |
27 | case ETH_P_IP: | 27 | case ETH_P_IP: |
28 | if (local->srx.transport.family == AF_INET6) { | 28 | srx->transport_type = SOCK_DGRAM; |
29 | srx->transport_type = SOCK_DGRAM; | 29 | srx->transport_len = sizeof(srx->transport.sin); |
30 | srx->transport_len = sizeof(srx->transport.sin6); | 30 | srx->transport.sin.sin_family = AF_INET; |
31 | srx->transport.sin6.sin6_family = AF_INET6; | 31 | srx->transport.sin.sin_port = udp_hdr(skb)->source; |
32 | srx->transport.sin6.sin6_port = udp_hdr(skb)->source; | 32 | srx->transport.sin.sin_addr.s_addr = ip_hdr(skb)->saddr; |
33 | srx->transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff); | ||
34 | srx->transport.sin6.sin6_addr.s6_addr32[3] = ip_hdr(skb)->saddr; | ||
35 | } else { | ||
36 | srx->transport_type = SOCK_DGRAM; | ||
37 | srx->transport_len = sizeof(srx->transport.sin); | ||
38 | srx->transport.sin.sin_family = AF_INET; | ||
39 | srx->transport.sin.sin_port = udp_hdr(skb)->source; | ||
40 | srx->transport.sin.sin_addr.s_addr = ip_hdr(skb)->saddr; | ||
41 | } | ||
42 | return 0; | 33 | return 0; |
43 | 34 | ||
44 | #ifdef CONFIG_AF_RXRPC_IPV6 | 35 | #ifdef CONFIG_AF_RXRPC_IPV6 |