162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/* AF_RXRPC implementation
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
562306a36Sopenharmony_ci * Written by David Howells (dhowells@redhat.com)
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci#include <linux/kernel.h>
1262306a36Sopenharmony_ci#include <linux/net.h>
1362306a36Sopenharmony_ci#include <linux/slab.h>
1462306a36Sopenharmony_ci#include <linux/skbuff.h>
1562306a36Sopenharmony_ci#include <linux/random.h>
1662306a36Sopenharmony_ci#include <linux/poll.h>
1762306a36Sopenharmony_ci#include <linux/proc_fs.h>
1862306a36Sopenharmony_ci#include <linux/key-type.h>
1962306a36Sopenharmony_ci#include <net/net_namespace.h>
2062306a36Sopenharmony_ci#include <net/sock.h>
2162306a36Sopenharmony_ci#include <net/af_rxrpc.h>
2262306a36Sopenharmony_ci#define CREATE_TRACE_POINTS
2362306a36Sopenharmony_ci#include "ar-internal.h"
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ciMODULE_DESCRIPTION("RxRPC network protocol");
2662306a36Sopenharmony_ciMODULE_AUTHOR("Red Hat, Inc.");
2762306a36Sopenharmony_ciMODULE_LICENSE("GPL");
2862306a36Sopenharmony_ciMODULE_ALIAS_NETPROTO(PF_RXRPC);
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ciunsigned int rxrpc_debug; // = RXRPC_DEBUG_KPROTO;
3162306a36Sopenharmony_cimodule_param_named(debug, rxrpc_debug, uint, 0644);
3262306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "RxRPC debugging mask");
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic struct proto rxrpc_proto;
3562306a36Sopenharmony_cistatic const struct proto_ops rxrpc_rpc_ops;
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci/* current debugging ID */
3862306a36Sopenharmony_ciatomic_t rxrpc_debug_id;
3962306a36Sopenharmony_ciEXPORT_SYMBOL(rxrpc_debug_id);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci/* count of skbs currently in use */
4262306a36Sopenharmony_ciatomic_t rxrpc_n_rx_skbs;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistruct workqueue_struct *rxrpc_workqueue;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistatic void rxrpc_sock_destructor(struct sock *);
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci/*
4962306a36Sopenharmony_ci * see if an RxRPC socket is currently writable
5062306a36Sopenharmony_ci */
5162306a36Sopenharmony_cistatic inline int rxrpc_writable(struct sock *sk)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	return refcount_read(&sk->sk_wmem_alloc) < (size_t) sk->sk_sndbuf;
5462306a36Sopenharmony_ci}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/*
5762306a36Sopenharmony_ci * wait for write bufferage to become available
5862306a36Sopenharmony_ci */
5962306a36Sopenharmony_cistatic void rxrpc_write_space(struct sock *sk)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	_enter("%p", sk);
6262306a36Sopenharmony_ci	rcu_read_lock();
6362306a36Sopenharmony_ci	if (rxrpc_writable(sk)) {
6462306a36Sopenharmony_ci		struct socket_wq *wq = rcu_dereference(sk->sk_wq);
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci		if (skwq_has_sleeper(wq))
6762306a36Sopenharmony_ci			wake_up_interruptible(&wq->wait);
6862306a36Sopenharmony_ci		sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
6962306a36Sopenharmony_ci	}
7062306a36Sopenharmony_ci	rcu_read_unlock();
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/*
7462306a36Sopenharmony_ci * validate an RxRPC address
7562306a36Sopenharmony_ci */
7662306a36Sopenharmony_cistatic int rxrpc_validate_address(struct rxrpc_sock *rx,
7762306a36Sopenharmony_ci				  struct sockaddr_rxrpc *srx,
7862306a36Sopenharmony_ci				  int len)
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci	unsigned int tail;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	if (len < sizeof(struct sockaddr_rxrpc))
8362306a36Sopenharmony_ci		return -EINVAL;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	if (srx->srx_family != AF_RXRPC)
8662306a36Sopenharmony_ci		return -EAFNOSUPPORT;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	if (srx->transport_type != SOCK_DGRAM)
8962306a36Sopenharmony_ci		return -ESOCKTNOSUPPORT;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	len -= offsetof(struct sockaddr_rxrpc, transport);
9262306a36Sopenharmony_ci	if (srx->transport_len < sizeof(sa_family_t) ||
9362306a36Sopenharmony_ci	    srx->transport_len > len)
9462306a36Sopenharmony_ci		return -EINVAL;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	switch (srx->transport.family) {
9762306a36Sopenharmony_ci	case AF_INET:
9862306a36Sopenharmony_ci		if (rx->family != AF_INET &&
9962306a36Sopenharmony_ci		    rx->family != AF_INET6)
10062306a36Sopenharmony_ci			return -EAFNOSUPPORT;
10162306a36Sopenharmony_ci		if (srx->transport_len < sizeof(struct sockaddr_in))
10262306a36Sopenharmony_ci			return -EINVAL;
10362306a36Sopenharmony_ci		tail = offsetof(struct sockaddr_rxrpc, transport.sin.__pad);
10462306a36Sopenharmony_ci		break;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci#ifdef CONFIG_AF_RXRPC_IPV6
10762306a36Sopenharmony_ci	case AF_INET6:
10862306a36Sopenharmony_ci		if (rx->family != AF_INET6)
10962306a36Sopenharmony_ci			return -EAFNOSUPPORT;
11062306a36Sopenharmony_ci		if (srx->transport_len < sizeof(struct sockaddr_in6))
11162306a36Sopenharmony_ci			return -EINVAL;
11262306a36Sopenharmony_ci		tail = offsetof(struct sockaddr_rxrpc, transport) +
11362306a36Sopenharmony_ci			sizeof(struct sockaddr_in6);
11462306a36Sopenharmony_ci		break;
11562306a36Sopenharmony_ci#endif
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	default:
11862306a36Sopenharmony_ci		return -EAFNOSUPPORT;
11962306a36Sopenharmony_ci	}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	if (tail < len)
12262306a36Sopenharmony_ci		memset((void *)srx + tail, 0, len - tail);
12362306a36Sopenharmony_ci	_debug("INET: %pISp", &srx->transport);
12462306a36Sopenharmony_ci	return 0;
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci/*
12862306a36Sopenharmony_ci * bind a local address to an RxRPC socket
12962306a36Sopenharmony_ci */
13062306a36Sopenharmony_cistatic int rxrpc_bind(struct socket *sock, struct sockaddr *saddr, int len)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	struct sockaddr_rxrpc *srx = (struct sockaddr_rxrpc *)saddr;
13362306a36Sopenharmony_ci	struct rxrpc_local *local;
13462306a36Sopenharmony_ci	struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
13562306a36Sopenharmony_ci	u16 service_id;
13662306a36Sopenharmony_ci	int ret;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	_enter("%p,%p,%d", rx, saddr, len);
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	ret = rxrpc_validate_address(rx, srx, len);
14162306a36Sopenharmony_ci	if (ret < 0)
14262306a36Sopenharmony_ci		goto error;
14362306a36Sopenharmony_ci	service_id = srx->srx_service;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	lock_sock(&rx->sk);
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	switch (rx->sk.sk_state) {
14862306a36Sopenharmony_ci	case RXRPC_UNBOUND:
14962306a36Sopenharmony_ci		rx->srx = *srx;
15062306a36Sopenharmony_ci		local = rxrpc_lookup_local(sock_net(&rx->sk), &rx->srx);
15162306a36Sopenharmony_ci		if (IS_ERR(local)) {
15262306a36Sopenharmony_ci			ret = PTR_ERR(local);
15362306a36Sopenharmony_ci			goto error_unlock;
15462306a36Sopenharmony_ci		}
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci		if (service_id) {
15762306a36Sopenharmony_ci			write_lock(&local->services_lock);
15862306a36Sopenharmony_ci			if (local->service)
15962306a36Sopenharmony_ci				goto service_in_use;
16062306a36Sopenharmony_ci			rx->local = local;
16162306a36Sopenharmony_ci			local->service = rx;
16262306a36Sopenharmony_ci			write_unlock(&local->services_lock);
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci			rx->sk.sk_state = RXRPC_SERVER_BOUND;
16562306a36Sopenharmony_ci		} else {
16662306a36Sopenharmony_ci			rx->local = local;
16762306a36Sopenharmony_ci			rx->sk.sk_state = RXRPC_CLIENT_BOUND;
16862306a36Sopenharmony_ci		}
16962306a36Sopenharmony_ci		break;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	case RXRPC_SERVER_BOUND:
17262306a36Sopenharmony_ci		ret = -EINVAL;
17362306a36Sopenharmony_ci		if (service_id == 0)
17462306a36Sopenharmony_ci			goto error_unlock;
17562306a36Sopenharmony_ci		ret = -EADDRINUSE;
17662306a36Sopenharmony_ci		if (service_id == rx->srx.srx_service)
17762306a36Sopenharmony_ci			goto error_unlock;
17862306a36Sopenharmony_ci		ret = -EINVAL;
17962306a36Sopenharmony_ci		srx->srx_service = rx->srx.srx_service;
18062306a36Sopenharmony_ci		if (memcmp(srx, &rx->srx, sizeof(*srx)) != 0)
18162306a36Sopenharmony_ci			goto error_unlock;
18262306a36Sopenharmony_ci		rx->second_service = service_id;
18362306a36Sopenharmony_ci		rx->sk.sk_state = RXRPC_SERVER_BOUND2;
18462306a36Sopenharmony_ci		break;
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	default:
18762306a36Sopenharmony_ci		ret = -EINVAL;
18862306a36Sopenharmony_ci		goto error_unlock;
18962306a36Sopenharmony_ci	}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	release_sock(&rx->sk);
19262306a36Sopenharmony_ci	_leave(" = 0");
19362306a36Sopenharmony_ci	return 0;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ciservice_in_use:
19662306a36Sopenharmony_ci	write_unlock(&local->services_lock);
19762306a36Sopenharmony_ci	rxrpc_unuse_local(local, rxrpc_local_unuse_bind);
19862306a36Sopenharmony_ci	rxrpc_put_local(local, rxrpc_local_put_bind);
19962306a36Sopenharmony_ci	ret = -EADDRINUSE;
20062306a36Sopenharmony_cierror_unlock:
20162306a36Sopenharmony_ci	release_sock(&rx->sk);
20262306a36Sopenharmony_cierror:
20362306a36Sopenharmony_ci	_leave(" = %d", ret);
20462306a36Sopenharmony_ci	return ret;
20562306a36Sopenharmony_ci}
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci/*
20862306a36Sopenharmony_ci * set the number of pending calls permitted on a listening socket
20962306a36Sopenharmony_ci */
21062306a36Sopenharmony_cistatic int rxrpc_listen(struct socket *sock, int backlog)
21162306a36Sopenharmony_ci{
21262306a36Sopenharmony_ci	struct sock *sk = sock->sk;
21362306a36Sopenharmony_ci	struct rxrpc_sock *rx = rxrpc_sk(sk);
21462306a36Sopenharmony_ci	unsigned int max, old;
21562306a36Sopenharmony_ci	int ret;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	_enter("%p,%d", rx, backlog);
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	lock_sock(&rx->sk);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	switch (rx->sk.sk_state) {
22262306a36Sopenharmony_ci	case RXRPC_UNBOUND:
22362306a36Sopenharmony_ci		ret = -EADDRNOTAVAIL;
22462306a36Sopenharmony_ci		break;
22562306a36Sopenharmony_ci	case RXRPC_SERVER_BOUND:
22662306a36Sopenharmony_ci	case RXRPC_SERVER_BOUND2:
22762306a36Sopenharmony_ci		ASSERT(rx->local != NULL);
22862306a36Sopenharmony_ci		max = READ_ONCE(rxrpc_max_backlog);
22962306a36Sopenharmony_ci		ret = -EINVAL;
23062306a36Sopenharmony_ci		if (backlog == INT_MAX)
23162306a36Sopenharmony_ci			backlog = max;
23262306a36Sopenharmony_ci		else if (backlog < 0 || backlog > max)
23362306a36Sopenharmony_ci			break;
23462306a36Sopenharmony_ci		old = sk->sk_max_ack_backlog;
23562306a36Sopenharmony_ci		sk->sk_max_ack_backlog = backlog;
23662306a36Sopenharmony_ci		ret = rxrpc_service_prealloc(rx, GFP_KERNEL);
23762306a36Sopenharmony_ci		if (ret == 0)
23862306a36Sopenharmony_ci			rx->sk.sk_state = RXRPC_SERVER_LISTENING;
23962306a36Sopenharmony_ci		else
24062306a36Sopenharmony_ci			sk->sk_max_ack_backlog = old;
24162306a36Sopenharmony_ci		break;
24262306a36Sopenharmony_ci	case RXRPC_SERVER_LISTENING:
24362306a36Sopenharmony_ci		if (backlog == 0) {
24462306a36Sopenharmony_ci			rx->sk.sk_state = RXRPC_SERVER_LISTEN_DISABLED;
24562306a36Sopenharmony_ci			sk->sk_max_ack_backlog = 0;
24662306a36Sopenharmony_ci			rxrpc_discard_prealloc(rx);
24762306a36Sopenharmony_ci			ret = 0;
24862306a36Sopenharmony_ci			break;
24962306a36Sopenharmony_ci		}
25062306a36Sopenharmony_ci		fallthrough;
25162306a36Sopenharmony_ci	default:
25262306a36Sopenharmony_ci		ret = -EBUSY;
25362306a36Sopenharmony_ci		break;
25462306a36Sopenharmony_ci	}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	release_sock(&rx->sk);
25762306a36Sopenharmony_ci	_leave(" = %d", ret);
25862306a36Sopenharmony_ci	return ret;
25962306a36Sopenharmony_ci}
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci/**
26262306a36Sopenharmony_ci * rxrpc_kernel_begin_call - Allow a kernel service to begin a call
26362306a36Sopenharmony_ci * @sock: The socket on which to make the call
26462306a36Sopenharmony_ci * @srx: The address of the peer to contact
26562306a36Sopenharmony_ci * @key: The security context to use (defaults to socket setting)
26662306a36Sopenharmony_ci * @user_call_ID: The ID to use
26762306a36Sopenharmony_ci * @tx_total_len: Total length of data to transmit during the call (or -1)
26862306a36Sopenharmony_ci * @hard_timeout: The maximum lifespan of the call in sec
26962306a36Sopenharmony_ci * @gfp: The allocation constraints
27062306a36Sopenharmony_ci * @notify_rx: Where to send notifications instead of socket queue
27162306a36Sopenharmony_ci * @upgrade: Request service upgrade for call
27262306a36Sopenharmony_ci * @interruptibility: The call is interruptible, or can be canceled.
27362306a36Sopenharmony_ci * @debug_id: The debug ID for tracing to be assigned to the call
27462306a36Sopenharmony_ci *
27562306a36Sopenharmony_ci * Allow a kernel service to begin a call on the nominated socket.  This just
27662306a36Sopenharmony_ci * sets up all the internal tracking structures and allocates connection and
27762306a36Sopenharmony_ci * call IDs as appropriate.  The call to be used is returned.
27862306a36Sopenharmony_ci *
27962306a36Sopenharmony_ci * The default socket destination address and security may be overridden by
28062306a36Sopenharmony_ci * supplying @srx and @key.
28162306a36Sopenharmony_ci */
28262306a36Sopenharmony_cistruct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
28362306a36Sopenharmony_ci					   struct sockaddr_rxrpc *srx,
28462306a36Sopenharmony_ci					   struct key *key,
28562306a36Sopenharmony_ci					   unsigned long user_call_ID,
28662306a36Sopenharmony_ci					   s64 tx_total_len,
28762306a36Sopenharmony_ci					   u32 hard_timeout,
28862306a36Sopenharmony_ci					   gfp_t gfp,
28962306a36Sopenharmony_ci					   rxrpc_notify_rx_t notify_rx,
29062306a36Sopenharmony_ci					   bool upgrade,
29162306a36Sopenharmony_ci					   enum rxrpc_interruptibility interruptibility,
29262306a36Sopenharmony_ci					   unsigned int debug_id)
29362306a36Sopenharmony_ci{
29462306a36Sopenharmony_ci	struct rxrpc_conn_parameters cp;
29562306a36Sopenharmony_ci	struct rxrpc_call_params p;
29662306a36Sopenharmony_ci	struct rxrpc_call *call;
29762306a36Sopenharmony_ci	struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
29862306a36Sopenharmony_ci	int ret;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	_enter(",,%x,%lx", key_serial(key), user_call_ID);
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	ret = rxrpc_validate_address(rx, srx, sizeof(*srx));
30362306a36Sopenharmony_ci	if (ret < 0)
30462306a36Sopenharmony_ci		return ERR_PTR(ret);
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	lock_sock(&rx->sk);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	if (!key)
30962306a36Sopenharmony_ci		key = rx->key;
31062306a36Sopenharmony_ci	if (key && !key->payload.data[0])
31162306a36Sopenharmony_ci		key = NULL; /* a no-security key */
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	memset(&p, 0, sizeof(p));
31462306a36Sopenharmony_ci	p.user_call_ID		= user_call_ID;
31562306a36Sopenharmony_ci	p.tx_total_len		= tx_total_len;
31662306a36Sopenharmony_ci	p.interruptibility	= interruptibility;
31762306a36Sopenharmony_ci	p.kernel		= true;
31862306a36Sopenharmony_ci	p.timeouts.hard		= hard_timeout;
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	memset(&cp, 0, sizeof(cp));
32162306a36Sopenharmony_ci	cp.local		= rx->local;
32262306a36Sopenharmony_ci	cp.key			= key;
32362306a36Sopenharmony_ci	cp.security_level	= rx->min_sec_level;
32462306a36Sopenharmony_ci	cp.exclusive		= false;
32562306a36Sopenharmony_ci	cp.upgrade		= upgrade;
32662306a36Sopenharmony_ci	cp.service_id		= srx->srx_service;
32762306a36Sopenharmony_ci	call = rxrpc_new_client_call(rx, &cp, srx, &p, gfp, debug_id);
32862306a36Sopenharmony_ci	/* The socket has been unlocked. */
32962306a36Sopenharmony_ci	if (!IS_ERR(call)) {
33062306a36Sopenharmony_ci		call->notify_rx = notify_rx;
33162306a36Sopenharmony_ci		mutex_unlock(&call->user_mutex);
33262306a36Sopenharmony_ci	}
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	_leave(" = %p", call);
33562306a36Sopenharmony_ci	return call;
33662306a36Sopenharmony_ci}
33762306a36Sopenharmony_ciEXPORT_SYMBOL(rxrpc_kernel_begin_call);
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci/*
34062306a36Sopenharmony_ci * Dummy function used to stop the notifier talking to recvmsg().
34162306a36Sopenharmony_ci */
34262306a36Sopenharmony_cistatic void rxrpc_dummy_notify_rx(struct sock *sk, struct rxrpc_call *rxcall,
34362306a36Sopenharmony_ci				  unsigned long call_user_ID)
34462306a36Sopenharmony_ci{
34562306a36Sopenharmony_ci}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci/**
34862306a36Sopenharmony_ci * rxrpc_kernel_shutdown_call - Allow a kernel service to shut down a call it was using
34962306a36Sopenharmony_ci * @sock: The socket the call is on
35062306a36Sopenharmony_ci * @call: The call to end
35162306a36Sopenharmony_ci *
35262306a36Sopenharmony_ci * Allow a kernel service to shut down a call it was using.  The call must be
35362306a36Sopenharmony_ci * complete before this is called (the call should be aborted if necessary).
35462306a36Sopenharmony_ci */
35562306a36Sopenharmony_civoid rxrpc_kernel_shutdown_call(struct socket *sock, struct rxrpc_call *call)
35662306a36Sopenharmony_ci{
35762306a36Sopenharmony_ci	_enter("%d{%d}", call->debug_id, refcount_read(&call->ref));
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	mutex_lock(&call->user_mutex);
36062306a36Sopenharmony_ci	if (!test_bit(RXRPC_CALL_RELEASED, &call->flags)) {
36162306a36Sopenharmony_ci		rxrpc_release_call(rxrpc_sk(sock->sk), call);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci		/* Make sure we're not going to call back into a kernel service */
36462306a36Sopenharmony_ci		if (call->notify_rx) {
36562306a36Sopenharmony_ci			spin_lock(&call->notify_lock);
36662306a36Sopenharmony_ci			call->notify_rx = rxrpc_dummy_notify_rx;
36762306a36Sopenharmony_ci			spin_unlock(&call->notify_lock);
36862306a36Sopenharmony_ci		}
36962306a36Sopenharmony_ci	}
37062306a36Sopenharmony_ci	mutex_unlock(&call->user_mutex);
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ciEXPORT_SYMBOL(rxrpc_kernel_shutdown_call);
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci/**
37562306a36Sopenharmony_ci * rxrpc_kernel_put_call - Release a reference to a call
37662306a36Sopenharmony_ci * @sock: The socket the call is on
37762306a36Sopenharmony_ci * @call: The call to put
37862306a36Sopenharmony_ci *
37962306a36Sopenharmony_ci * Drop the application's ref on an rxrpc call.
38062306a36Sopenharmony_ci */
38162306a36Sopenharmony_civoid rxrpc_kernel_put_call(struct socket *sock, struct rxrpc_call *call)
38262306a36Sopenharmony_ci{
38362306a36Sopenharmony_ci	rxrpc_put_call(call, rxrpc_call_put_kernel);
38462306a36Sopenharmony_ci}
38562306a36Sopenharmony_ciEXPORT_SYMBOL(rxrpc_kernel_put_call);
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci/**
38862306a36Sopenharmony_ci * rxrpc_kernel_check_life - Check to see whether a call is still alive
38962306a36Sopenharmony_ci * @sock: The socket the call is on
39062306a36Sopenharmony_ci * @call: The call to check
39162306a36Sopenharmony_ci *
39262306a36Sopenharmony_ci * Allow a kernel service to find out whether a call is still alive - whether
39362306a36Sopenharmony_ci * it has completed successfully and all received data has been consumed.
39462306a36Sopenharmony_ci */
39562306a36Sopenharmony_cibool rxrpc_kernel_check_life(const struct socket *sock,
39662306a36Sopenharmony_ci			     const struct rxrpc_call *call)
39762306a36Sopenharmony_ci{
39862306a36Sopenharmony_ci	if (!rxrpc_call_is_complete(call))
39962306a36Sopenharmony_ci		return true;
40062306a36Sopenharmony_ci	if (call->completion != RXRPC_CALL_SUCCEEDED)
40162306a36Sopenharmony_ci		return false;
40262306a36Sopenharmony_ci	return !skb_queue_empty(&call->recvmsg_queue);
40362306a36Sopenharmony_ci}
40462306a36Sopenharmony_ciEXPORT_SYMBOL(rxrpc_kernel_check_life);
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci/**
40762306a36Sopenharmony_ci * rxrpc_kernel_get_epoch - Retrieve the epoch value from a call.
40862306a36Sopenharmony_ci * @sock: The socket the call is on
40962306a36Sopenharmony_ci * @call: The call to query
41062306a36Sopenharmony_ci *
41162306a36Sopenharmony_ci * Allow a kernel service to retrieve the epoch value from a service call to
41262306a36Sopenharmony_ci * see if the client at the other end rebooted.
41362306a36Sopenharmony_ci */
41462306a36Sopenharmony_ciu32 rxrpc_kernel_get_epoch(struct socket *sock, struct rxrpc_call *call)
41562306a36Sopenharmony_ci{
41662306a36Sopenharmony_ci	return call->conn->proto.epoch;
41762306a36Sopenharmony_ci}
41862306a36Sopenharmony_ciEXPORT_SYMBOL(rxrpc_kernel_get_epoch);
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci/**
42162306a36Sopenharmony_ci * rxrpc_kernel_new_call_notification - Get notifications of new calls
42262306a36Sopenharmony_ci * @sock: The socket to intercept received messages on
42362306a36Sopenharmony_ci * @notify_new_call: Function to be called when new calls appear
42462306a36Sopenharmony_ci * @discard_new_call: Function to discard preallocated calls
42562306a36Sopenharmony_ci *
42662306a36Sopenharmony_ci * Allow a kernel service to be given notifications about new calls.
42762306a36Sopenharmony_ci */
42862306a36Sopenharmony_civoid rxrpc_kernel_new_call_notification(
42962306a36Sopenharmony_ci	struct socket *sock,
43062306a36Sopenharmony_ci	rxrpc_notify_new_call_t notify_new_call,
43162306a36Sopenharmony_ci	rxrpc_discard_new_call_t discard_new_call)
43262306a36Sopenharmony_ci{
43362306a36Sopenharmony_ci	struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	rx->notify_new_call = notify_new_call;
43662306a36Sopenharmony_ci	rx->discard_new_call = discard_new_call;
43762306a36Sopenharmony_ci}
43862306a36Sopenharmony_ciEXPORT_SYMBOL(rxrpc_kernel_new_call_notification);
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci/**
44162306a36Sopenharmony_ci * rxrpc_kernel_set_max_life - Set maximum lifespan on a call
44262306a36Sopenharmony_ci * @sock: The socket the call is on
44362306a36Sopenharmony_ci * @call: The call to configure
44462306a36Sopenharmony_ci * @hard_timeout: The maximum lifespan of the call in jiffies
44562306a36Sopenharmony_ci *
44662306a36Sopenharmony_ci * Set the maximum lifespan of a call.  The call will end with ETIME or
44762306a36Sopenharmony_ci * ETIMEDOUT if it takes longer than this.
44862306a36Sopenharmony_ci */
44962306a36Sopenharmony_civoid rxrpc_kernel_set_max_life(struct socket *sock, struct rxrpc_call *call,
45062306a36Sopenharmony_ci			       unsigned long hard_timeout)
45162306a36Sopenharmony_ci{
45262306a36Sopenharmony_ci	unsigned long now;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	mutex_lock(&call->user_mutex);
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	now = jiffies;
45762306a36Sopenharmony_ci	hard_timeout += now;
45862306a36Sopenharmony_ci	WRITE_ONCE(call->expect_term_by, hard_timeout);
45962306a36Sopenharmony_ci	rxrpc_reduce_call_timer(call, hard_timeout, now, rxrpc_timer_set_for_hard);
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	mutex_unlock(&call->user_mutex);
46262306a36Sopenharmony_ci}
46362306a36Sopenharmony_ciEXPORT_SYMBOL(rxrpc_kernel_set_max_life);
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci/*
46662306a36Sopenharmony_ci * connect an RxRPC socket
46762306a36Sopenharmony_ci * - this just targets it at a specific destination; no actual connection
46862306a36Sopenharmony_ci *   negotiation takes place
46962306a36Sopenharmony_ci */
47062306a36Sopenharmony_cistatic int rxrpc_connect(struct socket *sock, struct sockaddr *addr,
47162306a36Sopenharmony_ci			 int addr_len, int flags)
47262306a36Sopenharmony_ci{
47362306a36Sopenharmony_ci	struct sockaddr_rxrpc *srx = (struct sockaddr_rxrpc *)addr;
47462306a36Sopenharmony_ci	struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
47562306a36Sopenharmony_ci	int ret;
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	_enter("%p,%p,%d,%d", rx, addr, addr_len, flags);
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	ret = rxrpc_validate_address(rx, srx, addr_len);
48062306a36Sopenharmony_ci	if (ret < 0) {
48162306a36Sopenharmony_ci		_leave(" = %d [bad addr]", ret);
48262306a36Sopenharmony_ci		return ret;
48362306a36Sopenharmony_ci	}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	lock_sock(&rx->sk);
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	ret = -EISCONN;
48862306a36Sopenharmony_ci	if (test_bit(RXRPC_SOCK_CONNECTED, &rx->flags))
48962306a36Sopenharmony_ci		goto error;
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	switch (rx->sk.sk_state) {
49262306a36Sopenharmony_ci	case RXRPC_UNBOUND:
49362306a36Sopenharmony_ci		rx->sk.sk_state = RXRPC_CLIENT_UNBOUND;
49462306a36Sopenharmony_ci		break;
49562306a36Sopenharmony_ci	case RXRPC_CLIENT_UNBOUND:
49662306a36Sopenharmony_ci	case RXRPC_CLIENT_BOUND:
49762306a36Sopenharmony_ci		break;
49862306a36Sopenharmony_ci	default:
49962306a36Sopenharmony_ci		ret = -EBUSY;
50062306a36Sopenharmony_ci		goto error;
50162306a36Sopenharmony_ci	}
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	rx->connect_srx = *srx;
50462306a36Sopenharmony_ci	set_bit(RXRPC_SOCK_CONNECTED, &rx->flags);
50562306a36Sopenharmony_ci	ret = 0;
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_cierror:
50862306a36Sopenharmony_ci	release_sock(&rx->sk);
50962306a36Sopenharmony_ci	return ret;
51062306a36Sopenharmony_ci}
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci/*
51362306a36Sopenharmony_ci * send a message through an RxRPC socket
51462306a36Sopenharmony_ci * - in a client this does a number of things:
51562306a36Sopenharmony_ci *   - finds/sets up a connection for the security specified (if any)
51662306a36Sopenharmony_ci *   - initiates a call (ID in control data)
51762306a36Sopenharmony_ci *   - ends the request phase of a call (if MSG_MORE is not set)
51862306a36Sopenharmony_ci *   - sends a call data packet
51962306a36Sopenharmony_ci *   - may send an abort (abort code in control data)
52062306a36Sopenharmony_ci */
52162306a36Sopenharmony_cistatic int rxrpc_sendmsg(struct socket *sock, struct msghdr *m, size_t len)
52262306a36Sopenharmony_ci{
52362306a36Sopenharmony_ci	struct rxrpc_local *local;
52462306a36Sopenharmony_ci	struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
52562306a36Sopenharmony_ci	int ret;
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	_enter(",{%d},,%zu", rx->sk.sk_state, len);
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	if (m->msg_flags & MSG_OOB)
53062306a36Sopenharmony_ci		return -EOPNOTSUPP;
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	if (m->msg_name) {
53362306a36Sopenharmony_ci		ret = rxrpc_validate_address(rx, m->msg_name, m->msg_namelen);
53462306a36Sopenharmony_ci		if (ret < 0) {
53562306a36Sopenharmony_ci			_leave(" = %d [bad addr]", ret);
53662306a36Sopenharmony_ci			return ret;
53762306a36Sopenharmony_ci		}
53862306a36Sopenharmony_ci	}
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	lock_sock(&rx->sk);
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	switch (rx->sk.sk_state) {
54362306a36Sopenharmony_ci	case RXRPC_UNBOUND:
54462306a36Sopenharmony_ci	case RXRPC_CLIENT_UNBOUND:
54562306a36Sopenharmony_ci		rx->srx.srx_family = AF_RXRPC;
54662306a36Sopenharmony_ci		rx->srx.srx_service = 0;
54762306a36Sopenharmony_ci		rx->srx.transport_type = SOCK_DGRAM;
54862306a36Sopenharmony_ci		rx->srx.transport.family = rx->family;
54962306a36Sopenharmony_ci		switch (rx->family) {
55062306a36Sopenharmony_ci		case AF_INET:
55162306a36Sopenharmony_ci			rx->srx.transport_len = sizeof(struct sockaddr_in);
55262306a36Sopenharmony_ci			break;
55362306a36Sopenharmony_ci#ifdef CONFIG_AF_RXRPC_IPV6
55462306a36Sopenharmony_ci		case AF_INET6:
55562306a36Sopenharmony_ci			rx->srx.transport_len = sizeof(struct sockaddr_in6);
55662306a36Sopenharmony_ci			break;
55762306a36Sopenharmony_ci#endif
55862306a36Sopenharmony_ci		default:
55962306a36Sopenharmony_ci			ret = -EAFNOSUPPORT;
56062306a36Sopenharmony_ci			goto error_unlock;
56162306a36Sopenharmony_ci		}
56262306a36Sopenharmony_ci		local = rxrpc_lookup_local(sock_net(sock->sk), &rx->srx);
56362306a36Sopenharmony_ci		if (IS_ERR(local)) {
56462306a36Sopenharmony_ci			ret = PTR_ERR(local);
56562306a36Sopenharmony_ci			goto error_unlock;
56662306a36Sopenharmony_ci		}
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci		rx->local = local;
56962306a36Sopenharmony_ci		rx->sk.sk_state = RXRPC_CLIENT_BOUND;
57062306a36Sopenharmony_ci		fallthrough;
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	case RXRPC_CLIENT_BOUND:
57362306a36Sopenharmony_ci		if (!m->msg_name &&
57462306a36Sopenharmony_ci		    test_bit(RXRPC_SOCK_CONNECTED, &rx->flags)) {
57562306a36Sopenharmony_ci			m->msg_name = &rx->connect_srx;
57662306a36Sopenharmony_ci			m->msg_namelen = sizeof(rx->connect_srx);
57762306a36Sopenharmony_ci		}
57862306a36Sopenharmony_ci		fallthrough;
57962306a36Sopenharmony_ci	case RXRPC_SERVER_BOUND:
58062306a36Sopenharmony_ci	case RXRPC_SERVER_LISTENING:
58162306a36Sopenharmony_ci		ret = rxrpc_do_sendmsg(rx, m, len);
58262306a36Sopenharmony_ci		/* The socket has been unlocked */
58362306a36Sopenharmony_ci		goto out;
58462306a36Sopenharmony_ci	default:
58562306a36Sopenharmony_ci		ret = -EINVAL;
58662306a36Sopenharmony_ci		goto error_unlock;
58762306a36Sopenharmony_ci	}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_cierror_unlock:
59062306a36Sopenharmony_ci	release_sock(&rx->sk);
59162306a36Sopenharmony_ciout:
59262306a36Sopenharmony_ci	_leave(" = %d", ret);
59362306a36Sopenharmony_ci	return ret;
59462306a36Sopenharmony_ci}
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ciint rxrpc_sock_set_min_security_level(struct sock *sk, unsigned int val)
59762306a36Sopenharmony_ci{
59862306a36Sopenharmony_ci	if (sk->sk_state != RXRPC_UNBOUND)
59962306a36Sopenharmony_ci		return -EISCONN;
60062306a36Sopenharmony_ci	if (val > RXRPC_SECURITY_MAX)
60162306a36Sopenharmony_ci		return -EINVAL;
60262306a36Sopenharmony_ci	lock_sock(sk);
60362306a36Sopenharmony_ci	rxrpc_sk(sk)->min_sec_level = val;
60462306a36Sopenharmony_ci	release_sock(sk);
60562306a36Sopenharmony_ci	return 0;
60662306a36Sopenharmony_ci}
60762306a36Sopenharmony_ciEXPORT_SYMBOL(rxrpc_sock_set_min_security_level);
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci/*
61062306a36Sopenharmony_ci * set RxRPC socket options
61162306a36Sopenharmony_ci */
61262306a36Sopenharmony_cistatic int rxrpc_setsockopt(struct socket *sock, int level, int optname,
61362306a36Sopenharmony_ci			    sockptr_t optval, unsigned int optlen)
61462306a36Sopenharmony_ci{
61562306a36Sopenharmony_ci	struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
61662306a36Sopenharmony_ci	unsigned int min_sec_level;
61762306a36Sopenharmony_ci	u16 service_upgrade[2];
61862306a36Sopenharmony_ci	int ret;
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	_enter(",%d,%d,,%d", level, optname, optlen);
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	lock_sock(&rx->sk);
62362306a36Sopenharmony_ci	ret = -EOPNOTSUPP;
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	if (level == SOL_RXRPC) {
62662306a36Sopenharmony_ci		switch (optname) {
62762306a36Sopenharmony_ci		case RXRPC_EXCLUSIVE_CONNECTION:
62862306a36Sopenharmony_ci			ret = -EINVAL;
62962306a36Sopenharmony_ci			if (optlen != 0)
63062306a36Sopenharmony_ci				goto error;
63162306a36Sopenharmony_ci			ret = -EISCONN;
63262306a36Sopenharmony_ci			if (rx->sk.sk_state != RXRPC_UNBOUND)
63362306a36Sopenharmony_ci				goto error;
63462306a36Sopenharmony_ci			rx->exclusive = true;
63562306a36Sopenharmony_ci			goto success;
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci		case RXRPC_SECURITY_KEY:
63862306a36Sopenharmony_ci			ret = -EINVAL;
63962306a36Sopenharmony_ci			if (rx->key)
64062306a36Sopenharmony_ci				goto error;
64162306a36Sopenharmony_ci			ret = -EISCONN;
64262306a36Sopenharmony_ci			if (rx->sk.sk_state != RXRPC_UNBOUND)
64362306a36Sopenharmony_ci				goto error;
64462306a36Sopenharmony_ci			ret = rxrpc_request_key(rx, optval, optlen);
64562306a36Sopenharmony_ci			goto error;
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci		case RXRPC_SECURITY_KEYRING:
64862306a36Sopenharmony_ci			ret = -EINVAL;
64962306a36Sopenharmony_ci			if (rx->key)
65062306a36Sopenharmony_ci				goto error;
65162306a36Sopenharmony_ci			ret = -EISCONN;
65262306a36Sopenharmony_ci			if (rx->sk.sk_state != RXRPC_UNBOUND)
65362306a36Sopenharmony_ci				goto error;
65462306a36Sopenharmony_ci			ret = rxrpc_server_keyring(rx, optval, optlen);
65562306a36Sopenharmony_ci			goto error;
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci		case RXRPC_MIN_SECURITY_LEVEL:
65862306a36Sopenharmony_ci			ret = -EINVAL;
65962306a36Sopenharmony_ci			if (optlen != sizeof(unsigned int))
66062306a36Sopenharmony_ci				goto error;
66162306a36Sopenharmony_ci			ret = -EISCONN;
66262306a36Sopenharmony_ci			if (rx->sk.sk_state != RXRPC_UNBOUND)
66362306a36Sopenharmony_ci				goto error;
66462306a36Sopenharmony_ci			ret = copy_from_sockptr(&min_sec_level, optval,
66562306a36Sopenharmony_ci				       sizeof(unsigned int));
66662306a36Sopenharmony_ci			if (ret < 0)
66762306a36Sopenharmony_ci				goto error;
66862306a36Sopenharmony_ci			ret = -EINVAL;
66962306a36Sopenharmony_ci			if (min_sec_level > RXRPC_SECURITY_MAX)
67062306a36Sopenharmony_ci				goto error;
67162306a36Sopenharmony_ci			rx->min_sec_level = min_sec_level;
67262306a36Sopenharmony_ci			goto success;
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci		case RXRPC_UPGRADEABLE_SERVICE:
67562306a36Sopenharmony_ci			ret = -EINVAL;
67662306a36Sopenharmony_ci			if (optlen != sizeof(service_upgrade) ||
67762306a36Sopenharmony_ci			    rx->service_upgrade.from != 0)
67862306a36Sopenharmony_ci				goto error;
67962306a36Sopenharmony_ci			ret = -EISCONN;
68062306a36Sopenharmony_ci			if (rx->sk.sk_state != RXRPC_SERVER_BOUND2)
68162306a36Sopenharmony_ci				goto error;
68262306a36Sopenharmony_ci			ret = -EFAULT;
68362306a36Sopenharmony_ci			if (copy_from_sockptr(service_upgrade, optval,
68462306a36Sopenharmony_ci					   sizeof(service_upgrade)) != 0)
68562306a36Sopenharmony_ci				goto error;
68662306a36Sopenharmony_ci			ret = -EINVAL;
68762306a36Sopenharmony_ci			if ((service_upgrade[0] != rx->srx.srx_service ||
68862306a36Sopenharmony_ci			     service_upgrade[1] != rx->second_service) &&
68962306a36Sopenharmony_ci			    (service_upgrade[0] != rx->second_service ||
69062306a36Sopenharmony_ci			     service_upgrade[1] != rx->srx.srx_service))
69162306a36Sopenharmony_ci				goto error;
69262306a36Sopenharmony_ci			rx->service_upgrade.from = service_upgrade[0];
69362306a36Sopenharmony_ci			rx->service_upgrade.to = service_upgrade[1];
69462306a36Sopenharmony_ci			goto success;
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci		default:
69762306a36Sopenharmony_ci			break;
69862306a36Sopenharmony_ci		}
69962306a36Sopenharmony_ci	}
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_cisuccess:
70262306a36Sopenharmony_ci	ret = 0;
70362306a36Sopenharmony_cierror:
70462306a36Sopenharmony_ci	release_sock(&rx->sk);
70562306a36Sopenharmony_ci	return ret;
70662306a36Sopenharmony_ci}
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci/*
70962306a36Sopenharmony_ci * Get socket options.
71062306a36Sopenharmony_ci */
71162306a36Sopenharmony_cistatic int rxrpc_getsockopt(struct socket *sock, int level, int optname,
71262306a36Sopenharmony_ci			    char __user *optval, int __user *_optlen)
71362306a36Sopenharmony_ci{
71462306a36Sopenharmony_ci	int optlen;
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci	if (level != SOL_RXRPC)
71762306a36Sopenharmony_ci		return -EOPNOTSUPP;
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	if (get_user(optlen, _optlen))
72062306a36Sopenharmony_ci		return -EFAULT;
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	switch (optname) {
72362306a36Sopenharmony_ci	case RXRPC_SUPPORTED_CMSG:
72462306a36Sopenharmony_ci		if (optlen < sizeof(int))
72562306a36Sopenharmony_ci			return -ETOOSMALL;
72662306a36Sopenharmony_ci		if (put_user(RXRPC__SUPPORTED - 1, (int __user *)optval) ||
72762306a36Sopenharmony_ci		    put_user(sizeof(int), _optlen))
72862306a36Sopenharmony_ci			return -EFAULT;
72962306a36Sopenharmony_ci		return 0;
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	default:
73262306a36Sopenharmony_ci		return -EOPNOTSUPP;
73362306a36Sopenharmony_ci	}
73462306a36Sopenharmony_ci}
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci/*
73762306a36Sopenharmony_ci * permit an RxRPC socket to be polled
73862306a36Sopenharmony_ci */
73962306a36Sopenharmony_cistatic __poll_t rxrpc_poll(struct file *file, struct socket *sock,
74062306a36Sopenharmony_ci			       poll_table *wait)
74162306a36Sopenharmony_ci{
74262306a36Sopenharmony_ci	struct sock *sk = sock->sk;
74362306a36Sopenharmony_ci	struct rxrpc_sock *rx = rxrpc_sk(sk);
74462306a36Sopenharmony_ci	__poll_t mask;
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	sock_poll_wait(file, sock, wait);
74762306a36Sopenharmony_ci	mask = 0;
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci	/* the socket is readable if there are any messages waiting on the Rx
75062306a36Sopenharmony_ci	 * queue */
75162306a36Sopenharmony_ci	if (!list_empty(&rx->recvmsg_q))
75262306a36Sopenharmony_ci		mask |= EPOLLIN | EPOLLRDNORM;
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_ci	/* the socket is writable if there is space to add new data to the
75562306a36Sopenharmony_ci	 * socket; there is no guarantee that any particular call in progress
75662306a36Sopenharmony_ci	 * on the socket may have space in the Tx ACK window */
75762306a36Sopenharmony_ci	if (rxrpc_writable(sk))
75862306a36Sopenharmony_ci		mask |= EPOLLOUT | EPOLLWRNORM;
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	return mask;
76162306a36Sopenharmony_ci}
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci/*
76462306a36Sopenharmony_ci * create an RxRPC socket
76562306a36Sopenharmony_ci */
76662306a36Sopenharmony_cistatic int rxrpc_create(struct net *net, struct socket *sock, int protocol,
76762306a36Sopenharmony_ci			int kern)
76862306a36Sopenharmony_ci{
76962306a36Sopenharmony_ci	struct rxrpc_net *rxnet;
77062306a36Sopenharmony_ci	struct rxrpc_sock *rx;
77162306a36Sopenharmony_ci	struct sock *sk;
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	_enter("%p,%d", sock, protocol);
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci	/* we support transport protocol UDP/UDP6 only */
77662306a36Sopenharmony_ci	if (protocol != PF_INET &&
77762306a36Sopenharmony_ci	    IS_ENABLED(CONFIG_AF_RXRPC_IPV6) && protocol != PF_INET6)
77862306a36Sopenharmony_ci		return -EPROTONOSUPPORT;
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_ci	if (sock->type != SOCK_DGRAM)
78162306a36Sopenharmony_ci		return -ESOCKTNOSUPPORT;
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci	sock->ops = &rxrpc_rpc_ops;
78462306a36Sopenharmony_ci	sock->state = SS_UNCONNECTED;
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	sk = sk_alloc(net, PF_RXRPC, GFP_KERNEL, &rxrpc_proto, kern);
78762306a36Sopenharmony_ci	if (!sk)
78862306a36Sopenharmony_ci		return -ENOMEM;
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci	sock_init_data(sock, sk);
79162306a36Sopenharmony_ci	sock_set_flag(sk, SOCK_RCU_FREE);
79262306a36Sopenharmony_ci	sk->sk_state		= RXRPC_UNBOUND;
79362306a36Sopenharmony_ci	sk->sk_write_space	= rxrpc_write_space;
79462306a36Sopenharmony_ci	sk->sk_max_ack_backlog	= 0;
79562306a36Sopenharmony_ci	sk->sk_destruct		= rxrpc_sock_destructor;
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci	rx = rxrpc_sk(sk);
79862306a36Sopenharmony_ci	rx->family = protocol;
79962306a36Sopenharmony_ci	rx->calls = RB_ROOT;
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci	spin_lock_init(&rx->incoming_lock);
80262306a36Sopenharmony_ci	INIT_LIST_HEAD(&rx->sock_calls);
80362306a36Sopenharmony_ci	INIT_LIST_HEAD(&rx->to_be_accepted);
80462306a36Sopenharmony_ci	INIT_LIST_HEAD(&rx->recvmsg_q);
80562306a36Sopenharmony_ci	spin_lock_init(&rx->recvmsg_lock);
80662306a36Sopenharmony_ci	rwlock_init(&rx->call_lock);
80762306a36Sopenharmony_ci	memset(&rx->srx, 0, sizeof(rx->srx));
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci	rxnet = rxrpc_net(sock_net(&rx->sk));
81062306a36Sopenharmony_ci	timer_reduce(&rxnet->peer_keepalive_timer, jiffies + 1);
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci	_leave(" = 0 [%p]", rx);
81362306a36Sopenharmony_ci	return 0;
81462306a36Sopenharmony_ci}
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci/*
81762306a36Sopenharmony_ci * Kill all the calls on a socket and shut it down.
81862306a36Sopenharmony_ci */
81962306a36Sopenharmony_cistatic int rxrpc_shutdown(struct socket *sock, int flags)
82062306a36Sopenharmony_ci{
82162306a36Sopenharmony_ci	struct sock *sk = sock->sk;
82262306a36Sopenharmony_ci	struct rxrpc_sock *rx = rxrpc_sk(sk);
82362306a36Sopenharmony_ci	int ret = 0;
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_ci	_enter("%p,%d", sk, flags);
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci	if (flags != SHUT_RDWR)
82862306a36Sopenharmony_ci		return -EOPNOTSUPP;
82962306a36Sopenharmony_ci	if (sk->sk_state == RXRPC_CLOSE)
83062306a36Sopenharmony_ci		return -ESHUTDOWN;
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	lock_sock(sk);
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	if (sk->sk_state < RXRPC_CLOSE) {
83562306a36Sopenharmony_ci		sk->sk_state = RXRPC_CLOSE;
83662306a36Sopenharmony_ci		sk->sk_shutdown = SHUTDOWN_MASK;
83762306a36Sopenharmony_ci	} else {
83862306a36Sopenharmony_ci		ret = -ESHUTDOWN;
83962306a36Sopenharmony_ci	}
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci	rxrpc_discard_prealloc(rx);
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	release_sock(sk);
84462306a36Sopenharmony_ci	return ret;
84562306a36Sopenharmony_ci}
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci/*
84862306a36Sopenharmony_ci * RxRPC socket destructor
84962306a36Sopenharmony_ci */
85062306a36Sopenharmony_cistatic void rxrpc_sock_destructor(struct sock *sk)
85162306a36Sopenharmony_ci{
85262306a36Sopenharmony_ci	_enter("%p", sk);
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	rxrpc_purge_queue(&sk->sk_receive_queue);
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	WARN_ON(refcount_read(&sk->sk_wmem_alloc));
85762306a36Sopenharmony_ci	WARN_ON(!sk_unhashed(sk));
85862306a36Sopenharmony_ci	WARN_ON(sk->sk_socket);
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci	if (!sock_flag(sk, SOCK_DEAD)) {
86162306a36Sopenharmony_ci		printk("Attempt to release alive rxrpc socket: %p\n", sk);
86262306a36Sopenharmony_ci		return;
86362306a36Sopenharmony_ci	}
86462306a36Sopenharmony_ci}
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci/*
86762306a36Sopenharmony_ci * release an RxRPC socket
86862306a36Sopenharmony_ci */
86962306a36Sopenharmony_cistatic int rxrpc_release_sock(struct sock *sk)
87062306a36Sopenharmony_ci{
87162306a36Sopenharmony_ci	struct rxrpc_sock *rx = rxrpc_sk(sk);
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci	_enter("%p{%d,%d}", sk, sk->sk_state, refcount_read(&sk->sk_refcnt));
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci	/* declare the socket closed for business */
87662306a36Sopenharmony_ci	sock_orphan(sk);
87762306a36Sopenharmony_ci	sk->sk_shutdown = SHUTDOWN_MASK;
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	/* We want to kill off all connections from a service socket
88062306a36Sopenharmony_ci	 * as fast as possible because we can't share these; client
88162306a36Sopenharmony_ci	 * sockets, on the other hand, can share an endpoint.
88262306a36Sopenharmony_ci	 */
88362306a36Sopenharmony_ci	switch (sk->sk_state) {
88462306a36Sopenharmony_ci	case RXRPC_SERVER_BOUND:
88562306a36Sopenharmony_ci	case RXRPC_SERVER_BOUND2:
88662306a36Sopenharmony_ci	case RXRPC_SERVER_LISTENING:
88762306a36Sopenharmony_ci	case RXRPC_SERVER_LISTEN_DISABLED:
88862306a36Sopenharmony_ci		rx->local->service_closed = true;
88962306a36Sopenharmony_ci		break;
89062306a36Sopenharmony_ci	}
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci	sk->sk_state = RXRPC_CLOSE;
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_ci	if (rx->local && rx->local->service == rx) {
89562306a36Sopenharmony_ci		write_lock(&rx->local->services_lock);
89662306a36Sopenharmony_ci		rx->local->service = NULL;
89762306a36Sopenharmony_ci		write_unlock(&rx->local->services_lock);
89862306a36Sopenharmony_ci	}
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	/* try to flush out this socket */
90162306a36Sopenharmony_ci	rxrpc_discard_prealloc(rx);
90262306a36Sopenharmony_ci	rxrpc_release_calls_on_socket(rx);
90362306a36Sopenharmony_ci	flush_workqueue(rxrpc_workqueue);
90462306a36Sopenharmony_ci	rxrpc_purge_queue(&sk->sk_receive_queue);
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	rxrpc_unuse_local(rx->local, rxrpc_local_unuse_release_sock);
90762306a36Sopenharmony_ci	rxrpc_put_local(rx->local, rxrpc_local_put_release_sock);
90862306a36Sopenharmony_ci	rx->local = NULL;
90962306a36Sopenharmony_ci	key_put(rx->key);
91062306a36Sopenharmony_ci	rx->key = NULL;
91162306a36Sopenharmony_ci	key_put(rx->securities);
91262306a36Sopenharmony_ci	rx->securities = NULL;
91362306a36Sopenharmony_ci	sock_put(sk);
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	_leave(" = 0");
91662306a36Sopenharmony_ci	return 0;
91762306a36Sopenharmony_ci}
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci/*
92062306a36Sopenharmony_ci * release an RxRPC BSD socket on close() or equivalent
92162306a36Sopenharmony_ci */
92262306a36Sopenharmony_cistatic int rxrpc_release(struct socket *sock)
92362306a36Sopenharmony_ci{
92462306a36Sopenharmony_ci	struct sock *sk = sock->sk;
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci	_enter("%p{%p}", sock, sk);
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci	if (!sk)
92962306a36Sopenharmony_ci		return 0;
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	sock->sk = NULL;
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci	return rxrpc_release_sock(sk);
93462306a36Sopenharmony_ci}
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci/*
93762306a36Sopenharmony_ci * RxRPC network protocol
93862306a36Sopenharmony_ci */
93962306a36Sopenharmony_cistatic const struct proto_ops rxrpc_rpc_ops = {
94062306a36Sopenharmony_ci	.family		= PF_RXRPC,
94162306a36Sopenharmony_ci	.owner		= THIS_MODULE,
94262306a36Sopenharmony_ci	.release	= rxrpc_release,
94362306a36Sopenharmony_ci	.bind		= rxrpc_bind,
94462306a36Sopenharmony_ci	.connect	= rxrpc_connect,
94562306a36Sopenharmony_ci	.socketpair	= sock_no_socketpair,
94662306a36Sopenharmony_ci	.accept		= sock_no_accept,
94762306a36Sopenharmony_ci	.getname	= sock_no_getname,
94862306a36Sopenharmony_ci	.poll		= rxrpc_poll,
94962306a36Sopenharmony_ci	.ioctl		= sock_no_ioctl,
95062306a36Sopenharmony_ci	.listen		= rxrpc_listen,
95162306a36Sopenharmony_ci	.shutdown	= rxrpc_shutdown,
95262306a36Sopenharmony_ci	.setsockopt	= rxrpc_setsockopt,
95362306a36Sopenharmony_ci	.getsockopt	= rxrpc_getsockopt,
95462306a36Sopenharmony_ci	.sendmsg	= rxrpc_sendmsg,
95562306a36Sopenharmony_ci	.recvmsg	= rxrpc_recvmsg,
95662306a36Sopenharmony_ci	.mmap		= sock_no_mmap,
95762306a36Sopenharmony_ci};
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_cistatic struct proto rxrpc_proto = {
96062306a36Sopenharmony_ci	.name		= "RXRPC",
96162306a36Sopenharmony_ci	.owner		= THIS_MODULE,
96262306a36Sopenharmony_ci	.obj_size	= sizeof(struct rxrpc_sock),
96362306a36Sopenharmony_ci	.max_header	= sizeof(struct rxrpc_wire_header),
96462306a36Sopenharmony_ci};
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_cistatic const struct net_proto_family rxrpc_family_ops = {
96762306a36Sopenharmony_ci	.family	= PF_RXRPC,
96862306a36Sopenharmony_ci	.create = rxrpc_create,
96962306a36Sopenharmony_ci	.owner	= THIS_MODULE,
97062306a36Sopenharmony_ci};
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci/*
97362306a36Sopenharmony_ci * initialise and register the RxRPC protocol
97462306a36Sopenharmony_ci */
97562306a36Sopenharmony_cistatic int __init af_rxrpc_init(void)
97662306a36Sopenharmony_ci{
97762306a36Sopenharmony_ci	int ret = -1;
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct rxrpc_skb_priv) > sizeof_field(struct sk_buff, cb));
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci	ret = -ENOMEM;
98262306a36Sopenharmony_ci	rxrpc_gen_version_string();
98362306a36Sopenharmony_ci	rxrpc_call_jar = kmem_cache_create(
98462306a36Sopenharmony_ci		"rxrpc_call_jar", sizeof(struct rxrpc_call), 0,
98562306a36Sopenharmony_ci		SLAB_HWCACHE_ALIGN, NULL);
98662306a36Sopenharmony_ci	if (!rxrpc_call_jar) {
98762306a36Sopenharmony_ci		pr_notice("Failed to allocate call jar\n");
98862306a36Sopenharmony_ci		goto error_call_jar;
98962306a36Sopenharmony_ci	}
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	rxrpc_workqueue = alloc_ordered_workqueue("krxrpcd", WQ_HIGHPRI | WQ_MEM_RECLAIM);
99262306a36Sopenharmony_ci	if (!rxrpc_workqueue) {
99362306a36Sopenharmony_ci		pr_notice("Failed to allocate work queue\n");
99462306a36Sopenharmony_ci		goto error_work_queue;
99562306a36Sopenharmony_ci	}
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci	ret = rxrpc_init_security();
99862306a36Sopenharmony_ci	if (ret < 0) {
99962306a36Sopenharmony_ci		pr_crit("Cannot initialise security\n");
100062306a36Sopenharmony_ci		goto error_security;
100162306a36Sopenharmony_ci	}
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_ci	ret = register_pernet_device(&rxrpc_net_ops);
100462306a36Sopenharmony_ci	if (ret)
100562306a36Sopenharmony_ci		goto error_pernet;
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	ret = proto_register(&rxrpc_proto, 1);
100862306a36Sopenharmony_ci	if (ret < 0) {
100962306a36Sopenharmony_ci		pr_crit("Cannot register protocol\n");
101062306a36Sopenharmony_ci		goto error_proto;
101162306a36Sopenharmony_ci	}
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci	ret = sock_register(&rxrpc_family_ops);
101462306a36Sopenharmony_ci	if (ret < 0) {
101562306a36Sopenharmony_ci		pr_crit("Cannot register socket family\n");
101662306a36Sopenharmony_ci		goto error_sock;
101762306a36Sopenharmony_ci	}
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	ret = register_key_type(&key_type_rxrpc);
102062306a36Sopenharmony_ci	if (ret < 0) {
102162306a36Sopenharmony_ci		pr_crit("Cannot register client key type\n");
102262306a36Sopenharmony_ci		goto error_key_type;
102362306a36Sopenharmony_ci	}
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci	ret = register_key_type(&key_type_rxrpc_s);
102662306a36Sopenharmony_ci	if (ret < 0) {
102762306a36Sopenharmony_ci		pr_crit("Cannot register server key type\n");
102862306a36Sopenharmony_ci		goto error_key_type_s;
102962306a36Sopenharmony_ci	}
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci	ret = rxrpc_sysctl_init();
103262306a36Sopenharmony_ci	if (ret < 0) {
103362306a36Sopenharmony_ci		pr_crit("Cannot register sysctls\n");
103462306a36Sopenharmony_ci		goto error_sysctls;
103562306a36Sopenharmony_ci	}
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci	return 0;
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_cierror_sysctls:
104062306a36Sopenharmony_ci	unregister_key_type(&key_type_rxrpc_s);
104162306a36Sopenharmony_cierror_key_type_s:
104262306a36Sopenharmony_ci	unregister_key_type(&key_type_rxrpc);
104362306a36Sopenharmony_cierror_key_type:
104462306a36Sopenharmony_ci	sock_unregister(PF_RXRPC);
104562306a36Sopenharmony_cierror_sock:
104662306a36Sopenharmony_ci	proto_unregister(&rxrpc_proto);
104762306a36Sopenharmony_cierror_proto:
104862306a36Sopenharmony_ci	unregister_pernet_device(&rxrpc_net_ops);
104962306a36Sopenharmony_cierror_pernet:
105062306a36Sopenharmony_ci	rxrpc_exit_security();
105162306a36Sopenharmony_cierror_security:
105262306a36Sopenharmony_ci	destroy_workqueue(rxrpc_workqueue);
105362306a36Sopenharmony_cierror_work_queue:
105462306a36Sopenharmony_ci	kmem_cache_destroy(rxrpc_call_jar);
105562306a36Sopenharmony_cierror_call_jar:
105662306a36Sopenharmony_ci	return ret;
105762306a36Sopenharmony_ci}
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci/*
106062306a36Sopenharmony_ci * unregister the RxRPC protocol
106162306a36Sopenharmony_ci */
106262306a36Sopenharmony_cistatic void __exit af_rxrpc_exit(void)
106362306a36Sopenharmony_ci{
106462306a36Sopenharmony_ci	_enter("");
106562306a36Sopenharmony_ci	rxrpc_sysctl_exit();
106662306a36Sopenharmony_ci	unregister_key_type(&key_type_rxrpc_s);
106762306a36Sopenharmony_ci	unregister_key_type(&key_type_rxrpc);
106862306a36Sopenharmony_ci	sock_unregister(PF_RXRPC);
106962306a36Sopenharmony_ci	proto_unregister(&rxrpc_proto);
107062306a36Sopenharmony_ci	unregister_pernet_device(&rxrpc_net_ops);
107162306a36Sopenharmony_ci	ASSERTCMP(atomic_read(&rxrpc_n_rx_skbs), ==, 0);
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci	/* Make sure the local and peer records pinned by any dying connections
107462306a36Sopenharmony_ci	 * are released.
107562306a36Sopenharmony_ci	 */
107662306a36Sopenharmony_ci	rcu_barrier();
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	destroy_workqueue(rxrpc_workqueue);
107962306a36Sopenharmony_ci	rxrpc_exit_security();
108062306a36Sopenharmony_ci	kmem_cache_destroy(rxrpc_call_jar);
108162306a36Sopenharmony_ci	_leave("");
108262306a36Sopenharmony_ci}
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_cimodule_init(af_rxrpc_init);
108562306a36Sopenharmony_cimodule_exit(af_rxrpc_exit);
1086