12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
217926a79SDavid Howells /* AF_RXRPC implementation
317926a79SDavid Howells *
417926a79SDavid Howells * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
517926a79SDavid Howells * Written by David Howells (dhowells@redhat.com)
617926a79SDavid Howells */
717926a79SDavid Howells
89b6d5398SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
99b6d5398SJoe Perches
1017926a79SDavid Howells #include <linux/module.h>
11ce6654cfSYOSHIFUJI Hideaki / 吉藤英明 #include <linux/kernel.h>
1217926a79SDavid Howells #include <linux/net.h>
135a0e3ad6STejun Heo #include <linux/slab.h>
1417926a79SDavid Howells #include <linux/skbuff.h>
155f2d9c44SDavid Howells #include <linux/random.h>
1617926a79SDavid Howells #include <linux/poll.h>
1717926a79SDavid Howells #include <linux/proc_fs.h>
1876181c13SDavid Howells #include <linux/key-type.h>
19457c4cbcSEric W. Biederman #include <net/net_namespace.h>
2017926a79SDavid Howells #include <net/sock.h>
2117926a79SDavid Howells #include <net/af_rxrpc.h>
22df844fd4SDavid Howells #define CREATE_TRACE_POINTS
2317926a79SDavid Howells #include "ar-internal.h"
2417926a79SDavid Howells
2517926a79SDavid Howells MODULE_DESCRIPTION("RxRPC network protocol");
2617926a79SDavid Howells MODULE_AUTHOR("Red Hat, Inc.");
2717926a79SDavid Howells MODULE_LICENSE("GPL");
2817926a79SDavid Howells MODULE_ALIAS_NETPROTO(PF_RXRPC);
2917926a79SDavid Howells
3095c96174SEric Dumazet unsigned int rxrpc_debug; // = RXRPC_DEBUG_KPROTO;
31d6444062SJoe Perches module_param_named(debug, rxrpc_debug, uint, 0644);
32424b00e2SPaul Bolle MODULE_PARM_DESC(debug, "RxRPC debugging mask");
3317926a79SDavid Howells
3417926a79SDavid Howells static struct proto rxrpc_proto;
3517926a79SDavid Howells static const struct proto_ops rxrpc_rpc_ops;
3617926a79SDavid Howells
3717926a79SDavid Howells /* current debugging ID */
3817926a79SDavid Howells atomic_t rxrpc_debug_id;
39a25e21f0SDavid Howells EXPORT_SYMBOL(rxrpc_debug_id);
4017926a79SDavid Howells
4117926a79SDavid Howells /* count of skbs currently in use */
42a4ea4c47SDavid Howells atomic_t rxrpc_n_rx_skbs;
4317926a79SDavid Howells
44651350d1SDavid Howells struct workqueue_struct *rxrpc_workqueue;
45651350d1SDavid Howells
4617926a79SDavid Howells static void rxrpc_sock_destructor(struct sock *);
4717926a79SDavid Howells
4817926a79SDavid Howells /*
4917926a79SDavid Howells * see if an RxRPC socket is currently writable
5017926a79SDavid Howells */
rxrpc_writable(struct sock * sk)5117926a79SDavid Howells static inline int rxrpc_writable(struct sock *sk)
5217926a79SDavid Howells {
5314afee4bSReshetova, Elena return refcount_read(&sk->sk_wmem_alloc) < (size_t) sk->sk_sndbuf;
5417926a79SDavid Howells }
5517926a79SDavid Howells
5617926a79SDavid Howells /*
5717926a79SDavid Howells * wait for write bufferage to become available
5817926a79SDavid Howells */
rxrpc_write_space(struct sock * sk)5917926a79SDavid Howells static void rxrpc_write_space(struct sock *sk)
6017926a79SDavid Howells {
6117926a79SDavid Howells _enter("%p", sk);
6243815482SEric Dumazet rcu_read_lock();
6317926a79SDavid Howells if (rxrpc_writable(sk)) {
6443815482SEric Dumazet struct socket_wq *wq = rcu_dereference(sk->sk_wq);
6543815482SEric Dumazet
661ce0bf50SHerbert Xu if (skwq_has_sleeper(wq))
6743815482SEric Dumazet wake_up_interruptible(&wq->wait);
688d8ad9d7SPavel Emelyanov sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
6917926a79SDavid Howells }
7043815482SEric Dumazet rcu_read_unlock();
7117926a79SDavid Howells }
7217926a79SDavid Howells
7317926a79SDavid Howells /*
7417926a79SDavid Howells * validate an RxRPC address
7517926a79SDavid Howells */
rxrpc_validate_address(struct rxrpc_sock * rx,struct sockaddr_rxrpc * srx,int len)7617926a79SDavid Howells static int rxrpc_validate_address(struct rxrpc_sock *rx,
7717926a79SDavid Howells struct sockaddr_rxrpc *srx,
7817926a79SDavid Howells int len)
7917926a79SDavid Howells {
80dad8aff7SDavid Howells unsigned int tail;
81ab802ee0SDavid Howells
8217926a79SDavid Howells if (len < sizeof(struct sockaddr_rxrpc))
8317926a79SDavid Howells return -EINVAL;
8417926a79SDavid Howells
8517926a79SDavid Howells if (srx->srx_family != AF_RXRPC)
8617926a79SDavid Howells return -EAFNOSUPPORT;
8717926a79SDavid Howells
8817926a79SDavid Howells if (srx->transport_type != SOCK_DGRAM)
8917926a79SDavid Howells return -ESOCKTNOSUPPORT;
9017926a79SDavid Howells
9117926a79SDavid Howells len -= offsetof(struct sockaddr_rxrpc, transport);
9217926a79SDavid Howells if (srx->transport_len < sizeof(sa_family_t) ||
9317926a79SDavid Howells srx->transport_len > len)
9417926a79SDavid Howells return -EINVAL;
9517926a79SDavid Howells
9617926a79SDavid Howells switch (srx->transport.family) {
9717926a79SDavid Howells case AF_INET:
9866f6fd27SDavid Howells if (rx->family != AF_INET &&
9966f6fd27SDavid Howells rx->family != AF_INET6)
10066f6fd27SDavid Howells return -EAFNOSUPPORT;
1014f95dd78SDavid Howells if (srx->transport_len < sizeof(struct sockaddr_in))
1024f95dd78SDavid Howells return -EINVAL;
103ab802ee0SDavid Howells tail = offsetof(struct sockaddr_rxrpc, transport.sin.__pad);
10417926a79SDavid Howells break;
10517926a79SDavid Howells
106d1912747SDavid Howells #ifdef CONFIG_AF_RXRPC_IPV6
10717926a79SDavid Howells case AF_INET6:
10866f6fd27SDavid Howells if (rx->family != AF_INET6)
10966f6fd27SDavid Howells return -EAFNOSUPPORT;
11075b54cb5SDavid Howells if (srx->transport_len < sizeof(struct sockaddr_in6))
11175b54cb5SDavid Howells return -EINVAL;
11275b54cb5SDavid Howells tail = offsetof(struct sockaddr_rxrpc, transport) +
11375b54cb5SDavid Howells sizeof(struct sockaddr_in6);
11475b54cb5SDavid Howells break;
115d1912747SDavid Howells #endif
11675b54cb5SDavid Howells
11717926a79SDavid Howells default:
11817926a79SDavid Howells return -EAFNOSUPPORT;
11917926a79SDavid Howells }
12017926a79SDavid Howells
121ab802ee0SDavid Howells if (tail < len)
122ab802ee0SDavid Howells memset((void *)srx + tail, 0, len - tail);
12375b54cb5SDavid Howells _debug("INET: %pISp", &srx->transport);
12417926a79SDavid Howells return 0;
12517926a79SDavid Howells }
12617926a79SDavid Howells
12717926a79SDavid Howells /*
12817926a79SDavid Howells * bind a local address to an RxRPC socket
12917926a79SDavid Howells */
rxrpc_bind(struct socket * sock,struct sockaddr * saddr,int len)13017926a79SDavid Howells static int rxrpc_bind(struct socket *sock, struct sockaddr *saddr, int len)
13117926a79SDavid Howells {
13217926a79SDavid Howells struct sockaddr_rxrpc *srx = (struct sockaddr_rxrpc *)saddr;
13317926a79SDavid Howells struct rxrpc_local *local;
13468d6d1aeSDavid Howells struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
135a9107a14STetsuo Handa u16 service_id;
13617926a79SDavid Howells int ret;
13717926a79SDavid Howells
13817926a79SDavid Howells _enter("%p,%p,%d", rx, saddr, len);
13917926a79SDavid Howells
14017926a79SDavid Howells ret = rxrpc_validate_address(rx, srx, len);
14117926a79SDavid Howells if (ret < 0)
14217926a79SDavid Howells goto error;
143a9107a14STetsuo Handa service_id = srx->srx_service;
14417926a79SDavid Howells
14517926a79SDavid Howells lock_sock(&rx->sk);
14617926a79SDavid Howells
14728036f44SDavid Howells switch (rx->sk.sk_state) {
14828036f44SDavid Howells case RXRPC_UNBOUND:
14928036f44SDavid Howells rx->srx = *srx;
15068d6d1aeSDavid Howells local = rxrpc_lookup_local(sock_net(&rx->sk), &rx->srx);
15117926a79SDavid Howells if (IS_ERR(local)) {
15217926a79SDavid Howells ret = PTR_ERR(local);
15317926a79SDavid Howells goto error_unlock;
15417926a79SDavid Howells }
15517926a79SDavid Howells
1561e9e5c95SDavid Howells if (service_id) {
157248f219cSDavid Howells write_lock(&local->services_lock);
15842f229c3SDavid Howells if (local->service)
15917926a79SDavid Howells goto service_in_use;
1602341e077SDavid Howells rx->local = local;
16142f229c3SDavid Howells local->service = rx;
162248f219cSDavid Howells write_unlock(&local->services_lock);
16317926a79SDavid Howells
16417926a79SDavid Howells rx->sk.sk_state = RXRPC_SERVER_BOUND;
16517926a79SDavid Howells } else {
1662341e077SDavid Howells rx->local = local;
16717926a79SDavid Howells rx->sk.sk_state = RXRPC_CLIENT_BOUND;
16817926a79SDavid Howells }
16928036f44SDavid Howells break;
17028036f44SDavid Howells
17128036f44SDavid Howells case RXRPC_SERVER_BOUND:
17228036f44SDavid Howells ret = -EINVAL;
17328036f44SDavid Howells if (service_id == 0)
17428036f44SDavid Howells goto error_unlock;
17528036f44SDavid Howells ret = -EADDRINUSE;
17628036f44SDavid Howells if (service_id == rx->srx.srx_service)
17728036f44SDavid Howells goto error_unlock;
17828036f44SDavid Howells ret = -EINVAL;
17928036f44SDavid Howells srx->srx_service = rx->srx.srx_service;
18028036f44SDavid Howells if (memcmp(srx, &rx->srx, sizeof(*srx)) != 0)
18128036f44SDavid Howells goto error_unlock;
18228036f44SDavid Howells rx->second_service = service_id;
18328036f44SDavid Howells rx->sk.sk_state = RXRPC_SERVER_BOUND2;
18428036f44SDavid Howells break;
18528036f44SDavid Howells
18628036f44SDavid Howells default:
18728036f44SDavid Howells ret = -EINVAL;
18828036f44SDavid Howells goto error_unlock;
18928036f44SDavid Howells }
19017926a79SDavid Howells
19117926a79SDavid Howells release_sock(&rx->sk);
19217926a79SDavid Howells _leave(" = 0");
19317926a79SDavid Howells return 0;
19417926a79SDavid Howells
19517926a79SDavid Howells service_in_use:
196248f219cSDavid Howells write_unlock(&local->services_lock);
1970fde882fSDavid Howells rxrpc_unuse_local(local, rxrpc_local_unuse_bind);
1980fde882fSDavid Howells rxrpc_put_local(local, rxrpc_local_put_bind);
1992341e077SDavid Howells ret = -EADDRINUSE;
20017926a79SDavid Howells error_unlock:
20117926a79SDavid Howells release_sock(&rx->sk);
20217926a79SDavid Howells error:
20317926a79SDavid Howells _leave(" = %d", ret);
20417926a79SDavid Howells return ret;
20517926a79SDavid Howells }
20617926a79SDavid Howells
20717926a79SDavid Howells /*
20817926a79SDavid Howells * set the number of pending calls permitted on a listening socket
20917926a79SDavid Howells */
rxrpc_listen(struct socket * sock,int backlog)21017926a79SDavid Howells static int rxrpc_listen(struct socket *sock, int backlog)
21117926a79SDavid Howells {
21217926a79SDavid Howells struct sock *sk = sock->sk;
21317926a79SDavid Howells struct rxrpc_sock *rx = rxrpc_sk(sk);
21400e90712SDavid Howells unsigned int max, old;
21517926a79SDavid Howells int ret;
21617926a79SDavid Howells
21717926a79SDavid Howells _enter("%p,%d", rx, backlog);
21817926a79SDavid Howells
21917926a79SDavid Howells lock_sock(&rx->sk);
22017926a79SDavid Howells
22117926a79SDavid Howells switch (rx->sk.sk_state) {
2222341e077SDavid Howells case RXRPC_UNBOUND:
22317926a79SDavid Howells ret = -EADDRNOTAVAIL;
22417926a79SDavid Howells break;
22517926a79SDavid Howells case RXRPC_SERVER_BOUND:
22628036f44SDavid Howells case RXRPC_SERVER_BOUND2:
22717926a79SDavid Howells ASSERT(rx->local != NULL);
2280e119b41SDavid Howells max = READ_ONCE(rxrpc_max_backlog);
2290e119b41SDavid Howells ret = -EINVAL;
2300e119b41SDavid Howells if (backlog == INT_MAX)
2310e119b41SDavid Howells backlog = max;
2320e119b41SDavid Howells else if (backlog < 0 || backlog > max)
2330e119b41SDavid Howells break;
23400e90712SDavid Howells old = sk->sk_max_ack_backlog;
23517926a79SDavid Howells sk->sk_max_ack_backlog = backlog;
23600e90712SDavid Howells ret = rxrpc_service_prealloc(rx, GFP_KERNEL);
23700e90712SDavid Howells if (ret == 0)
23817926a79SDavid Howells rx->sk.sk_state = RXRPC_SERVER_LISTENING;
23900e90712SDavid Howells else
24000e90712SDavid Howells sk->sk_max_ack_backlog = old;
24117926a79SDavid Howells break;
242210f0353SDavid Howells case RXRPC_SERVER_LISTENING:
243210f0353SDavid Howells if (backlog == 0) {
244210f0353SDavid Howells rx->sk.sk_state = RXRPC_SERVER_LISTEN_DISABLED;
245210f0353SDavid Howells sk->sk_max_ack_backlog = 0;
246210f0353SDavid Howells rxrpc_discard_prealloc(rx);
247210f0353SDavid Howells ret = 0;
248210f0353SDavid Howells break;
249210f0353SDavid Howells }
250df561f66SGustavo A. R. Silva fallthrough;
2510e119b41SDavid Howells default:
2520e119b41SDavid Howells ret = -EBUSY;
2530e119b41SDavid Howells break;
25417926a79SDavid Howells }
25517926a79SDavid Howells
25617926a79SDavid Howells release_sock(&rx->sk);
25717926a79SDavid Howells _leave(" = %d", ret);
25817926a79SDavid Howells return ret;
25917926a79SDavid Howells }
26017926a79SDavid Howells
261651350d1SDavid Howells /**
262651350d1SDavid Howells * rxrpc_kernel_begin_call - Allow a kernel service to begin a call
263651350d1SDavid Howells * @sock: The socket on which to make the call
2642341e077SDavid Howells * @srx: The address of the peer to contact
265651350d1SDavid Howells * @key: The security context to use (defaults to socket setting)
266651350d1SDavid Howells * @user_call_ID: The ID to use
267e754eba6SDavid Howells * @tx_total_len: Total length of data to transmit during the call (or -1)
268db099c62SDavid Howells * @hard_timeout: The maximum lifespan of the call in sec
269d001648eSDavid Howells * @gfp: The allocation constraints
270d001648eSDavid Howells * @notify_rx: Where to send notifications instead of socket queue
271a68f4a27SDavid Howells * @upgrade: Request service upgrade for call
27276f2fe73SAndrew Lunn * @interruptibility: The call is interruptible, or can be canceled.
273a25e21f0SDavid Howells * @debug_id: The debug ID for tracing to be assigned to the call
274651350d1SDavid Howells *
275651350d1SDavid Howells * Allow a kernel service to begin a call on the nominated socket. This just
276651350d1SDavid Howells * sets up all the internal tracking structures and allocates connection and
277651350d1SDavid Howells * call IDs as appropriate. The call to be used is returned.
278651350d1SDavid Howells *
279651350d1SDavid Howells * The default socket destination address and security may be overridden by
280651350d1SDavid Howells * supplying @srx and @key.
281651350d1SDavid Howells */
rxrpc_kernel_begin_call(struct socket * sock,struct sockaddr_rxrpc * srx,struct key * key,unsigned long user_call_ID,s64 tx_total_len,u32 hard_timeout,gfp_t gfp,rxrpc_notify_rx_t notify_rx,bool upgrade,enum rxrpc_interruptibility interruptibility,unsigned int debug_id)282651350d1SDavid Howells struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
283651350d1SDavid Howells struct sockaddr_rxrpc *srx,
284651350d1SDavid Howells struct key *key,
285651350d1SDavid Howells unsigned long user_call_ID,
286e754eba6SDavid Howells s64 tx_total_len,
287db099c62SDavid Howells u32 hard_timeout,
288d001648eSDavid Howells gfp_t gfp,
289a68f4a27SDavid Howells rxrpc_notify_rx_t notify_rx,
290a25e21f0SDavid Howells bool upgrade,
291e138aa7dSDavid Howells enum rxrpc_interruptibility interruptibility,
292a25e21f0SDavid Howells unsigned int debug_id)
293651350d1SDavid Howells {
29419ffa01cSDavid Howells struct rxrpc_conn_parameters cp;
29548124178SDavid Howells struct rxrpc_call_params p;
296651350d1SDavid Howells struct rxrpc_call *call;
297651350d1SDavid Howells struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
298f4552c2dSDavid Howells int ret;
299651350d1SDavid Howells
300651350d1SDavid Howells _enter(",,%x,%lx", key_serial(key), user_call_ID);
301651350d1SDavid Howells
302f4552c2dSDavid Howells ret = rxrpc_validate_address(rx, srx, sizeof(*srx));
303f4552c2dSDavid Howells if (ret < 0)
304f4552c2dSDavid Howells return ERR_PTR(ret);
305f4552c2dSDavid Howells
306651350d1SDavid Howells lock_sock(&rx->sk);
307651350d1SDavid Howells
30819ffa01cSDavid Howells if (!key)
30919ffa01cSDavid Howells key = rx->key;
31019ffa01cSDavid Howells if (key && !key->payload.data[0])
31119ffa01cSDavid Howells key = NULL; /* a no-security key */
31219ffa01cSDavid Howells
31348124178SDavid Howells memset(&p, 0, sizeof(p));
31448124178SDavid Howells p.user_call_ID = user_call_ID;
31548124178SDavid Howells p.tx_total_len = tx_total_len;
316e138aa7dSDavid Howells p.interruptibility = interruptibility;
317b7a7d674SDavid Howells p.kernel = true;
318db099c62SDavid Howells p.timeouts.hard = hard_timeout;
31948124178SDavid Howells
32019ffa01cSDavid Howells memset(&cp, 0, sizeof(cp));
32119ffa01cSDavid Howells cp.local = rx->local;
32219ffa01cSDavid Howells cp.key = key;
32393864fc3SDavid Howells cp.security_level = rx->min_sec_level;
32419ffa01cSDavid Howells cp.exclusive = false;
325a68f4a27SDavid Howells cp.upgrade = upgrade;
32619ffa01cSDavid Howells cp.service_id = srx->srx_service;
327a25e21f0SDavid Howells call = rxrpc_new_client_call(rx, &cp, srx, &p, gfp, debug_id);
328540b1c48SDavid Howells /* The socket has been unlocked. */
3296cb3ece9SDavid Howells if (!IS_ERR(call)) {
330d001648eSDavid Howells call->notify_rx = notify_rx;
331540b1c48SDavid Howells mutex_unlock(&call->user_mutex);
3326cb3ece9SDavid Howells }
3336cb3ece9SDavid Howells
334651350d1SDavid Howells _leave(" = %p", call);
335651350d1SDavid Howells return call;
336651350d1SDavid Howells }
337651350d1SDavid Howells EXPORT_SYMBOL(rxrpc_kernel_begin_call);
338651350d1SDavid Howells
33920acbd9aSDavid Howells /*
34020acbd9aSDavid Howells * Dummy function used to stop the notifier talking to recvmsg().
34120acbd9aSDavid Howells */
rxrpc_dummy_notify_rx(struct sock * sk,struct rxrpc_call * rxcall,unsigned long call_user_ID)34220acbd9aSDavid Howells static void rxrpc_dummy_notify_rx(struct sock *sk, struct rxrpc_call *rxcall,
34320acbd9aSDavid Howells unsigned long call_user_ID)
34420acbd9aSDavid Howells {
34520acbd9aSDavid Howells }
34620acbd9aSDavid Howells
347651350d1SDavid Howells /**
348e0416e7dSDavid Howells * rxrpc_kernel_shutdown_call - Allow a kernel service to shut down a call it was using
3494de48af6SDavid Howells * @sock: The socket the call is on
350651350d1SDavid Howells * @call: The call to end
351651350d1SDavid Howells *
352e0416e7dSDavid Howells * Allow a kernel service to shut down a call it was using. The call must be
353651350d1SDavid Howells * complete before this is called (the call should be aborted if necessary).
354651350d1SDavid Howells */
rxrpc_kernel_shutdown_call(struct socket * sock,struct rxrpc_call * call)355e0416e7dSDavid Howells void rxrpc_kernel_shutdown_call(struct socket *sock, struct rxrpc_call *call)
356651350d1SDavid Howells {
357a0575429SDavid Howells _enter("%d{%d}", call->debug_id, refcount_read(&call->ref));
358540b1c48SDavid Howells
359540b1c48SDavid Howells mutex_lock(&call->user_mutex);
360e0416e7dSDavid Howells if (!test_bit(RXRPC_CALL_RELEASED, &call->flags)) {
3618d94aa38SDavid Howells rxrpc_release_call(rxrpc_sk(sock->sk), call);
36220acbd9aSDavid Howells
36320acbd9aSDavid Howells /* Make sure we're not going to call back into a kernel service */
36420acbd9aSDavid Howells if (call->notify_rx) {
3653dd9c8b5SDavid Howells spin_lock(&call->notify_lock);
36620acbd9aSDavid Howells call->notify_rx = rxrpc_dummy_notify_rx;
3673dd9c8b5SDavid Howells spin_unlock(&call->notify_lock);
36820acbd9aSDavid Howells }
369e0416e7dSDavid Howells }
370540b1c48SDavid Howells mutex_unlock(&call->user_mutex);
371e0416e7dSDavid Howells }
372e0416e7dSDavid Howells EXPORT_SYMBOL(rxrpc_kernel_shutdown_call);
373e0416e7dSDavid Howells
374e0416e7dSDavid Howells /**
375e0416e7dSDavid Howells * rxrpc_kernel_put_call - Release a reference to a call
376e0416e7dSDavid Howells * @sock: The socket the call is on
377e0416e7dSDavid Howells * @call: The call to put
378e0416e7dSDavid Howells *
379e0416e7dSDavid Howells * Drop the application's ref on an rxrpc call.
380e0416e7dSDavid Howells */
rxrpc_kernel_put_call(struct socket * sock,struct rxrpc_call * call)381e0416e7dSDavid Howells void rxrpc_kernel_put_call(struct socket *sock, struct rxrpc_call *call)
382e0416e7dSDavid Howells {
383cbd00891SDavid Howells rxrpc_put_call(call, rxrpc_call_put_kernel);
384651350d1SDavid Howells }
385e0416e7dSDavid Howells EXPORT_SYMBOL(rxrpc_kernel_put_call);
386651350d1SDavid Howells
387651350d1SDavid Howells /**
388f4d15fb6SDavid Howells * rxrpc_kernel_check_life - Check to see whether a call is still alive
389f4d15fb6SDavid Howells * @sock: The socket the call is on
390f4d15fb6SDavid Howells * @call: The call to check
391f4d15fb6SDavid Howells *
39293368b6bSDavid Howells * Allow a kernel service to find out whether a call is still alive - whether
39393368b6bSDavid Howells * it has completed successfully and all received data has been consumed.
394f4d15fb6SDavid Howells */
rxrpc_kernel_check_life(const struct socket * sock,const struct rxrpc_call * call)3954611da30SMarc Dionne bool rxrpc_kernel_check_life(const struct socket *sock,
3967d7587dbSDavid Howells const struct rxrpc_call *call)
397f4d15fb6SDavid Howells {
39893368b6bSDavid Howells if (!rxrpc_call_is_complete(call))
39993368b6bSDavid Howells return true;
40093368b6bSDavid Howells if (call->completion != RXRPC_CALL_SUCCEEDED)
40193368b6bSDavid Howells return false;
40293368b6bSDavid Howells return !skb_queue_empty(&call->recvmsg_queue);
403f4d15fb6SDavid Howells }
404f4d15fb6SDavid Howells EXPORT_SYMBOL(rxrpc_kernel_check_life);
405f4d15fb6SDavid Howells
406f4d15fb6SDavid Howells /**
407e908bcf4SDavid Howells * rxrpc_kernel_get_epoch - Retrieve the epoch value from a call.
408e908bcf4SDavid Howells * @sock: The socket the call is on
409e908bcf4SDavid Howells * @call: The call to query
410e908bcf4SDavid Howells *
411e908bcf4SDavid Howells * Allow a kernel service to retrieve the epoch value from a service call to
412e908bcf4SDavid Howells * see if the client at the other end rebooted.
413e908bcf4SDavid Howells */
rxrpc_kernel_get_epoch(struct socket * sock,struct rxrpc_call * call)414e908bcf4SDavid Howells u32 rxrpc_kernel_get_epoch(struct socket *sock, struct rxrpc_call *call)
415e908bcf4SDavid Howells {
416e908bcf4SDavid Howells return call->conn->proto.epoch;
417e908bcf4SDavid Howells }
418e908bcf4SDavid Howells EXPORT_SYMBOL(rxrpc_kernel_get_epoch);
419e908bcf4SDavid Howells
420e908bcf4SDavid Howells /**
421d001648eSDavid Howells * rxrpc_kernel_new_call_notification - Get notifications of new calls
422651350d1SDavid Howells * @sock: The socket to intercept received messages on
423d001648eSDavid Howells * @notify_new_call: Function to be called when new calls appear
42400e90712SDavid Howells * @discard_new_call: Function to discard preallocated calls
425651350d1SDavid Howells *
426d001648eSDavid Howells * Allow a kernel service to be given notifications about new calls.
427651350d1SDavid Howells */
rxrpc_kernel_new_call_notification(struct socket * sock,rxrpc_notify_new_call_t notify_new_call,rxrpc_discard_new_call_t discard_new_call)428d001648eSDavid Howells void rxrpc_kernel_new_call_notification(
429d001648eSDavid Howells struct socket *sock,
43000e90712SDavid Howells rxrpc_notify_new_call_t notify_new_call,
43100e90712SDavid Howells rxrpc_discard_new_call_t discard_new_call)
432651350d1SDavid Howells {
433651350d1SDavid Howells struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
434651350d1SDavid Howells
435d001648eSDavid Howells rx->notify_new_call = notify_new_call;
43600e90712SDavid Howells rx->discard_new_call = discard_new_call;
437651350d1SDavid Howells }
438d001648eSDavid Howells EXPORT_SYMBOL(rxrpc_kernel_new_call_notification);
439651350d1SDavid Howells
440bbd172e3SDavid Howells /**
441bbd172e3SDavid Howells * rxrpc_kernel_set_max_life - Set maximum lifespan on a call
442bbd172e3SDavid Howells * @sock: The socket the call is on
443bbd172e3SDavid Howells * @call: The call to configure
444bbd172e3SDavid Howells * @hard_timeout: The maximum lifespan of the call in jiffies
445bbd172e3SDavid Howells *
446bbd172e3SDavid Howells * Set the maximum lifespan of a call. The call will end with ETIME or
447bbd172e3SDavid Howells * ETIMEDOUT if it takes longer than this.
448bbd172e3SDavid Howells */
rxrpc_kernel_set_max_life(struct socket * sock,struct rxrpc_call * call,unsigned long hard_timeout)449bbd172e3SDavid Howells void rxrpc_kernel_set_max_life(struct socket *sock, struct rxrpc_call *call,
450bbd172e3SDavid Howells unsigned long hard_timeout)
451bbd172e3SDavid Howells {
452bbd172e3SDavid Howells unsigned long now;
453bbd172e3SDavid Howells
454bbd172e3SDavid Howells mutex_lock(&call->user_mutex);
455bbd172e3SDavid Howells
456bbd172e3SDavid Howells now = jiffies;
457bbd172e3SDavid Howells hard_timeout += now;
458bbd172e3SDavid Howells WRITE_ONCE(call->expect_term_by, hard_timeout);
459bbd172e3SDavid Howells rxrpc_reduce_call_timer(call, hard_timeout, now, rxrpc_timer_set_for_hard);
460bbd172e3SDavid Howells
461bbd172e3SDavid Howells mutex_unlock(&call->user_mutex);
462bbd172e3SDavid Howells }
463bbd172e3SDavid Howells EXPORT_SYMBOL(rxrpc_kernel_set_max_life);
464bbd172e3SDavid Howells
46517926a79SDavid Howells /*
46617926a79SDavid Howells * connect an RxRPC socket
46717926a79SDavid Howells * - this just targets it at a specific destination; no actual connection
46817926a79SDavid Howells * negotiation takes place
46917926a79SDavid Howells */
rxrpc_connect(struct socket * sock,struct sockaddr * addr,int addr_len,int flags)47017926a79SDavid Howells static int rxrpc_connect(struct socket *sock, struct sockaddr *addr,
47117926a79SDavid Howells int addr_len, int flags)
47217926a79SDavid Howells {
47317926a79SDavid Howells struct sockaddr_rxrpc *srx = (struct sockaddr_rxrpc *)addr;
4742341e077SDavid Howells struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
47517926a79SDavid Howells int ret;
47617926a79SDavid Howells
47717926a79SDavid Howells _enter("%p,%p,%d,%d", rx, addr, addr_len, flags);
47817926a79SDavid Howells
47917926a79SDavid Howells ret = rxrpc_validate_address(rx, srx, addr_len);
48017926a79SDavid Howells if (ret < 0) {
48117926a79SDavid Howells _leave(" = %d [bad addr]", ret);
48217926a79SDavid Howells return ret;
48317926a79SDavid Howells }
48417926a79SDavid Howells
48517926a79SDavid Howells lock_sock(&rx->sk);
48617926a79SDavid Howells
4872341e077SDavid Howells ret = -EISCONN;
4882341e077SDavid Howells if (test_bit(RXRPC_SOCK_CONNECTED, &rx->flags))
4892341e077SDavid Howells goto error;
4902341e077SDavid Howells
49117926a79SDavid Howells switch (rx->sk.sk_state) {
4922341e077SDavid Howells case RXRPC_UNBOUND:
4932341e077SDavid Howells rx->sk.sk_state = RXRPC_CLIENT_UNBOUND;
49440e67c12SGustavo A. R. Silva break;
4952341e077SDavid Howells case RXRPC_CLIENT_UNBOUND:
49617926a79SDavid Howells case RXRPC_CLIENT_BOUND:
49717926a79SDavid Howells break;
49817926a79SDavid Howells default:
4992341e077SDavid Howells ret = -EBUSY;
5002341e077SDavid Howells goto error;
50117926a79SDavid Howells }
50217926a79SDavid Howells
5032341e077SDavid Howells rx->connect_srx = *srx;
5042341e077SDavid Howells set_bit(RXRPC_SOCK_CONNECTED, &rx->flags);
5052341e077SDavid Howells ret = 0;
50617926a79SDavid Howells
5072341e077SDavid Howells error:
50817926a79SDavid Howells release_sock(&rx->sk);
5092341e077SDavid Howells return ret;
51017926a79SDavid Howells }
51117926a79SDavid Howells
51217926a79SDavid Howells /*
51317926a79SDavid Howells * send a message through an RxRPC socket
51417926a79SDavid Howells * - in a client this does a number of things:
51517926a79SDavid Howells * - finds/sets up a connection for the security specified (if any)
51617926a79SDavid Howells * - initiates a call (ID in control data)
51717926a79SDavid Howells * - ends the request phase of a call (if MSG_MORE is not set)
51817926a79SDavid Howells * - sends a call data packet
51917926a79SDavid Howells * - may send an abort (abort code in control data)
52017926a79SDavid Howells */
rxrpc_sendmsg(struct socket * sock,struct msghdr * m,size_t len)5211b784140SYing Xue static int rxrpc_sendmsg(struct socket *sock, struct msghdr *m, size_t len)
52217926a79SDavid Howells {
5232341e077SDavid Howells struct rxrpc_local *local;
52417926a79SDavid Howells struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
52517926a79SDavid Howells int ret;
52617926a79SDavid Howells
52717926a79SDavid Howells _enter(",{%d},,%zu", rx->sk.sk_state, len);
52817926a79SDavid Howells
52917926a79SDavid Howells if (m->msg_flags & MSG_OOB)
53017926a79SDavid Howells return -EOPNOTSUPP;
53117926a79SDavid Howells
53217926a79SDavid Howells if (m->msg_name) {
53317926a79SDavid Howells ret = rxrpc_validate_address(rx, m->msg_name, m->msg_namelen);
53417926a79SDavid Howells if (ret < 0) {
53517926a79SDavid Howells _leave(" = %d [bad addr]", ret);
53617926a79SDavid Howells return ret;
53717926a79SDavid Howells }
53817926a79SDavid Howells }
53917926a79SDavid Howells
54017926a79SDavid Howells lock_sock(&rx->sk);
54117926a79SDavid Howells
5422341e077SDavid Howells switch (rx->sk.sk_state) {
5432341e077SDavid Howells case RXRPC_UNBOUND:
544e835ada0SDavid Howells case RXRPC_CLIENT_UNBOUND:
545cd5892c7SDavid Howells rx->srx.srx_family = AF_RXRPC;
546cd5892c7SDavid Howells rx->srx.srx_service = 0;
547cd5892c7SDavid Howells rx->srx.transport_type = SOCK_DGRAM;
548cd5892c7SDavid Howells rx->srx.transport.family = rx->family;
549cd5892c7SDavid Howells switch (rx->family) {
550cd5892c7SDavid Howells case AF_INET:
551cd5892c7SDavid Howells rx->srx.transport_len = sizeof(struct sockaddr_in);
552cd5892c7SDavid Howells break;
553d1912747SDavid Howells #ifdef CONFIG_AF_RXRPC_IPV6
55475b54cb5SDavid Howells case AF_INET6:
55575b54cb5SDavid Howells rx->srx.transport_len = sizeof(struct sockaddr_in6);
55675b54cb5SDavid Howells break;
557d1912747SDavid Howells #endif
558cd5892c7SDavid Howells default:
559cd5892c7SDavid Howells ret = -EAFNOSUPPORT;
560cd5892c7SDavid Howells goto error_unlock;
561cd5892c7SDavid Howells }
5622baec2c3SDavid Howells local = rxrpc_lookup_local(sock_net(sock->sk), &rx->srx);
5632341e077SDavid Howells if (IS_ERR(local)) {
5642341e077SDavid Howells ret = PTR_ERR(local);
5652341e077SDavid Howells goto error_unlock;
56617926a79SDavid Howells }
56717926a79SDavid Howells
5682341e077SDavid Howells rx->local = local;
569e835ada0SDavid Howells rx->sk.sk_state = RXRPC_CLIENT_BOUND;
570df561f66SGustavo A. R. Silva fallthrough;
5712341e077SDavid Howells
5722341e077SDavid Howells case RXRPC_CLIENT_BOUND:
5732341e077SDavid Howells if (!m->msg_name &&
5742341e077SDavid Howells test_bit(RXRPC_SOCK_CONNECTED, &rx->flags)) {
5752341e077SDavid Howells m->msg_name = &rx->connect_srx;
5762341e077SDavid Howells m->msg_namelen = sizeof(rx->connect_srx);
57717926a79SDavid Howells }
578df561f66SGustavo A. R. Silva fallthrough;
57917926a79SDavid Howells case RXRPC_SERVER_BOUND:
5802341e077SDavid Howells case RXRPC_SERVER_LISTENING:
5812341e077SDavid Howells ret = rxrpc_do_sendmsg(rx, m, len);
582540b1c48SDavid Howells /* The socket has been unlocked */
583540b1c48SDavid Howells goto out;
58417926a79SDavid Howells default:
5852341e077SDavid Howells ret = -EINVAL;
586540b1c48SDavid Howells goto error_unlock;
58717926a79SDavid Howells }
58817926a79SDavid Howells
5892341e077SDavid Howells error_unlock:
59017926a79SDavid Howells release_sock(&rx->sk);
591540b1c48SDavid Howells out:
59217926a79SDavid Howells _leave(" = %d", ret);
59317926a79SDavid Howells return ret;
59417926a79SDavid Howells }
59517926a79SDavid Howells
rxrpc_sock_set_min_security_level(struct sock * sk,unsigned int val)596298cd88aSChristoph Hellwig int rxrpc_sock_set_min_security_level(struct sock *sk, unsigned int val)
597298cd88aSChristoph Hellwig {
598298cd88aSChristoph Hellwig if (sk->sk_state != RXRPC_UNBOUND)
599298cd88aSChristoph Hellwig return -EISCONN;
600298cd88aSChristoph Hellwig if (val > RXRPC_SECURITY_MAX)
601298cd88aSChristoph Hellwig return -EINVAL;
602298cd88aSChristoph Hellwig lock_sock(sk);
603298cd88aSChristoph Hellwig rxrpc_sk(sk)->min_sec_level = val;
604298cd88aSChristoph Hellwig release_sock(sk);
605298cd88aSChristoph Hellwig return 0;
606298cd88aSChristoph Hellwig }
607298cd88aSChristoph Hellwig EXPORT_SYMBOL(rxrpc_sock_set_min_security_level);
608298cd88aSChristoph Hellwig
60917926a79SDavid Howells /*
61017926a79SDavid Howells * set RxRPC socket options
61117926a79SDavid Howells */
rxrpc_setsockopt(struct socket * sock,int level,int optname,sockptr_t optval,unsigned int optlen)61217926a79SDavid Howells static int rxrpc_setsockopt(struct socket *sock, int level, int optname,
613a7b75c5aSChristoph Hellwig sockptr_t optval, unsigned int optlen)
61417926a79SDavid Howells {
61517926a79SDavid Howells struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
61695c96174SEric Dumazet unsigned int min_sec_level;
6174722974dSDavid Howells u16 service_upgrade[2];
61817926a79SDavid Howells int ret;
61917926a79SDavid Howells
62017926a79SDavid Howells _enter(",%d,%d,,%d", level, optname, optlen);
62117926a79SDavid Howells
62217926a79SDavid Howells lock_sock(&rx->sk);
62317926a79SDavid Howells ret = -EOPNOTSUPP;
62417926a79SDavid Howells
62517926a79SDavid Howells if (level == SOL_RXRPC) {
62617926a79SDavid Howells switch (optname) {
62717926a79SDavid Howells case RXRPC_EXCLUSIVE_CONNECTION:
62817926a79SDavid Howells ret = -EINVAL;
62917926a79SDavid Howells if (optlen != 0)
63017926a79SDavid Howells goto error;
63117926a79SDavid Howells ret = -EISCONN;
6322341e077SDavid Howells if (rx->sk.sk_state != RXRPC_UNBOUND)
63317926a79SDavid Howells goto error;
634cc8feb8eSDavid Howells rx->exclusive = true;
63517926a79SDavid Howells goto success;
63617926a79SDavid Howells
63717926a79SDavid Howells case RXRPC_SECURITY_KEY:
63817926a79SDavid Howells ret = -EINVAL;
63917926a79SDavid Howells if (rx->key)
64017926a79SDavid Howells goto error;
64117926a79SDavid Howells ret = -EISCONN;
6422341e077SDavid Howells if (rx->sk.sk_state != RXRPC_UNBOUND)
64317926a79SDavid Howells goto error;
64417926a79SDavid Howells ret = rxrpc_request_key(rx, optval, optlen);
64517926a79SDavid Howells goto error;
64617926a79SDavid Howells
64717926a79SDavid Howells case RXRPC_SECURITY_KEYRING:
64817926a79SDavid Howells ret = -EINVAL;
64917926a79SDavid Howells if (rx->key)
65017926a79SDavid Howells goto error;
65117926a79SDavid Howells ret = -EISCONN;
6522341e077SDavid Howells if (rx->sk.sk_state != RXRPC_UNBOUND)
65317926a79SDavid Howells goto error;
65417926a79SDavid Howells ret = rxrpc_server_keyring(rx, optval, optlen);
65517926a79SDavid Howells goto error;
65617926a79SDavid Howells
65717926a79SDavid Howells case RXRPC_MIN_SECURITY_LEVEL:
65817926a79SDavid Howells ret = -EINVAL;
65995c96174SEric Dumazet if (optlen != sizeof(unsigned int))
66017926a79SDavid Howells goto error;
66117926a79SDavid Howells ret = -EISCONN;
6622341e077SDavid Howells if (rx->sk.sk_state != RXRPC_UNBOUND)
66317926a79SDavid Howells goto error;
664*265f1f22SMichal Luczaj ret = copy_safe_from_sockptr(&min_sec_level,
665*265f1f22SMichal Luczaj sizeof(min_sec_level),
666*265f1f22SMichal Luczaj optval, optlen);
667*265f1f22SMichal Luczaj if (ret)
66817926a79SDavid Howells goto error;
66917926a79SDavid Howells ret = -EINVAL;
67017926a79SDavid Howells if (min_sec_level > RXRPC_SECURITY_MAX)
67117926a79SDavid Howells goto error;
67217926a79SDavid Howells rx->min_sec_level = min_sec_level;
67317926a79SDavid Howells goto success;
67417926a79SDavid Howells
6754722974dSDavid Howells case RXRPC_UPGRADEABLE_SERVICE:
6764722974dSDavid Howells ret = -EINVAL;
6774722974dSDavid Howells if (optlen != sizeof(service_upgrade) ||
6784722974dSDavid Howells rx->service_upgrade.from != 0)
6794722974dSDavid Howells goto error;
6804722974dSDavid Howells ret = -EISCONN;
6814722974dSDavid Howells if (rx->sk.sk_state != RXRPC_SERVER_BOUND2)
6824722974dSDavid Howells goto error;
6834722974dSDavid Howells ret = -EFAULT;
684a7b75c5aSChristoph Hellwig if (copy_from_sockptr(service_upgrade, optval,
6854722974dSDavid Howells sizeof(service_upgrade)) != 0)
6864722974dSDavid Howells goto error;
6874722974dSDavid Howells ret = -EINVAL;
6884722974dSDavid Howells if ((service_upgrade[0] != rx->srx.srx_service ||
6894722974dSDavid Howells service_upgrade[1] != rx->second_service) &&
6904722974dSDavid Howells (service_upgrade[0] != rx->second_service ||
6914722974dSDavid Howells service_upgrade[1] != rx->srx.srx_service))
6924722974dSDavid Howells goto error;
6934722974dSDavid Howells rx->service_upgrade.from = service_upgrade[0];
6944722974dSDavid Howells rx->service_upgrade.to = service_upgrade[1];
6954722974dSDavid Howells goto success;
6964722974dSDavid Howells
69717926a79SDavid Howells default:
69817926a79SDavid Howells break;
69917926a79SDavid Howells }
70017926a79SDavid Howells }
70117926a79SDavid Howells
70217926a79SDavid Howells success:
70317926a79SDavid Howells ret = 0;
70417926a79SDavid Howells error:
70517926a79SDavid Howells release_sock(&rx->sk);
70617926a79SDavid Howells return ret;
70717926a79SDavid Howells }
70817926a79SDavid Howells
70917926a79SDavid Howells /*
710515559caSDavid Howells * Get socket options.
711515559caSDavid Howells */
rxrpc_getsockopt(struct socket * sock,int level,int optname,char __user * optval,int __user * _optlen)712515559caSDavid Howells static int rxrpc_getsockopt(struct socket *sock, int level, int optname,
713515559caSDavid Howells char __user *optval, int __user *_optlen)
714515559caSDavid Howells {
715515559caSDavid Howells int optlen;
716515559caSDavid Howells
717515559caSDavid Howells if (level != SOL_RXRPC)
718515559caSDavid Howells return -EOPNOTSUPP;
719515559caSDavid Howells
720515559caSDavid Howells if (get_user(optlen, _optlen))
721515559caSDavid Howells return -EFAULT;
722515559caSDavid Howells
723515559caSDavid Howells switch (optname) {
724515559caSDavid Howells case RXRPC_SUPPORTED_CMSG:
725515559caSDavid Howells if (optlen < sizeof(int))
726515559caSDavid Howells return -ETOOSMALL;
727515559caSDavid Howells if (put_user(RXRPC__SUPPORTED - 1, (int __user *)optval) ||
728515559caSDavid Howells put_user(sizeof(int), _optlen))
729515559caSDavid Howells return -EFAULT;
730515559caSDavid Howells return 0;
731515559caSDavid Howells
732515559caSDavid Howells default:
733515559caSDavid Howells return -EOPNOTSUPP;
734515559caSDavid Howells }
735515559caSDavid Howells }
736515559caSDavid Howells
737515559caSDavid Howells /*
73817926a79SDavid Howells * permit an RxRPC socket to be polled
73917926a79SDavid Howells */
rxrpc_poll(struct file * file,struct socket * sock,poll_table * wait)740a11e1d43SLinus Torvalds static __poll_t rxrpc_poll(struct file *file, struct socket *sock,
741a11e1d43SLinus Torvalds poll_table *wait)
74217926a79SDavid Howells {
74317926a79SDavid Howells struct sock *sk = sock->sk;
744248f219cSDavid Howells struct rxrpc_sock *rx = rxrpc_sk(sk);
745a11e1d43SLinus Torvalds __poll_t mask;
746a11e1d43SLinus Torvalds
74789ab066dSKarsten Graul sock_poll_wait(file, sock, wait);
748a11e1d43SLinus Torvalds mask = 0;
74917926a79SDavid Howells
75017926a79SDavid Howells /* the socket is readable if there are any messages waiting on the Rx
75117926a79SDavid Howells * queue */
752248f219cSDavid Howells if (!list_empty(&rx->recvmsg_q))
753a9a08845SLinus Torvalds mask |= EPOLLIN | EPOLLRDNORM;
75417926a79SDavid Howells
75517926a79SDavid Howells /* the socket is writable if there is space to add new data to the
75617926a79SDavid Howells * socket; there is no guarantee that any particular call in progress
75717926a79SDavid Howells * on the socket may have space in the Tx ACK window */
75817926a79SDavid Howells if (rxrpc_writable(sk))
759a9a08845SLinus Torvalds mask |= EPOLLOUT | EPOLLWRNORM;
76017926a79SDavid Howells
76117926a79SDavid Howells return mask;
76217926a79SDavid Howells }
76317926a79SDavid Howells
76417926a79SDavid Howells /*
76517926a79SDavid Howells * create an RxRPC socket
76617926a79SDavid Howells */
rxrpc_create(struct net * net,struct socket * sock,int protocol,int kern)7673f378b68SEric Paris static int rxrpc_create(struct net *net, struct socket *sock, int protocol,
7683f378b68SEric Paris int kern)
76917926a79SDavid Howells {
770ace45becSDavid Howells struct rxrpc_net *rxnet;
77117926a79SDavid Howells struct rxrpc_sock *rx;
77217926a79SDavid Howells struct sock *sk;
77317926a79SDavid Howells
77417926a79SDavid Howells _enter("%p,%d", sock, protocol);
77517926a79SDavid Howells
776b4f1342fSDavid Howells /* we support transport protocol UDP/UDP6 only */
777d1912747SDavid Howells if (protocol != PF_INET &&
778d1912747SDavid Howells IS_ENABLED(CONFIG_AF_RXRPC_IPV6) && protocol != PF_INET6)
77917926a79SDavid Howells return -EPROTONOSUPPORT;
78017926a79SDavid Howells
78117926a79SDavid Howells if (sock->type != SOCK_DGRAM)
78217926a79SDavid Howells return -ESOCKTNOSUPPORT;
78317926a79SDavid Howells
78417926a79SDavid Howells sock->ops = &rxrpc_rpc_ops;
78517926a79SDavid Howells sock->state = SS_UNCONNECTED;
78617926a79SDavid Howells
78711aa9c28SEric W. Biederman sk = sk_alloc(net, PF_RXRPC, GFP_KERNEL, &rxrpc_proto, kern);
78817926a79SDavid Howells if (!sk)
78917926a79SDavid Howells return -ENOMEM;
79017926a79SDavid Howells
79117926a79SDavid Howells sock_init_data(sock, sk);
7928d94aa38SDavid Howells sock_set_flag(sk, SOCK_RCU_FREE);
7932341e077SDavid Howells sk->sk_state = RXRPC_UNBOUND;
79417926a79SDavid Howells sk->sk_write_space = rxrpc_write_space;
7950e119b41SDavid Howells sk->sk_max_ack_backlog = 0;
79617926a79SDavid Howells sk->sk_destruct = rxrpc_sock_destructor;
79717926a79SDavid Howells
79817926a79SDavid Howells rx = rxrpc_sk(sk);
79919ffa01cSDavid Howells rx->family = protocol;
80017926a79SDavid Howells rx->calls = RB_ROOT;
80117926a79SDavid Howells
802248f219cSDavid Howells spin_lock_init(&rx->incoming_lock);
803248f219cSDavid Howells INIT_LIST_HEAD(&rx->sock_calls);
804248f219cSDavid Howells INIT_LIST_HEAD(&rx->to_be_accepted);
805248f219cSDavid Howells INIT_LIST_HEAD(&rx->recvmsg_q);
806223f5901SDavid Howells spin_lock_init(&rx->recvmsg_lock);
80717926a79SDavid Howells rwlock_init(&rx->call_lock);
80817926a79SDavid Howells memset(&rx->srx, 0, sizeof(rx->srx));
80917926a79SDavid Howells
810ace45becSDavid Howells rxnet = rxrpc_net(sock_net(&rx->sk));
811ace45becSDavid Howells timer_reduce(&rxnet->peer_keepalive_timer, jiffies + 1);
812ace45becSDavid Howells
81317926a79SDavid Howells _leave(" = 0 [%p]", rx);
81417926a79SDavid Howells return 0;
81517926a79SDavid Howells }
81617926a79SDavid Howells
81717926a79SDavid Howells /*
818248f219cSDavid Howells * Kill all the calls on a socket and shut it down.
819248f219cSDavid Howells */
rxrpc_shutdown(struct socket * sock,int flags)820248f219cSDavid Howells static int rxrpc_shutdown(struct socket *sock, int flags)
821248f219cSDavid Howells {
822248f219cSDavid Howells struct sock *sk = sock->sk;
823248f219cSDavid Howells struct rxrpc_sock *rx = rxrpc_sk(sk);
824248f219cSDavid Howells int ret = 0;
825248f219cSDavid Howells
826248f219cSDavid Howells _enter("%p,%d", sk, flags);
827248f219cSDavid Howells
828248f219cSDavid Howells if (flags != SHUT_RDWR)
829248f219cSDavid Howells return -EOPNOTSUPP;
830248f219cSDavid Howells if (sk->sk_state == RXRPC_CLOSE)
831248f219cSDavid Howells return -ESHUTDOWN;
832248f219cSDavid Howells
833248f219cSDavid Howells lock_sock(sk);
834248f219cSDavid Howells
835248f219cSDavid Howells if (sk->sk_state < RXRPC_CLOSE) {
836248f219cSDavid Howells sk->sk_state = RXRPC_CLOSE;
837248f219cSDavid Howells sk->sk_shutdown = SHUTDOWN_MASK;
838248f219cSDavid Howells } else {
839248f219cSDavid Howells ret = -ESHUTDOWN;
840248f219cSDavid Howells }
841248f219cSDavid Howells
842248f219cSDavid Howells rxrpc_discard_prealloc(rx);
843248f219cSDavid Howells
844248f219cSDavid Howells release_sock(sk);
845248f219cSDavid Howells return ret;
846248f219cSDavid Howells }
847248f219cSDavid Howells
848248f219cSDavid Howells /*
84917926a79SDavid Howells * RxRPC socket destructor
85017926a79SDavid Howells */
rxrpc_sock_destructor(struct sock * sk)85117926a79SDavid Howells static void rxrpc_sock_destructor(struct sock *sk)
85217926a79SDavid Howells {
85317926a79SDavid Howells _enter("%p", sk);
85417926a79SDavid Howells
85517926a79SDavid Howells rxrpc_purge_queue(&sk->sk_receive_queue);
85617926a79SDavid Howells
85714afee4bSReshetova, Elena WARN_ON(refcount_read(&sk->sk_wmem_alloc));
858547b792cSIlpo Järvinen WARN_ON(!sk_unhashed(sk));
859547b792cSIlpo Järvinen WARN_ON(sk->sk_socket);
86017926a79SDavid Howells
86117926a79SDavid Howells if (!sock_flag(sk, SOCK_DEAD)) {
86217926a79SDavid Howells printk("Attempt to release alive rxrpc socket: %p\n", sk);
86317926a79SDavid Howells return;
86417926a79SDavid Howells }
86517926a79SDavid Howells }
86617926a79SDavid Howells
86717926a79SDavid Howells /*
86817926a79SDavid Howells * release an RxRPC socket
86917926a79SDavid Howells */
rxrpc_release_sock(struct sock * sk)87017926a79SDavid Howells static int rxrpc_release_sock(struct sock *sk)
87117926a79SDavid Howells {
87217926a79SDavid Howells struct rxrpc_sock *rx = rxrpc_sk(sk);
87317926a79SDavid Howells
87441c6d650SReshetova, Elena _enter("%p{%d,%d}", sk, sk->sk_state, refcount_read(&sk->sk_refcnt));
87517926a79SDavid Howells
87617926a79SDavid Howells /* declare the socket closed for business */
87717926a79SDavid Howells sock_orphan(sk);
87817926a79SDavid Howells sk->sk_shutdown = SHUTDOWN_MASK;
87917926a79SDavid Howells
880f859ab61SDavid Howells /* We want to kill off all connections from a service socket
881f859ab61SDavid Howells * as fast as possible because we can't share these; client
882f859ab61SDavid Howells * sockets, on the other hand, can share an endpoint.
883f859ab61SDavid Howells */
884f859ab61SDavid Howells switch (sk->sk_state) {
885f859ab61SDavid Howells case RXRPC_SERVER_BOUND:
886f859ab61SDavid Howells case RXRPC_SERVER_BOUND2:
887f859ab61SDavid Howells case RXRPC_SERVER_LISTENING:
888f859ab61SDavid Howells case RXRPC_SERVER_LISTEN_DISABLED:
889f859ab61SDavid Howells rx->local->service_closed = true;
890f859ab61SDavid Howells break;
891f859ab61SDavid Howells }
892f859ab61SDavid Howells
89317926a79SDavid Howells sk->sk_state = RXRPC_CLOSE;
89417926a79SDavid Howells
89542f229c3SDavid Howells if (rx->local && rx->local->service == rx) {
896248f219cSDavid Howells write_lock(&rx->local->services_lock);
89742f229c3SDavid Howells rx->local->service = NULL;
898248f219cSDavid Howells write_unlock(&rx->local->services_lock);
89917926a79SDavid Howells }
90017926a79SDavid Howells
90117926a79SDavid Howells /* try to flush out this socket */
90200e90712SDavid Howells rxrpc_discard_prealloc(rx);
90317926a79SDavid Howells rxrpc_release_calls_on_socket(rx);
904651350d1SDavid Howells flush_workqueue(rxrpc_workqueue);
90517926a79SDavid Howells rxrpc_purge_queue(&sk->sk_receive_queue);
90617926a79SDavid Howells
9070fde882fSDavid Howells rxrpc_unuse_local(rx->local, rxrpc_local_unuse_release_sock);
9080fde882fSDavid Howells rxrpc_put_local(rx->local, rxrpc_local_put_release_sock);
90917926a79SDavid Howells rx->local = NULL;
91017926a79SDavid Howells key_put(rx->key);
91117926a79SDavid Howells rx->key = NULL;
91217926a79SDavid Howells key_put(rx->securities);
91317926a79SDavid Howells rx->securities = NULL;
91417926a79SDavid Howells sock_put(sk);
91517926a79SDavid Howells
91617926a79SDavid Howells _leave(" = 0");
91717926a79SDavid Howells return 0;
91817926a79SDavid Howells }
91917926a79SDavid Howells
92017926a79SDavid Howells /*
92117926a79SDavid Howells * release an RxRPC BSD socket on close() or equivalent
92217926a79SDavid Howells */
rxrpc_release(struct socket * sock)92317926a79SDavid Howells static int rxrpc_release(struct socket *sock)
92417926a79SDavid Howells {
92517926a79SDavid Howells struct sock *sk = sock->sk;
92617926a79SDavid Howells
92717926a79SDavid Howells _enter("%p{%p}", sock, sk);
92817926a79SDavid Howells
92917926a79SDavid Howells if (!sk)
93017926a79SDavid Howells return 0;
93117926a79SDavid Howells
93217926a79SDavid Howells sock->sk = NULL;
93317926a79SDavid Howells
93417926a79SDavid Howells return rxrpc_release_sock(sk);
93517926a79SDavid Howells }
93617926a79SDavid Howells
93717926a79SDavid Howells /*
93817926a79SDavid Howells * RxRPC network protocol
93917926a79SDavid Howells */
94017926a79SDavid Howells static const struct proto_ops rxrpc_rpc_ops = {
941e33b3d97SDavid Howells .family = PF_RXRPC,
94217926a79SDavid Howells .owner = THIS_MODULE,
94317926a79SDavid Howells .release = rxrpc_release,
94417926a79SDavid Howells .bind = rxrpc_bind,
94517926a79SDavid Howells .connect = rxrpc_connect,
94617926a79SDavid Howells .socketpair = sock_no_socketpair,
94717926a79SDavid Howells .accept = sock_no_accept,
94817926a79SDavid Howells .getname = sock_no_getname,
949a11e1d43SLinus Torvalds .poll = rxrpc_poll,
95017926a79SDavid Howells .ioctl = sock_no_ioctl,
95117926a79SDavid Howells .listen = rxrpc_listen,
952248f219cSDavid Howells .shutdown = rxrpc_shutdown,
95317926a79SDavid Howells .setsockopt = rxrpc_setsockopt,
954515559caSDavid Howells .getsockopt = rxrpc_getsockopt,
95517926a79SDavid Howells .sendmsg = rxrpc_sendmsg,
95617926a79SDavid Howells .recvmsg = rxrpc_recvmsg,
95717926a79SDavid Howells .mmap = sock_no_mmap,
95817926a79SDavid Howells };
95917926a79SDavid Howells
96017926a79SDavid Howells static struct proto rxrpc_proto = {
96117926a79SDavid Howells .name = "RXRPC",
96217926a79SDavid Howells .owner = THIS_MODULE,
96317926a79SDavid Howells .obj_size = sizeof(struct rxrpc_sock),
9640d12f8a4SDavid Howells .max_header = sizeof(struct rxrpc_wire_header),
96517926a79SDavid Howells };
96617926a79SDavid Howells
967ec1b4cf7SStephen Hemminger static const struct net_proto_family rxrpc_family_ops = {
96817926a79SDavid Howells .family = PF_RXRPC,
96917926a79SDavid Howells .create = rxrpc_create,
97017926a79SDavid Howells .owner = THIS_MODULE,
97117926a79SDavid Howells };
97217926a79SDavid Howells
97317926a79SDavid Howells /*
97417926a79SDavid Howells * initialise and register the RxRPC protocol
97517926a79SDavid Howells */
af_rxrpc_init(void)97617926a79SDavid Howells static int __init af_rxrpc_init(void)
97717926a79SDavid Howells {
97817926a79SDavid Howells int ret = -1;
97917926a79SDavid Howells
980c593642cSPankaj Bharadiya BUILD_BUG_ON(sizeof(struct rxrpc_skb_priv) > sizeof_field(struct sk_buff, cb));
98117926a79SDavid Howells
982651350d1SDavid Howells ret = -ENOMEM;
983020c69c1SDavid Howells rxrpc_gen_version_string();
98417926a79SDavid Howells rxrpc_call_jar = kmem_cache_create(
98517926a79SDavid Howells "rxrpc_call_jar", sizeof(struct rxrpc_call), 0,
98620c2df83SPaul Mundt SLAB_HWCACHE_ALIGN, NULL);
98717926a79SDavid Howells if (!rxrpc_call_jar) {
9889b6d5398SJoe Perches pr_notice("Failed to allocate call jar\n");
98917926a79SDavid Howells goto error_call_jar;
99017926a79SDavid Howells }
99117926a79SDavid Howells
99278ef9703STejun Heo rxrpc_workqueue = alloc_ordered_workqueue("krxrpcd", WQ_HIGHPRI | WQ_MEM_RECLAIM);
993651350d1SDavid Howells if (!rxrpc_workqueue) {
9949b6d5398SJoe Perches pr_notice("Failed to allocate work queue\n");
995651350d1SDavid Howells goto error_work_queue;
996651350d1SDavid Howells }
997651350d1SDavid Howells
998648af7fcSDavid Howells ret = rxrpc_init_security();
999648af7fcSDavid Howells if (ret < 0) {
10009b6d5398SJoe Perches pr_crit("Cannot initialise security\n");
1001648af7fcSDavid Howells goto error_security;
1002648af7fcSDavid Howells }
1003648af7fcSDavid Howells
10045399d522SDavid Howells ret = register_pernet_device(&rxrpc_net_ops);
10052baec2c3SDavid Howells if (ret)
10062baec2c3SDavid Howells goto error_pernet;
10072baec2c3SDavid Howells
100817926a79SDavid Howells ret = proto_register(&rxrpc_proto, 1);
100917926a79SDavid Howells if (ret < 0) {
10109b6d5398SJoe Perches pr_crit("Cannot register protocol\n");
101117926a79SDavid Howells goto error_proto;
101217926a79SDavid Howells }
101317926a79SDavid Howells
101417926a79SDavid Howells ret = sock_register(&rxrpc_family_ops);
101517926a79SDavid Howells if (ret < 0) {
10169b6d5398SJoe Perches pr_crit("Cannot register socket family\n");
101717926a79SDavid Howells goto error_sock;
101817926a79SDavid Howells }
101917926a79SDavid Howells
102017926a79SDavid Howells ret = register_key_type(&key_type_rxrpc);
102117926a79SDavid Howells if (ret < 0) {
10229b6d5398SJoe Perches pr_crit("Cannot register client key type\n");
102317926a79SDavid Howells goto error_key_type;
102417926a79SDavid Howells }
102517926a79SDavid Howells
102617926a79SDavid Howells ret = register_key_type(&key_type_rxrpc_s);
102717926a79SDavid Howells if (ret < 0) {
10289b6d5398SJoe Perches pr_crit("Cannot register server key type\n");
102917926a79SDavid Howells goto error_key_type_s;
103017926a79SDavid Howells }
103117926a79SDavid Howells
10325873c083SDavid Howells ret = rxrpc_sysctl_init();
10335873c083SDavid Howells if (ret < 0) {
10349b6d5398SJoe Perches pr_crit("Cannot register sysctls\n");
10355873c083SDavid Howells goto error_sysctls;
10365873c083SDavid Howells }
10375873c083SDavid Howells
103817926a79SDavid Howells return 0;
103917926a79SDavid Howells
10405873c083SDavid Howells error_sysctls:
10415873c083SDavid Howells unregister_key_type(&key_type_rxrpc_s);
104217926a79SDavid Howells error_key_type_s:
104317926a79SDavid Howells unregister_key_type(&key_type_rxrpc);
104417926a79SDavid Howells error_key_type:
104517926a79SDavid Howells sock_unregister(PF_RXRPC);
104617926a79SDavid Howells error_sock:
104717926a79SDavid Howells proto_unregister(&rxrpc_proto);
104817926a79SDavid Howells error_proto:
10495399d522SDavid Howells unregister_pernet_device(&rxrpc_net_ops);
10502baec2c3SDavid Howells error_pernet:
1051648af7fcSDavid Howells rxrpc_exit_security();
10528addc044SWei Yongjun error_security:
10538addc044SWei Yongjun destroy_workqueue(rxrpc_workqueue);
1054651350d1SDavid Howells error_work_queue:
105517926a79SDavid Howells kmem_cache_destroy(rxrpc_call_jar);
105617926a79SDavid Howells error_call_jar:
105717926a79SDavid Howells return ret;
105817926a79SDavid Howells }
105917926a79SDavid Howells
106017926a79SDavid Howells /*
106117926a79SDavid Howells * unregister the RxRPC protocol
106217926a79SDavid Howells */
af_rxrpc_exit(void)106317926a79SDavid Howells static void __exit af_rxrpc_exit(void)
106417926a79SDavid Howells {
106517926a79SDavid Howells _enter("");
10665873c083SDavid Howells rxrpc_sysctl_exit();
106717926a79SDavid Howells unregister_key_type(&key_type_rxrpc_s);
106817926a79SDavid Howells unregister_key_type(&key_type_rxrpc);
106917926a79SDavid Howells sock_unregister(PF_RXRPC);
107017926a79SDavid Howells proto_unregister(&rxrpc_proto);
10715399d522SDavid Howells unregister_pernet_device(&rxrpc_net_ops);
107271f3ca40SDavid Howells ASSERTCMP(atomic_read(&rxrpc_n_rx_skbs), ==, 0);
10734f95dd78SDavid Howells
10742baec2c3SDavid Howells /* Make sure the local and peer records pinned by any dying connections
10752baec2c3SDavid Howells * are released.
10762baec2c3SDavid Howells */
10772baec2c3SDavid Howells rcu_barrier();
10782baec2c3SDavid Howells
1079651350d1SDavid Howells destroy_workqueue(rxrpc_workqueue);
1080648af7fcSDavid Howells rxrpc_exit_security();
108117926a79SDavid Howells kmem_cache_destroy(rxrpc_call_jar);
108217926a79SDavid Howells _leave("");
108317926a79SDavid Howells }
108417926a79SDavid Howells
108517926a79SDavid Howells module_init(af_rxrpc_init);
108617926a79SDavid Howells module_exit(af_rxrpc_exit);
1087