Commit 37a675e7 authored by David Howells's avatar David Howells

rxrpc: Fix transport sockopts to get IPv4 errors on an IPv6 socket

It seems that enabling IPV6_RECVERR on an IPv6 socket doesn't also turn on
IP_RECVERR, so neither local errors nor ICMP-transported remote errors from
IPv4 peer addresses are returned to the AF_RXRPC protocol.

Make the sockopt setting code in rxrpc_open_socket() fall through from the
AF_INET6 case to the AF_INET case to turn on all the AF_INET options too in
the AF_INET6 case.

Fixes: f2aeed3a ("rxrpc: Fix error reception on AF_INET6 sockets")
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 0099dc58
...@@ -135,10 +135,10 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net) ...@@ -135,10 +135,10 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
} }
switch (local->srx.transport.family) { switch (local->srx.transport.family) {
case AF_INET: case AF_INET6:
/* we want to receive ICMP errors */ /* we want to receive ICMPv6 errors */
opt = 1; opt = 1;
ret = kernel_setsockopt(local->socket, SOL_IP, IP_RECVERR, ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_RECVERR,
(char *) &opt, sizeof(opt)); (char *) &opt, sizeof(opt));
if (ret < 0) { if (ret < 0) {
_debug("setsockopt failed"); _debug("setsockopt failed");
...@@ -146,19 +146,22 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net) ...@@ -146,19 +146,22 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
} }
/* we want to set the don't fragment bit */ /* we want to set the don't fragment bit */
opt = IP_PMTUDISC_DO; opt = IPV6_PMTUDISC_DO;
ret = kernel_setsockopt(local->socket, SOL_IP, IP_MTU_DISCOVER, ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_MTU_DISCOVER,
(char *) &opt, sizeof(opt)); (char *) &opt, sizeof(opt));
if (ret < 0) { if (ret < 0) {
_debug("setsockopt failed"); _debug("setsockopt failed");
goto error; goto error;
} }
break;
case AF_INET6: /* Fall through and set IPv4 options too otherwise we don't get
* errors from IPv4 packets sent through the IPv6 socket.
*/
case AF_INET:
/* we want to receive ICMP errors */ /* we want to receive ICMP errors */
opt = 1; opt = 1;
ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_RECVERR, ret = kernel_setsockopt(local->socket, SOL_IP, IP_RECVERR,
(char *) &opt, sizeof(opt)); (char *) &opt, sizeof(opt));
if (ret < 0) { if (ret < 0) {
_debug("setsockopt failed"); _debug("setsockopt failed");
...@@ -166,8 +169,8 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net) ...@@ -166,8 +169,8 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
} }
/* we want to set the don't fragment bit */ /* we want to set the don't fragment bit */
opt = IPV6_PMTUDISC_DO; opt = IP_PMTUDISC_DO;
ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_MTU_DISCOVER, ret = kernel_setsockopt(local->socket, SOL_IP, IP_MTU_DISCOVER,
(char *) &opt, sizeof(opt)); (char *) &opt, sizeof(opt));
if (ret < 0) { if (ret < 0) {
_debug("setsockopt failed"); _debug("setsockopt failed");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment