Skip to content

Commit

Permalink
rxrpc: Fix error reception on AF_INET6 sockets
Browse files Browse the repository at this point in the history
AF_RXRPC tries to turn on IP_RECVERR and IP_MTU_DISCOVER on the UDP socket
it just opened for communications with the outside world, regardless of the
type of socket.  Unfortunately, this doesn't work with an AF_INET6 socket.

Fix this by turning on IPV6_RECVERR and IPV6_MTU_DISCOVER instead if the
socket is of the AF_INET6 family.

Without this, kAFS server and address rotation doesn't work correctly
because the algorithm doesn't detect received network errors.

Fixes: 75b54cb ("rxrpc: Add IPv6 support")
Signed-off-by: David Howells <dhowells@redhat.com>
  • Loading branch information
David Howells committed May 10, 2018
1 parent c54e43d commit f2aeed3
Showing 1 changed file with 42 additions and 15 deletions.
57 changes: 42 additions & 15 deletions net/rxrpc/local_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,22 +134,49 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
}
}

/* we want to receive ICMP errors */
opt = 1;
ret = kernel_setsockopt(local->socket, SOL_IP, IP_RECVERR,
(char *) &opt, sizeof(opt));
if (ret < 0) {
_debug("setsockopt failed");
goto error;
}
switch (local->srx.transport.family) {
case AF_INET:
/* we want to receive ICMP errors */
opt = 1;
ret = kernel_setsockopt(local->socket, SOL_IP, IP_RECVERR,
(char *) &opt, sizeof(opt));
if (ret < 0) {
_debug("setsockopt failed");
goto error;
}

/* we want to set the don't fragment bit */
opt = IP_PMTUDISC_DO;
ret = kernel_setsockopt(local->socket, SOL_IP, IP_MTU_DISCOVER,
(char *) &opt, sizeof(opt));
if (ret < 0) {
_debug("setsockopt failed");
goto error;
/* we want to set the don't fragment bit */
opt = IP_PMTUDISC_DO;
ret = kernel_setsockopt(local->socket, SOL_IP, IP_MTU_DISCOVER,
(char *) &opt, sizeof(opt));
if (ret < 0) {
_debug("setsockopt failed");
goto error;
}
break;

case AF_INET6:
/* we want to receive ICMP errors */
opt = 1;
ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_RECVERR,
(char *) &opt, sizeof(opt));
if (ret < 0) {
_debug("setsockopt failed");
goto error;
}

/* we want to set the don't fragment bit */
opt = IPV6_PMTUDISC_DO;
ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_MTU_DISCOVER,
(char *) &opt, sizeof(opt));
if (ret < 0) {
_debug("setsockopt failed");
goto error;
}
break;

default:
BUG();
}

/* set the socket up */
Expand Down

0 comments on commit f2aeed3

Please sign in to comment.