Commit | Line | Data |
---|---|---|
2874c5fd | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
17926a79 DH |
2 | /* connection-level event handling |
3 | * | |
4 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | |
5 | * Written by David Howells (dhowells@redhat.com) | |
17926a79 DH |
6 | */ |
7 | ||
9b6d5398 JP |
8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
9 | ||
17926a79 DH |
10 | #include <linux/module.h> |
11 | #include <linux/net.h> | |
12 | #include <linux/skbuff.h> | |
13 | #include <linux/errqueue.h> | |
17926a79 DH |
14 | #include <net/sock.h> |
15 | #include <net/af_rxrpc.h> | |
16 | #include <net/ip.h> | |
17 | #include "ar-internal.h" | |
18 | ||
18bfeba5 DH |
19 | /* |
20 | * Retransmit terminal ACK or ABORT of the previous call. | |
21 | */ | |
30df927b DH |
22 | void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn, |
23 | struct sk_buff *skb, | |
24 | unsigned int channel) | |
18bfeba5 | 25 | { |
3136ef49 | 26 | struct rxrpc_skb_priv *sp = skb ? rxrpc_skb(skb) : NULL; |
18bfeba5 DH |
27 | struct rxrpc_channel *chan; |
28 | struct msghdr msg; | |
5fc62f6a | 29 | struct kvec iov[3]; |
18bfeba5 DH |
30 | struct { |
31 | struct rxrpc_wire_header whdr; | |
32 | union { | |
5fc62f6a DH |
33 | __be32 abort_code; |
34 | struct rxrpc_ackpacket ack; | |
18bfeba5 DH |
35 | }; |
36 | } __attribute__((packed)) pkt; | |
5fc62f6a | 37 | struct rxrpc_ackinfo ack_info; |
18bfeba5 | 38 | size_t len; |
6b47fe1d | 39 | int ret, ioc; |
5fc62f6a | 40 | u32 serial, mtu, call_id, padding; |
18bfeba5 DH |
41 | |
42 | _enter("%d", conn->debug_id); | |
43 | ||
3136ef49 | 44 | chan = &conn->channels[channel]; |
18bfeba5 DH |
45 | |
46 | /* If the last call got moved on whilst we were waiting to run, just | |
47 | * ignore this packet. | |
48 | */ | |
49 | call_id = READ_ONCE(chan->last_call); | |
50 | /* Sync with __rxrpc_disconnect_call() */ | |
51 | smp_rmb(); | |
3136ef49 | 52 | if (skb && call_id != sp->hdr.callNumber) |
18bfeba5 DH |
53 | return; |
54 | ||
2cc80086 DH |
55 | msg.msg_name = &conn->peer->srx.transport; |
56 | msg.msg_namelen = conn->peer->srx.transport_len; | |
18bfeba5 DH |
57 | msg.msg_control = NULL; |
58 | msg.msg_controllen = 0; | |
59 | msg.msg_flags = 0; | |
60 | ||
5fc62f6a DH |
61 | iov[0].iov_base = &pkt; |
62 | iov[0].iov_len = sizeof(pkt.whdr); | |
63 | iov[1].iov_base = &padding; | |
64 | iov[1].iov_len = 3; | |
65 | iov[2].iov_base = &ack_info; | |
66 | iov[2].iov_len = sizeof(ack_info); | |
67 | ||
3136ef49 | 68 | pkt.whdr.epoch = htonl(conn->proto.epoch); |
fb1967a6 | 69 | pkt.whdr.cid = htonl(conn->proto.cid | channel); |
3136ef49 | 70 | pkt.whdr.callNumber = htonl(call_id); |
18bfeba5 DH |
71 | pkt.whdr.seq = 0; |
72 | pkt.whdr.type = chan->last_type; | |
73 | pkt.whdr.flags = conn->out_clientflag; | |
74 | pkt.whdr.userStatus = 0; | |
75 | pkt.whdr.securityIndex = conn->security_ix; | |
76 | pkt.whdr._rsvd = 0; | |
68d6d1ae | 77 | pkt.whdr.serviceId = htons(conn->service_id); |
18bfeba5 DH |
78 | |
79 | len = sizeof(pkt.whdr); | |
80 | switch (chan->last_type) { | |
81 | case RXRPC_PACKET_TYPE_ABORT: | |
5fc62f6a DH |
82 | pkt.abort_code = htonl(chan->last_abort); |
83 | iov[0].iov_len += sizeof(pkt.abort_code); | |
84 | len += sizeof(pkt.abort_code); | |
85 | ioc = 1; | |
18bfeba5 DH |
86 | break; |
87 | ||
88 | case RXRPC_PACKET_TYPE_ACK: | |
2cc80086 DH |
89 | mtu = conn->peer->if_mtu; |
90 | mtu -= conn->peer->hdrsize; | |
18bfeba5 | 91 | pkt.ack.bufferSpace = 0; |
3136ef49 DH |
92 | pkt.ack.maxSkew = htons(skb ? skb->priority : 0); |
93 | pkt.ack.firstPacket = htonl(chan->last_seq + 1); | |
94 | pkt.ack.previousPacket = htonl(chan->last_seq); | |
95 | pkt.ack.serial = htonl(skb ? sp->hdr.serial : 0); | |
96 | pkt.ack.reason = skb ? RXRPC_ACK_DUPLICATE : RXRPC_ACK_IDLE; | |
18bfeba5 | 97 | pkt.ack.nAcks = 0; |
5fc62f6a DH |
98 | ack_info.rxMTU = htonl(rxrpc_rx_mtu); |
99 | ack_info.maxMTU = htonl(mtu); | |
100 | ack_info.rwind = htonl(rxrpc_rx_window_size); | |
101 | ack_info.jumbo_max = htonl(rxrpc_rx_jumbo_max); | |
57494343 | 102 | pkt.whdr.flags |= RXRPC_SLOW_START_OK; |
5fc62f6a DH |
103 | padding = 0; |
104 | iov[0].iov_len += sizeof(pkt.ack); | |
105 | len += sizeof(pkt.ack) + 3 + sizeof(ack_info); | |
106 | ioc = 3; | |
18bfeba5 | 107 | break; |
5fc62f6a DH |
108 | |
109 | default: | |
110 | return; | |
18bfeba5 DH |
111 | } |
112 | ||
113 | /* Resync with __rxrpc_disconnect_call() and check that the last call | |
114 | * didn't get advanced whilst we were filling out the packets. | |
115 | */ | |
116 | smp_rmb(); | |
117 | if (READ_ONCE(chan->last_call) != call_id) | |
118 | return; | |
119 | ||
18bfeba5 DH |
120 | serial = atomic_inc_return(&conn->serial); |
121 | pkt.whdr.serial = htonl(serial); | |
122 | ||
123 | switch (chan->last_type) { | |
124 | case RXRPC_PACKET_TYPE_ABORT: | |
18bfeba5 DH |
125 | break; |
126 | case RXRPC_PACKET_TYPE_ACK: | |
4764c0da | 127 | trace_rxrpc_tx_ack(chan->call_debug_id, serial, |
f3f8337c DH |
128 | ntohl(pkt.ack.firstPacket), |
129 | ntohl(pkt.ack.serial), | |
130 | pkt.ack.reason, 0); | |
18bfeba5 DH |
131 | break; |
132 | } | |
133 | ||
2cc80086 DH |
134 | ret = kernel_sendmsg(conn->local->socket, &msg, iov, ioc, len); |
135 | conn->peer->last_tx_at = ktime_get_seconds(); | |
6b47fe1d | 136 | if (ret < 0) |
4764c0da DH |
137 | trace_rxrpc_tx_fail(chan->call_debug_id, serial, ret, |
138 | rxrpc_tx_point_call_final_resend); | |
139 | else | |
140 | trace_rxrpc_tx_packet(chan->call_debug_id, &pkt.whdr, | |
141 | rxrpc_tx_point_call_final_resend); | |
6b47fe1d | 142 | |
18bfeba5 | 143 | _leave(""); |
18bfeba5 DH |
144 | } |
145 | ||
17926a79 DH |
146 | /* |
147 | * pass a connection-level abort onto all calls on that connection | |
148 | */ | |
f5c17aae | 149 | static void rxrpc_abort_calls(struct rxrpc_connection *conn, |
39ce6755 DH |
150 | enum rxrpc_call_completion compl, |
151 | rxrpc_serial_t serial) | |
17926a79 DH |
152 | { |
153 | struct rxrpc_call *call; | |
248f219c | 154 | int i; |
17926a79 | 155 | |
64753092 | 156 | _enter("{%d},%x", conn->debug_id, conn->abort_code); |
17926a79 | 157 | |
245500d8 | 158 | spin_lock(&conn->bundle->channel_lock); |
17926a79 | 159 | |
a1399f8b DH |
160 | for (i = 0; i < RXRPC_MAXCALLS; i++) { |
161 | call = rcu_dereference_protected( | |
162 | conn->channels[i].call, | |
245500d8 | 163 | lockdep_is_held(&conn->bundle->channel_lock)); |
ccbd3dbe | 164 | if (call) { |
5a42976d | 165 | if (compl == RXRPC_CALL_LOCALLY_ABORTED) |
a25e21f0 DH |
166 | trace_rxrpc_abort(call->debug_id, |
167 | "CON", call->cid, | |
5a42976d | 168 | call->call_id, 0, |
64753092 DH |
169 | conn->abort_code, |
170 | conn->error); | |
39ce6755 DH |
171 | else |
172 | trace_rxrpc_rx_abort(call, serial, | |
173 | conn->abort_code); | |
5ac0d622 DH |
174 | rxrpc_set_call_completion(call, compl, |
175 | conn->abort_code, | |
176 | conn->error); | |
17926a79 | 177 | } |
17926a79 DH |
178 | } |
179 | ||
245500d8 | 180 | spin_unlock(&conn->bundle->channel_lock); |
17926a79 DH |
181 | _leave(""); |
182 | } | |
183 | ||
184 | /* | |
185 | * generate a connection-level abort | |
186 | */ | |
187 | static int rxrpc_abort_connection(struct rxrpc_connection *conn, | |
3a92789a | 188 | int error, u32 abort_code) |
17926a79 | 189 | { |
0d12f8a4 | 190 | struct rxrpc_wire_header whdr; |
17926a79 DH |
191 | struct msghdr msg; |
192 | struct kvec iov[2]; | |
193 | __be32 word; | |
194 | size_t len; | |
0d12f8a4 | 195 | u32 serial; |
17926a79 DH |
196 | int ret; |
197 | ||
198 | _enter("%d,,%u,%u", conn->debug_id, error, abort_code); | |
199 | ||
200 | /* generate a connection-level abort */ | |
3dd9c8b5 | 201 | spin_lock(&conn->state_lock); |
f5c17aae | 202 | if (conn->state >= RXRPC_CONN_REMOTELY_ABORTED) { |
3dd9c8b5 | 203 | spin_unlock(&conn->state_lock); |
17926a79 DH |
204 | _leave(" = 0 [already dead]"); |
205 | return 0; | |
206 | } | |
207 | ||
64753092 DH |
208 | conn->error = error; |
209 | conn->abort_code = abort_code; | |
f5c17aae | 210 | conn->state = RXRPC_CONN_LOCALLY_ABORTED; |
245500d8 | 211 | set_bit(RXRPC_CONN_DONT_REUSE, &conn->flags); |
3dd9c8b5 | 212 | spin_unlock(&conn->state_lock); |
f5c17aae | 213 | |
2cc80086 DH |
214 | msg.msg_name = &conn->peer->srx.transport; |
215 | msg.msg_namelen = conn->peer->srx.transport_len; | |
17926a79 DH |
216 | msg.msg_control = NULL; |
217 | msg.msg_controllen = 0; | |
218 | msg.msg_flags = 0; | |
219 | ||
19ffa01c DH |
220 | whdr.epoch = htonl(conn->proto.epoch); |
221 | whdr.cid = htonl(conn->proto.cid); | |
0d12f8a4 DH |
222 | whdr.callNumber = 0; |
223 | whdr.seq = 0; | |
224 | whdr.type = RXRPC_PACKET_TYPE_ABORT; | |
225 | whdr.flags = conn->out_clientflag; | |
226 | whdr.userStatus = 0; | |
227 | whdr.securityIndex = conn->security_ix; | |
228 | whdr._rsvd = 0; | |
68d6d1ae | 229 | whdr.serviceId = htons(conn->service_id); |
17926a79 | 230 | |
64753092 | 231 | word = htonl(conn->abort_code); |
17926a79 | 232 | |
0d12f8a4 DH |
233 | iov[0].iov_base = &whdr; |
234 | iov[0].iov_len = sizeof(whdr); | |
17926a79 DH |
235 | iov[1].iov_base = &word; |
236 | iov[1].iov_len = sizeof(word); | |
237 | ||
238 | len = iov[0].iov_len + iov[1].iov_len; | |
239 | ||
0d12f8a4 | 240 | serial = atomic_inc_return(&conn->serial); |
39ce6755 | 241 | rxrpc_abort_calls(conn, RXRPC_CALL_LOCALLY_ABORTED, serial); |
0d12f8a4 | 242 | whdr.serial = htonl(serial); |
17926a79 | 243 | |
2cc80086 | 244 | ret = kernel_sendmsg(conn->local->socket, &msg, iov, 2, len); |
17926a79 | 245 | if (ret < 0) { |
6b47fe1d | 246 | trace_rxrpc_tx_fail(conn->debug_id, serial, ret, |
4764c0da | 247 | rxrpc_tx_point_conn_abort); |
17926a79 DH |
248 | _debug("sendmsg failed: %d", ret); |
249 | return -EAGAIN; | |
250 | } | |
251 | ||
4764c0da DH |
252 | trace_rxrpc_tx_packet(conn->debug_id, &whdr, rxrpc_tx_point_conn_abort); |
253 | ||
2cc80086 | 254 | conn->peer->last_tx_at = ktime_get_seconds(); |
ace45bec | 255 | |
17926a79 DH |
256 | _leave(" = 0"); |
257 | return 0; | |
258 | } | |
259 | ||
260 | /* | |
261 | * mark a call as being on a now-secured channel | |
248f219c | 262 | * - must be called with BH's disabled. |
17926a79 | 263 | */ |
5eaa65b2 | 264 | static void rxrpc_call_is_secure(struct rxrpc_call *call) |
17926a79 DH |
265 | { |
266 | _enter("%p", call); | |
267 | if (call) { | |
3dd9c8b5 | 268 | write_lock(&call->state_lock); |
248f219c | 269 | if (call->state == RXRPC_CALL_SERVER_SECURING) { |
2d914c1b | 270 | call->state = RXRPC_CALL_SERVER_RECV_REQUEST; |
248f219c DH |
271 | rxrpc_notify_socket(call); |
272 | } | |
3dd9c8b5 | 273 | write_unlock(&call->state_lock); |
17926a79 DH |
274 | } |
275 | } | |
276 | ||
277 | /* | |
278 | * connection-level Rx packet processor | |
279 | */ | |
280 | static int rxrpc_process_event(struct rxrpc_connection *conn, | |
281 | struct sk_buff *skb, | |
282 | u32 *_abort_code) | |
283 | { | |
284 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | |
17926a79 DH |
285 | int loop, ret; |
286 | ||
519d2567 | 287 | if (conn->state >= RXRPC_CONN_REMOTELY_ABORTED) { |
248f219c | 288 | _leave(" = -ECONNABORTED [%u]", conn->state); |
17926a79 | 289 | return -ECONNABORTED; |
519d2567 | 290 | } |
17926a79 | 291 | |
0d12f8a4 | 292 | _enter("{%d},{%u,%%%u},", conn->debug_id, sp->hdr.type, sp->hdr.serial); |
519d2567 | 293 | |
17926a79 | 294 | switch (sp->hdr.type) { |
17926a79 | 295 | case RXRPC_PACKET_TYPE_CHALLENGE: |
e0e4d82f DH |
296 | return conn->security->respond_to_challenge(conn, skb, |
297 | _abort_code); | |
17926a79 DH |
298 | |
299 | case RXRPC_PACKET_TYPE_RESPONSE: | |
17926a79 DH |
300 | ret = conn->security->verify_response(conn, skb, _abort_code); |
301 | if (ret < 0) | |
302 | return ret; | |
303 | ||
41057ebd | 304 | ret = conn->security->init_connection_security( |
2cc80086 | 305 | conn, conn->key->payload.data[0]); |
17926a79 DH |
306 | if (ret < 0) |
307 | return ret; | |
308 | ||
245500d8 | 309 | spin_lock(&conn->bundle->channel_lock); |
3dd9c8b5 | 310 | spin_lock(&conn->state_lock); |
17926a79 | 311 | |
bba304db DH |
312 | if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING) { |
313 | conn->state = RXRPC_CONN_SERVICE; | |
3dd9c8b5 | 314 | spin_unlock(&conn->state_lock); |
17926a79 | 315 | for (loop = 0; loop < RXRPC_MAXCALLS; loop++) |
dee46364 DH |
316 | rxrpc_call_is_secure( |
317 | rcu_dereference_protected( | |
a1399f8b | 318 | conn->channels[loop].call, |
245500d8 | 319 | lockdep_is_held(&conn->bundle->channel_lock))); |
248f219c | 320 | } else { |
3dd9c8b5 | 321 | spin_unlock(&conn->state_lock); |
17926a79 DH |
322 | } |
323 | ||
245500d8 | 324 | spin_unlock(&conn->bundle->channel_lock); |
17926a79 DH |
325 | return 0; |
326 | ||
327 | default: | |
fb46f6ee DH |
328 | trace_rxrpc_rx_eproto(NULL, sp->hdr.serial, |
329 | tracepoint_string("bad_conn_pkt")); | |
17926a79 DH |
330 | return -EPROTO; |
331 | } | |
332 | } | |
333 | ||
334 | /* | |
335 | * set up security and issue a challenge | |
336 | */ | |
337 | static void rxrpc_secure_connection(struct rxrpc_connection *conn) | |
338 | { | |
339 | u32 abort_code; | |
340 | int ret; | |
341 | ||
342 | _enter("{%d}", conn->debug_id); | |
343 | ||
344 | ASSERT(conn->security_ix != 0); | |
17926a79 | 345 | |
17926a79 DH |
346 | if (conn->security->issue_challenge(conn) < 0) { |
347 | abort_code = RX_CALL_DEAD; | |
348 | ret = -ENOMEM; | |
349 | goto abort; | |
350 | } | |
351 | ||
352 | _leave(""); | |
353 | return; | |
354 | ||
355 | abort: | |
356 | _debug("abort %d, %d", ret, abort_code); | |
3a92789a | 357 | rxrpc_abort_connection(conn, ret, abort_code); |
17926a79 DH |
358 | _leave(" [aborted]"); |
359 | } | |
360 | ||
3136ef49 DH |
361 | /* |
362 | * Process delayed final ACKs that we haven't subsumed into a subsequent call. | |
363 | */ | |
ddc7834a | 364 | void rxrpc_process_delayed_final_acks(struct rxrpc_connection *conn, bool force) |
3136ef49 DH |
365 | { |
366 | unsigned long j = jiffies, next_j; | |
367 | unsigned int channel; | |
368 | bool set; | |
369 | ||
370 | again: | |
371 | next_j = j + LONG_MAX; | |
372 | set = false; | |
373 | for (channel = 0; channel < RXRPC_MAXCALLS; channel++) { | |
374 | struct rxrpc_channel *chan = &conn->channels[channel]; | |
375 | unsigned long ack_at; | |
376 | ||
377 | if (!test_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags)) | |
378 | continue; | |
379 | ||
380 | smp_rmb(); /* vs rxrpc_disconnect_client_call */ | |
381 | ack_at = READ_ONCE(chan->final_ack_at); | |
382 | ||
ddc7834a | 383 | if (time_before(j, ack_at) && !force) { |
3136ef49 DH |
384 | if (time_before(ack_at, next_j)) { |
385 | next_j = ack_at; | |
386 | set = true; | |
387 | } | |
388 | continue; | |
389 | } | |
390 | ||
391 | if (test_and_clear_bit(RXRPC_CONN_FINAL_ACK_0 + channel, | |
392 | &conn->flags)) | |
393 | rxrpc_conn_retransmit_call(conn, NULL, channel); | |
394 | } | |
395 | ||
396 | j = jiffies; | |
397 | if (time_before_eq(next_j, j)) | |
398 | goto again; | |
399 | if (set) | |
400 | rxrpc_reduce_conn_timer(conn, next_j); | |
401 | } | |
402 | ||
17926a79 DH |
403 | /* |
404 | * connection-level event processor | |
405 | */ | |
04d36d74 | 406 | static void rxrpc_do_process_connection(struct rxrpc_connection *conn) |
17926a79 | 407 | { |
17926a79 DH |
408 | struct sk_buff *skb; |
409 | u32 abort_code = RX_PROTOCOL_ERROR; | |
410 | int ret; | |
411 | ||
2c4579e4 | 412 | if (test_and_clear_bit(RXRPC_CONN_EV_CHALLENGE, &conn->events)) |
17926a79 | 413 | rxrpc_secure_connection(conn); |
17926a79 DH |
414 | |
415 | /* go through the conn-level event packets, releasing the ref on this | |
416 | * connection that each one has when we've finished with it */ | |
417 | while ((skb = skb_dequeue(&conn->rx_queue))) { | |
9a36a6bc | 418 | rxrpc_see_skb(skb, rxrpc_skb_see_conn_work); |
17926a79 DH |
419 | ret = rxrpc_process_event(conn, skb, &abort_code); |
420 | switch (ret) { | |
421 | case -EPROTO: | |
422 | case -EKEYEXPIRED: | |
423 | case -EKEYREJECTED: | |
424 | goto protocol_error; | |
8c2f826d | 425 | case -ENOMEM: |
17926a79 DH |
426 | case -EAGAIN: |
427 | goto requeue_and_leave; | |
428 | case -ECONNABORTED: | |
429 | default: | |
9a36a6bc | 430 | rxrpc_free_skb(skb, rxrpc_skb_put_conn_work); |
17926a79 DH |
431 | break; |
432 | } | |
433 | } | |
434 | ||
17926a79 DH |
435 | return; |
436 | ||
437 | requeue_and_leave: | |
438 | skb_queue_head(&conn->rx_queue, skb); | |
04d36d74 | 439 | return; |
17926a79 DH |
440 | |
441 | protocol_error: | |
3a92789a | 442 | if (rxrpc_abort_connection(conn, ret, abort_code) < 0) |
17926a79 | 443 | goto requeue_and_leave; |
9a36a6bc | 444 | rxrpc_free_skb(skb, rxrpc_skb_put_conn_work); |
04d36d74 DH |
445 | return; |
446 | } | |
447 | ||
448 | void rxrpc_process_connection(struct work_struct *work) | |
449 | { | |
450 | struct rxrpc_connection *conn = | |
451 | container_of(work, struct rxrpc_connection, processor); | |
452 | ||
7fa25105 | 453 | rxrpc_see_connection(conn, rxrpc_conn_see_work); |
04d36d74 | 454 | |
0fde882f | 455 | if (__rxrpc_use_local(conn->local, rxrpc_local_use_conn_work)) { |
04d36d74 | 456 | rxrpc_do_process_connection(conn); |
0fde882f | 457 | rxrpc_unuse_local(conn->local, rxrpc_local_unuse_conn_work); |
04d36d74 | 458 | } |
17926a79 | 459 | } |
5e6ef4f1 DH |
460 | |
461 | /* | |
462 | * post connection-level events to the connection | |
463 | * - this includes challenges, responses, some aborts and call terminal packet | |
464 | * retransmission. | |
465 | */ | |
466 | static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn, | |
467 | struct sk_buff *skb) | |
468 | { | |
469 | _enter("%p,%p", conn, skb); | |
470 | ||
471 | rxrpc_get_skb(skb, rxrpc_skb_get_conn_work); | |
472 | skb_queue_tail(&conn->rx_queue, skb); | |
473 | rxrpc_queue_conn(conn, rxrpc_conn_queue_rx_work); | |
474 | } | |
475 | ||
476 | /* | |
477 | * Input a connection-level packet. | |
478 | */ | |
479 | int rxrpc_input_conn_packet(struct rxrpc_connection *conn, struct sk_buff *skb) | |
480 | { | |
481 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | |
482 | ||
483 | if (conn->state >= RXRPC_CONN_REMOTELY_ABORTED) { | |
484 | _leave(" = -ECONNABORTED [%u]", conn->state); | |
30df927b | 485 | return 0; |
5e6ef4f1 DH |
486 | } |
487 | ||
488 | _enter("{%d},{%u,%%%u},", conn->debug_id, sp->hdr.type, sp->hdr.serial); | |
489 | ||
490 | switch (sp->hdr.type) { | |
5e6ef4f1 DH |
491 | case RXRPC_PACKET_TYPE_BUSY: |
492 | /* Just ignore BUSY packets for now. */ | |
493 | return 0; | |
494 | ||
495 | case RXRPC_PACKET_TYPE_ABORT: | |
496 | conn->error = -ECONNABORTED; | |
497 | conn->abort_code = skb->priority; | |
498 | conn->state = RXRPC_CONN_REMOTELY_ABORTED; | |
499 | set_bit(RXRPC_CONN_DONT_REUSE, &conn->flags); | |
500 | rxrpc_abort_calls(conn, RXRPC_CALL_REMOTELY_ABORTED, sp->hdr.serial); | |
30df927b | 501 | return 0; |
5e6ef4f1 DH |
502 | |
503 | case RXRPC_PACKET_TYPE_CHALLENGE: | |
504 | case RXRPC_PACKET_TYPE_RESPONSE: | |
505 | rxrpc_post_packet_to_conn(conn, skb); | |
506 | return 0; | |
507 | ||
508 | default: | |
509 | trace_rxrpc_rx_eproto(NULL, sp->hdr.serial, | |
510 | tracepoint_string("bad_conn_pkt")); | |
511 | return -EPROTO; | |
512 | } | |
513 | } | |
f2cce89a DH |
514 | |
515 | /* | |
516 | * Input a connection event. | |
517 | */ | |
518 | void rxrpc_input_conn_event(struct rxrpc_connection *conn, struct sk_buff *skb) | |
519 | { | |
520 | /* Process delayed ACKs whose time has come. */ | |
521 | if (conn->flags & RXRPC_CONN_FINAL_ACK_MASK) | |
522 | rxrpc_process_delayed_final_acks(conn, false); | |
523 | } |