162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/* RxRPC packet reception
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2007, 2016, 2022 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 "ar-internal.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistatic int rxrpc_input_packet_on_conn(struct rxrpc_connection *conn,
1362306a36Sopenharmony_ci				      struct sockaddr_rxrpc *peer_srx,
1462306a36Sopenharmony_ci				      struct sk_buff *skb);
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/*
1762306a36Sopenharmony_ci * handle data received on the local endpoint
1862306a36Sopenharmony_ci * - may be called in interrupt context
1962306a36Sopenharmony_ci *
2062306a36Sopenharmony_ci * [!] Note that as this is called from the encap_rcv hook, the socket is not
2162306a36Sopenharmony_ci * held locked by the caller and nothing prevents sk_user_data on the UDP from
2262306a36Sopenharmony_ci * being cleared in the middle of processing this function.
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * Called with the RCU read lock held from the IP layer via UDP.
2562306a36Sopenharmony_ci */
2662306a36Sopenharmony_ciint rxrpc_encap_rcv(struct sock *udp_sk, struct sk_buff *skb)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	struct sk_buff_head *rx_queue;
2962306a36Sopenharmony_ci	struct rxrpc_local *local = rcu_dereference_sk_user_data(udp_sk);
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	if (unlikely(!local)) {
3262306a36Sopenharmony_ci		kfree_skb(skb);
3362306a36Sopenharmony_ci		return 0;
3462306a36Sopenharmony_ci	}
3562306a36Sopenharmony_ci	if (skb->tstamp == 0)
3662306a36Sopenharmony_ci		skb->tstamp = ktime_get_real();
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	skb->mark = RXRPC_SKB_MARK_PACKET;
3962306a36Sopenharmony_ci	rxrpc_new_skb(skb, rxrpc_skb_new_encap_rcv);
4062306a36Sopenharmony_ci	rx_queue = &local->rx_queue;
4162306a36Sopenharmony_ci#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
4262306a36Sopenharmony_ci	if (rxrpc_inject_rx_delay ||
4362306a36Sopenharmony_ci	    !skb_queue_empty(&local->rx_delay_queue)) {
4462306a36Sopenharmony_ci		skb->tstamp = ktime_add_ms(skb->tstamp, rxrpc_inject_rx_delay);
4562306a36Sopenharmony_ci		rx_queue = &local->rx_delay_queue;
4662306a36Sopenharmony_ci	}
4762306a36Sopenharmony_ci#endif
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	skb_queue_tail(rx_queue, skb);
5062306a36Sopenharmony_ci	rxrpc_wake_up_io_thread(local);
5162306a36Sopenharmony_ci	return 0;
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci/*
5562306a36Sopenharmony_ci * Handle an error received on the local endpoint.
5662306a36Sopenharmony_ci */
5762306a36Sopenharmony_civoid rxrpc_error_report(struct sock *sk)
5862306a36Sopenharmony_ci{
5962306a36Sopenharmony_ci	struct rxrpc_local *local;
6062306a36Sopenharmony_ci	struct sk_buff *skb;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	rcu_read_lock();
6362306a36Sopenharmony_ci	local = rcu_dereference_sk_user_data(sk);
6462306a36Sopenharmony_ci	if (unlikely(!local)) {
6562306a36Sopenharmony_ci		rcu_read_unlock();
6662306a36Sopenharmony_ci		return;
6762306a36Sopenharmony_ci	}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	while ((skb = skb_dequeue(&sk->sk_error_queue))) {
7062306a36Sopenharmony_ci		skb->mark = RXRPC_SKB_MARK_ERROR;
7162306a36Sopenharmony_ci		rxrpc_new_skb(skb, rxrpc_skb_new_error_report);
7262306a36Sopenharmony_ci		skb_queue_tail(&local->rx_queue, skb);
7362306a36Sopenharmony_ci	}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	rxrpc_wake_up_io_thread(local);
7662306a36Sopenharmony_ci	rcu_read_unlock();
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci/*
8062306a36Sopenharmony_ci * Directly produce an abort from a packet.
8162306a36Sopenharmony_ci */
8262306a36Sopenharmony_cibool rxrpc_direct_abort(struct sk_buff *skb, enum rxrpc_abort_reason why,
8362306a36Sopenharmony_ci			s32 abort_code, int err)
8462306a36Sopenharmony_ci{
8562306a36Sopenharmony_ci	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	trace_rxrpc_abort(0, why, sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
8862306a36Sopenharmony_ci			  abort_code, err);
8962306a36Sopenharmony_ci	skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
9062306a36Sopenharmony_ci	skb->priority = abort_code;
9162306a36Sopenharmony_ci	return false;
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic bool rxrpc_bad_message(struct sk_buff *skb, enum rxrpc_abort_reason why)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	return rxrpc_direct_abort(skb, why, RX_PROTOCOL_ERROR, -EBADMSG);
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci#define just_discard true
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci/*
10262306a36Sopenharmony_ci * Process event packets targeted at a local endpoint.
10362306a36Sopenharmony_ci */
10462306a36Sopenharmony_cistatic bool rxrpc_input_version(struct rxrpc_local *local, struct sk_buff *skb)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
10762306a36Sopenharmony_ci	char v;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	_enter("");
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	rxrpc_see_skb(skb, rxrpc_skb_see_version);
11262306a36Sopenharmony_ci	if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), &v, 1) >= 0) {
11362306a36Sopenharmony_ci		if (v == 0)
11462306a36Sopenharmony_ci			rxrpc_send_version_request(local, &sp->hdr, skb);
11562306a36Sopenharmony_ci	}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	return true;
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci/*
12162306a36Sopenharmony_ci * Extract the wire header from a packet and translate the byte order.
12262306a36Sopenharmony_ci */
12362306a36Sopenharmony_cistatic bool rxrpc_extract_header(struct rxrpc_skb_priv *sp,
12462306a36Sopenharmony_ci				 struct sk_buff *skb)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	struct rxrpc_wire_header whdr;
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	/* dig out the RxRPC connection details */
12962306a36Sopenharmony_ci	if (skb_copy_bits(skb, 0, &whdr, sizeof(whdr)) < 0)
13062306a36Sopenharmony_ci		return rxrpc_bad_message(skb, rxrpc_badmsg_short_hdr);
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	memset(sp, 0, sizeof(*sp));
13362306a36Sopenharmony_ci	sp->hdr.epoch		= ntohl(whdr.epoch);
13462306a36Sopenharmony_ci	sp->hdr.cid		= ntohl(whdr.cid);
13562306a36Sopenharmony_ci	sp->hdr.callNumber	= ntohl(whdr.callNumber);
13662306a36Sopenharmony_ci	sp->hdr.seq		= ntohl(whdr.seq);
13762306a36Sopenharmony_ci	sp->hdr.serial		= ntohl(whdr.serial);
13862306a36Sopenharmony_ci	sp->hdr.flags		= whdr.flags;
13962306a36Sopenharmony_ci	sp->hdr.type		= whdr.type;
14062306a36Sopenharmony_ci	sp->hdr.userStatus	= whdr.userStatus;
14162306a36Sopenharmony_ci	sp->hdr.securityIndex	= whdr.securityIndex;
14262306a36Sopenharmony_ci	sp->hdr._rsvd		= ntohs(whdr._rsvd);
14362306a36Sopenharmony_ci	sp->hdr.serviceId	= ntohs(whdr.serviceId);
14462306a36Sopenharmony_ci	return true;
14562306a36Sopenharmony_ci}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci/*
14862306a36Sopenharmony_ci * Extract the abort code from an ABORT packet and stash it in skb->priority.
14962306a36Sopenharmony_ci */
15062306a36Sopenharmony_cistatic bool rxrpc_extract_abort(struct sk_buff *skb)
15162306a36Sopenharmony_ci{
15262306a36Sopenharmony_ci	__be32 wtmp;
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
15562306a36Sopenharmony_ci			  &wtmp, sizeof(wtmp)) < 0)
15662306a36Sopenharmony_ci		return false;
15762306a36Sopenharmony_ci	skb->priority = ntohl(wtmp);
15862306a36Sopenharmony_ci	return true;
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci/*
16262306a36Sopenharmony_ci * Process packets received on the local endpoint
16362306a36Sopenharmony_ci */
16462306a36Sopenharmony_cistatic bool rxrpc_input_packet(struct rxrpc_local *local, struct sk_buff **_skb)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	struct rxrpc_connection *conn;
16762306a36Sopenharmony_ci	struct sockaddr_rxrpc peer_srx;
16862306a36Sopenharmony_ci	struct rxrpc_skb_priv *sp;
16962306a36Sopenharmony_ci	struct rxrpc_peer *peer = NULL;
17062306a36Sopenharmony_ci	struct sk_buff *skb = *_skb;
17162306a36Sopenharmony_ci	bool ret = false;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	skb_pull(skb, sizeof(struct udphdr));
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	sp = rxrpc_skb(skb);
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	/* dig out the RxRPC connection details */
17862306a36Sopenharmony_ci	if (!rxrpc_extract_header(sp, skb))
17962306a36Sopenharmony_ci		return just_discard;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_AF_RXRPC_INJECT_LOSS)) {
18262306a36Sopenharmony_ci		static int lose;
18362306a36Sopenharmony_ci		if ((lose++ & 7) == 7) {
18462306a36Sopenharmony_ci			trace_rxrpc_rx_lose(sp);
18562306a36Sopenharmony_ci			return just_discard;
18662306a36Sopenharmony_ci		}
18762306a36Sopenharmony_ci	}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	trace_rxrpc_rx_packet(sp);
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	switch (sp->hdr.type) {
19262306a36Sopenharmony_ci	case RXRPC_PACKET_TYPE_VERSION:
19362306a36Sopenharmony_ci		if (rxrpc_to_client(sp))
19462306a36Sopenharmony_ci			return just_discard;
19562306a36Sopenharmony_ci		return rxrpc_input_version(local, skb);
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	case RXRPC_PACKET_TYPE_BUSY:
19862306a36Sopenharmony_ci		if (rxrpc_to_server(sp))
19962306a36Sopenharmony_ci			return just_discard;
20062306a36Sopenharmony_ci		fallthrough;
20162306a36Sopenharmony_ci	case RXRPC_PACKET_TYPE_ACK:
20262306a36Sopenharmony_ci	case RXRPC_PACKET_TYPE_ACKALL:
20362306a36Sopenharmony_ci		if (sp->hdr.callNumber == 0)
20462306a36Sopenharmony_ci			return rxrpc_bad_message(skb, rxrpc_badmsg_zero_call);
20562306a36Sopenharmony_ci		break;
20662306a36Sopenharmony_ci	case RXRPC_PACKET_TYPE_ABORT:
20762306a36Sopenharmony_ci		if (!rxrpc_extract_abort(skb))
20862306a36Sopenharmony_ci			return just_discard; /* Just discard if malformed */
20962306a36Sopenharmony_ci		break;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	case RXRPC_PACKET_TYPE_DATA:
21262306a36Sopenharmony_ci		if (sp->hdr.callNumber == 0)
21362306a36Sopenharmony_ci			return rxrpc_bad_message(skb, rxrpc_badmsg_zero_call);
21462306a36Sopenharmony_ci		if (sp->hdr.seq == 0)
21562306a36Sopenharmony_ci			return rxrpc_bad_message(skb, rxrpc_badmsg_zero_seq);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci		/* Unshare the packet so that it can be modified for in-place
21862306a36Sopenharmony_ci		 * decryption.
21962306a36Sopenharmony_ci		 */
22062306a36Sopenharmony_ci		if (sp->hdr.securityIndex != 0) {
22162306a36Sopenharmony_ci			skb = skb_unshare(skb, GFP_ATOMIC);
22262306a36Sopenharmony_ci			if (!skb) {
22362306a36Sopenharmony_ci				rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare_nomem);
22462306a36Sopenharmony_ci				*_skb = NULL;
22562306a36Sopenharmony_ci				return just_discard;
22662306a36Sopenharmony_ci			}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci			if (skb != *_skb) {
22962306a36Sopenharmony_ci				rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare);
23062306a36Sopenharmony_ci				*_skb = skb;
23162306a36Sopenharmony_ci				rxrpc_new_skb(skb, rxrpc_skb_new_unshared);
23262306a36Sopenharmony_ci				sp = rxrpc_skb(skb);
23362306a36Sopenharmony_ci			}
23462306a36Sopenharmony_ci		}
23562306a36Sopenharmony_ci		break;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	case RXRPC_PACKET_TYPE_CHALLENGE:
23862306a36Sopenharmony_ci		if (rxrpc_to_server(sp))
23962306a36Sopenharmony_ci			return just_discard;
24062306a36Sopenharmony_ci		break;
24162306a36Sopenharmony_ci	case RXRPC_PACKET_TYPE_RESPONSE:
24262306a36Sopenharmony_ci		if (rxrpc_to_client(sp))
24362306a36Sopenharmony_ci			return just_discard;
24462306a36Sopenharmony_ci		break;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci		/* Packet types 9-11 should just be ignored. */
24762306a36Sopenharmony_ci	case RXRPC_PACKET_TYPE_PARAMS:
24862306a36Sopenharmony_ci	case RXRPC_PACKET_TYPE_10:
24962306a36Sopenharmony_ci	case RXRPC_PACKET_TYPE_11:
25062306a36Sopenharmony_ci		return just_discard;
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	default:
25362306a36Sopenharmony_ci		return rxrpc_bad_message(skb, rxrpc_badmsg_unsupported_packet);
25462306a36Sopenharmony_ci	}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	if (sp->hdr.serviceId == 0)
25762306a36Sopenharmony_ci		return rxrpc_bad_message(skb, rxrpc_badmsg_zero_service);
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	if (WARN_ON_ONCE(rxrpc_extract_addr_from_skb(&peer_srx, skb) < 0))
26062306a36Sopenharmony_ci		return just_discard; /* Unsupported address type. */
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	if (peer_srx.transport.family != local->srx.transport.family &&
26362306a36Sopenharmony_ci	    (peer_srx.transport.family == AF_INET &&
26462306a36Sopenharmony_ci	     local->srx.transport.family != AF_INET6)) {
26562306a36Sopenharmony_ci		pr_warn_ratelimited("AF_RXRPC: Protocol mismatch %u not %u\n",
26662306a36Sopenharmony_ci				    peer_srx.transport.family,
26762306a36Sopenharmony_ci				    local->srx.transport.family);
26862306a36Sopenharmony_ci		return just_discard; /* Wrong address type. */
26962306a36Sopenharmony_ci	}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	if (rxrpc_to_client(sp)) {
27262306a36Sopenharmony_ci		rcu_read_lock();
27362306a36Sopenharmony_ci		conn = rxrpc_find_client_connection_rcu(local, &peer_srx, skb);
27462306a36Sopenharmony_ci		conn = rxrpc_get_connection_maybe(conn, rxrpc_conn_get_call_input);
27562306a36Sopenharmony_ci		rcu_read_unlock();
27662306a36Sopenharmony_ci		if (!conn)
27762306a36Sopenharmony_ci			return rxrpc_protocol_error(skb, rxrpc_eproto_no_client_conn);
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci		ret = rxrpc_input_packet_on_conn(conn, &peer_srx, skb);
28062306a36Sopenharmony_ci		rxrpc_put_connection(conn, rxrpc_conn_put_call_input);
28162306a36Sopenharmony_ci		return ret;
28262306a36Sopenharmony_ci	}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	/* We need to look up service connections by the full protocol
28562306a36Sopenharmony_ci	 * parameter set.  We look up the peer first as an intermediate step
28662306a36Sopenharmony_ci	 * and then the connection from the peer's tree.
28762306a36Sopenharmony_ci	 */
28862306a36Sopenharmony_ci	rcu_read_lock();
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	peer = rxrpc_lookup_peer_rcu(local, &peer_srx);
29162306a36Sopenharmony_ci	if (!peer) {
29262306a36Sopenharmony_ci		rcu_read_unlock();
29362306a36Sopenharmony_ci		return rxrpc_new_incoming_call(local, NULL, NULL, &peer_srx, skb);
29462306a36Sopenharmony_ci	}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	conn = rxrpc_find_service_conn_rcu(peer, skb);
29762306a36Sopenharmony_ci	conn = rxrpc_get_connection_maybe(conn, rxrpc_conn_get_call_input);
29862306a36Sopenharmony_ci	if (conn) {
29962306a36Sopenharmony_ci		rcu_read_unlock();
30062306a36Sopenharmony_ci		ret = rxrpc_input_packet_on_conn(conn, &peer_srx, skb);
30162306a36Sopenharmony_ci		rxrpc_put_connection(conn, rxrpc_conn_put_call_input);
30262306a36Sopenharmony_ci		return ret;
30362306a36Sopenharmony_ci	}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	peer = rxrpc_get_peer_maybe(peer, rxrpc_peer_get_input);
30662306a36Sopenharmony_ci	rcu_read_unlock();
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	ret = rxrpc_new_incoming_call(local, peer, NULL, &peer_srx, skb);
30962306a36Sopenharmony_ci	rxrpc_put_peer(peer, rxrpc_peer_put_input);
31062306a36Sopenharmony_ci	return ret;
31162306a36Sopenharmony_ci}
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci/*
31462306a36Sopenharmony_ci * Deal with a packet that's associated with an extant connection.
31562306a36Sopenharmony_ci */
31662306a36Sopenharmony_cistatic int rxrpc_input_packet_on_conn(struct rxrpc_connection *conn,
31762306a36Sopenharmony_ci				      struct sockaddr_rxrpc *peer_srx,
31862306a36Sopenharmony_ci				      struct sk_buff *skb)
31962306a36Sopenharmony_ci{
32062306a36Sopenharmony_ci	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
32162306a36Sopenharmony_ci	struct rxrpc_channel *chan;
32262306a36Sopenharmony_ci	struct rxrpc_call *call = NULL;
32362306a36Sopenharmony_ci	unsigned int channel;
32462306a36Sopenharmony_ci	bool ret;
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	if (sp->hdr.securityIndex != conn->security_ix)
32762306a36Sopenharmony_ci		return rxrpc_direct_abort(skb, rxrpc_eproto_wrong_security,
32862306a36Sopenharmony_ci					  RXKADINCONSISTENCY, -EBADMSG);
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	if (sp->hdr.serviceId != conn->service_id) {
33162306a36Sopenharmony_ci		int old_id;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci		if (!test_bit(RXRPC_CONN_PROBING_FOR_UPGRADE, &conn->flags))
33462306a36Sopenharmony_ci			return rxrpc_protocol_error(skb, rxrpc_eproto_reupgrade);
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci		old_id = cmpxchg(&conn->service_id, conn->orig_service_id,
33762306a36Sopenharmony_ci				 sp->hdr.serviceId);
33862306a36Sopenharmony_ci		if (old_id != conn->orig_service_id &&
33962306a36Sopenharmony_ci		    old_id != sp->hdr.serviceId)
34062306a36Sopenharmony_ci			return rxrpc_protocol_error(skb, rxrpc_eproto_bad_upgrade);
34162306a36Sopenharmony_ci	}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	if (after(sp->hdr.serial, conn->hi_serial))
34462306a36Sopenharmony_ci		conn->hi_serial = sp->hdr.serial;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	/* It's a connection-level packet if the call number is 0. */
34762306a36Sopenharmony_ci	if (sp->hdr.callNumber == 0)
34862306a36Sopenharmony_ci		return rxrpc_input_conn_packet(conn, skb);
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	/* Call-bound packets are routed by connection channel. */
35162306a36Sopenharmony_ci	channel = sp->hdr.cid & RXRPC_CHANNELMASK;
35262306a36Sopenharmony_ci	chan = &conn->channels[channel];
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	/* Ignore really old calls */
35562306a36Sopenharmony_ci	if (sp->hdr.callNumber < chan->last_call)
35662306a36Sopenharmony_ci		return just_discard;
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	if (sp->hdr.callNumber == chan->last_call) {
35962306a36Sopenharmony_ci		if (chan->call ||
36062306a36Sopenharmony_ci		    sp->hdr.type == RXRPC_PACKET_TYPE_ABORT)
36162306a36Sopenharmony_ci			return just_discard;
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci		/* For the previous service call, if completed successfully, we
36462306a36Sopenharmony_ci		 * discard all further packets.
36562306a36Sopenharmony_ci		 */
36662306a36Sopenharmony_ci		if (rxrpc_conn_is_service(conn) &&
36762306a36Sopenharmony_ci		    chan->last_type == RXRPC_PACKET_TYPE_ACK)
36862306a36Sopenharmony_ci			return just_discard;
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci		/* But otherwise we need to retransmit the final packet from
37162306a36Sopenharmony_ci		 * data cached in the connection record.
37262306a36Sopenharmony_ci		 */
37362306a36Sopenharmony_ci		if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA)
37462306a36Sopenharmony_ci			trace_rxrpc_rx_data(chan->call_debug_id,
37562306a36Sopenharmony_ci					    sp->hdr.seq,
37662306a36Sopenharmony_ci					    sp->hdr.serial,
37762306a36Sopenharmony_ci					    sp->hdr.flags);
37862306a36Sopenharmony_ci		rxrpc_conn_retransmit_call(conn, skb, channel);
37962306a36Sopenharmony_ci		return just_discard;
38062306a36Sopenharmony_ci	}
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	call = rxrpc_try_get_call(chan->call, rxrpc_call_get_input);
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	if (sp->hdr.callNumber > chan->call_id) {
38562306a36Sopenharmony_ci		if (rxrpc_to_client(sp)) {
38662306a36Sopenharmony_ci			rxrpc_put_call(call, rxrpc_call_put_input);
38762306a36Sopenharmony_ci			return rxrpc_protocol_error(skb,
38862306a36Sopenharmony_ci						    rxrpc_eproto_unexpected_implicit_end);
38962306a36Sopenharmony_ci		}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci		if (call) {
39262306a36Sopenharmony_ci			rxrpc_implicit_end_call(call, skb);
39362306a36Sopenharmony_ci			rxrpc_put_call(call, rxrpc_call_put_input);
39462306a36Sopenharmony_ci			call = NULL;
39562306a36Sopenharmony_ci		}
39662306a36Sopenharmony_ci	}
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	if (!call) {
39962306a36Sopenharmony_ci		if (rxrpc_to_client(sp))
40062306a36Sopenharmony_ci			return rxrpc_protocol_error(skb, rxrpc_eproto_no_client_call);
40162306a36Sopenharmony_ci		return rxrpc_new_incoming_call(conn->local, conn->peer, conn,
40262306a36Sopenharmony_ci					       peer_srx, skb);
40362306a36Sopenharmony_ci	}
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	ret = rxrpc_input_call_event(call, skb);
40662306a36Sopenharmony_ci	rxrpc_put_call(call, rxrpc_call_put_input);
40762306a36Sopenharmony_ci	return ret;
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci/*
41162306a36Sopenharmony_ci * I/O and event handling thread.
41262306a36Sopenharmony_ci */
41362306a36Sopenharmony_ciint rxrpc_io_thread(void *data)
41462306a36Sopenharmony_ci{
41562306a36Sopenharmony_ci	struct rxrpc_connection *conn;
41662306a36Sopenharmony_ci	struct sk_buff_head rx_queue;
41762306a36Sopenharmony_ci	struct rxrpc_local *local = data;
41862306a36Sopenharmony_ci	struct rxrpc_call *call;
41962306a36Sopenharmony_ci	struct sk_buff *skb;
42062306a36Sopenharmony_ci#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
42162306a36Sopenharmony_ci	ktime_t now;
42262306a36Sopenharmony_ci#endif
42362306a36Sopenharmony_ci	bool should_stop;
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	complete(&local->io_thread_ready);
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	skb_queue_head_init(&rx_queue);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	set_user_nice(current, MIN_NICE);
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	for (;;) {
43262306a36Sopenharmony_ci		rxrpc_inc_stat(local->rxnet, stat_io_loop);
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci		/* Deal with connections that want immediate attention. */
43562306a36Sopenharmony_ci		conn = list_first_entry_or_null(&local->conn_attend_q,
43662306a36Sopenharmony_ci						struct rxrpc_connection,
43762306a36Sopenharmony_ci						attend_link);
43862306a36Sopenharmony_ci		if (conn) {
43962306a36Sopenharmony_ci			spin_lock_bh(&local->lock);
44062306a36Sopenharmony_ci			list_del_init(&conn->attend_link);
44162306a36Sopenharmony_ci			spin_unlock_bh(&local->lock);
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci			rxrpc_input_conn_event(conn, NULL);
44462306a36Sopenharmony_ci			rxrpc_put_connection(conn, rxrpc_conn_put_poke);
44562306a36Sopenharmony_ci			continue;
44662306a36Sopenharmony_ci		}
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci		if (test_and_clear_bit(RXRPC_CLIENT_CONN_REAP_TIMER,
44962306a36Sopenharmony_ci				       &local->client_conn_flags))
45062306a36Sopenharmony_ci			rxrpc_discard_expired_client_conns(local);
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci		/* Deal with calls that want immediate attention. */
45362306a36Sopenharmony_ci		if ((call = list_first_entry_or_null(&local->call_attend_q,
45462306a36Sopenharmony_ci						     struct rxrpc_call,
45562306a36Sopenharmony_ci						     attend_link))) {
45662306a36Sopenharmony_ci			spin_lock_bh(&local->lock);
45762306a36Sopenharmony_ci			list_del_init(&call->attend_link);
45862306a36Sopenharmony_ci			spin_unlock_bh(&local->lock);
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci			trace_rxrpc_call_poked(call);
46162306a36Sopenharmony_ci			rxrpc_input_call_event(call, NULL);
46262306a36Sopenharmony_ci			rxrpc_put_call(call, rxrpc_call_put_poke);
46362306a36Sopenharmony_ci			continue;
46462306a36Sopenharmony_ci		}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci		if (!list_empty(&local->new_client_calls))
46762306a36Sopenharmony_ci			rxrpc_connect_client_calls(local);
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci		/* Process received packets and errors. */
47062306a36Sopenharmony_ci		if ((skb = __skb_dequeue(&rx_queue))) {
47162306a36Sopenharmony_ci			struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
47262306a36Sopenharmony_ci			switch (skb->mark) {
47362306a36Sopenharmony_ci			case RXRPC_SKB_MARK_PACKET:
47462306a36Sopenharmony_ci				skb->priority = 0;
47562306a36Sopenharmony_ci				if (!rxrpc_input_packet(local, &skb))
47662306a36Sopenharmony_ci					rxrpc_reject_packet(local, skb);
47762306a36Sopenharmony_ci				trace_rxrpc_rx_done(skb->mark, skb->priority);
47862306a36Sopenharmony_ci				rxrpc_free_skb(skb, rxrpc_skb_put_input);
47962306a36Sopenharmony_ci				break;
48062306a36Sopenharmony_ci			case RXRPC_SKB_MARK_ERROR:
48162306a36Sopenharmony_ci				rxrpc_input_error(local, skb);
48262306a36Sopenharmony_ci				rxrpc_free_skb(skb, rxrpc_skb_put_error_report);
48362306a36Sopenharmony_ci				break;
48462306a36Sopenharmony_ci			case RXRPC_SKB_MARK_SERVICE_CONN_SECURED:
48562306a36Sopenharmony_ci				rxrpc_input_conn_event(sp->conn, skb);
48662306a36Sopenharmony_ci				rxrpc_put_connection(sp->conn, rxrpc_conn_put_poke);
48762306a36Sopenharmony_ci				rxrpc_free_skb(skb, rxrpc_skb_put_conn_secured);
48862306a36Sopenharmony_ci				break;
48962306a36Sopenharmony_ci			default:
49062306a36Sopenharmony_ci				WARN_ON_ONCE(1);
49162306a36Sopenharmony_ci				rxrpc_free_skb(skb, rxrpc_skb_put_unknown);
49262306a36Sopenharmony_ci				break;
49362306a36Sopenharmony_ci			}
49462306a36Sopenharmony_ci			continue;
49562306a36Sopenharmony_ci		}
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci		/* Inject a delay into packets if requested. */
49862306a36Sopenharmony_ci#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
49962306a36Sopenharmony_ci		now = ktime_get_real();
50062306a36Sopenharmony_ci		while ((skb = skb_peek(&local->rx_delay_queue))) {
50162306a36Sopenharmony_ci			if (ktime_before(now, skb->tstamp))
50262306a36Sopenharmony_ci				break;
50362306a36Sopenharmony_ci			skb = skb_dequeue(&local->rx_delay_queue);
50462306a36Sopenharmony_ci			skb_queue_tail(&local->rx_queue, skb);
50562306a36Sopenharmony_ci		}
50662306a36Sopenharmony_ci#endif
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci		if (!skb_queue_empty(&local->rx_queue)) {
50962306a36Sopenharmony_ci			spin_lock_irq(&local->rx_queue.lock);
51062306a36Sopenharmony_ci			skb_queue_splice_tail_init(&local->rx_queue, &rx_queue);
51162306a36Sopenharmony_ci			spin_unlock_irq(&local->rx_queue.lock);
51262306a36Sopenharmony_ci			continue;
51362306a36Sopenharmony_ci		}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci		set_current_state(TASK_INTERRUPTIBLE);
51662306a36Sopenharmony_ci		should_stop = kthread_should_stop();
51762306a36Sopenharmony_ci		if (!skb_queue_empty(&local->rx_queue) ||
51862306a36Sopenharmony_ci		    !list_empty(&local->call_attend_q) ||
51962306a36Sopenharmony_ci		    !list_empty(&local->conn_attend_q) ||
52062306a36Sopenharmony_ci		    !list_empty(&local->new_client_calls) ||
52162306a36Sopenharmony_ci		    test_bit(RXRPC_CLIENT_CONN_REAP_TIMER,
52262306a36Sopenharmony_ci			     &local->client_conn_flags)) {
52362306a36Sopenharmony_ci			__set_current_state(TASK_RUNNING);
52462306a36Sopenharmony_ci			continue;
52562306a36Sopenharmony_ci		}
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci		if (should_stop)
52862306a36Sopenharmony_ci			break;
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
53162306a36Sopenharmony_ci		skb = skb_peek(&local->rx_delay_queue);
53262306a36Sopenharmony_ci		if (skb) {
53362306a36Sopenharmony_ci			unsigned long timeout;
53462306a36Sopenharmony_ci			ktime_t tstamp = skb->tstamp;
53562306a36Sopenharmony_ci			ktime_t now = ktime_get_real();
53662306a36Sopenharmony_ci			s64 delay_ns = ktime_to_ns(ktime_sub(tstamp, now));
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci			if (delay_ns <= 0) {
53962306a36Sopenharmony_ci				__set_current_state(TASK_RUNNING);
54062306a36Sopenharmony_ci				continue;
54162306a36Sopenharmony_ci			}
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci			timeout = nsecs_to_jiffies(delay_ns);
54462306a36Sopenharmony_ci			timeout = max(timeout, 1UL);
54562306a36Sopenharmony_ci			schedule_timeout(timeout);
54662306a36Sopenharmony_ci			__set_current_state(TASK_RUNNING);
54762306a36Sopenharmony_ci			continue;
54862306a36Sopenharmony_ci		}
54962306a36Sopenharmony_ci#endif
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci		schedule();
55262306a36Sopenharmony_ci	}
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	__set_current_state(TASK_RUNNING);
55562306a36Sopenharmony_ci	rxrpc_see_local(local, rxrpc_local_stop);
55662306a36Sopenharmony_ci	rxrpc_destroy_local(local);
55762306a36Sopenharmony_ci	local->io_thread = NULL;
55862306a36Sopenharmony_ci	rxrpc_see_local(local, rxrpc_local_stopped);
55962306a36Sopenharmony_ci	return 0;
56062306a36Sopenharmony_ci}
561