1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Peer event handling, typically ICMP messages.
4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
8 #include <linux/module.h>
10 #include <linux/skbuff.h>
11 #include <linux/errqueue.h>
12 #include <linux/udp.h>
14 #include <linux/in6.h>
15 #include <linux/icmp.h>
17 #include <net/af_rxrpc.h>
19 #include "ar-internal.h"
21 static void rxrpc_store_error(struct rxrpc_peer
*, struct sk_buff
*);
22 static void rxrpc_distribute_error(struct rxrpc_peer
*, struct sk_buff
*,
23 enum rxrpc_call_completion
, int);
26 * Find the peer associated with a local error.
28 static struct rxrpc_peer
*rxrpc_lookup_peer_local_rcu(struct rxrpc_local
*local
,
29 const struct sk_buff
*skb
,
30 struct sockaddr_rxrpc
*srx
)
32 struct sock_exterr_skb
*serr
= SKB_EXT_ERR(skb
);
36 memset(srx
, 0, sizeof(*srx
));
37 srx
->transport_type
= local
->srx
.transport_type
;
38 srx
->transport_len
= local
->srx
.transport_len
;
39 srx
->transport
.family
= local
->srx
.transport
.family
;
41 /* Can we see an ICMP4 packet on an ICMP6 listening socket? and vice
44 switch (srx
->transport
.family
) {
46 srx
->transport_len
= sizeof(srx
->transport
.sin
);
47 srx
->transport
.family
= AF_INET
;
48 srx
->transport
.sin
.sin_port
= serr
->port
;
49 switch (serr
->ee
.ee_origin
) {
50 case SO_EE_ORIGIN_ICMP
:
51 memcpy(&srx
->transport
.sin
.sin_addr
,
52 skb_network_header(skb
) + serr
->addr_offset
,
53 sizeof(struct in_addr
));
55 case SO_EE_ORIGIN_ICMP6
:
56 memcpy(&srx
->transport
.sin
.sin_addr
,
57 skb_network_header(skb
) + serr
->addr_offset
+ 12,
58 sizeof(struct in_addr
));
61 memcpy(&srx
->transport
.sin
.sin_addr
, &ip_hdr(skb
)->saddr
,
62 sizeof(struct in_addr
));
67 #ifdef CONFIG_AF_RXRPC_IPV6
69 switch (serr
->ee
.ee_origin
) {
70 case SO_EE_ORIGIN_ICMP6
:
71 srx
->transport
.sin6
.sin6_port
= serr
->port
;
72 memcpy(&srx
->transport
.sin6
.sin6_addr
,
73 skb_network_header(skb
) + serr
->addr_offset
,
74 sizeof(struct in6_addr
));
76 case SO_EE_ORIGIN_ICMP
:
77 srx
->transport_len
= sizeof(srx
->transport
.sin
);
78 srx
->transport
.family
= AF_INET
;
79 srx
->transport
.sin
.sin_port
= serr
->port
;
80 memcpy(&srx
->transport
.sin
.sin_addr
,
81 skb_network_header(skb
) + serr
->addr_offset
,
82 sizeof(struct in_addr
));
85 memcpy(&srx
->transport
.sin6
.sin6_addr
,
86 &ipv6_hdr(skb
)->saddr
,
87 sizeof(struct in6_addr
));
97 return rxrpc_lookup_peer_rcu(local
, srx
);
101 * Handle an MTU/fragmentation problem.
103 static void rxrpc_adjust_mtu(struct rxrpc_peer
*peer
, unsigned int mtu
)
105 /* wind down the local interface MTU */
106 if (mtu
> 0 && peer
->if_mtu
== 65535 && mtu
< peer
->if_mtu
)
110 /* they didn't give us a size, estimate one */
118 if (mtu
< peer
->hdrsize
)
119 mtu
= peer
->hdrsize
+ 4;
123 if (mtu
< peer
->mtu
) {
124 spin_lock(&peer
->lock
);
126 peer
->maxdata
= peer
->mtu
- peer
->hdrsize
;
127 spin_unlock(&peer
->lock
);
132 * Handle an error received on the local endpoint.
134 void rxrpc_input_error(struct rxrpc_local
*local
, struct sk_buff
*skb
)
136 struct sock_exterr_skb
*serr
= SKB_EXT_ERR(skb
);
137 struct sockaddr_rxrpc srx
;
138 struct rxrpc_peer
*peer
= NULL
;
140 _enter("L=%x", local
->debug_id
);
142 if (!skb
->len
&& serr
->ee
.ee_origin
== SO_EE_ORIGIN_TIMESTAMPING
) {
143 _leave("UDP empty message");
148 peer
= rxrpc_lookup_peer_local_rcu(local
, skb
, &srx
);
149 if (peer
&& !rxrpc_get_peer_maybe(peer
, rxrpc_peer_get_input_error
))
155 trace_rxrpc_rx_icmp(peer
, &serr
->ee
, &srx
);
157 if ((serr
->ee
.ee_origin
== SO_EE_ORIGIN_ICMP
&&
158 serr
->ee
.ee_type
== ICMP_DEST_UNREACH
&&
159 serr
->ee
.ee_code
== ICMP_FRAG_NEEDED
)) {
160 rxrpc_adjust_mtu(peer
, serr
->ee
.ee_info
);
164 rxrpc_store_error(peer
, skb
);
166 rxrpc_put_peer(peer
, rxrpc_peer_put_input_error
);
170 * Map an error report to error codes on the peer record.
172 static void rxrpc_store_error(struct rxrpc_peer
*peer
, struct sk_buff
*skb
)
174 enum rxrpc_call_completion
compl = RXRPC_CALL_NETWORK_ERROR
;
175 struct sock_exterr_skb
*serr
= SKB_EXT_ERR(skb
);
176 struct sock_extended_err
*ee
= &serr
->ee
;
177 int err
= ee
->ee_errno
;
181 switch (ee
->ee_origin
) {
182 case SO_EE_ORIGIN_NONE
:
183 case SO_EE_ORIGIN_LOCAL
:
184 compl = RXRPC_CALL_LOCAL_ERROR
;
187 case SO_EE_ORIGIN_ICMP6
:
191 case SO_EE_ORIGIN_ICMP
:
196 rxrpc_distribute_error(peer
, skb
, compl, err
);
200 * Distribute an error that occurred on a peer.
202 static void rxrpc_distribute_error(struct rxrpc_peer
*peer
, struct sk_buff
*skb
,
203 enum rxrpc_call_completion
compl, int err
)
205 struct rxrpc_call
*call
;
206 HLIST_HEAD(error_targets
);
208 spin_lock(&peer
->lock
);
209 hlist_move_list(&peer
->error_targets
, &error_targets
);
211 while (!hlist_empty(&error_targets
)) {
212 call
= hlist_entry(error_targets
.first
,
213 struct rxrpc_call
, error_link
);
214 hlist_del_init(&call
->error_link
);
215 spin_unlock(&peer
->lock
);
217 rxrpc_see_call(call
, rxrpc_call_see_distribute_error
);
218 rxrpc_set_call_completion(call
, compl, 0, -err
);
219 rxrpc_input_call_event(call
, skb
);
221 spin_lock(&peer
->lock
);
224 spin_unlock(&peer
->lock
);
228 * Perform keep-alive pings.
230 static void rxrpc_peer_keepalive_dispatch(struct rxrpc_net
*rxnet
,
231 struct list_head
*collector
,
235 struct rxrpc_peer
*peer
;
236 const u8 mask
= ARRAY_SIZE(rxnet
->peer_keepalive
) - 1;
237 time64_t keepalive_at
;
241 spin_lock(&rxnet
->peer_hash_lock
);
243 while (!list_empty(collector
)) {
244 peer
= list_entry(collector
->next
,
245 struct rxrpc_peer
, keepalive_link
);
247 list_del_init(&peer
->keepalive_link
);
248 if (!rxrpc_get_peer_maybe(peer
, rxrpc_peer_get_keepalive
))
251 use
= __rxrpc_use_local(peer
->local
, rxrpc_local_use_peer_keepalive
);
252 spin_unlock(&rxnet
->peer_hash_lock
);
255 keepalive_at
= peer
->last_tx_at
+ RXRPC_KEEPALIVE_TIME
;
256 slot
= keepalive_at
- base
;
257 _debug("%02x peer %u t=%d {%pISp}",
258 cursor
, peer
->debug_id
, slot
, &peer
->srx
.transport
);
260 if (keepalive_at
<= base
||
261 keepalive_at
> base
+ RXRPC_KEEPALIVE_TIME
) {
262 rxrpc_send_keepalive(peer
);
263 slot
= RXRPC_KEEPALIVE_TIME
;
266 /* A transmission to this peer occurred since last we
267 * examined it so put it into the appropriate future
272 spin_lock(&rxnet
->peer_hash_lock
);
273 list_add_tail(&peer
->keepalive_link
,
274 &rxnet
->peer_keepalive
[slot
& mask
]);
275 spin_unlock(&rxnet
->peer_hash_lock
);
276 rxrpc_unuse_local(peer
->local
, rxrpc_local_unuse_peer_keepalive
);
278 rxrpc_put_peer(peer
, rxrpc_peer_put_keepalive
);
279 spin_lock(&rxnet
->peer_hash_lock
);
282 spin_unlock(&rxnet
->peer_hash_lock
);
286 * Perform keep-alive pings with VERSION packets to keep any NAT alive.
288 void rxrpc_peer_keepalive_worker(struct work_struct
*work
)
290 struct rxrpc_net
*rxnet
=
291 container_of(work
, struct rxrpc_net
, peer_keepalive_work
);
292 const u8 mask
= ARRAY_SIZE(rxnet
->peer_keepalive
) - 1;
293 time64_t base
, now
, delay
;
295 LIST_HEAD(collector
);
297 now
= ktime_get_seconds();
298 base
= rxnet
->peer_keepalive_base
;
299 cursor
= rxnet
->peer_keepalive_cursor
;
300 _enter("%lld,%u", base
- now
, cursor
);
305 /* Remove to a temporary list all the peers that are currently lodged
306 * in expired buckets plus all new peers.
308 * Everything in the bucket at the cursor is processed this
309 * second; the bucket at cursor + 1 goes at now + 1s and so
312 spin_lock(&rxnet
->peer_hash_lock
);
313 list_splice_init(&rxnet
->peer_keepalive_new
, &collector
);
315 stop
= cursor
+ ARRAY_SIZE(rxnet
->peer_keepalive
);
316 while (base
<= now
&& (s8
)(cursor
- stop
) < 0) {
317 list_splice_tail_init(&rxnet
->peer_keepalive
[cursor
& mask
],
324 spin_unlock(&rxnet
->peer_hash_lock
);
326 rxnet
->peer_keepalive_base
= base
;
327 rxnet
->peer_keepalive_cursor
= cursor
;
328 rxrpc_peer_keepalive_dispatch(rxnet
, &collector
, base
, cursor
);
329 ASSERT(list_empty(&collector
));
331 /* Schedule the timer for the next occupied timeslot. */
332 cursor
= rxnet
->peer_keepalive_cursor
;
333 stop
= cursor
+ RXRPC_KEEPALIVE_TIME
- 1;
334 for (; (s8
)(cursor
- stop
) < 0; cursor
++) {
335 if (!list_empty(&rxnet
->peer_keepalive
[cursor
& mask
]))
340 now
= ktime_get_seconds();
346 timer_reduce(&rxnet
->peer_keepalive_timer
, jiffies
+ delay
);