Blame view

net/rxrpc/sendmsg.c 15.2 KB
0b58b8a18   David Howells   rxrpc: Split send...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /* AF_RXRPC sendmsg() implementation.
   *
   * Copyright (C) 2007, 2016 Red Hat, Inc. All Rights Reserved.
   * Written by David Howells (dhowells@redhat.com)
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public Licence
   * as published by the Free Software Foundation; either version
   * 2 of the Licence, or (at your option) any later version.
   */
  
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  
  #include <linux/net.h>
  #include <linux/gfp.h>
  #include <linux/skbuff.h>
  #include <linux/export.h>
0b58b8a18   David Howells   rxrpc: Split send...
18
19
20
  #include <net/sock.h>
  #include <net/af_rxrpc.h>
  #include "ar-internal.h"
3dc20f090   David Howells   rxrpc Move enum r...
21
22
23
24
25
26
  enum rxrpc_command {
  	RXRPC_CMD_SEND_DATA,		/* send data message */
  	RXRPC_CMD_SEND_ABORT,		/* request abort generation */
  	RXRPC_CMD_ACCEPT,		/* [server] accept incoming call */
  	RXRPC_CMD_REJECT_BUSY,		/* [server] reject a call as busy */
  };
0b58b8a18   David Howells   rxrpc: Split send...
27
  /*
df423a4af   David Howells   rxrpc: Rearrange ...
28
29
   * wait for space to appear in the transmit/ACK window
   * - caller holds the socket locked
0b58b8a18   David Howells   rxrpc: Split send...
30
   */
df423a4af   David Howells   rxrpc: Rearrange ...
31
32
33
  static int rxrpc_wait_for_tx_window(struct rxrpc_sock *rx,
  				    struct rxrpc_call *call,
  				    long *timeo)
0b58b8a18   David Howells   rxrpc: Split send...
34
  {
df423a4af   David Howells   rxrpc: Rearrange ...
35
36
  	DECLARE_WAITQUEUE(myself, current);
  	int ret;
0b58b8a18   David Howells   rxrpc: Split send...
37

248f219cb   David Howells   rxrpc: Rewrite th...
38
39
  	_enter(",{%u,%u,%u}",
  	       call->tx_hard_ack, call->tx_top, call->tx_winsize);
0b58b8a18   David Howells   rxrpc: Split send...
40

df423a4af   David Howells   rxrpc: Rearrange ...
41
  	add_wait_queue(&call->waitq, &myself);
0b58b8a18   David Howells   rxrpc: Split send...
42

df423a4af   David Howells   rxrpc: Rearrange ...
43
44
45
  	for (;;) {
  		set_current_state(TASK_INTERRUPTIBLE);
  		ret = 0;
57494343c   David Howells   rxrpc: Implement ...
46
47
48
  		if (call->tx_top - call->tx_hard_ack <
  		    min_t(unsigned int, call->tx_winsize,
  			  call->cong_cwnd + call->cong_extra))
0b58b8a18   David Howells   rxrpc: Split send...
49
  			break;
248f219cb   David Howells   rxrpc: Rewrite th...
50
51
52
53
  		if (call->state >= RXRPC_CALL_COMPLETE) {
  			ret = -call->error;
  			break;
  		}
df423a4af   David Howells   rxrpc: Rearrange ...
54
55
  		if (signal_pending(current)) {
  			ret = sock_intr_errno(*timeo);
0b58b8a18   David Howells   rxrpc: Split send...
56
  			break;
0b58b8a18   David Howells   rxrpc: Split send...
57
  		}
df423a4af   David Howells   rxrpc: Rearrange ...
58

a124fe3ee   David Howells   rxrpc: Add a trac...
59
  		trace_rxrpc_transmit(call, rxrpc_transmit_wait);
df423a4af   David Howells   rxrpc: Rearrange ...
60
61
62
  		release_sock(&rx->sk);
  		*timeo = schedule_timeout(*timeo);
  		lock_sock(&rx->sk);
0b58b8a18   David Howells   rxrpc: Split send...
63
  	}
df423a4af   David Howells   rxrpc: Rearrange ...
64
65
66
67
  	remove_wait_queue(&call->waitq, &myself);
  	set_current_state(TASK_RUNNING);
  	_leave(" = %d", ret);
  	return ret;
0b58b8a18   David Howells   rxrpc: Split send...
68
69
70
  }
  
  /*
248f219cb   David Howells   rxrpc: Rewrite th...
71
   * Schedule an instant Tx resend.
0b58b8a18   David Howells   rxrpc: Split send...
72
   */
248f219cb   David Howells   rxrpc: Rewrite th...
73
  static inline void rxrpc_instant_resend(struct rxrpc_call *call, int ix)
0b58b8a18   David Howells   rxrpc: Split send...
74
  {
248f219cb   David Howells   rxrpc: Rewrite th...
75
76
77
78
79
  	spin_lock_bh(&call->lock);
  
  	if (call->state < RXRPC_CALL_COMPLETE) {
  		call->rxtx_annotations[ix] = RXRPC_TX_ANNO_RETRANS;
  		if (!test_and_set_bit(RXRPC_CALL_EV_RESEND, &call->events))
df423a4af   David Howells   rxrpc: Rearrange ...
80
  			rxrpc_queue_call(call);
0b58b8a18   David Howells   rxrpc: Split send...
81
  	}
248f219cb   David Howells   rxrpc: Rewrite th...
82
83
  
  	spin_unlock_bh(&call->lock);
0b58b8a18   David Howells   rxrpc: Split send...
84
85
86
  }
  
  /*
248f219cb   David Howells   rxrpc: Rewrite th...
87
88
   * Queue a DATA packet for transmission, set the resend timeout and send the
   * packet immediately
0b58b8a18   David Howells   rxrpc: Split send...
89
   */
df423a4af   David Howells   rxrpc: Rearrange ...
90
91
  static void rxrpc_queue_packet(struct rxrpc_call *call, struct sk_buff *skb,
  			       bool last)
0b58b8a18   David Howells   rxrpc: Split send...
92
  {
df423a4af   David Howells   rxrpc: Rearrange ...
93
  	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
248f219cb   David Howells   rxrpc: Rewrite th...
94
95
  	rxrpc_seq_t seq = sp->hdr.seq;
  	int ret, ix;
70790dbe3   David Howells   rxrpc: Pass the l...
96
  	u8 annotation = RXRPC_TX_ANNO_UNACK;
248f219cb   David Howells   rxrpc: Rewrite th...
97
98
  
  	_net("queue skb %p [%d]", skb, seq);
0b58b8a18   David Howells   rxrpc: Split send...
99

248f219cb   David Howells   rxrpc: Rewrite th...
100
  	ASSERTCMP(seq, ==, call->tx_top + 1);
0b58b8a18   David Howells   rxrpc: Split send...
101

70790dbe3   David Howells   rxrpc: Pass the l...
102
103
  	if (last)
  		annotation |= RXRPC_TX_ANNO_LAST;
b24d2891c   David Howells   rxrpc: Preset tim...
104
105
106
107
  	/* We have to set the timestamp before queueing as the retransmit
  	 * algorithm can see the packet as soon as we queue it.
  	 */
  	skb->tstamp = ktime_get_real();
248f219cb   David Howells   rxrpc: Rewrite th...
108
  	ix = seq & RXRPC_RXTX_BUFF_MASK;
71f3ca408   David Howells   rxrpc: Improve sk...
109
  	rxrpc_get_skb(skb, rxrpc_skb_tx_got);
70790dbe3   David Howells   rxrpc: Pass the l...
110
  	call->rxtx_annotations[ix] = annotation;
df423a4af   David Howells   rxrpc: Rearrange ...
111
  	smp_wmb();
248f219cb   David Howells   rxrpc: Rewrite th...
112
113
  	call->rxtx_buffer[ix] = skb;
  	call->tx_top = seq;
70790dbe3   David Howells   rxrpc: Pass the l...
114
  	if (last)
a124fe3ee   David Howells   rxrpc: Add a trac...
115
  		trace_rxrpc_transmit(call, rxrpc_transmit_queue_last);
70790dbe3   David Howells   rxrpc: Pass the l...
116
  	else
a124fe3ee   David Howells   rxrpc: Add a trac...
117
  		trace_rxrpc_transmit(call, rxrpc_transmit_queue);
0b58b8a18   David Howells   rxrpc: Split send...
118

df423a4af   David Howells   rxrpc: Rearrange ...
119
120
121
122
123
124
125
126
127
  	if (last || call->state == RXRPC_CALL_SERVER_ACK_REQUEST) {
  		_debug("________awaiting reply/ACK__________");
  		write_lock_bh(&call->state_lock);
  		switch (call->state) {
  		case RXRPC_CALL_CLIENT_SEND_REQUEST:
  			call->state = RXRPC_CALL_CLIENT_AWAIT_REPLY;
  			break;
  		case RXRPC_CALL_SERVER_ACK_REQUEST:
  			call->state = RXRPC_CALL_SERVER_SEND_REPLY;
9749fd2be   David Howells   rxrpc: Need to pr...
128
129
130
131
132
  			call->ack_at = call->expire_at;
  			if (call->ackr_reason == RXRPC_ACK_DELAY)
  				call->ackr_reason = 0;
  			__rxrpc_set_timer(call, rxrpc_timer_init_for_send_reply,
  					  ktime_get_real());
df423a4af   David Howells   rxrpc: Rearrange ...
133
134
135
136
137
138
139
140
141
142
  			if (!last)
  				break;
  		case RXRPC_CALL_SERVER_SEND_REPLY:
  			call->state = RXRPC_CALL_SERVER_AWAIT_ACK;
  			break;
  		default:
  			break;
  		}
  		write_unlock_bh(&call->state_lock);
  	}
0b58b8a18   David Howells   rxrpc: Split send...
143

248f219cb   David Howells   rxrpc: Rewrite th...
144
145
  	if (seq == 1 && rxrpc_is_client_call(call))
  		rxrpc_expose_client_call(call);
df423a4af   David Howells   rxrpc: Rearrange ...
146

a1767077b   David Howells   rxrpc: Make Tx lo...
147
  	ret = rxrpc_send_data_packet(call, skb, false);
df423a4af   David Howells   rxrpc: Rearrange ...
148
149
  	if (ret < 0) {
  		_debug("need instant resend %d", ret);
248f219cb   David Howells   rxrpc: Rewrite th...
150
  		rxrpc_instant_resend(call, ix);
dfc3da440   David Howells   rxrpc: Need to st...
151
  	} else {
df0adc788   David Howells   rxrpc: Keep the c...
152
  		ktime_t now = ktime_get_real(), resend_at;
dfc3da440   David Howells   rxrpc: Need to st...
153

df0adc788   David Howells   rxrpc: Keep the c...
154
  		resend_at = ktime_add_ms(now, rxrpc_resend_timeout);
dfc3da440   David Howells   rxrpc: Need to st...
155

df0adc788   David Howells   rxrpc: Keep the c...
156
  		if (ktime_before(resend_at, call->resend_at)) {
dfc3da440   David Howells   rxrpc: Need to st...
157
  			call->resend_at = resend_at;
df0adc788   David Howells   rxrpc: Keep the c...
158
  			rxrpc_set_timer(call, rxrpc_timer_set_for_send, now);
dfc3da440   David Howells   rxrpc: Need to st...
159
  		}
df423a4af   David Howells   rxrpc: Rearrange ...
160
  	}
71f3ca408   David Howells   rxrpc: Improve sk...
161
  	rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
df423a4af   David Howells   rxrpc: Rearrange ...
162
  	_leave("");
0b58b8a18   David Howells   rxrpc: Split send...
163
164
165
  }
  
  /*
df423a4af   David Howells   rxrpc: Rearrange ...
166
167
   * send data through a socket
   * - must be called in process context
0b58b8a18   David Howells   rxrpc: Split send...
168
   * - caller holds the socket locked
0b58b8a18   David Howells   rxrpc: Split send...
169
   */
df423a4af   David Howells   rxrpc: Rearrange ...
170
171
172
  static int rxrpc_send_data(struct rxrpc_sock *rx,
  			   struct rxrpc_call *call,
  			   struct msghdr *msg, size_t len)
0b58b8a18   David Howells   rxrpc: Split send...
173
  {
df423a4af   David Howells   rxrpc: Rearrange ...
174
175
176
177
178
179
  	struct rxrpc_skb_priv *sp;
  	struct sk_buff *skb;
  	struct sock *sk = &rx->sk;
  	long timeo;
  	bool more;
  	int ret, copied;
0b58b8a18   David Howells   rxrpc: Split send...
180

df423a4af   David Howells   rxrpc: Rearrange ...
181
  	timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
0b58b8a18   David Howells   rxrpc: Split send...
182

df423a4af   David Howells   rxrpc: Rearrange ...
183
184
  	/* this should be in poll */
  	sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
0b58b8a18   David Howells   rxrpc: Split send...
185

df423a4af   David Howells   rxrpc: Rearrange ...
186
187
  	if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
  		return -EPIPE;
0b58b8a18   David Howells   rxrpc: Split send...
188

df423a4af   David Howells   rxrpc: Rearrange ...
189
  	more = msg->msg_flags & MSG_MORE;
0b58b8a18   David Howells   rxrpc: Split send...
190

df423a4af   David Howells   rxrpc: Rearrange ...
191
192
  	skb = call->tx_pending;
  	call->tx_pending = NULL;
71f3ca408   David Howells   rxrpc: Improve sk...
193
  	rxrpc_see_skb(skb, rxrpc_skb_tx_seen);
0b58b8a18   David Howells   rxrpc: Split send...
194

df423a4af   David Howells   rxrpc: Rearrange ...
195
196
  	copied = 0;
  	do {
7aa51da7c   David Howells   rxrpc: Expedite p...
197
198
  		/* Check to see if there's a ping ACK to reply to. */
  		if (call->ackr_reason == RXRPC_ACK_PING_RESPONSE)
a5af7e1fc   David Howells   rxrpc: Fix loss o...
199
  			rxrpc_send_ack_packet(call, false);
7aa51da7c   David Howells   rxrpc: Expedite p...
200

df423a4af   David Howells   rxrpc: Rearrange ...
201
202
  		if (!skb) {
  			size_t size, chunk, max, space;
0b58b8a18   David Howells   rxrpc: Split send...
203

df423a4af   David Howells   rxrpc: Rearrange ...
204
  			_debug("alloc");
0b58b8a18   David Howells   rxrpc: Split send...
205

248f219cb   David Howells   rxrpc: Rewrite th...
206
  			if (call->tx_top - call->tx_hard_ack >=
57494343c   David Howells   rxrpc: Implement ...
207
208
  			    min_t(unsigned int, call->tx_winsize,
  				  call->cong_cwnd + call->cong_extra)) {
df423a4af   David Howells   rxrpc: Rearrange ...
209
210
211
212
213
214
215
216
  				ret = -EAGAIN;
  				if (msg->msg_flags & MSG_DONTWAIT)
  					goto maybe_error;
  				ret = rxrpc_wait_for_tx_window(rx, call,
  							       &timeo);
  				if (ret < 0)
  					goto maybe_error;
  			}
0b58b8a18   David Howells   rxrpc: Split send...
217

182f50562   David Howells   rxrpc: Fix the ba...
218
  			max = RXRPC_JUMBO_DATALEN;
df423a4af   David Howells   rxrpc: Rearrange ...
219
220
  			max -= call->conn->security_size;
  			max &= ~(call->conn->size_align - 1UL);
0b58b8a18   David Howells   rxrpc: Split send...
221

df423a4af   David Howells   rxrpc: Rearrange ...
222
223
224
  			chunk = max;
  			if (chunk > msg_data_left(msg) && !more)
  				chunk = msg_data_left(msg);
0b58b8a18   David Howells   rxrpc: Split send...
225

df423a4af   David Howells   rxrpc: Rearrange ...
226
227
  			space = chunk + call->conn->size_align;
  			space &= ~(call->conn->size_align - 1UL);
0b58b8a18   David Howells   rxrpc: Split send...
228

5a924b895   David Howells   rxrpc: Don't stor...
229
  			size = space + call->conn->security_size;
0b58b8a18   David Howells   rxrpc: Split send...
230

df423a4af   David Howells   rxrpc: Rearrange ...
231
  			_debug("SIZE: %zu/%zu/%zu", chunk, space, size);
0b58b8a18   David Howells   rxrpc: Split send...
232

df423a4af   David Howells   rxrpc: Rearrange ...
233
234
235
236
237
  			/* create a buffer that we can retain until it's ACK'd */
  			skb = sock_alloc_send_skb(
  				sk, size, msg->msg_flags & MSG_DONTWAIT, &ret);
  			if (!skb)
  				goto maybe_error;
0b58b8a18   David Howells   rxrpc: Split send...
238

71f3ca408   David Howells   rxrpc: Improve sk...
239
  			rxrpc_new_skb(skb, rxrpc_skb_tx_new);
0b58b8a18   David Howells   rxrpc: Split send...
240

df423a4af   David Howells   rxrpc: Rearrange ...
241
  			_debug("ALLOC SEND %p", skb);
0b58b8a18   David Howells   rxrpc: Split send...
242

df423a4af   David Howells   rxrpc: Rearrange ...
243
  			ASSERTCMP(skb->mark, ==, 0);
0b58b8a18   David Howells   rxrpc: Split send...
244

5a924b895   David Howells   rxrpc: Don't stor...
245
246
247
  			_debug("HS: %u", call->conn->security_size);
  			skb_reserve(skb, call->conn->security_size);
  			skb->len += call->conn->security_size;
0b58b8a18   David Howells   rxrpc: Split send...
248

df423a4af   David Howells   rxrpc: Rearrange ...
249
250
251
252
  			sp = rxrpc_skb(skb);
  			sp->remain = chunk;
  			if (sp->remain > skb_tailroom(skb))
  				sp->remain = skb_tailroom(skb);
0b58b8a18   David Howells   rxrpc: Split send...
253

df423a4af   David Howells   rxrpc: Rearrange ...
254
255
256
257
258
  			_net("skb: hr %d, tr %d, hl %d, rm %d",
  			       skb_headroom(skb),
  			       skb_tailroom(skb),
  			       skb_headlen(skb),
  			       sp->remain);
0b58b8a18   David Howells   rxrpc: Split send...
259

df423a4af   David Howells   rxrpc: Rearrange ...
260
261
  			skb->ip_summed = CHECKSUM_UNNECESSARY;
  		}
0b58b8a18   David Howells   rxrpc: Split send...
262

df423a4af   David Howells   rxrpc: Rearrange ...
263
264
  		_debug("append");
  		sp = rxrpc_skb(skb);
0b58b8a18   David Howells   rxrpc: Split send...
265

df423a4af   David Howells   rxrpc: Rearrange ...
266
267
268
269
270
271
272
273
  		/* append next segment of data to the current buffer */
  		if (msg_data_left(msg) > 0) {
  			int copy = skb_tailroom(skb);
  			ASSERTCMP(copy, >, 0);
  			if (copy > msg_data_left(msg))
  				copy = msg_data_left(msg);
  			if (copy > sp->remain)
  				copy = sp->remain;
0b58b8a18   David Howells   rxrpc: Split send...
274

df423a4af   David Howells   rxrpc: Rearrange ...
275
276
277
278
279
280
281
282
  			_debug("add");
  			ret = skb_add_data(skb, &msg->msg_iter, copy);
  			_debug("added");
  			if (ret < 0)
  				goto efault;
  			sp->remain -= copy;
  			skb->mark += copy;
  			copied += copy;
0b58b8a18   David Howells   rxrpc: Split send...
283
  		}
df423a4af   David Howells   rxrpc: Rearrange ...
284
285
286
287
  		/* check for the far side aborting the call or a network error
  		 * occurring */
  		if (call->state == RXRPC_CALL_COMPLETE)
  			goto call_terminated;
0b58b8a18   David Howells   rxrpc: Split send...
288

df423a4af   David Howells   rxrpc: Rearrange ...
289
290
291
292
293
294
  		/* add the packet to the send queue if it's now full */
  		if (sp->remain <= 0 ||
  		    (msg_data_left(msg) == 0 && !more)) {
  			struct rxrpc_connection *conn = call->conn;
  			uint32_t seq;
  			size_t pad;
0b58b8a18   David Howells   rxrpc: Split send...
295

df423a4af   David Howells   rxrpc: Rearrange ...
296
297
298
299
300
301
302
303
304
  			/* pad out if we're using security */
  			if (conn->security_ix) {
  				pad = conn->security_size + skb->mark;
  				pad = conn->size_align - pad;
  				pad &= conn->size_align - 1;
  				_debug("pad %zu", pad);
  				if (pad)
  					memset(skb_put(skb, pad), 0, pad);
  			}
0b58b8a18   David Howells   rxrpc: Split send...
305

248f219cb   David Howells   rxrpc: Rewrite th...
306
  			seq = call->tx_top + 1;
0b58b8a18   David Howells   rxrpc: Split send...
307

df423a4af   David Howells   rxrpc: Rearrange ...
308
  			sp->hdr.seq	= seq;
df423a4af   David Howells   rxrpc: Rearrange ...
309
  			sp->hdr._rsvd	= 0;
5a924b895   David Howells   rxrpc: Don't stor...
310
  			sp->hdr.flags	= conn->out_clientflag;
0b58b8a18   David Howells   rxrpc: Split send...
311

df423a4af   David Howells   rxrpc: Rearrange ...
312
313
  			if (msg_data_left(msg) == 0 && !more)
  				sp->hdr.flags |= RXRPC_LAST_PACKET;
248f219cb   David Howells   rxrpc: Rewrite th...
314
315
  			else if (call->tx_top - call->tx_hard_ack <
  				 call->tx_winsize)
df423a4af   David Howells   rxrpc: Rearrange ...
316
  				sp->hdr.flags |= RXRPC_MORE_PACKETS;
0b58b8a18   David Howells   rxrpc: Split send...
317

df423a4af   David Howells   rxrpc: Rearrange ...
318
  			ret = conn->security->secure_packet(
5a924b895   David Howells   rxrpc: Don't stor...
319
  				call, skb, skb->mark, skb->head);
df423a4af   David Howells   rxrpc: Rearrange ...
320
321
  			if (ret < 0)
  				goto out;
0b58b8a18   David Howells   rxrpc: Split send...
322

df423a4af   David Howells   rxrpc: Rearrange ...
323
324
325
326
  			rxrpc_queue_packet(call, skb, !msg_data_left(msg) && !more);
  			skb = NULL;
  		}
  	} while (msg_data_left(msg) > 0);
0b58b8a18   David Howells   rxrpc: Split send...
327

df423a4af   David Howells   rxrpc: Rearrange ...
328
329
330
331
332
333
  success:
  	ret = copied;
  out:
  	call->tx_pending = skb;
  	_leave(" = %d", ret);
  	return ret;
0b58b8a18   David Howells   rxrpc: Split send...
334

df423a4af   David Howells   rxrpc: Rearrange ...
335
  call_terminated:
71f3ca408   David Howells   rxrpc: Improve sk...
336
  	rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
df423a4af   David Howells   rxrpc: Rearrange ...
337
  	_leave(" = %d", -call->error);
248f219cb   David Howells   rxrpc: Rewrite th...
338
  	return -call->error;
0b58b8a18   David Howells   rxrpc: Split send...
339

df423a4af   David Howells   rxrpc: Rearrange ...
340
341
342
343
  maybe_error:
  	if (copied)
  		goto success;
  	goto out;
0b58b8a18   David Howells   rxrpc: Split send...
344

df423a4af   David Howells   rxrpc: Rearrange ...
345
346
347
  efault:
  	ret = -EFAULT;
  	goto out;
0b58b8a18   David Howells   rxrpc: Split send...
348
349
350
  }
  
  /*
df423a4af   David Howells   rxrpc: Rearrange ...
351
   * extract control messages from the sendmsg() control buffer
0b58b8a18   David Howells   rxrpc: Split send...
352
   */
df423a4af   David Howells   rxrpc: Rearrange ...
353
354
355
356
357
  static int rxrpc_sendmsg_cmsg(struct msghdr *msg,
  			      unsigned long *user_call_ID,
  			      enum rxrpc_command *command,
  			      u32 *abort_code,
  			      bool *_exclusive)
0b58b8a18   David Howells   rxrpc: Split send...
358
  {
df423a4af   David Howells   rxrpc: Rearrange ...
359
360
361
  	struct cmsghdr *cmsg;
  	bool got_user_ID = false;
  	int len;
0b58b8a18   David Howells   rxrpc: Split send...
362

df423a4af   David Howells   rxrpc: Rearrange ...
363
  	*command = RXRPC_CMD_SEND_DATA;
0b58b8a18   David Howells   rxrpc: Split send...
364

df423a4af   David Howells   rxrpc: Rearrange ...
365
366
  	if (msg->msg_controllen == 0)
  		return -EINVAL;
0b58b8a18   David Howells   rxrpc: Split send...
367

df423a4af   David Howells   rxrpc: Rearrange ...
368
369
370
  	for_each_cmsghdr(cmsg, msg) {
  		if (!CMSG_OK(msg, cmsg))
  			return -EINVAL;
0b58b8a18   David Howells   rxrpc: Split send...
371

df423a4af   David Howells   rxrpc: Rearrange ...
372
373
374
  		len = cmsg->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr));
  		_debug("CMSG %d, %d, %d",
  		       cmsg->cmsg_level, cmsg->cmsg_type, len);
0b58b8a18   David Howells   rxrpc: Split send...
375

df423a4af   David Howells   rxrpc: Rearrange ...
376
377
  		if (cmsg->cmsg_level != SOL_RXRPC)
  			continue;
0b58b8a18   David Howells   rxrpc: Split send...
378

df423a4af   David Howells   rxrpc: Rearrange ...
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
  		switch (cmsg->cmsg_type) {
  		case RXRPC_USER_CALL_ID:
  			if (msg->msg_flags & MSG_CMSG_COMPAT) {
  				if (len != sizeof(u32))
  					return -EINVAL;
  				*user_call_ID = *(u32 *) CMSG_DATA(cmsg);
  			} else {
  				if (len != sizeof(unsigned long))
  					return -EINVAL;
  				*user_call_ID = *(unsigned long *)
  					CMSG_DATA(cmsg);
  			}
  			_debug("User Call ID %lx", *user_call_ID);
  			got_user_ID = true;
  			break;
0b58b8a18   David Howells   rxrpc: Split send...
394

df423a4af   David Howells   rxrpc: Rearrange ...
395
396
397
398
399
400
401
402
403
404
405
  		case RXRPC_ABORT:
  			if (*command != RXRPC_CMD_SEND_DATA)
  				return -EINVAL;
  			*command = RXRPC_CMD_SEND_ABORT;
  			if (len != sizeof(*abort_code))
  				return -EINVAL;
  			*abort_code = *(unsigned int *) CMSG_DATA(cmsg);
  			_debug("Abort %x", *abort_code);
  			if (*abort_code == 0)
  				return -EINVAL;
  			break;
0b58b8a18   David Howells   rxrpc: Split send...
406

df423a4af   David Howells   rxrpc: Rearrange ...
407
408
409
410
411
412
413
  		case RXRPC_ACCEPT:
  			if (*command != RXRPC_CMD_SEND_DATA)
  				return -EINVAL;
  			*command = RXRPC_CMD_ACCEPT;
  			if (len != 0)
  				return -EINVAL;
  			break;
0b58b8a18   David Howells   rxrpc: Split send...
414

df423a4af   David Howells   rxrpc: Rearrange ...
415
416
417
418
419
420
421
422
423
  		case RXRPC_EXCLUSIVE_CALL:
  			*_exclusive = true;
  			if (len != 0)
  				return -EINVAL;
  			break;
  		default:
  			return -EINVAL;
  		}
  	}
0b58b8a18   David Howells   rxrpc: Split send...
424

df423a4af   David Howells   rxrpc: Rearrange ...
425
426
427
428
429
  	if (!got_user_ID)
  		return -EINVAL;
  	_leave(" = 0");
  	return 0;
  }
0b58b8a18   David Howells   rxrpc: Split send...
430

df423a4af   David Howells   rxrpc: Rearrange ...
431
  /*
df423a4af   David Howells   rxrpc: Rearrange ...
432
433
434
435
436
437
438
439
440
   * Create a new client call for sendmsg().
   */
  static struct rxrpc_call *
  rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg,
  				  unsigned long user_call_ID, bool exclusive)
  {
  	struct rxrpc_conn_parameters cp;
  	struct rxrpc_call *call;
  	struct key *key;
0b58b8a18   David Howells   rxrpc: Split send...
441

df423a4af   David Howells   rxrpc: Rearrange ...
442
  	DECLARE_SOCKADDR(struct sockaddr_rxrpc *, srx, msg->msg_name);
0b58b8a18   David Howells   rxrpc: Split send...
443

df423a4af   David Howells   rxrpc: Rearrange ...
444
  	_enter("");
0b58b8a18   David Howells   rxrpc: Split send...
445

df423a4af   David Howells   rxrpc: Rearrange ...
446
447
  	if (!msg->msg_name)
  		return ERR_PTR(-EDESTADDRREQ);
0b58b8a18   David Howells   rxrpc: Split send...
448

df423a4af   David Howells   rxrpc: Rearrange ...
449
450
451
  	key = rx->key;
  	if (key && !rx->key->payload.data[0])
  		key = NULL;
0b58b8a18   David Howells   rxrpc: Split send...
452

df423a4af   David Howells   rxrpc: Rearrange ...
453
454
455
456
457
458
459
  	memset(&cp, 0, sizeof(cp));
  	cp.local		= rx->local;
  	cp.key			= rx->key;
  	cp.security_level	= rx->min_sec_level;
  	cp.exclusive		= rx->exclusive | exclusive;
  	cp.service_id		= srx->srx_service;
  	call = rxrpc_new_client_call(rx, &cp, srx, user_call_ID, GFP_KERNEL);
0b58b8a18   David Howells   rxrpc: Split send...
460

df423a4af   David Howells   rxrpc: Rearrange ...
461
462
463
464
  	_leave(" = %p
  ", call);
  	return call;
  }
0b58b8a18   David Howells   rxrpc: Split send...
465

df423a4af   David Howells   rxrpc: Rearrange ...
466
467
468
469
470
471
472
473
474
475
476
477
478
  /*
   * send a message forming part of a client call through an RxRPC socket
   * - caller holds the socket locked
   * - the socket may be either a client socket or a server socket
   */
  int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
  {
  	enum rxrpc_command cmd;
  	struct rxrpc_call *call;
  	unsigned long user_call_ID = 0;
  	bool exclusive = false;
  	u32 abort_code = 0;
  	int ret;
0b58b8a18   David Howells   rxrpc: Split send...
479

df423a4af   David Howells   rxrpc: Rearrange ...
480
  	_enter("");
0b58b8a18   David Howells   rxrpc: Split send...
481

df423a4af   David Howells   rxrpc: Rearrange ...
482
483
484
485
  	ret = rxrpc_sendmsg_cmsg(msg, &user_call_ID, &cmd, &abort_code,
  				 &exclusive);
  	if (ret < 0)
  		return ret;
0b58b8a18   David Howells   rxrpc: Split send...
486

df423a4af   David Howells   rxrpc: Rearrange ...
487
488
489
490
491
492
  	if (cmd == RXRPC_CMD_ACCEPT) {
  		if (rx->sk.sk_state != RXRPC_SERVER_LISTENING)
  			return -EINVAL;
  		call = rxrpc_accept_call(rx, user_call_ID, NULL);
  		if (IS_ERR(call))
  			return PTR_ERR(call);
fff72429c   David Howells   rxrpc: Improve th...
493
  		rxrpc_put_call(call, rxrpc_call_put);
df423a4af   David Howells   rxrpc: Rearrange ...
494
495
  		return 0;
  	}
0b58b8a18   David Howells   rxrpc: Split send...
496

df423a4af   David Howells   rxrpc: Rearrange ...
497
498
499
500
501
502
503
504
505
  	call = rxrpc_find_call_by_user_ID(rx, user_call_ID);
  	if (!call) {
  		if (cmd != RXRPC_CMD_SEND_DATA)
  			return -EBADSLT;
  		call = rxrpc_new_client_call_for_sendmsg(rx, msg, user_call_ID,
  							 exclusive);
  		if (IS_ERR(call))
  			return PTR_ERR(call);
  	}
0b58b8a18   David Howells   rxrpc: Split send...
506

df423a4af   David Howells   rxrpc: Rearrange ...
507
508
  	_debug("CALL %d USR %lx ST %d on CONN %p",
  	       call->debug_id, call->user_call_ID, call->state, call->conn);
0b58b8a18   David Howells   rxrpc: Split send...
509

df423a4af   David Howells   rxrpc: Rearrange ...
510
511
512
513
  	if (call->state >= RXRPC_CALL_COMPLETE) {
  		/* it's too late for this call */
  		ret = -ESHUTDOWN;
  	} else if (cmd == RXRPC_CMD_SEND_ABORT) {
df423a4af   David Howells   rxrpc: Rearrange ...
514
  		ret = 0;
248f219cb   David Howells   rxrpc: Rewrite th...
515
  		if (rxrpc_abort_call("CMD", call, 0, abort_code, ECONNABORTED))
26cb02aa6   David Howells   rxrpc: Fix warnin...
516
  			ret = rxrpc_send_abort_packet(call);
df423a4af   David Howells   rxrpc: Rearrange ...
517
518
519
520
521
522
523
524
525
526
527
528
529
530
  	} else if (cmd != RXRPC_CMD_SEND_DATA) {
  		ret = -EINVAL;
  	} else if (rxrpc_is_client_call(call) &&
  		   call->state != RXRPC_CALL_CLIENT_SEND_REQUEST) {
  		/* request phase complete for this client call */
  		ret = -EPROTO;
  	} else if (rxrpc_is_service_call(call) &&
  		   call->state != RXRPC_CALL_SERVER_ACK_REQUEST &&
  		   call->state != RXRPC_CALL_SERVER_SEND_REPLY) {
  		/* Reply phase not begun or not complete for service call. */
  		ret = -EPROTO;
  	} else {
  		ret = rxrpc_send_data(rx, call, msg, len);
  	}
0b58b8a18   David Howells   rxrpc: Split send...
531

fff72429c   David Howells   rxrpc: Improve th...
532
  	rxrpc_put_call(call, rxrpc_call_put);
df423a4af   David Howells   rxrpc: Rearrange ...
533
534
535
  	_leave(" = %d", ret);
  	return ret;
  }
0b58b8a18   David Howells   rxrpc: Split send...
536

df423a4af   David Howells   rxrpc: Rearrange ...
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
  /**
   * rxrpc_kernel_send_data - Allow a kernel service to send data on a call
   * @sock: The socket the call is on
   * @call: The call to send data through
   * @msg: The data to send
   * @len: The amount of data to send
   *
   * Allow a kernel service to send data on a call.  The call must be in an state
   * appropriate to sending data.  No control data should be supplied in @msg,
   * nor should an address be supplied.  MSG_MORE should be flagged if there's
   * more data to come, otherwise this data will end the transmission phase.
   */
  int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call,
  			   struct msghdr *msg, size_t len)
  {
  	int ret;
0b58b8a18   David Howells   rxrpc: Split send...
553

df423a4af   David Howells   rxrpc: Rearrange ...
554
  	_enter("{%d,%s},", call->debug_id, rxrpc_call_states[call->state]);
0b58b8a18   David Howells   rxrpc: Split send...
555

df423a4af   David Howells   rxrpc: Rearrange ...
556
557
  	ASSERTCMP(msg->msg_name, ==, NULL);
  	ASSERTCMP(msg->msg_control, ==, NULL);
0b58b8a18   David Howells   rxrpc: Split send...
558

df423a4af   David Howells   rxrpc: Rearrange ...
559
  	lock_sock(sock->sk);
0b58b8a18   David Howells   rxrpc: Split send...
560

df423a4af   David Howells   rxrpc: Rearrange ...
561
562
  	_debug("CALL %d USR %lx ST %d on CONN %p",
  	       call->debug_id, call->user_call_ID, call->state, call->conn);
0b58b8a18   David Howells   rxrpc: Split send...
563

df423a4af   David Howells   rxrpc: Rearrange ...
564
565
566
567
568
569
570
571
572
573
574
  	if (call->state >= RXRPC_CALL_COMPLETE) {
  		ret = -ESHUTDOWN; /* it's too late for this call */
  	} else if (call->state != RXRPC_CALL_CLIENT_SEND_REQUEST &&
  		   call->state != RXRPC_CALL_SERVER_ACK_REQUEST &&
  		   call->state != RXRPC_CALL_SERVER_SEND_REPLY) {
  		ret = -EPROTO; /* request phase complete for this client call */
  	} else {
  		ret = rxrpc_send_data(rxrpc_sk(sock->sk), call, msg, len);
  	}
  
  	release_sock(sock->sk);
0b58b8a18   David Howells   rxrpc: Split send...
575
576
  	_leave(" = %d", ret);
  	return ret;
df423a4af   David Howells   rxrpc: Rearrange ...
577
578
  }
  EXPORT_SYMBOL(rxrpc_kernel_send_data);
0b58b8a18   David Howells   rxrpc: Split send...
579

df423a4af   David Howells   rxrpc: Rearrange ...
580
581
582
583
584
  /**
   * rxrpc_kernel_abort_call - Allow a kernel service to abort a call
   * @sock: The socket the call is on
   * @call: The call to be aborted
   * @abort_code: The abort code to stick into the ABORT packet
5a42976d4   David Howells   rxrpc: Add tracep...
585
586
   * @error: Local error value
   * @why: 3-char string indicating why.
df423a4af   David Howells   rxrpc: Rearrange ...
587
588
589
590
   *
   * Allow a kernel service to abort a call, if it's still in an abortable state.
   */
  void rxrpc_kernel_abort_call(struct socket *sock, struct rxrpc_call *call,
5a42976d4   David Howells   rxrpc: Add tracep...
591
  			     u32 abort_code, int error, const char *why)
df423a4af   David Howells   rxrpc: Rearrange ...
592
  {
5a42976d4   David Howells   rxrpc: Add tracep...
593
  	_enter("{%d},%d,%d,%s", call->debug_id, abort_code, error, why);
0b58b8a18   David Howells   rxrpc: Split send...
594

df423a4af   David Howells   rxrpc: Rearrange ...
595
  	lock_sock(sock->sk);
0b58b8a18   David Howells   rxrpc: Split send...
596

248f219cb   David Howells   rxrpc: Rewrite th...
597
  	if (rxrpc_abort_call(why, call, 0, abort_code, error))
26cb02aa6   David Howells   rxrpc: Fix warnin...
598
  		rxrpc_send_abort_packet(call);
df423a4af   David Howells   rxrpc: Rearrange ...
599
600
601
  
  	release_sock(sock->sk);
  	_leave("");
0b58b8a18   David Howells   rxrpc: Split send...
602
  }
df423a4af   David Howells   rxrpc: Rearrange ...
603
604
  
  EXPORT_SYMBOL(rxrpc_kernel_abort_call);