xref: /openbmc/linux/net/rxrpc/af_rxrpc.c (revision ecc23d0a422a3118fcf6e4f0a46e17a6c2047b02)
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