hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/net/rxrpc/peer_event.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* Peer event handling, typically ICMP messages.
23 *
34 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
45 * Written by David Howells (dhowells@redhat.com)
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of the GNU General Public License
8
- * as published by the Free Software Foundation; either version
9
- * 2 of the License, or (at your option) any later version.
106 */
117
128 #include <linux/module.h>
....@@ -47,6 +43,8 @@
4743 */
4844 switch (srx->transport.family) {
4945 case AF_INET:
46
+ srx->transport_len = sizeof(srx->transport.sin);
47
+ srx->transport.family = AF_INET;
5048 srx->transport.sin.sin_port = serr->port;
5149 switch (serr->ee.ee_origin) {
5250 case SO_EE_ORIGIN_ICMP:
....@@ -70,20 +68,20 @@
7068
7169 #ifdef CONFIG_AF_RXRPC_IPV6
7270 case AF_INET6:
73
- srx->transport.sin6.sin6_port = serr->port;
7471 switch (serr->ee.ee_origin) {
7572 case SO_EE_ORIGIN_ICMP6:
7673 _net("Rx ICMP6");
74
+ srx->transport.sin6.sin6_port = serr->port;
7775 memcpy(&srx->transport.sin6.sin6_addr,
7876 skb_network_header(skb) + serr->addr_offset,
7977 sizeof(struct in6_addr));
8078 break;
8179 case SO_EE_ORIGIN_ICMP:
8280 _net("Rx ICMP on v6 sock");
83
- srx->transport.sin6.sin6_addr.s6_addr32[0] = 0;
84
- srx->transport.sin6.sin6_addr.s6_addr32[1] = 0;
85
- srx->transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
86
- memcpy(srx->transport.sin6.sin6_addr.s6_addr + 12,
81
+ srx->transport_len = sizeof(srx->transport.sin);
82
+ srx->transport.family = AF_INET;
83
+ srx->transport.sin.sin_port = serr->port;
84
+ memcpy(&srx->transport.sin.sin_addr,
8785 skb_network_header(skb) + serr->addr_offset,
8886 sizeof(struct in_addr));
8987 break;
....@@ -149,35 +147,44 @@
149147 {
150148 struct sock_exterr_skb *serr;
151149 struct sockaddr_rxrpc srx;
152
- struct rxrpc_local *local = sk->sk_user_data;
150
+ struct rxrpc_local *local;
153151 struct rxrpc_peer *peer;
154152 struct sk_buff *skb;
155153
156
- if (unlikely(!local))
154
+ rcu_read_lock();
155
+ local = rcu_dereference_sk_user_data(sk);
156
+ if (unlikely(!local)) {
157
+ rcu_read_unlock();
157158 return;
158
-
159
+ }
159160 _enter("%p{%d}", sk, local->debug_id);
161
+
162
+ /* Clear the outstanding error value on the socket so that it doesn't
163
+ * cause kernel_sendmsg() to return it later.
164
+ */
165
+ sock_error(sk);
160166
161167 skb = sock_dequeue_err_skb(sk);
162168 if (!skb) {
169
+ rcu_read_unlock();
163170 _leave("UDP socket errqueue empty");
164171 return;
165172 }
166
- rxrpc_new_skb(skb, rxrpc_skb_rx_received);
173
+ rxrpc_new_skb(skb, rxrpc_skb_received);
167174 serr = SKB_EXT_ERR(skb);
168175 if (!skb->len && serr->ee.ee_origin == SO_EE_ORIGIN_TIMESTAMPING) {
169176 _leave("UDP empty message");
170
- rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
177
+ rcu_read_unlock();
178
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
171179 return;
172180 }
173181
174
- rcu_read_lock();
175182 peer = rxrpc_lookup_peer_icmp_rcu(local, skb, &srx);
176183 if (peer && !rxrpc_get_peer_maybe(peer))
177184 peer = NULL;
178185 if (!peer) {
179186 rcu_read_unlock();
180
- rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
187
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
181188 _leave(" [no peer]");
182189 return;
183190 }
....@@ -189,7 +196,7 @@
189196 serr->ee.ee_code == ICMP_FRAG_NEEDED)) {
190197 rxrpc_adjust_mtu(peer, serr);
191198 rcu_read_unlock();
192
- rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
199
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
193200 rxrpc_put_peer(peer);
194201 _leave(" [MTU update]");
195202 return;
....@@ -197,7 +204,7 @@
197204
198205 rxrpc_store_error(peer, serr);
199206 rcu_read_unlock();
200
- rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
207
+ rxrpc_free_skb(skb, rxrpc_skb_freed);
201208 rxrpc_put_peer(peer);
202209
203210 _leave("");
....@@ -264,6 +271,9 @@
264271 break;
265272
266273 case SO_EE_ORIGIN_ICMP6:
274
+ if (err == EACCES)
275
+ err = EHOSTUNREACH;
276
+ fallthrough;
267277 default:
268278 _proto("Rx Received error report { orig=%u }", ee->ee_origin);
269279 break;
....@@ -282,56 +292,8 @@
282292
283293 hlist_for_each_entry_rcu(call, &peer->error_targets, error_link) {
284294 rxrpc_see_call(call);
285
- if (call->state < RXRPC_CALL_COMPLETE &&
286
- rxrpc_set_call_completion(call, compl, 0, -error))
287
- rxrpc_notify_socket(call);
295
+ rxrpc_set_call_completion(call, compl, 0, -error);
288296 }
289
-}
290
-
291
-/*
292
- * Add RTT information to cache. This is called in softirq mode and has
293
- * exclusive access to the peer RTT data.
294
- */
295
-void rxrpc_peer_add_rtt(struct rxrpc_call *call, enum rxrpc_rtt_rx_trace why,
296
- rxrpc_serial_t send_serial, rxrpc_serial_t resp_serial,
297
- ktime_t send_time, ktime_t resp_time)
298
-{
299
- struct rxrpc_peer *peer = call->peer;
300
- s64 rtt;
301
- u64 sum = peer->rtt_sum, avg;
302
- u8 cursor = peer->rtt_cursor, usage = peer->rtt_usage;
303
-
304
- rtt = ktime_to_ns(ktime_sub(resp_time, send_time));
305
- if (rtt < 0)
306
- return;
307
-
308
- spin_lock(&peer->rtt_input_lock);
309
-
310
- /* Replace the oldest datum in the RTT buffer */
311
- sum -= peer->rtt_cache[cursor];
312
- sum += rtt;
313
- peer->rtt_cache[cursor] = rtt;
314
- peer->rtt_cursor = (cursor + 1) & (RXRPC_RTT_CACHE_SIZE - 1);
315
- peer->rtt_sum = sum;
316
- if (usage < RXRPC_RTT_CACHE_SIZE) {
317
- usage++;
318
- peer->rtt_usage = usage;
319
- }
320
-
321
- spin_unlock(&peer->rtt_input_lock);
322
-
323
- /* Now recalculate the average */
324
- if (usage == RXRPC_RTT_CACHE_SIZE) {
325
- avg = sum / RXRPC_RTT_CACHE_SIZE;
326
- } else {
327
- avg = sum;
328
- do_div(avg, usage);
329
- }
330
-
331
- /* Don't need to update this under lock */
332
- peer->rtt = avg;
333
- trace_rxrpc_rtt_rx(call, why, send_serial, resp_serial, rtt,
334
- usage, avg);
335297 }
336298
337299 /*