Commit | Line | Data |
---|---|---|
17926a79 DH |
1 | /* connection-level event handling |
2 | * | |
3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | |
4 | * Written by David Howells (dhowells@redhat.com) | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License | |
8 | * as published by the Free Software Foundation; either version | |
9 | * 2 of the License, or (at your option) any later version. | |
10 | */ | |
11 | ||
9b6d5398 JP |
12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
13 | ||
17926a79 DH |
14 | #include <linux/module.h> |
15 | #include <linux/net.h> | |
16 | #include <linux/skbuff.h> | |
17 | #include <linux/errqueue.h> | |
18 | #include <linux/udp.h> | |
19 | #include <linux/in.h> | |
20 | #include <linux/in6.h> | |
21 | #include <linux/icmp.h> | |
22 | #include <net/sock.h> | |
23 | #include <net/af_rxrpc.h> | |
24 | #include <net/ip.h> | |
25 | #include "ar-internal.h" | |
26 | ||
18bfeba5 DH |
27 | /* |
28 | * Retransmit terminal ACK or ABORT of the previous call. | |
29 | */ | |
f5c17aae DH |
30 | static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn, |
31 | struct sk_buff *skb) | |
18bfeba5 DH |
32 | { |
33 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | |
34 | struct rxrpc_channel *chan; | |
35 | struct msghdr msg; | |
36 | struct kvec iov; | |
37 | struct { | |
38 | struct rxrpc_wire_header whdr; | |
39 | union { | |
40 | struct { | |
41 | __be32 code; | |
42 | } abort; | |
43 | struct { | |
44 | struct rxrpc_ackpacket ack; | |
2266ffde | 45 | u8 padding[3]; |
18bfeba5 DH |
46 | struct rxrpc_ackinfo info; |
47 | }; | |
48 | }; | |
49 | } __attribute__((packed)) pkt; | |
50 | size_t len; | |
51 | u32 serial, mtu, call_id; | |
52 | ||
53 | _enter("%d", conn->debug_id); | |
54 | ||
55 | chan = &conn->channels[sp->hdr.cid & RXRPC_CHANNELMASK]; | |
56 | ||
57 | /* If the last call got moved on whilst we were waiting to run, just | |
58 | * ignore this packet. | |
59 | */ | |
60 | call_id = READ_ONCE(chan->last_call); | |
61 | /* Sync with __rxrpc_disconnect_call() */ | |
62 | smp_rmb(); | |
63 | if (call_id != sp->hdr.callNumber) | |
64 | return; | |
65 | ||
66 | msg.msg_name = &conn->params.peer->srx.transport; | |
67 | msg.msg_namelen = conn->params.peer->srx.transport_len; | |
68 | msg.msg_control = NULL; | |
69 | msg.msg_controllen = 0; | |
70 | msg.msg_flags = 0; | |
71 | ||
72 | pkt.whdr.epoch = htonl(sp->hdr.epoch); | |
73 | pkt.whdr.cid = htonl(sp->hdr.cid); | |
74 | pkt.whdr.callNumber = htonl(sp->hdr.callNumber); | |
75 | pkt.whdr.seq = 0; | |
76 | pkt.whdr.type = chan->last_type; | |
77 | pkt.whdr.flags = conn->out_clientflag; | |
78 | pkt.whdr.userStatus = 0; | |
79 | pkt.whdr.securityIndex = conn->security_ix; | |
80 | pkt.whdr._rsvd = 0; | |
81 | pkt.whdr.serviceId = htons(chan->last_service_id); | |
82 | ||
83 | len = sizeof(pkt.whdr); | |
84 | switch (chan->last_type) { | |
85 | case RXRPC_PACKET_TYPE_ABORT: | |
86 | pkt.abort.code = htonl(chan->last_abort); | |
87 | len += sizeof(pkt.abort); | |
88 | break; | |
89 | ||
90 | case RXRPC_PACKET_TYPE_ACK: | |
91 | mtu = conn->params.peer->if_mtu; | |
92 | mtu -= conn->params.peer->hdrsize; | |
93 | pkt.ack.bufferSpace = 0; | |
94 | pkt.ack.maxSkew = htons(skb->priority); | |
95 | pkt.ack.firstPacket = htonl(chan->last_seq); | |
96 | pkt.ack.previousPacket = htonl(chan->last_seq - 1); | |
97 | pkt.ack.serial = htonl(sp->hdr.serial); | |
98 | pkt.ack.reason = RXRPC_ACK_DUPLICATE; | |
99 | pkt.ack.nAcks = 0; | |
100 | pkt.info.rxMTU = htonl(rxrpc_rx_mtu); | |
101 | pkt.info.maxMTU = htonl(mtu); | |
102 | pkt.info.rwind = htonl(rxrpc_rx_window_size); | |
103 | pkt.info.jumbo_max = htonl(rxrpc_rx_jumbo_max); | |
104 | len += sizeof(pkt.ack) + sizeof(pkt.info); | |
105 | break; | |
106 | } | |
107 | ||
108 | /* Resync with __rxrpc_disconnect_call() and check that the last call | |
109 | * didn't get advanced whilst we were filling out the packets. | |
110 | */ | |
111 | smp_rmb(); | |
112 | if (READ_ONCE(chan->last_call) != call_id) | |
113 | return; | |
114 | ||
115 | iov.iov_base = &pkt; | |
116 | iov.iov_len = len; | |
117 | ||
118 | serial = atomic_inc_return(&conn->serial); | |
119 | pkt.whdr.serial = htonl(serial); | |
120 | ||
121 | switch (chan->last_type) { | |
122 | case RXRPC_PACKET_TYPE_ABORT: | |
123 | _proto("Tx ABORT %%%u { %d } [re]", serial, conn->local_abort); | |
124 | break; | |
125 | case RXRPC_PACKET_TYPE_ACK: | |
126 | _proto("Tx ACK %%%u [re]", serial); | |
127 | break; | |
128 | } | |
129 | ||
130 | kernel_sendmsg(conn->params.local->socket, &msg, &iov, 1, len); | |
131 | _leave(""); | |
132 | return; | |
133 | } | |
134 | ||
17926a79 DH |
135 | /* |
136 | * pass a connection-level abort onto all calls on that connection | |
137 | */ | |
f5c17aae DH |
138 | static void rxrpc_abort_calls(struct rxrpc_connection *conn, |
139 | enum rxrpc_call_completion compl, | |
140 | u32 abort_code, int error) | |
17926a79 DH |
141 | { |
142 | struct rxrpc_call *call; | |
f5c17aae DH |
143 | bool queue; |
144 | int i, bit; | |
17926a79 DH |
145 | |
146 | _enter("{%d},%x", conn->debug_id, abort_code); | |
147 | ||
f5c17aae DH |
148 | if (compl == RXRPC_CALL_LOCALLY_ABORTED) |
149 | bit = RXRPC_CALL_EV_CONN_ABORT; | |
150 | else | |
151 | bit = RXRPC_CALL_EV_RCVD_ABORT; | |
152 | ||
a1399f8b | 153 | spin_lock(&conn->channel_lock); |
17926a79 | 154 | |
a1399f8b DH |
155 | for (i = 0; i < RXRPC_MAXCALLS; i++) { |
156 | call = rcu_dereference_protected( | |
157 | conn->channels[i].call, | |
158 | lockdep_is_held(&conn->channel_lock)); | |
ccbd3dbe | 159 | if (call) { |
e34d4234 | 160 | rxrpc_see_call(call); |
ccbd3dbe | 161 | write_lock_bh(&call->state_lock); |
f5c17aae DH |
162 | if (rxrpc_set_call_completion(call, compl, abort_code, |
163 | error)) { | |
164 | set_bit(bit, &call->events); | |
165 | queue = true; | |
dc44b3a0 | 166 | } |
ccbd3dbe | 167 | write_unlock_bh(&call->state_lock); |
f5c17aae DH |
168 | if (queue) |
169 | rxrpc_queue_call(call); | |
17926a79 | 170 | } |
17926a79 DH |
171 | } |
172 | ||
a1399f8b | 173 | spin_unlock(&conn->channel_lock); |
17926a79 DH |
174 | _leave(""); |
175 | } | |
176 | ||
177 | /* | |
178 | * generate a connection-level abort | |
179 | */ | |
180 | static int rxrpc_abort_connection(struct rxrpc_connection *conn, | |
181 | u32 error, u32 abort_code) | |
182 | { | |
0d12f8a4 | 183 | struct rxrpc_wire_header whdr; |
17926a79 DH |
184 | struct msghdr msg; |
185 | struct kvec iov[2]; | |
186 | __be32 word; | |
187 | size_t len; | |
0d12f8a4 | 188 | u32 serial; |
17926a79 DH |
189 | int ret; |
190 | ||
191 | _enter("%d,,%u,%u", conn->debug_id, error, abort_code); | |
192 | ||
193 | /* generate a connection-level abort */ | |
194 | spin_lock_bh(&conn->state_lock); | |
f5c17aae | 195 | if (conn->state >= RXRPC_CONN_REMOTELY_ABORTED) { |
17926a79 DH |
196 | spin_unlock_bh(&conn->state_lock); |
197 | _leave(" = 0 [already dead]"); | |
198 | return 0; | |
199 | } | |
200 | ||
f5c17aae DH |
201 | conn->state = RXRPC_CONN_LOCALLY_ABORTED; |
202 | spin_unlock_bh(&conn->state_lock); | |
203 | ||
204 | rxrpc_abort_calls(conn, RXRPC_CALL_LOCALLY_ABORTED, abort_code, error); | |
17926a79 | 205 | |
85f32278 DH |
206 | msg.msg_name = &conn->params.peer->srx.transport; |
207 | msg.msg_namelen = conn->params.peer->srx.transport_len; | |
17926a79 DH |
208 | msg.msg_control = NULL; |
209 | msg.msg_controllen = 0; | |
210 | msg.msg_flags = 0; | |
211 | ||
19ffa01c DH |
212 | whdr.epoch = htonl(conn->proto.epoch); |
213 | whdr.cid = htonl(conn->proto.cid); | |
0d12f8a4 DH |
214 | whdr.callNumber = 0; |
215 | whdr.seq = 0; | |
216 | whdr.type = RXRPC_PACKET_TYPE_ABORT; | |
217 | whdr.flags = conn->out_clientflag; | |
218 | whdr.userStatus = 0; | |
219 | whdr.securityIndex = conn->security_ix; | |
220 | whdr._rsvd = 0; | |
19ffa01c | 221 | whdr.serviceId = htons(conn->params.service_id); |
17926a79 | 222 | |
dc44b3a0 | 223 | word = htonl(conn->local_abort); |
17926a79 | 224 | |
0d12f8a4 DH |
225 | iov[0].iov_base = &whdr; |
226 | iov[0].iov_len = sizeof(whdr); | |
17926a79 DH |
227 | iov[1].iov_base = &word; |
228 | iov[1].iov_len = sizeof(word); | |
229 | ||
230 | len = iov[0].iov_len + iov[1].iov_len; | |
231 | ||
0d12f8a4 DH |
232 | serial = atomic_inc_return(&conn->serial); |
233 | whdr.serial = htonl(serial); | |
dc44b3a0 | 234 | _proto("Tx CONN ABORT %%%u { %d }", serial, conn->local_abort); |
17926a79 | 235 | |
85f32278 | 236 | ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len); |
17926a79 DH |
237 | if (ret < 0) { |
238 | _debug("sendmsg failed: %d", ret); | |
239 | return -EAGAIN; | |
240 | } | |
241 | ||
242 | _leave(" = 0"); | |
243 | return 0; | |
244 | } | |
245 | ||
246 | /* | |
247 | * mark a call as being on a now-secured channel | |
248 | * - must be called with softirqs disabled | |
249 | */ | |
5eaa65b2 | 250 | static void rxrpc_call_is_secure(struct rxrpc_call *call) |
17926a79 DH |
251 | { |
252 | _enter("%p", call); | |
253 | if (call) { | |
254 | read_lock(&call->state_lock); | |
255 | if (call->state < RXRPC_CALL_COMPLETE && | |
4c198ad1 | 256 | !test_and_set_bit(RXRPC_CALL_EV_SECURED, &call->events)) |
651350d1 | 257 | rxrpc_queue_call(call); |
17926a79 DH |
258 | read_unlock(&call->state_lock); |
259 | } | |
260 | } | |
261 | ||
262 | /* | |
263 | * connection-level Rx packet processor | |
264 | */ | |
265 | static int rxrpc_process_event(struct rxrpc_connection *conn, | |
266 | struct sk_buff *skb, | |
267 | u32 *_abort_code) | |
268 | { | |
269 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | |
0d12f8a4 DH |
270 | __be32 wtmp; |
271 | u32 abort_code; | |
17926a79 DH |
272 | int loop, ret; |
273 | ||
519d2567 DH |
274 | if (conn->state >= RXRPC_CONN_REMOTELY_ABORTED) { |
275 | kleave(" = -ECONNABORTED [%u]", conn->state); | |
17926a79 | 276 | return -ECONNABORTED; |
519d2567 | 277 | } |
17926a79 | 278 | |
0d12f8a4 | 279 | _enter("{%d},{%u,%%%u},", conn->debug_id, sp->hdr.type, sp->hdr.serial); |
519d2567 | 280 | |
17926a79 | 281 | switch (sp->hdr.type) { |
18bfeba5 DH |
282 | case RXRPC_PACKET_TYPE_DATA: |
283 | case RXRPC_PACKET_TYPE_ACK: | |
f5c17aae | 284 | rxrpc_conn_retransmit_call(conn, skb); |
18bfeba5 DH |
285 | return 0; |
286 | ||
17926a79 | 287 | case RXRPC_PACKET_TYPE_ABORT: |
0d12f8a4 | 288 | if (skb_copy_bits(skb, 0, &wtmp, sizeof(wtmp)) < 0) |
17926a79 | 289 | return -EPROTO; |
0d12f8a4 DH |
290 | abort_code = ntohl(wtmp); |
291 | _proto("Rx ABORT %%%u { ac=%d }", sp->hdr.serial, abort_code); | |
17926a79 DH |
292 | |
293 | conn->state = RXRPC_CONN_REMOTELY_ABORTED; | |
f5c17aae | 294 | rxrpc_abort_calls(conn, 0, RXRPC_CALL_REMOTELY_ABORTED, |
0d12f8a4 | 295 | abort_code); |
17926a79 DH |
296 | return -ECONNABORTED; |
297 | ||
298 | case RXRPC_PACKET_TYPE_CHALLENGE: | |
e0e4d82f DH |
299 | return conn->security->respond_to_challenge(conn, skb, |
300 | _abort_code); | |
17926a79 DH |
301 | |
302 | case RXRPC_PACKET_TYPE_RESPONSE: | |
17926a79 DH |
303 | ret = conn->security->verify_response(conn, skb, _abort_code); |
304 | if (ret < 0) | |
305 | return ret; | |
306 | ||
307 | ret = conn->security->init_connection_security(conn); | |
308 | if (ret < 0) | |
309 | return ret; | |
310 | ||
a263629d HX |
311 | ret = conn->security->prime_packet_security(conn); |
312 | if (ret < 0) | |
313 | return ret; | |
314 | ||
a1399f8b | 315 | spin_lock(&conn->channel_lock); |
17926a79 DH |
316 | spin_lock(&conn->state_lock); |
317 | ||
bba304db DH |
318 | if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING) { |
319 | conn->state = RXRPC_CONN_SERVICE; | |
17926a79 | 320 | for (loop = 0; loop < RXRPC_MAXCALLS; loop++) |
dee46364 DH |
321 | rxrpc_call_is_secure( |
322 | rcu_dereference_protected( | |
a1399f8b DH |
323 | conn->channels[loop].call, |
324 | lockdep_is_held(&conn->channel_lock))); | |
17926a79 DH |
325 | } |
326 | ||
327 | spin_unlock(&conn->state_lock); | |
a1399f8b | 328 | spin_unlock(&conn->channel_lock); |
17926a79 DH |
329 | return 0; |
330 | ||
331 | default: | |
519d2567 | 332 | _leave(" = -EPROTO [%u]", sp->hdr.type); |
17926a79 DH |
333 | return -EPROTO; |
334 | } | |
335 | } | |
336 | ||
337 | /* | |
338 | * set up security and issue a challenge | |
339 | */ | |
340 | static void rxrpc_secure_connection(struct rxrpc_connection *conn) | |
341 | { | |
342 | u32 abort_code; | |
343 | int ret; | |
344 | ||
345 | _enter("{%d}", conn->debug_id); | |
346 | ||
347 | ASSERT(conn->security_ix != 0); | |
348 | ||
19ffa01c | 349 | if (!conn->params.key) { |
17926a79 DH |
350 | _debug("set up security"); |
351 | ret = rxrpc_init_server_conn_security(conn); | |
352 | switch (ret) { | |
353 | case 0: | |
354 | break; | |
355 | case -ENOENT: | |
356 | abort_code = RX_CALL_DEAD; | |
357 | goto abort; | |
358 | default: | |
359 | abort_code = RXKADNOAUTH; | |
360 | goto abort; | |
361 | } | |
362 | } | |
363 | ||
17926a79 DH |
364 | if (conn->security->issue_challenge(conn) < 0) { |
365 | abort_code = RX_CALL_DEAD; | |
366 | ret = -ENOMEM; | |
367 | goto abort; | |
368 | } | |
369 | ||
370 | _leave(""); | |
371 | return; | |
372 | ||
373 | abort: | |
374 | _debug("abort %d, %d", ret, abort_code); | |
375 | rxrpc_abort_connection(conn, -ret, abort_code); | |
376 | _leave(" [aborted]"); | |
377 | } | |
378 | ||
379 | /* | |
380 | * connection-level event processor | |
381 | */ | |
382 | void rxrpc_process_connection(struct work_struct *work) | |
383 | { | |
384 | struct rxrpc_connection *conn = | |
385 | container_of(work, struct rxrpc_connection, processor); | |
17926a79 DH |
386 | struct sk_buff *skb; |
387 | u32 abort_code = RX_PROTOCOL_ERROR; | |
388 | int ret; | |
389 | ||
390 | _enter("{%d}", conn->debug_id); | |
391 | ||
2c4579e4 | 392 | if (test_and_clear_bit(RXRPC_CONN_EV_CHALLENGE, &conn->events)) |
17926a79 | 393 | rxrpc_secure_connection(conn); |
17926a79 DH |
394 | |
395 | /* go through the conn-level event packets, releasing the ref on this | |
396 | * connection that each one has when we've finished with it */ | |
397 | while ((skb = skb_dequeue(&conn->rx_queue))) { | |
df844fd4 | 398 | rxrpc_see_skb(skb); |
17926a79 DH |
399 | ret = rxrpc_process_event(conn, skb, &abort_code); |
400 | switch (ret) { | |
401 | case -EPROTO: | |
402 | case -EKEYEXPIRED: | |
403 | case -EKEYREJECTED: | |
404 | goto protocol_error; | |
405 | case -EAGAIN: | |
406 | goto requeue_and_leave; | |
407 | case -ECONNABORTED: | |
408 | default: | |
17926a79 DH |
409 | rxrpc_free_skb(skb); |
410 | break; | |
411 | } | |
412 | } | |
413 | ||
414 | out: | |
415 | rxrpc_put_connection(conn); | |
416 | _leave(""); | |
417 | return; | |
418 | ||
419 | requeue_and_leave: | |
420 | skb_queue_head(&conn->rx_queue, skb); | |
421 | goto out; | |
422 | ||
423 | protocol_error: | |
424 | if (rxrpc_abort_connection(conn, -ret, abort_code) < 0) | |
425 | goto requeue_and_leave; | |
17926a79 DH |
426 | rxrpc_free_skb(skb); |
427 | _leave(" [EPROTO]"); | |
428 | goto out; | |
429 | } | |
430 | ||
651350d1 DH |
431 | /* |
432 | * put a packet up for transport-level abort | |
433 | */ | |
434 | void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb) | |
435 | { | |
436 | CHECK_SLAB_OKAY(&local->usage); | |
437 | ||
651350d1 | 438 | skb_queue_tail(&local->reject_queue, skb); |
5acbee46 | 439 | rxrpc_queue_local(local); |
651350d1 DH |
440 | } |
441 | ||
17926a79 DH |
442 | /* |
443 | * reject packets through the local endpoint | |
444 | */ | |
4f95dd78 | 445 | void rxrpc_reject_packets(struct rxrpc_local *local) |
17926a79 DH |
446 | { |
447 | union { | |
448 | struct sockaddr sa; | |
449 | struct sockaddr_in sin; | |
450 | } sa; | |
451 | struct rxrpc_skb_priv *sp; | |
0d12f8a4 | 452 | struct rxrpc_wire_header whdr; |
17926a79 DH |
453 | struct sk_buff *skb; |
454 | struct msghdr msg; | |
455 | struct kvec iov[2]; | |
456 | size_t size; | |
457 | __be32 code; | |
458 | ||
17926a79 DH |
459 | _enter("%d", local->debug_id); |
460 | ||
0d12f8a4 DH |
461 | iov[0].iov_base = &whdr; |
462 | iov[0].iov_len = sizeof(whdr); | |
17926a79 DH |
463 | iov[1].iov_base = &code; |
464 | iov[1].iov_len = sizeof(code); | |
0d12f8a4 | 465 | size = sizeof(whdr) + sizeof(code); |
17926a79 DH |
466 | |
467 | msg.msg_name = &sa; | |
468 | msg.msg_control = NULL; | |
469 | msg.msg_controllen = 0; | |
470 | msg.msg_flags = 0; | |
471 | ||
472 | memset(&sa, 0, sizeof(sa)); | |
473 | sa.sa.sa_family = local->srx.transport.family; | |
474 | switch (sa.sa.sa_family) { | |
475 | case AF_INET: | |
476 | msg.msg_namelen = sizeof(sa.sin); | |
477 | break; | |
478 | default: | |
479 | msg.msg_namelen = 0; | |
480 | break; | |
481 | } | |
482 | ||
0d12f8a4 DH |
483 | memset(&whdr, 0, sizeof(whdr)); |
484 | whdr.type = RXRPC_PACKET_TYPE_ABORT; | |
17926a79 DH |
485 | |
486 | while ((skb = skb_dequeue(&local->reject_queue))) { | |
df844fd4 | 487 | rxrpc_see_skb(skb); |
17926a79 DH |
488 | sp = rxrpc_skb(skb); |
489 | switch (sa.sa.sa_family) { | |
490 | case AF_INET: | |
491 | sa.sin.sin_port = udp_hdr(skb)->source; | |
492 | sa.sin.sin_addr.s_addr = ip_hdr(skb)->saddr; | |
493 | code = htonl(skb->priority); | |
494 | ||
0d12f8a4 DH |
495 | whdr.epoch = htonl(sp->hdr.epoch); |
496 | whdr.cid = htonl(sp->hdr.cid); | |
497 | whdr.callNumber = htonl(sp->hdr.callNumber); | |
498 | whdr.serviceId = htons(sp->hdr.serviceId); | |
499 | whdr.flags = sp->hdr.flags; | |
500 | whdr.flags ^= RXRPC_CLIENT_INITIATED; | |
501 | whdr.flags &= RXRPC_CLIENT_INITIATED; | |
17926a79 DH |
502 | |
503 | kernel_sendmsg(local->socket, &msg, iov, 2, size); | |
504 | break; | |
505 | ||
506 | default: | |
507 | break; | |
508 | } | |
509 | ||
510 | rxrpc_free_skb(skb); | |
17926a79 DH |
511 | } |
512 | ||
17926a79 DH |
513 | _leave(""); |
514 | } |