summaryrefslogtreecommitdiffstats
path: root/net/rxrpc
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2018-10-04 04:32:28 -0400
committerDavid Howells <dhowells@redhat.com>2018-10-04 04:32:28 -0400
commit46894a13599a977ac35411b536fb3e0b2feefa95 (patch)
tree7900ce31700b2b9c23528fd844f65c10c6010bb6 /net/rxrpc
parent66be646bd9a7d50961afbf48c1d0df148e37d416 (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.c3
-rw-r--r--net/rxrpc/conn_object.c5
-rw-r--r--net/rxrpc/peer_event.c12
-rw-r--r--net/rxrpc/utils.c19
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