diff options
author | David Howells <dhowells@redhat.com> | 2018-05-10 18:26:00 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2018-05-10 18:26:00 -0400 |
commit | f2aeed3a591ff29a82495eeaa92ac4780bad7487 (patch) | |
tree | c92adff145aee3ca0a9b29400171eedb6f98210d /net | |
parent | c54e43d752c7187595c8c62a231e0b0d53c7fded (diff) |
rxrpc: Fix error reception on AF_INET6 sockets
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: 75b54cb57ca3 ("rxrpc: Add IPv6 support")
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/rxrpc/local_object.c | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c index 8b54e9531d52..b493e6b62740 100644 --- a/net/rxrpc/local_object.c +++ b/net/rxrpc/local_object.c | |||
@@ -134,22 +134,49 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net) | |||
134 | } | 134 | } |
135 | } | 135 | } |
136 | 136 | ||
137 | /* we want to receive ICMP errors */ | 137 | switch (local->srx.transport.family) { |
138 | opt = 1; | 138 | case AF_INET: |
139 | ret = kernel_setsockopt(local->socket, SOL_IP, IP_RECVERR, | 139 | /* we want to receive ICMP errors */ |
140 | (char *) &opt, sizeof(opt)); | 140 | opt = 1; |
141 | if (ret < 0) { | 141 | ret = kernel_setsockopt(local->socket, SOL_IP, IP_RECVERR, |
142 | _debug("setsockopt failed"); | 142 | (char *) &opt, sizeof(opt)); |
143 | goto error; | 143 | if (ret < 0) { |
144 | } | 144 | _debug("setsockopt failed"); |
145 | goto error; | ||
146 | } | ||
145 | 147 | ||
146 | /* we want to set the don't fragment bit */ | 148 | /* we want to set the don't fragment bit */ |
147 | opt = IP_PMTUDISC_DO; | 149 | opt = IP_PMTUDISC_DO; |
148 | ret = kernel_setsockopt(local->socket, SOL_IP, IP_MTU_DISCOVER, | 150 | ret = kernel_setsockopt(local->socket, SOL_IP, IP_MTU_DISCOVER, |
149 | (char *) &opt, sizeof(opt)); | 151 | (char *) &opt, sizeof(opt)); |
150 | if (ret < 0) { | 152 | if (ret < 0) { |
151 | _debug("setsockopt failed"); | 153 | _debug("setsockopt failed"); |
152 | goto error; | 154 | goto error; |
155 | } | ||
156 | break; | ||
157 | |||
158 | case AF_INET6: | ||
159 | /* we want to receive ICMP errors */ | ||
160 | opt = 1; | ||
161 | ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_RECVERR, | ||
162 | (char *) &opt, sizeof(opt)); | ||
163 | if (ret < 0) { | ||
164 | _debug("setsockopt failed"); | ||
165 | goto error; | ||
166 | } | ||
167 | |||
168 | /* we want to set the don't fragment bit */ | ||
169 | opt = IPV6_PMTUDISC_DO; | ||
170 | ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_MTU_DISCOVER, | ||
171 | (char *) &opt, sizeof(opt)); | ||
172 | if (ret < 0) { | ||
173 | _debug("setsockopt failed"); | ||
174 | goto error; | ||
175 | } | ||
176 | break; | ||
177 | |||
178 | default: | ||
179 | BUG(); | ||
153 | } | 180 | } |
154 | 181 | ||
155 | /* set the socket up */ | 182 | /* set the socket up */ |