xref: /kernel/linux/linux-5.10/net/rxrpc/recvmsg.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/* RxRPC recvmsg() implementation
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
58c2ecf20Sopenharmony_ci * Written by David Howells (dhowells@redhat.com)
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/net.h>
118c2ecf20Sopenharmony_ci#include <linux/skbuff.h>
128c2ecf20Sopenharmony_ci#include <linux/export.h>
138c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include <net/sock.h>
168c2ecf20Sopenharmony_ci#include <net/af_rxrpc.h>
178c2ecf20Sopenharmony_ci#include "ar-internal.h"
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/*
208c2ecf20Sopenharmony_ci * Post a call for attention by the socket or kernel service.  Further
218c2ecf20Sopenharmony_ci * notifications are suppressed by putting recvmsg_link on a dummy queue.
228c2ecf20Sopenharmony_ci */
238c2ecf20Sopenharmony_civoid rxrpc_notify_socket(struct rxrpc_call *call)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci	struct rxrpc_sock *rx;
268c2ecf20Sopenharmony_ci	struct sock *sk;
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	_enter("%d", call->debug_id);
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	if (!list_empty(&call->recvmsg_link))
318c2ecf20Sopenharmony_ci		return;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	rcu_read_lock();
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	rx = rcu_dereference(call->socket);
368c2ecf20Sopenharmony_ci	sk = &rx->sk;
378c2ecf20Sopenharmony_ci	if (rx && sk->sk_state < RXRPC_CLOSE) {
388c2ecf20Sopenharmony_ci		if (call->notify_rx) {
398c2ecf20Sopenharmony_ci			spin_lock_bh(&call->notify_lock);
408c2ecf20Sopenharmony_ci			call->notify_rx(sk, call, call->user_call_ID);
418c2ecf20Sopenharmony_ci			spin_unlock_bh(&call->notify_lock);
428c2ecf20Sopenharmony_ci		} else {
438c2ecf20Sopenharmony_ci			write_lock_bh(&rx->recvmsg_lock);
448c2ecf20Sopenharmony_ci			if (list_empty(&call->recvmsg_link)) {
458c2ecf20Sopenharmony_ci				rxrpc_get_call(call, rxrpc_call_got);
468c2ecf20Sopenharmony_ci				list_add_tail(&call->recvmsg_link, &rx->recvmsg_q);
478c2ecf20Sopenharmony_ci			}
488c2ecf20Sopenharmony_ci			write_unlock_bh(&rx->recvmsg_lock);
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci			if (!sock_flag(sk, SOCK_DEAD)) {
518c2ecf20Sopenharmony_ci				_debug("call %ps", sk->sk_data_ready);
528c2ecf20Sopenharmony_ci				sk->sk_data_ready(sk);
538c2ecf20Sopenharmony_ci			}
548c2ecf20Sopenharmony_ci		}
558c2ecf20Sopenharmony_ci	}
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	rcu_read_unlock();
588c2ecf20Sopenharmony_ci	_leave("");
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/*
628c2ecf20Sopenharmony_ci * Transition a call to the complete state.
638c2ecf20Sopenharmony_ci */
648c2ecf20Sopenharmony_cibool __rxrpc_set_call_completion(struct rxrpc_call *call,
658c2ecf20Sopenharmony_ci				 enum rxrpc_call_completion compl,
668c2ecf20Sopenharmony_ci				 u32 abort_code,
678c2ecf20Sopenharmony_ci				 int error)
688c2ecf20Sopenharmony_ci{
698c2ecf20Sopenharmony_ci	if (call->state < RXRPC_CALL_COMPLETE) {
708c2ecf20Sopenharmony_ci		call->abort_code = abort_code;
718c2ecf20Sopenharmony_ci		call->error = error;
728c2ecf20Sopenharmony_ci		call->completion = compl,
738c2ecf20Sopenharmony_ci		call->state = RXRPC_CALL_COMPLETE;
748c2ecf20Sopenharmony_ci		trace_rxrpc_call_complete(call);
758c2ecf20Sopenharmony_ci		wake_up(&call->waitq);
768c2ecf20Sopenharmony_ci		rxrpc_notify_socket(call);
778c2ecf20Sopenharmony_ci		return true;
788c2ecf20Sopenharmony_ci	}
798c2ecf20Sopenharmony_ci	return false;
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cibool rxrpc_set_call_completion(struct rxrpc_call *call,
838c2ecf20Sopenharmony_ci			       enum rxrpc_call_completion compl,
848c2ecf20Sopenharmony_ci			       u32 abort_code,
858c2ecf20Sopenharmony_ci			       int error)
868c2ecf20Sopenharmony_ci{
878c2ecf20Sopenharmony_ci	bool ret = false;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	if (call->state < RXRPC_CALL_COMPLETE) {
908c2ecf20Sopenharmony_ci		write_lock_bh(&call->state_lock);
918c2ecf20Sopenharmony_ci		ret = __rxrpc_set_call_completion(call, compl, abort_code, error);
928c2ecf20Sopenharmony_ci		write_unlock_bh(&call->state_lock);
938c2ecf20Sopenharmony_ci	}
948c2ecf20Sopenharmony_ci	return ret;
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci/*
988c2ecf20Sopenharmony_ci * Record that a call successfully completed.
998c2ecf20Sopenharmony_ci */
1008c2ecf20Sopenharmony_cibool __rxrpc_call_completed(struct rxrpc_call *call)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	return __rxrpc_set_call_completion(call, RXRPC_CALL_SUCCEEDED, 0, 0);
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cibool rxrpc_call_completed(struct rxrpc_call *call)
1068c2ecf20Sopenharmony_ci{
1078c2ecf20Sopenharmony_ci	bool ret = false;
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	if (call->state < RXRPC_CALL_COMPLETE) {
1108c2ecf20Sopenharmony_ci		write_lock_bh(&call->state_lock);
1118c2ecf20Sopenharmony_ci		ret = __rxrpc_call_completed(call);
1128c2ecf20Sopenharmony_ci		write_unlock_bh(&call->state_lock);
1138c2ecf20Sopenharmony_ci	}
1148c2ecf20Sopenharmony_ci	return ret;
1158c2ecf20Sopenharmony_ci}
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci/*
1188c2ecf20Sopenharmony_ci * Record that a call is locally aborted.
1198c2ecf20Sopenharmony_ci */
1208c2ecf20Sopenharmony_cibool __rxrpc_abort_call(const char *why, struct rxrpc_call *call,
1218c2ecf20Sopenharmony_ci			rxrpc_seq_t seq, u32 abort_code, int error)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	trace_rxrpc_abort(call->debug_id, why, call->cid, call->call_id, seq,
1248c2ecf20Sopenharmony_ci			  abort_code, error);
1258c2ecf20Sopenharmony_ci	return __rxrpc_set_call_completion(call, RXRPC_CALL_LOCALLY_ABORTED,
1268c2ecf20Sopenharmony_ci					   abort_code, error);
1278c2ecf20Sopenharmony_ci}
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_cibool rxrpc_abort_call(const char *why, struct rxrpc_call *call,
1308c2ecf20Sopenharmony_ci		      rxrpc_seq_t seq, u32 abort_code, int error)
1318c2ecf20Sopenharmony_ci{
1328c2ecf20Sopenharmony_ci	bool ret;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	write_lock_bh(&call->state_lock);
1358c2ecf20Sopenharmony_ci	ret = __rxrpc_abort_call(why, call, seq, abort_code, error);
1368c2ecf20Sopenharmony_ci	write_unlock_bh(&call->state_lock);
1378c2ecf20Sopenharmony_ci	return ret;
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci/*
1418c2ecf20Sopenharmony_ci * Pass a call terminating message to userspace.
1428c2ecf20Sopenharmony_ci */
1438c2ecf20Sopenharmony_cistatic int rxrpc_recvmsg_term(struct rxrpc_call *call, struct msghdr *msg)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	u32 tmp = 0;
1468c2ecf20Sopenharmony_ci	int ret;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	switch (call->completion) {
1498c2ecf20Sopenharmony_ci	case RXRPC_CALL_SUCCEEDED:
1508c2ecf20Sopenharmony_ci		ret = 0;
1518c2ecf20Sopenharmony_ci		if (rxrpc_is_service_call(call))
1528c2ecf20Sopenharmony_ci			ret = put_cmsg(msg, SOL_RXRPC, RXRPC_ACK, 0, &tmp);
1538c2ecf20Sopenharmony_ci		break;
1548c2ecf20Sopenharmony_ci	case RXRPC_CALL_REMOTELY_ABORTED:
1558c2ecf20Sopenharmony_ci		tmp = call->abort_code;
1568c2ecf20Sopenharmony_ci		ret = put_cmsg(msg, SOL_RXRPC, RXRPC_ABORT, 4, &tmp);
1578c2ecf20Sopenharmony_ci		break;
1588c2ecf20Sopenharmony_ci	case RXRPC_CALL_LOCALLY_ABORTED:
1598c2ecf20Sopenharmony_ci		tmp = call->abort_code;
1608c2ecf20Sopenharmony_ci		ret = put_cmsg(msg, SOL_RXRPC, RXRPC_ABORT, 4, &tmp);
1618c2ecf20Sopenharmony_ci		break;
1628c2ecf20Sopenharmony_ci	case RXRPC_CALL_NETWORK_ERROR:
1638c2ecf20Sopenharmony_ci		tmp = -call->error;
1648c2ecf20Sopenharmony_ci		ret = put_cmsg(msg, SOL_RXRPC, RXRPC_NET_ERROR, 4, &tmp);
1658c2ecf20Sopenharmony_ci		break;
1668c2ecf20Sopenharmony_ci	case RXRPC_CALL_LOCAL_ERROR:
1678c2ecf20Sopenharmony_ci		tmp = -call->error;
1688c2ecf20Sopenharmony_ci		ret = put_cmsg(msg, SOL_RXRPC, RXRPC_LOCAL_ERROR, 4, &tmp);
1698c2ecf20Sopenharmony_ci		break;
1708c2ecf20Sopenharmony_ci	default:
1718c2ecf20Sopenharmony_ci		pr_err("Invalid terminal call state %u\n", call->state);
1728c2ecf20Sopenharmony_ci		BUG();
1738c2ecf20Sopenharmony_ci		break;
1748c2ecf20Sopenharmony_ci	}
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	trace_rxrpc_recvmsg(call, rxrpc_recvmsg_terminal, call->rx_hard_ack,
1778c2ecf20Sopenharmony_ci			    call->rx_pkt_offset, call->rx_pkt_len, ret);
1788c2ecf20Sopenharmony_ci	return ret;
1798c2ecf20Sopenharmony_ci}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci/*
1828c2ecf20Sopenharmony_ci * End the packet reception phase.
1838c2ecf20Sopenharmony_ci */
1848c2ecf20Sopenharmony_cistatic void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
1858c2ecf20Sopenharmony_ci{
1868c2ecf20Sopenharmony_ci	_enter("%d,%s", call->debug_id, rxrpc_call_states[call->state]);
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	trace_rxrpc_receive(call, rxrpc_receive_end, 0, call->rx_top);
1898c2ecf20Sopenharmony_ci	ASSERTCMP(call->rx_hard_ack, ==, call->rx_top);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	if (call->state == RXRPC_CALL_CLIENT_RECV_REPLY) {
1928c2ecf20Sopenharmony_ci		rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, serial, false, true,
1938c2ecf20Sopenharmony_ci				  rxrpc_propose_ack_terminal_ack);
1948c2ecf20Sopenharmony_ci		//rxrpc_send_ack_packet(call, false, NULL);
1958c2ecf20Sopenharmony_ci	}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	write_lock_bh(&call->state_lock);
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	switch (call->state) {
2008c2ecf20Sopenharmony_ci	case RXRPC_CALL_CLIENT_RECV_REPLY:
2018c2ecf20Sopenharmony_ci		__rxrpc_call_completed(call);
2028c2ecf20Sopenharmony_ci		write_unlock_bh(&call->state_lock);
2038c2ecf20Sopenharmony_ci		break;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	case RXRPC_CALL_SERVER_RECV_REQUEST:
2068c2ecf20Sopenharmony_ci		call->tx_phase = true;
2078c2ecf20Sopenharmony_ci		call->state = RXRPC_CALL_SERVER_ACK_REQUEST;
2088c2ecf20Sopenharmony_ci		call->expect_req_by = jiffies + MAX_JIFFY_OFFSET;
2098c2ecf20Sopenharmony_ci		write_unlock_bh(&call->state_lock);
2108c2ecf20Sopenharmony_ci		rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial, false, true,
2118c2ecf20Sopenharmony_ci				  rxrpc_propose_ack_processing_op);
2128c2ecf20Sopenharmony_ci		break;
2138c2ecf20Sopenharmony_ci	default:
2148c2ecf20Sopenharmony_ci		write_unlock_bh(&call->state_lock);
2158c2ecf20Sopenharmony_ci		break;
2168c2ecf20Sopenharmony_ci	}
2178c2ecf20Sopenharmony_ci}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci/*
2208c2ecf20Sopenharmony_ci * Discard a packet we've used up and advance the Rx window by one.
2218c2ecf20Sopenharmony_ci */
2228c2ecf20Sopenharmony_cistatic void rxrpc_rotate_rx_window(struct rxrpc_call *call)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	struct rxrpc_skb_priv *sp;
2258c2ecf20Sopenharmony_ci	struct sk_buff *skb;
2268c2ecf20Sopenharmony_ci	rxrpc_serial_t serial;
2278c2ecf20Sopenharmony_ci	rxrpc_seq_t hard_ack, top;
2288c2ecf20Sopenharmony_ci	bool last = false;
2298c2ecf20Sopenharmony_ci	u8 subpacket;
2308c2ecf20Sopenharmony_ci	int ix;
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	_enter("%d", call->debug_id);
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	hard_ack = call->rx_hard_ack;
2358c2ecf20Sopenharmony_ci	top = smp_load_acquire(&call->rx_top);
2368c2ecf20Sopenharmony_ci	ASSERT(before(hard_ack, top));
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	hard_ack++;
2398c2ecf20Sopenharmony_ci	ix = hard_ack & RXRPC_RXTX_BUFF_MASK;
2408c2ecf20Sopenharmony_ci	skb = call->rxtx_buffer[ix];
2418c2ecf20Sopenharmony_ci	rxrpc_see_skb(skb, rxrpc_skb_rotated);
2428c2ecf20Sopenharmony_ci	sp = rxrpc_skb(skb);
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	subpacket = call->rxtx_annotations[ix] & RXRPC_RX_ANNO_SUBPACKET;
2458c2ecf20Sopenharmony_ci	serial = sp->hdr.serial + subpacket;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	if (subpacket == sp->nr_subpackets - 1 &&
2488c2ecf20Sopenharmony_ci	    sp->rx_flags & RXRPC_SKB_INCL_LAST)
2498c2ecf20Sopenharmony_ci		last = true;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	call->rxtx_buffer[ix] = NULL;
2528c2ecf20Sopenharmony_ci	call->rxtx_annotations[ix] = 0;
2538c2ecf20Sopenharmony_ci	/* Barrier against rxrpc_input_data(). */
2548c2ecf20Sopenharmony_ci	smp_store_release(&call->rx_hard_ack, hard_ack);
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	rxrpc_free_skb(skb, rxrpc_skb_freed);
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack);
2598c2ecf20Sopenharmony_ci	if (last) {
2608c2ecf20Sopenharmony_ci		rxrpc_end_rx_phase(call, serial);
2618c2ecf20Sopenharmony_ci	} else {
2628c2ecf20Sopenharmony_ci		/* Check to see if there's an ACK that needs sending. */
2638c2ecf20Sopenharmony_ci		if (atomic_inc_return(&call->ackr_nr_consumed) > 2)
2648c2ecf20Sopenharmony_ci			rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, serial,
2658c2ecf20Sopenharmony_ci					  true, false,
2668c2ecf20Sopenharmony_ci					  rxrpc_propose_ack_rotate_rx);
2678c2ecf20Sopenharmony_ci		if (call->ackr_reason && call->ackr_reason != RXRPC_ACK_DELAY)
2688c2ecf20Sopenharmony_ci			rxrpc_send_ack_packet(call, false, NULL);
2698c2ecf20Sopenharmony_ci	}
2708c2ecf20Sopenharmony_ci}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci/*
2738c2ecf20Sopenharmony_ci * Decrypt and verify a (sub)packet.  The packet's length may be changed due to
2748c2ecf20Sopenharmony_ci * padding, but if this is the case, the packet length will be resident in the
2758c2ecf20Sopenharmony_ci * socket buffer.  Note that we can't modify the master skb info as the skb may
2768c2ecf20Sopenharmony_ci * be the home to multiple subpackets.
2778c2ecf20Sopenharmony_ci */
2788c2ecf20Sopenharmony_cistatic int rxrpc_verify_packet(struct rxrpc_call *call, struct sk_buff *skb,
2798c2ecf20Sopenharmony_ci			       u8 annotation,
2808c2ecf20Sopenharmony_ci			       unsigned int offset, unsigned int len)
2818c2ecf20Sopenharmony_ci{
2828c2ecf20Sopenharmony_ci	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
2838c2ecf20Sopenharmony_ci	rxrpc_seq_t seq = sp->hdr.seq;
2848c2ecf20Sopenharmony_ci	u16 cksum = sp->hdr.cksum;
2858c2ecf20Sopenharmony_ci	u8 subpacket = annotation & RXRPC_RX_ANNO_SUBPACKET;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	_enter("");
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	/* For all but the head jumbo subpacket, the security checksum is in a
2908c2ecf20Sopenharmony_ci	 * jumbo header immediately prior to the data.
2918c2ecf20Sopenharmony_ci	 */
2928c2ecf20Sopenharmony_ci	if (subpacket > 0) {
2938c2ecf20Sopenharmony_ci		__be16 tmp;
2948c2ecf20Sopenharmony_ci		if (skb_copy_bits(skb, offset - 2, &tmp, 2) < 0)
2958c2ecf20Sopenharmony_ci			BUG();
2968c2ecf20Sopenharmony_ci		cksum = ntohs(tmp);
2978c2ecf20Sopenharmony_ci		seq += subpacket;
2988c2ecf20Sopenharmony_ci	}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	return call->security->verify_packet(call, skb, offset, len,
3018c2ecf20Sopenharmony_ci					     seq, cksum);
3028c2ecf20Sopenharmony_ci}
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci/*
3058c2ecf20Sopenharmony_ci * Locate the data within a packet.  This is complicated by:
3068c2ecf20Sopenharmony_ci *
3078c2ecf20Sopenharmony_ci * (1) An skb may contain a jumbo packet - so we have to find the appropriate
3088c2ecf20Sopenharmony_ci *     subpacket.
3098c2ecf20Sopenharmony_ci *
3108c2ecf20Sopenharmony_ci * (2) The (sub)packets may be encrypted and, if so, the encrypted portion
3118c2ecf20Sopenharmony_ci *     contains an extra header which includes the true length of the data,
3128c2ecf20Sopenharmony_ci *     excluding any encrypted padding.
3138c2ecf20Sopenharmony_ci */
3148c2ecf20Sopenharmony_cistatic int rxrpc_locate_data(struct rxrpc_call *call, struct sk_buff *skb,
3158c2ecf20Sopenharmony_ci			     u8 *_annotation,
3168c2ecf20Sopenharmony_ci			     unsigned int *_offset, unsigned int *_len,
3178c2ecf20Sopenharmony_ci			     bool *_last)
3188c2ecf20Sopenharmony_ci{
3198c2ecf20Sopenharmony_ci	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
3208c2ecf20Sopenharmony_ci	unsigned int offset = sizeof(struct rxrpc_wire_header);
3218c2ecf20Sopenharmony_ci	unsigned int len;
3228c2ecf20Sopenharmony_ci	bool last = false;
3238c2ecf20Sopenharmony_ci	int ret;
3248c2ecf20Sopenharmony_ci	u8 annotation = *_annotation;
3258c2ecf20Sopenharmony_ci	u8 subpacket = annotation & RXRPC_RX_ANNO_SUBPACKET;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	/* Locate the subpacket */
3288c2ecf20Sopenharmony_ci	offset += subpacket * RXRPC_JUMBO_SUBPKTLEN;
3298c2ecf20Sopenharmony_ci	len = skb->len - offset;
3308c2ecf20Sopenharmony_ci	if (subpacket < sp->nr_subpackets - 1)
3318c2ecf20Sopenharmony_ci		len = RXRPC_JUMBO_DATALEN;
3328c2ecf20Sopenharmony_ci	else if (sp->rx_flags & RXRPC_SKB_INCL_LAST)
3338c2ecf20Sopenharmony_ci		last = true;
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	if (!(annotation & RXRPC_RX_ANNO_VERIFIED)) {
3368c2ecf20Sopenharmony_ci		ret = rxrpc_verify_packet(call, skb, annotation, offset, len);
3378c2ecf20Sopenharmony_ci		if (ret < 0)
3388c2ecf20Sopenharmony_ci			return ret;
3398c2ecf20Sopenharmony_ci		*_annotation |= RXRPC_RX_ANNO_VERIFIED;
3408c2ecf20Sopenharmony_ci	}
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	*_offset = offset;
3438c2ecf20Sopenharmony_ci	*_len = len;
3448c2ecf20Sopenharmony_ci	*_last = last;
3458c2ecf20Sopenharmony_ci	call->security->locate_data(call, skb, _offset, _len);
3468c2ecf20Sopenharmony_ci	return 0;
3478c2ecf20Sopenharmony_ci}
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci/*
3508c2ecf20Sopenharmony_ci * Deliver messages to a call.  This keeps processing packets until the buffer
3518c2ecf20Sopenharmony_ci * is filled and we find either more DATA (returns 0) or the end of the DATA
3528c2ecf20Sopenharmony_ci * (returns 1).  If more packets are required, it returns -EAGAIN.
3538c2ecf20Sopenharmony_ci */
3548c2ecf20Sopenharmony_cistatic int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
3558c2ecf20Sopenharmony_ci			      struct msghdr *msg, struct iov_iter *iter,
3568c2ecf20Sopenharmony_ci			      size_t len, int flags, size_t *_offset)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	struct rxrpc_skb_priv *sp;
3598c2ecf20Sopenharmony_ci	struct sk_buff *skb;
3608c2ecf20Sopenharmony_ci	rxrpc_serial_t serial;
3618c2ecf20Sopenharmony_ci	rxrpc_seq_t hard_ack, top, seq;
3628c2ecf20Sopenharmony_ci	size_t remain;
3638c2ecf20Sopenharmony_ci	bool rx_pkt_last;
3648c2ecf20Sopenharmony_ci	unsigned int rx_pkt_offset, rx_pkt_len;
3658c2ecf20Sopenharmony_ci	int ix, copy, ret = -EAGAIN, ret2;
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci	if (test_and_clear_bit(RXRPC_CALL_RX_UNDERRUN, &call->flags) &&
3688c2ecf20Sopenharmony_ci	    call->ackr_reason)
3698c2ecf20Sopenharmony_ci		rxrpc_send_ack_packet(call, false, NULL);
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	rx_pkt_offset = call->rx_pkt_offset;
3728c2ecf20Sopenharmony_ci	rx_pkt_len = call->rx_pkt_len;
3738c2ecf20Sopenharmony_ci	rx_pkt_last = call->rx_pkt_last;
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci	if (call->state >= RXRPC_CALL_SERVER_ACK_REQUEST) {
3768c2ecf20Sopenharmony_ci		seq = call->rx_hard_ack;
3778c2ecf20Sopenharmony_ci		ret = 1;
3788c2ecf20Sopenharmony_ci		goto done;
3798c2ecf20Sopenharmony_ci	}
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	/* Barriers against rxrpc_input_data(). */
3828c2ecf20Sopenharmony_ci	hard_ack = call->rx_hard_ack;
3838c2ecf20Sopenharmony_ci	seq = hard_ack + 1;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	while (top = smp_load_acquire(&call->rx_top),
3868c2ecf20Sopenharmony_ci	       before_eq(seq, top)
3878c2ecf20Sopenharmony_ci	       ) {
3888c2ecf20Sopenharmony_ci		ix = seq & RXRPC_RXTX_BUFF_MASK;
3898c2ecf20Sopenharmony_ci		skb = call->rxtx_buffer[ix];
3908c2ecf20Sopenharmony_ci		if (!skb) {
3918c2ecf20Sopenharmony_ci			trace_rxrpc_recvmsg(call, rxrpc_recvmsg_hole, seq,
3928c2ecf20Sopenharmony_ci					    rx_pkt_offset, rx_pkt_len, 0);
3938c2ecf20Sopenharmony_ci			break;
3948c2ecf20Sopenharmony_ci		}
3958c2ecf20Sopenharmony_ci		smp_rmb();
3968c2ecf20Sopenharmony_ci		rxrpc_see_skb(skb, rxrpc_skb_seen);
3978c2ecf20Sopenharmony_ci		sp = rxrpc_skb(skb);
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci		if (!(flags & MSG_PEEK)) {
4008c2ecf20Sopenharmony_ci			serial = sp->hdr.serial;
4018c2ecf20Sopenharmony_ci			serial += call->rxtx_annotations[ix] & RXRPC_RX_ANNO_SUBPACKET;
4028c2ecf20Sopenharmony_ci			trace_rxrpc_receive(call, rxrpc_receive_front,
4038c2ecf20Sopenharmony_ci					    serial, seq);
4048c2ecf20Sopenharmony_ci		}
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci		if (msg)
4078c2ecf20Sopenharmony_ci			sock_recv_timestamp(msg, sock->sk, skb);
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci		if (rx_pkt_offset == 0) {
4108c2ecf20Sopenharmony_ci			ret2 = rxrpc_locate_data(call, skb,
4118c2ecf20Sopenharmony_ci						 &call->rxtx_annotations[ix],
4128c2ecf20Sopenharmony_ci						 &rx_pkt_offset, &rx_pkt_len,
4138c2ecf20Sopenharmony_ci						 &rx_pkt_last);
4148c2ecf20Sopenharmony_ci			trace_rxrpc_recvmsg(call, rxrpc_recvmsg_next, seq,
4158c2ecf20Sopenharmony_ci					    rx_pkt_offset, rx_pkt_len, ret2);
4168c2ecf20Sopenharmony_ci			if (ret2 < 0) {
4178c2ecf20Sopenharmony_ci				ret = ret2;
4188c2ecf20Sopenharmony_ci				goto out;
4198c2ecf20Sopenharmony_ci			}
4208c2ecf20Sopenharmony_ci		} else {
4218c2ecf20Sopenharmony_ci			trace_rxrpc_recvmsg(call, rxrpc_recvmsg_cont, seq,
4228c2ecf20Sopenharmony_ci					    rx_pkt_offset, rx_pkt_len, 0);
4238c2ecf20Sopenharmony_ci		}
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci		/* We have to handle short, empty and used-up DATA packets. */
4268c2ecf20Sopenharmony_ci		remain = len - *_offset;
4278c2ecf20Sopenharmony_ci		copy = rx_pkt_len;
4288c2ecf20Sopenharmony_ci		if (copy > remain)
4298c2ecf20Sopenharmony_ci			copy = remain;
4308c2ecf20Sopenharmony_ci		if (copy > 0) {
4318c2ecf20Sopenharmony_ci			ret2 = skb_copy_datagram_iter(skb, rx_pkt_offset, iter,
4328c2ecf20Sopenharmony_ci						      copy);
4338c2ecf20Sopenharmony_ci			if (ret2 < 0) {
4348c2ecf20Sopenharmony_ci				ret = ret2;
4358c2ecf20Sopenharmony_ci				goto out;
4368c2ecf20Sopenharmony_ci			}
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci			/* handle piecemeal consumption of data packets */
4398c2ecf20Sopenharmony_ci			rx_pkt_offset += copy;
4408c2ecf20Sopenharmony_ci			rx_pkt_len -= copy;
4418c2ecf20Sopenharmony_ci			*_offset += copy;
4428c2ecf20Sopenharmony_ci		}
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci		if (rx_pkt_len > 0) {
4458c2ecf20Sopenharmony_ci			trace_rxrpc_recvmsg(call, rxrpc_recvmsg_full, seq,
4468c2ecf20Sopenharmony_ci					    rx_pkt_offset, rx_pkt_len, 0);
4478c2ecf20Sopenharmony_ci			ASSERTCMP(*_offset, ==, len);
4488c2ecf20Sopenharmony_ci			ret = 0;
4498c2ecf20Sopenharmony_ci			break;
4508c2ecf20Sopenharmony_ci		}
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci		/* The whole packet has been transferred. */
4538c2ecf20Sopenharmony_ci		if (!(flags & MSG_PEEK))
4548c2ecf20Sopenharmony_ci			rxrpc_rotate_rx_window(call);
4558c2ecf20Sopenharmony_ci		rx_pkt_offset = 0;
4568c2ecf20Sopenharmony_ci		rx_pkt_len = 0;
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci		if (rx_pkt_last) {
4598c2ecf20Sopenharmony_ci			ASSERTCMP(seq, ==, READ_ONCE(call->rx_top));
4608c2ecf20Sopenharmony_ci			ret = 1;
4618c2ecf20Sopenharmony_ci			goto out;
4628c2ecf20Sopenharmony_ci		}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci		seq++;
4658c2ecf20Sopenharmony_ci	}
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ciout:
4688c2ecf20Sopenharmony_ci	if (!(flags & MSG_PEEK)) {
4698c2ecf20Sopenharmony_ci		call->rx_pkt_offset = rx_pkt_offset;
4708c2ecf20Sopenharmony_ci		call->rx_pkt_len = rx_pkt_len;
4718c2ecf20Sopenharmony_ci		call->rx_pkt_last = rx_pkt_last;
4728c2ecf20Sopenharmony_ci	}
4738c2ecf20Sopenharmony_cidone:
4748c2ecf20Sopenharmony_ci	trace_rxrpc_recvmsg(call, rxrpc_recvmsg_data_return, seq,
4758c2ecf20Sopenharmony_ci			    rx_pkt_offset, rx_pkt_len, ret);
4768c2ecf20Sopenharmony_ci	if (ret == -EAGAIN)
4778c2ecf20Sopenharmony_ci		set_bit(RXRPC_CALL_RX_UNDERRUN, &call->flags);
4788c2ecf20Sopenharmony_ci	return ret;
4798c2ecf20Sopenharmony_ci}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci/*
4828c2ecf20Sopenharmony_ci * Receive a message from an RxRPC socket
4838c2ecf20Sopenharmony_ci * - we need to be careful about two or more threads calling recvmsg
4848c2ecf20Sopenharmony_ci *   simultaneously
4858c2ecf20Sopenharmony_ci */
4868c2ecf20Sopenharmony_ciint rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
4878c2ecf20Sopenharmony_ci		  int flags)
4888c2ecf20Sopenharmony_ci{
4898c2ecf20Sopenharmony_ci	struct rxrpc_call *call;
4908c2ecf20Sopenharmony_ci	struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
4918c2ecf20Sopenharmony_ci	struct list_head *l;
4928c2ecf20Sopenharmony_ci	size_t copied = 0;
4938c2ecf20Sopenharmony_ci	long timeo;
4948c2ecf20Sopenharmony_ci	int ret;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	DEFINE_WAIT(wait);
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	trace_rxrpc_recvmsg(NULL, rxrpc_recvmsg_enter, 0, 0, 0, 0);
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	if (flags & (MSG_OOB | MSG_TRUNC))
5018c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	timeo = sock_rcvtimeo(&rx->sk, flags & MSG_DONTWAIT);
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_citry_again:
5068c2ecf20Sopenharmony_ci	lock_sock(&rx->sk);
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	/* Return immediately if a client socket has no outstanding calls */
5098c2ecf20Sopenharmony_ci	if (RB_EMPTY_ROOT(&rx->calls) &&
5108c2ecf20Sopenharmony_ci	    list_empty(&rx->recvmsg_q) &&
5118c2ecf20Sopenharmony_ci	    rx->sk.sk_state != RXRPC_SERVER_LISTENING) {
5128c2ecf20Sopenharmony_ci		release_sock(&rx->sk);
5138c2ecf20Sopenharmony_ci		return -EAGAIN;
5148c2ecf20Sopenharmony_ci	}
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	if (list_empty(&rx->recvmsg_q)) {
5178c2ecf20Sopenharmony_ci		ret = -EWOULDBLOCK;
5188c2ecf20Sopenharmony_ci		if (timeo == 0) {
5198c2ecf20Sopenharmony_ci			call = NULL;
5208c2ecf20Sopenharmony_ci			goto error_no_call;
5218c2ecf20Sopenharmony_ci		}
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci		release_sock(&rx->sk);
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci		/* Wait for something to happen */
5268c2ecf20Sopenharmony_ci		prepare_to_wait_exclusive(sk_sleep(&rx->sk), &wait,
5278c2ecf20Sopenharmony_ci					  TASK_INTERRUPTIBLE);
5288c2ecf20Sopenharmony_ci		ret = sock_error(&rx->sk);
5298c2ecf20Sopenharmony_ci		if (ret)
5308c2ecf20Sopenharmony_ci			goto wait_error;
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci		if (list_empty(&rx->recvmsg_q)) {
5338c2ecf20Sopenharmony_ci			if (signal_pending(current))
5348c2ecf20Sopenharmony_ci				goto wait_interrupted;
5358c2ecf20Sopenharmony_ci			trace_rxrpc_recvmsg(NULL, rxrpc_recvmsg_wait,
5368c2ecf20Sopenharmony_ci					    0, 0, 0, 0);
5378c2ecf20Sopenharmony_ci			timeo = schedule_timeout(timeo);
5388c2ecf20Sopenharmony_ci		}
5398c2ecf20Sopenharmony_ci		finish_wait(sk_sleep(&rx->sk), &wait);
5408c2ecf20Sopenharmony_ci		goto try_again;
5418c2ecf20Sopenharmony_ci	}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	/* Find the next call and dequeue it if we're not just peeking.  If we
5448c2ecf20Sopenharmony_ci	 * do dequeue it, that comes with a ref that we will need to release.
5458c2ecf20Sopenharmony_ci	 */
5468c2ecf20Sopenharmony_ci	write_lock_bh(&rx->recvmsg_lock);
5478c2ecf20Sopenharmony_ci	l = rx->recvmsg_q.next;
5488c2ecf20Sopenharmony_ci	call = list_entry(l, struct rxrpc_call, recvmsg_link);
5498c2ecf20Sopenharmony_ci	if (!(flags & MSG_PEEK))
5508c2ecf20Sopenharmony_ci		list_del_init(&call->recvmsg_link);
5518c2ecf20Sopenharmony_ci	else
5528c2ecf20Sopenharmony_ci		rxrpc_get_call(call, rxrpc_call_got);
5538c2ecf20Sopenharmony_ci	write_unlock_bh(&rx->recvmsg_lock);
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	trace_rxrpc_recvmsg(call, rxrpc_recvmsg_dequeue, 0, 0, 0, 0);
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	/* We're going to drop the socket lock, so we need to lock the call
5588c2ecf20Sopenharmony_ci	 * against interference by sendmsg.
5598c2ecf20Sopenharmony_ci	 */
5608c2ecf20Sopenharmony_ci	if (!mutex_trylock(&call->user_mutex)) {
5618c2ecf20Sopenharmony_ci		ret = -EWOULDBLOCK;
5628c2ecf20Sopenharmony_ci		if (flags & MSG_DONTWAIT)
5638c2ecf20Sopenharmony_ci			goto error_requeue_call;
5648c2ecf20Sopenharmony_ci		ret = -ERESTARTSYS;
5658c2ecf20Sopenharmony_ci		if (mutex_lock_interruptible(&call->user_mutex) < 0)
5668c2ecf20Sopenharmony_ci			goto error_requeue_call;
5678c2ecf20Sopenharmony_ci	}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	release_sock(&rx->sk);
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	if (test_bit(RXRPC_CALL_RELEASED, &call->flags))
5728c2ecf20Sopenharmony_ci		BUG();
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	if (test_bit(RXRPC_CALL_HAS_USERID, &call->flags)) {
5758c2ecf20Sopenharmony_ci		if (flags & MSG_CMSG_COMPAT) {
5768c2ecf20Sopenharmony_ci			unsigned int id32 = call->user_call_ID;
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci			ret = put_cmsg(msg, SOL_RXRPC, RXRPC_USER_CALL_ID,
5798c2ecf20Sopenharmony_ci				       sizeof(unsigned int), &id32);
5808c2ecf20Sopenharmony_ci		} else {
5818c2ecf20Sopenharmony_ci			unsigned long idl = call->user_call_ID;
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci			ret = put_cmsg(msg, SOL_RXRPC, RXRPC_USER_CALL_ID,
5848c2ecf20Sopenharmony_ci				       sizeof(unsigned long), &idl);
5858c2ecf20Sopenharmony_ci		}
5868c2ecf20Sopenharmony_ci		if (ret < 0)
5878c2ecf20Sopenharmony_ci			goto error_unlock_call;
5888c2ecf20Sopenharmony_ci	}
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	if (msg->msg_name && call->peer) {
5918c2ecf20Sopenharmony_ci		struct sockaddr_rxrpc *srx = msg->msg_name;
5928c2ecf20Sopenharmony_ci		size_t len = sizeof(call->peer->srx);
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci		memcpy(msg->msg_name, &call->peer->srx, len);
5958c2ecf20Sopenharmony_ci		srx->srx_service = call->service_id;
5968c2ecf20Sopenharmony_ci		msg->msg_namelen = len;
5978c2ecf20Sopenharmony_ci	}
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	switch (READ_ONCE(call->state)) {
6008c2ecf20Sopenharmony_ci	case RXRPC_CALL_CLIENT_RECV_REPLY:
6018c2ecf20Sopenharmony_ci	case RXRPC_CALL_SERVER_RECV_REQUEST:
6028c2ecf20Sopenharmony_ci	case RXRPC_CALL_SERVER_ACK_REQUEST:
6038c2ecf20Sopenharmony_ci		ret = rxrpc_recvmsg_data(sock, call, msg, &msg->msg_iter, len,
6048c2ecf20Sopenharmony_ci					 flags, &copied);
6058c2ecf20Sopenharmony_ci		if (ret == -EAGAIN)
6068c2ecf20Sopenharmony_ci			ret = 0;
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci		if (after(call->rx_top, call->rx_hard_ack) &&
6098c2ecf20Sopenharmony_ci		    call->rxtx_buffer[(call->rx_hard_ack + 1) & RXRPC_RXTX_BUFF_MASK])
6108c2ecf20Sopenharmony_ci			rxrpc_notify_socket(call);
6118c2ecf20Sopenharmony_ci		break;
6128c2ecf20Sopenharmony_ci	default:
6138c2ecf20Sopenharmony_ci		ret = 0;
6148c2ecf20Sopenharmony_ci		break;
6158c2ecf20Sopenharmony_ci	}
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	if (ret < 0)
6188c2ecf20Sopenharmony_ci		goto error_unlock_call;
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	if (call->state == RXRPC_CALL_COMPLETE) {
6218c2ecf20Sopenharmony_ci		ret = rxrpc_recvmsg_term(call, msg);
6228c2ecf20Sopenharmony_ci		if (ret < 0)
6238c2ecf20Sopenharmony_ci			goto error_unlock_call;
6248c2ecf20Sopenharmony_ci		if (!(flags & MSG_PEEK))
6258c2ecf20Sopenharmony_ci			rxrpc_release_call(rx, call);
6268c2ecf20Sopenharmony_ci		msg->msg_flags |= MSG_EOR;
6278c2ecf20Sopenharmony_ci		ret = 1;
6288c2ecf20Sopenharmony_ci	}
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	if (ret == 0)
6318c2ecf20Sopenharmony_ci		msg->msg_flags |= MSG_MORE;
6328c2ecf20Sopenharmony_ci	else
6338c2ecf20Sopenharmony_ci		msg->msg_flags &= ~MSG_MORE;
6348c2ecf20Sopenharmony_ci	ret = copied;
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_cierror_unlock_call:
6378c2ecf20Sopenharmony_ci	mutex_unlock(&call->user_mutex);
6388c2ecf20Sopenharmony_ci	rxrpc_put_call(call, rxrpc_call_put);
6398c2ecf20Sopenharmony_ci	trace_rxrpc_recvmsg(call, rxrpc_recvmsg_return, 0, 0, 0, ret);
6408c2ecf20Sopenharmony_ci	return ret;
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_cierror_requeue_call:
6438c2ecf20Sopenharmony_ci	if (!(flags & MSG_PEEK)) {
6448c2ecf20Sopenharmony_ci		write_lock_bh(&rx->recvmsg_lock);
6458c2ecf20Sopenharmony_ci		list_add(&call->recvmsg_link, &rx->recvmsg_q);
6468c2ecf20Sopenharmony_ci		write_unlock_bh(&rx->recvmsg_lock);
6478c2ecf20Sopenharmony_ci		trace_rxrpc_recvmsg(call, rxrpc_recvmsg_requeue, 0, 0, 0, 0);
6488c2ecf20Sopenharmony_ci	} else {
6498c2ecf20Sopenharmony_ci		rxrpc_put_call(call, rxrpc_call_put);
6508c2ecf20Sopenharmony_ci	}
6518c2ecf20Sopenharmony_cierror_no_call:
6528c2ecf20Sopenharmony_ci	release_sock(&rx->sk);
6538c2ecf20Sopenharmony_cierror_trace:
6548c2ecf20Sopenharmony_ci	trace_rxrpc_recvmsg(call, rxrpc_recvmsg_return, 0, 0, 0, ret);
6558c2ecf20Sopenharmony_ci	return ret;
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ciwait_interrupted:
6588c2ecf20Sopenharmony_ci	ret = sock_intr_errno(timeo);
6598c2ecf20Sopenharmony_ciwait_error:
6608c2ecf20Sopenharmony_ci	finish_wait(sk_sleep(&rx->sk), &wait);
6618c2ecf20Sopenharmony_ci	call = NULL;
6628c2ecf20Sopenharmony_ci	goto error_trace;
6638c2ecf20Sopenharmony_ci}
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci/**
6668c2ecf20Sopenharmony_ci * rxrpc_kernel_recv_data - Allow a kernel service to receive data/info
6678c2ecf20Sopenharmony_ci * @sock: The socket that the call exists on
6688c2ecf20Sopenharmony_ci * @call: The call to send data through
6698c2ecf20Sopenharmony_ci * @iter: The buffer to receive into
6708c2ecf20Sopenharmony_ci * @want_more: True if more data is expected to be read
6718c2ecf20Sopenharmony_ci * @_abort: Where the abort code is stored if -ECONNABORTED is returned
6728c2ecf20Sopenharmony_ci * @_service: Where to store the actual service ID (may be upgraded)
6738c2ecf20Sopenharmony_ci *
6748c2ecf20Sopenharmony_ci * Allow a kernel service to receive data and pick up information about the
6758c2ecf20Sopenharmony_ci * state of a call.  Returns 0 if got what was asked for and there's more
6768c2ecf20Sopenharmony_ci * available, 1 if we got what was asked for and we're at the end of the data
6778c2ecf20Sopenharmony_ci * and -EAGAIN if we need more data.
6788c2ecf20Sopenharmony_ci *
6798c2ecf20Sopenharmony_ci * Note that we may return -EAGAIN to drain empty packets at the end of the
6808c2ecf20Sopenharmony_ci * data, even if we've already copied over the requested data.
6818c2ecf20Sopenharmony_ci *
6828c2ecf20Sopenharmony_ci * *_abort should also be initialised to 0.
6838c2ecf20Sopenharmony_ci */
6848c2ecf20Sopenharmony_ciint rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call,
6858c2ecf20Sopenharmony_ci			   struct iov_iter *iter,
6868c2ecf20Sopenharmony_ci			   bool want_more, u32 *_abort, u16 *_service)
6878c2ecf20Sopenharmony_ci{
6888c2ecf20Sopenharmony_ci	size_t offset = 0;
6898c2ecf20Sopenharmony_ci	int ret;
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	_enter("{%d,%s},%zu,%d",
6928c2ecf20Sopenharmony_ci	       call->debug_id, rxrpc_call_states[call->state],
6938c2ecf20Sopenharmony_ci	       iov_iter_count(iter), want_more);
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	ASSERTCMP(call->state, !=, RXRPC_CALL_SERVER_SECURING);
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	mutex_lock(&call->user_mutex);
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	switch (READ_ONCE(call->state)) {
7008c2ecf20Sopenharmony_ci	case RXRPC_CALL_CLIENT_RECV_REPLY:
7018c2ecf20Sopenharmony_ci	case RXRPC_CALL_SERVER_RECV_REQUEST:
7028c2ecf20Sopenharmony_ci	case RXRPC_CALL_SERVER_ACK_REQUEST:
7038c2ecf20Sopenharmony_ci		ret = rxrpc_recvmsg_data(sock, call, NULL, iter,
7048c2ecf20Sopenharmony_ci					 iov_iter_count(iter), 0,
7058c2ecf20Sopenharmony_ci					 &offset);
7068c2ecf20Sopenharmony_ci		if (ret < 0)
7078c2ecf20Sopenharmony_ci			goto out;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci		/* We can only reach here with a partially full buffer if we
7108c2ecf20Sopenharmony_ci		 * have reached the end of the data.  We must otherwise have a
7118c2ecf20Sopenharmony_ci		 * full buffer or have been given -EAGAIN.
7128c2ecf20Sopenharmony_ci		 */
7138c2ecf20Sopenharmony_ci		if (ret == 1) {
7148c2ecf20Sopenharmony_ci			if (iov_iter_count(iter) > 0)
7158c2ecf20Sopenharmony_ci				goto short_data;
7168c2ecf20Sopenharmony_ci			if (!want_more)
7178c2ecf20Sopenharmony_ci				goto read_phase_complete;
7188c2ecf20Sopenharmony_ci			ret = 0;
7198c2ecf20Sopenharmony_ci			goto out;
7208c2ecf20Sopenharmony_ci		}
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci		if (!want_more)
7238c2ecf20Sopenharmony_ci			goto excess_data;
7248c2ecf20Sopenharmony_ci		goto out;
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	case RXRPC_CALL_COMPLETE:
7278c2ecf20Sopenharmony_ci		goto call_complete;
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	default:
7308c2ecf20Sopenharmony_ci		ret = -EINPROGRESS;
7318c2ecf20Sopenharmony_ci		goto out;
7328c2ecf20Sopenharmony_ci	}
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ciread_phase_complete:
7358c2ecf20Sopenharmony_ci	ret = 1;
7368c2ecf20Sopenharmony_ciout:
7378c2ecf20Sopenharmony_ci	switch (call->ackr_reason) {
7388c2ecf20Sopenharmony_ci	case RXRPC_ACK_IDLE:
7398c2ecf20Sopenharmony_ci		break;
7408c2ecf20Sopenharmony_ci	case RXRPC_ACK_DELAY:
7418c2ecf20Sopenharmony_ci		if (ret != -EAGAIN)
7428c2ecf20Sopenharmony_ci			break;
7438c2ecf20Sopenharmony_ci		fallthrough;
7448c2ecf20Sopenharmony_ci	default:
7458c2ecf20Sopenharmony_ci		rxrpc_send_ack_packet(call, false, NULL);
7468c2ecf20Sopenharmony_ci	}
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	if (_service)
7498c2ecf20Sopenharmony_ci		*_service = call->service_id;
7508c2ecf20Sopenharmony_ci	mutex_unlock(&call->user_mutex);
7518c2ecf20Sopenharmony_ci	_leave(" = %d [%zu,%d]", ret, iov_iter_count(iter), *_abort);
7528c2ecf20Sopenharmony_ci	return ret;
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_cishort_data:
7558c2ecf20Sopenharmony_ci	trace_rxrpc_rx_eproto(call, 0, tracepoint_string("short_data"));
7568c2ecf20Sopenharmony_ci	ret = -EBADMSG;
7578c2ecf20Sopenharmony_ci	goto out;
7588c2ecf20Sopenharmony_ciexcess_data:
7598c2ecf20Sopenharmony_ci	trace_rxrpc_rx_eproto(call, 0, tracepoint_string("excess_data"));
7608c2ecf20Sopenharmony_ci	ret = -EMSGSIZE;
7618c2ecf20Sopenharmony_ci	goto out;
7628c2ecf20Sopenharmony_cicall_complete:
7638c2ecf20Sopenharmony_ci	*_abort = call->abort_code;
7648c2ecf20Sopenharmony_ci	ret = call->error;
7658c2ecf20Sopenharmony_ci	if (call->completion == RXRPC_CALL_SUCCEEDED) {
7668c2ecf20Sopenharmony_ci		ret = 1;
7678c2ecf20Sopenharmony_ci		if (iov_iter_count(iter) > 0)
7688c2ecf20Sopenharmony_ci			ret = -ECONNRESET;
7698c2ecf20Sopenharmony_ci	}
7708c2ecf20Sopenharmony_ci	goto out;
7718c2ecf20Sopenharmony_ci}
7728c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rxrpc_kernel_recv_data);
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci/**
7758c2ecf20Sopenharmony_ci * rxrpc_kernel_get_reply_time - Get timestamp on first reply packet
7768c2ecf20Sopenharmony_ci * @sock: The socket that the call exists on
7778c2ecf20Sopenharmony_ci * @call: The call to query
7788c2ecf20Sopenharmony_ci * @_ts: Where to put the timestamp
7798c2ecf20Sopenharmony_ci *
7808c2ecf20Sopenharmony_ci * Retrieve the timestamp from the first DATA packet of the reply if it is
7818c2ecf20Sopenharmony_ci * in the ring.  Returns true if successful, false if not.
7828c2ecf20Sopenharmony_ci */
7838c2ecf20Sopenharmony_cibool rxrpc_kernel_get_reply_time(struct socket *sock, struct rxrpc_call *call,
7848c2ecf20Sopenharmony_ci				 ktime_t *_ts)
7858c2ecf20Sopenharmony_ci{
7868c2ecf20Sopenharmony_ci	struct sk_buff *skb;
7878c2ecf20Sopenharmony_ci	rxrpc_seq_t hard_ack, top, seq;
7888c2ecf20Sopenharmony_ci	bool success = false;
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	mutex_lock(&call->user_mutex);
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	if (READ_ONCE(call->state) != RXRPC_CALL_CLIENT_RECV_REPLY)
7938c2ecf20Sopenharmony_ci		goto out;
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	hard_ack = call->rx_hard_ack;
7968c2ecf20Sopenharmony_ci	if (hard_ack != 0)
7978c2ecf20Sopenharmony_ci		goto out;
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	seq = hard_ack + 1;
8008c2ecf20Sopenharmony_ci	top = smp_load_acquire(&call->rx_top);
8018c2ecf20Sopenharmony_ci	if (after(seq, top))
8028c2ecf20Sopenharmony_ci		goto out;
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci	skb = call->rxtx_buffer[seq & RXRPC_RXTX_BUFF_MASK];
8058c2ecf20Sopenharmony_ci	if (!skb)
8068c2ecf20Sopenharmony_ci		goto out;
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	*_ts = skb_get_ktime(skb);
8098c2ecf20Sopenharmony_ci	success = true;
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_ciout:
8128c2ecf20Sopenharmony_ci	mutex_unlock(&call->user_mutex);
8138c2ecf20Sopenharmony_ci	return success;
8148c2ecf20Sopenharmony_ci}
8158c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rxrpc_kernel_get_reply_time);
816