1 /* RxRPC remote transport endpoint record management
3 * Copyright (C) 2007, 2016 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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.
12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14 #include <linux/module.h>
15 #include <linux/net.h>
16 #include <linux/skbuff.h>
17 #include <linux/udp.h>
19 #include <linux/in6.h>
20 #include <linux/slab.h>
21 #include <linux/hashtable.h>
23 #include <net/af_rxrpc.h>
25 #include <net/route.h>
26 #include <net/ip6_route.h>
27 #include "ar-internal.h"
29 static DEFINE_HASHTABLE(rxrpc_peer_hash
, 10);
30 static DEFINE_SPINLOCK(rxrpc_peer_hash_lock
);
35 static unsigned long rxrpc_peer_hash_key(struct rxrpc_local
*local
,
36 const struct sockaddr_rxrpc
*srx
)
40 unsigned long hash_key
;
44 hash_key
= (unsigned long)local
/ __alignof__(*local
);
45 hash_key
+= srx
->transport_type
;
46 hash_key
+= srx
->transport_len
;
47 hash_key
+= srx
->transport
.family
;
49 switch (srx
->transport
.family
) {
51 hash_key
+= (u16 __force
)srx
->transport
.sin
.sin_port
;
52 size
= sizeof(srx
->transport
.sin
.sin_addr
);
53 p
= (u16
*)&srx
->transport
.sin
.sin_addr
;
56 hash_key
+= (u16 __force
)srx
->transport
.sin
.sin_port
;
57 size
= sizeof(srx
->transport
.sin6
.sin6_addr
);
58 p
= (u16
*)&srx
->transport
.sin6
.sin6_addr
;
61 WARN(1, "AF_RXRPC: Unsupported transport address family\n");
65 /* Step through the peer address in 16-bit portions for speed */
66 for (i
= 0; i
< size
; i
+= sizeof(*p
), p
++)
69 _leave(" 0x%lx", hash_key
);
74 * Compare a peer to a key. Return -ve, 0 or +ve to indicate less than, same
77 * Unfortunately, the primitives in linux/hashtable.h don't allow for sorted
78 * buckets and mid-bucket insertion, so we don't make full use of this
79 * information at this point.
81 static long rxrpc_peer_cmp_key(const struct rxrpc_peer
*peer
,
82 struct rxrpc_local
*local
,
83 const struct sockaddr_rxrpc
*srx
,
84 unsigned long hash_key
)
88 diff
= ((peer
->hash_key
- hash_key
) ?:
89 ((unsigned long)peer
->local
- (unsigned long)local
) ?:
90 (peer
->srx
.transport_type
- srx
->transport_type
) ?:
91 (peer
->srx
.transport_len
- srx
->transport_len
) ?:
92 (peer
->srx
.transport
.family
- srx
->transport
.family
));
96 switch (srx
->transport
.family
) {
98 return ((u16 __force
)peer
->srx
.transport
.sin
.sin_port
-
99 (u16 __force
)srx
->transport
.sin
.sin_port
) ?:
100 memcmp(&peer
->srx
.transport
.sin
.sin_addr
,
101 &srx
->transport
.sin
.sin_addr
,
102 sizeof(struct in_addr
));
104 return ((u16 __force
)peer
->srx
.transport
.sin6
.sin6_port
-
105 (u16 __force
)srx
->transport
.sin6
.sin6_port
) ?:
106 memcmp(&peer
->srx
.transport
.sin6
.sin6_addr
,
107 &srx
->transport
.sin6
.sin6_addr
,
108 sizeof(struct in6_addr
));
115 * Look up a remote transport endpoint for the specified address using RCU.
117 static struct rxrpc_peer
*__rxrpc_lookup_peer_rcu(
118 struct rxrpc_local
*local
,
119 const struct sockaddr_rxrpc
*srx
,
120 unsigned long hash_key
)
122 struct rxrpc_peer
*peer
;
124 hash_for_each_possible_rcu(rxrpc_peer_hash
, peer
, hash_link
, hash_key
) {
125 if (rxrpc_peer_cmp_key(peer
, local
, srx
, hash_key
) == 0) {
126 if (atomic_read(&peer
->usage
) == 0)
136 * Look up a remote transport endpoint for the specified address using RCU.
138 struct rxrpc_peer
*rxrpc_lookup_peer_rcu(struct rxrpc_local
*local
,
139 const struct sockaddr_rxrpc
*srx
)
141 struct rxrpc_peer
*peer
;
142 unsigned long hash_key
= rxrpc_peer_hash_key(local
, srx
);
144 peer
= __rxrpc_lookup_peer_rcu(local
, srx
, hash_key
);
146 _net("PEER %d {%pISp}", peer
->debug_id
, &peer
->srx
.transport
);
147 _leave(" = %p {u=%d}", peer
, atomic_read(&peer
->usage
));
153 * assess the MTU size for the network interface through which this peer is
156 static void rxrpc_assess_MTU_size(struct rxrpc_peer
*peer
)
158 struct dst_entry
*dst
;
161 struct flowi4
*fl4
= &fl
.u
.ip4
;
162 struct flowi6
*fl6
= &fl
.u
.ip6
;
166 memset(&fl
, 0, sizeof(fl
));
167 switch (peer
->srx
.transport
.family
) {
169 rt
= ip_route_output_ports(
170 &init_net
, fl4
, NULL
,
171 peer
->srx
.transport
.sin
.sin_addr
.s_addr
, 0,
172 htons(7000), htons(7001), IPPROTO_UDP
, 0, 0);
174 _leave(" [route err %ld]", PTR_ERR(rt
));
181 fl6
->flowi6_iif
= LOOPBACK_IFINDEX
;
182 fl6
->flowi6_scope
= RT_SCOPE_UNIVERSE
;
183 fl6
->flowi6_proto
= IPPROTO_UDP
;
184 memcpy(&fl6
->daddr
, &peer
->srx
.transport
.sin6
.sin6_addr
,
185 sizeof(struct in6_addr
));
186 fl6
->fl6_dport
= htons(7001);
187 fl6
->fl6_sport
= htons(7000);
188 dst
= ip6_route_output(&init_net
, NULL
, fl6
);
190 _leave(" [route err %ld]", PTR_ERR(dst
));
199 peer
->if_mtu
= dst_mtu(dst
);
202 _leave(" [if_mtu %u]", peer
->if_mtu
);
208 struct rxrpc_peer
*rxrpc_alloc_peer(struct rxrpc_local
*local
, gfp_t gfp
)
210 struct rxrpc_peer
*peer
;
214 peer
= kzalloc(sizeof(struct rxrpc_peer
), gfp
);
216 atomic_set(&peer
->usage
, 1);
218 INIT_HLIST_HEAD(&peer
->error_targets
);
219 INIT_WORK(&peer
->error_distributor
,
220 &rxrpc_peer_error_distributor
);
221 peer
->service_conns
= RB_ROOT
;
222 seqlock_init(&peer
->service_conn_lock
);
223 spin_lock_init(&peer
->lock
);
224 peer
->debug_id
= atomic_inc_return(&rxrpc_debug_id
);
227 _leave(" = %p", peer
);
232 * Initialise peer record.
234 static void rxrpc_init_peer(struct rxrpc_peer
*peer
, unsigned long hash_key
)
236 peer
->hash_key
= hash_key
;
237 rxrpc_assess_MTU_size(peer
);
238 peer
->mtu
= peer
->if_mtu
;
240 switch (peer
->srx
.transport
.family
) {
242 peer
->hdrsize
= sizeof(struct iphdr
);
245 peer
->hdrsize
= sizeof(struct ipv6hdr
);
251 switch (peer
->srx
.transport_type
) {
253 peer
->hdrsize
+= sizeof(struct udphdr
);
259 peer
->hdrsize
+= sizeof(struct rxrpc_wire_header
);
260 peer
->maxdata
= peer
->mtu
- peer
->hdrsize
;
266 static struct rxrpc_peer
*rxrpc_create_peer(struct rxrpc_local
*local
,
267 struct sockaddr_rxrpc
*srx
,
268 unsigned long hash_key
,
271 struct rxrpc_peer
*peer
;
275 peer
= rxrpc_alloc_peer(local
, gfp
);
277 memcpy(&peer
->srx
, srx
, sizeof(*srx
));
278 rxrpc_init_peer(peer
, hash_key
);
281 _leave(" = %p", peer
);
286 * Set up a new incoming peer. The address is prestored in the preallocated
289 struct rxrpc_peer
*rxrpc_lookup_incoming_peer(struct rxrpc_local
*local
,
290 struct rxrpc_peer
*prealloc
)
292 struct rxrpc_peer
*peer
;
293 unsigned long hash_key
;
295 hash_key
= rxrpc_peer_hash_key(local
, &prealloc
->srx
);
296 prealloc
->local
= local
;
297 rxrpc_init_peer(prealloc
, hash_key
);
299 spin_lock(&rxrpc_peer_hash_lock
);
301 /* Need to check that we aren't racing with someone else */
302 peer
= __rxrpc_lookup_peer_rcu(local
, &prealloc
->srx
, hash_key
);
303 if (peer
&& !rxrpc_get_peer_maybe(peer
))
307 hash_add_rcu(rxrpc_peer_hash
, &peer
->hash_link
, hash_key
);
310 spin_unlock(&rxrpc_peer_hash_lock
);
315 * obtain a remote transport endpoint for the specified address
317 struct rxrpc_peer
*rxrpc_lookup_peer(struct rxrpc_local
*local
,
318 struct sockaddr_rxrpc
*srx
, gfp_t gfp
)
320 struct rxrpc_peer
*peer
, *candidate
;
321 unsigned long hash_key
= rxrpc_peer_hash_key(local
, srx
);
323 _enter("{%pISp}", &srx
->transport
);
325 /* search the peer list first */
327 peer
= __rxrpc_lookup_peer_rcu(local
, srx
, hash_key
);
328 if (peer
&& !rxrpc_get_peer_maybe(peer
))
333 /* The peer is not yet present in hash - create a candidate
334 * for a new record and then redo the search.
336 candidate
= rxrpc_create_peer(local
, srx
, hash_key
, gfp
);
338 _leave(" = NULL [nomem]");
342 spin_lock_bh(&rxrpc_peer_hash_lock
);
344 /* Need to check that we aren't racing with someone else */
345 peer
= __rxrpc_lookup_peer_rcu(local
, srx
, hash_key
);
346 if (peer
&& !rxrpc_get_peer_maybe(peer
))
349 hash_add_rcu(rxrpc_peer_hash
,
350 &candidate
->hash_link
, hash_key
);
352 spin_unlock_bh(&rxrpc_peer_hash_lock
);
360 _net("PEER %d {%pISp}", peer
->debug_id
, &peer
->srx
.transport
);
362 _leave(" = %p {u=%d}", peer
, atomic_read(&peer
->usage
));
367 * Discard a ref on a remote peer record.
369 void __rxrpc_put_peer(struct rxrpc_peer
*peer
)
371 ASSERT(hlist_empty(&peer
->error_targets
));
373 spin_lock_bh(&rxrpc_peer_hash_lock
);
374 hash_del_rcu(&peer
->hash_link
);
375 spin_unlock_bh(&rxrpc_peer_hash_lock
);
377 kfree_rcu(peer
, rcu
);
381 * rxrpc_kernel_get_peer - Get the peer address of a call
382 * @sock: The socket on which the call is in progress.
383 * @call: The call to query
384 * @_srx: Where to place the result
386 * Get the address of the remote peer in a call.
388 void rxrpc_kernel_get_peer(struct socket
*sock
, struct rxrpc_call
*call
,
389 struct sockaddr_rxrpc
*_srx
)
391 *_srx
= call
->peer
->srx
;
393 EXPORT_SYMBOL(rxrpc_kernel_get_peer
);