12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
28c3e34a4SDavid Howells /* connection-level event handling
38c3e34a4SDavid Howells *
48c3e34a4SDavid Howells * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
58c3e34a4SDavid Howells * Written by David Howells (dhowells@redhat.com)
68c3e34a4SDavid Howells */
78c3e34a4SDavid Howells
88c3e34a4SDavid Howells #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
98c3e34a4SDavid Howells
108c3e34a4SDavid Howells #include <linux/module.h>
118c3e34a4SDavid Howells #include <linux/net.h>
128c3e34a4SDavid Howells #include <linux/skbuff.h>
138c3e34a4SDavid Howells #include <linux/errqueue.h>
148c3e34a4SDavid Howells #include <net/sock.h>
158c3e34a4SDavid Howells #include <net/af_rxrpc.h>
168c3e34a4SDavid Howells #include <net/ip.h>
178c3e34a4SDavid Howells #include "ar-internal.h"
188c3e34a4SDavid Howells
198c3e34a4SDavid Howells /*
20a00ce28bSDavid Howells * Set the completion state on an aborted connection.
21a00ce28bSDavid Howells */
rxrpc_set_conn_aborted(struct rxrpc_connection * conn,struct sk_buff * skb,s32 abort_code,int err,enum rxrpc_call_completion compl)22a00ce28bSDavid Howells static bool rxrpc_set_conn_aborted(struct rxrpc_connection *conn, struct sk_buff *skb,
23a00ce28bSDavid Howells s32 abort_code, int err,
24a00ce28bSDavid Howells enum rxrpc_call_completion compl)
25a00ce28bSDavid Howells {
26a00ce28bSDavid Howells bool aborted = false;
27a00ce28bSDavid Howells
28a00ce28bSDavid Howells if (conn->state != RXRPC_CONN_ABORTED) {
29a00ce28bSDavid Howells spin_lock(&conn->state_lock);
30a00ce28bSDavid Howells if (conn->state != RXRPC_CONN_ABORTED) {
31a00ce28bSDavid Howells conn->abort_code = abort_code;
32a00ce28bSDavid Howells conn->error = err;
33a00ce28bSDavid Howells conn->completion = compl;
34a00ce28bSDavid Howells /* Order the abort info before the state change. */
35a00ce28bSDavid Howells smp_store_release(&conn->state, RXRPC_CONN_ABORTED);
36a00ce28bSDavid Howells set_bit(RXRPC_CONN_DONT_REUSE, &conn->flags);
37a00ce28bSDavid Howells set_bit(RXRPC_CONN_EV_ABORT_CALLS, &conn->events);
38a00ce28bSDavid Howells aborted = true;
39a00ce28bSDavid Howells }
40a00ce28bSDavid Howells spin_unlock(&conn->state_lock);
41a00ce28bSDavid Howells }
42a00ce28bSDavid Howells
43a00ce28bSDavid Howells return aborted;
44a00ce28bSDavid Howells }
45a00ce28bSDavid Howells
46a00ce28bSDavid Howells /*
47a00ce28bSDavid Howells * Mark a socket buffer to indicate that the connection it's on should be aborted.
48a00ce28bSDavid Howells */
rxrpc_abort_conn(struct rxrpc_connection * conn,struct sk_buff * skb,s32 abort_code,int err,enum rxrpc_abort_reason why)49a00ce28bSDavid Howells int rxrpc_abort_conn(struct rxrpc_connection *conn, struct sk_buff *skb,
5057af281eSDavid Howells s32 abort_code, int err, enum rxrpc_abort_reason why)
51a00ce28bSDavid Howells {
52a00ce28bSDavid Howells struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
53a00ce28bSDavid Howells
54a00ce28bSDavid Howells if (rxrpc_set_conn_aborted(conn, skb, abort_code, err,
55a00ce28bSDavid Howells RXRPC_CALL_LOCALLY_ABORTED)) {
56a00ce28bSDavid Howells trace_rxrpc_abort(0, why, sp->hdr.cid, sp->hdr.callNumber,
57a00ce28bSDavid Howells sp->hdr.seq, abort_code, err);
58a00ce28bSDavid Howells rxrpc_poke_conn(conn, rxrpc_conn_get_poke_abort);
59a00ce28bSDavid Howells }
60a00ce28bSDavid Howells return -EPROTO;
61a00ce28bSDavid Howells }
62a00ce28bSDavid Howells
63a00ce28bSDavid Howells /*
64a00ce28bSDavid Howells * Mark a connection as being remotely aborted.
65a00ce28bSDavid Howells */
rxrpc_input_conn_abort(struct rxrpc_connection * conn,struct sk_buff * skb)66a00ce28bSDavid Howells static bool rxrpc_input_conn_abort(struct rxrpc_connection *conn,
67a00ce28bSDavid Howells struct sk_buff *skb)
68a00ce28bSDavid Howells {
69a00ce28bSDavid Howells return rxrpc_set_conn_aborted(conn, skb, skb->priority, -ECONNABORTED,
70a00ce28bSDavid Howells RXRPC_CALL_REMOTELY_ABORTED);
71a00ce28bSDavid Howells }
72a00ce28bSDavid Howells
73a00ce28bSDavid Howells /*
7418bfeba5SDavid Howells * Retransmit terminal ACK or ABORT of the previous call.
7518bfeba5SDavid Howells */
rxrpc_conn_retransmit_call(struct rxrpc_connection * conn,struct sk_buff * skb,unsigned int channel)7630df927bSDavid Howells void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
773136ef49SDavid Howells struct sk_buff *skb,
783136ef49SDavid Howells unsigned int channel)
7918bfeba5SDavid Howells {
803136ef49SDavid Howells struct rxrpc_skb_priv *sp = skb ? rxrpc_skb(skb) : NULL;
8118bfeba5SDavid Howells struct rxrpc_channel *chan;
8218bfeba5SDavid Howells struct msghdr msg;
835fc62f6aSDavid Howells struct kvec iov[3];
8418bfeba5SDavid Howells struct {
8518bfeba5SDavid Howells struct rxrpc_wire_header whdr;
8618bfeba5SDavid Howells union {
875fc62f6aSDavid Howells __be32 abort_code;
8818bfeba5SDavid Howells struct rxrpc_ackpacket ack;
8918bfeba5SDavid Howells };
9018bfeba5SDavid Howells } __attribute__((packed)) pkt;
9159881e57SDavid Howells struct rxrpc_acktrailer trailer;
9218bfeba5SDavid Howells size_t len;
936b47fe1dSDavid Howells int ret, ioc;
945fc62f6aSDavid Howells u32 serial, mtu, call_id, padding;
9518bfeba5SDavid Howells
9618bfeba5SDavid Howells _enter("%d", conn->debug_id);
9718bfeba5SDavid Howells
982868b8e4SDavid Howells if (sp && sp->hdr.type == RXRPC_PACKET_TYPE_ACK) {
992868b8e4SDavid Howells if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
1002868b8e4SDavid Howells &pkt.ack, sizeof(pkt.ack)) < 0)
1012868b8e4SDavid Howells return;
1022868b8e4SDavid Howells if (pkt.ack.reason == RXRPC_ACK_PING_RESPONSE)
1032868b8e4SDavid Howells return;
1042868b8e4SDavid Howells }
1052868b8e4SDavid Howells
1063136ef49SDavid Howells chan = &conn->channels[channel];
10718bfeba5SDavid Howells
10818bfeba5SDavid Howells /* If the last call got moved on whilst we were waiting to run, just
10918bfeba5SDavid Howells * ignore this packet.
11018bfeba5SDavid Howells */
1119d35d880SDavid Howells call_id = chan->last_call;
1123136ef49SDavid Howells if (skb && call_id != sp->hdr.callNumber)
11318bfeba5SDavid Howells return;
11418bfeba5SDavid Howells
1152cc80086SDavid Howells msg.msg_name = &conn->peer->srx.transport;
1162cc80086SDavid Howells msg.msg_namelen = conn->peer->srx.transport_len;
11718bfeba5SDavid Howells msg.msg_control = NULL;
11818bfeba5SDavid Howells msg.msg_controllen = 0;
11918bfeba5SDavid Howells msg.msg_flags = 0;
12018bfeba5SDavid Howells
1215fc62f6aSDavid Howells iov[0].iov_base = &pkt;
1225fc62f6aSDavid Howells iov[0].iov_len = sizeof(pkt.whdr);
1235fc62f6aSDavid Howells iov[1].iov_base = &padding;
1245fc62f6aSDavid Howells iov[1].iov_len = 3;
12559881e57SDavid Howells iov[2].iov_base = &trailer;
12659881e57SDavid Howells iov[2].iov_len = sizeof(trailer);
1275fc62f6aSDavid Howells
1282c9dc472SDavid Howells serial = rxrpc_get_next_serial(conn);
1299d35d880SDavid Howells
1303136ef49SDavid Howells pkt.whdr.epoch = htonl(conn->proto.epoch);
131fb1967a6SDavid Howells pkt.whdr.cid = htonl(conn->proto.cid | channel);
1323136ef49SDavid Howells pkt.whdr.callNumber = htonl(call_id);
1339d35d880SDavid Howells pkt.whdr.serial = htonl(serial);
13418bfeba5SDavid Howells pkt.whdr.seq = 0;
13518bfeba5SDavid Howells pkt.whdr.type = chan->last_type;
13618bfeba5SDavid Howells pkt.whdr.flags = conn->out_clientflag;
13718bfeba5SDavid Howells pkt.whdr.userStatus = 0;
13818bfeba5SDavid Howells pkt.whdr.securityIndex = conn->security_ix;
13918bfeba5SDavid Howells pkt.whdr._rsvd = 0;
14068d6d1aeSDavid Howells pkt.whdr.serviceId = htons(conn->service_id);
14118bfeba5SDavid Howells
14218bfeba5SDavid Howells len = sizeof(pkt.whdr);
14318bfeba5SDavid Howells switch (chan->last_type) {
14418bfeba5SDavid Howells case RXRPC_PACKET_TYPE_ABORT:
1455fc62f6aSDavid Howells pkt.abort_code = htonl(chan->last_abort);
1465fc62f6aSDavid Howells iov[0].iov_len += sizeof(pkt.abort_code);
1475fc62f6aSDavid Howells len += sizeof(pkt.abort_code);
1485fc62f6aSDavid Howells ioc = 1;
14918bfeba5SDavid Howells break;
15018bfeba5SDavid Howells
15118bfeba5SDavid Howells case RXRPC_PACKET_TYPE_ACK:
1522cc80086SDavid Howells mtu = conn->peer->if_mtu;
1532cc80086SDavid Howells mtu -= conn->peer->hdrsize;
15418bfeba5SDavid Howells pkt.ack.bufferSpace = 0;
1553136ef49SDavid Howells pkt.ack.maxSkew = htons(skb ? skb->priority : 0);
1563136ef49SDavid Howells pkt.ack.firstPacket = htonl(chan->last_seq + 1);
1573136ef49SDavid Howells pkt.ack.previousPacket = htonl(chan->last_seq);
1583136ef49SDavid Howells pkt.ack.serial = htonl(skb ? sp->hdr.serial : 0);
1593136ef49SDavid Howells pkt.ack.reason = skb ? RXRPC_ACK_DUPLICATE : RXRPC_ACK_IDLE;
16018bfeba5SDavid Howells pkt.ack.nAcks = 0;
16159881e57SDavid Howells trailer.maxMTU = htonl(rxrpc_rx_mtu);
16259881e57SDavid Howells trailer.ifMTU = htonl(mtu);
16359881e57SDavid Howells trailer.rwind = htonl(rxrpc_rx_window_size);
16459881e57SDavid Howells trailer.jumbo_max = htonl(rxrpc_rx_jumbo_max);
16557494343SDavid Howells pkt.whdr.flags |= RXRPC_SLOW_START_OK;
1665fc62f6aSDavid Howells padding = 0;
1675fc62f6aSDavid Howells iov[0].iov_len += sizeof(pkt.ack);
16859881e57SDavid Howells len += sizeof(pkt.ack) + 3 + sizeof(trailer);
1695fc62f6aSDavid Howells ioc = 3;
1705fc62f6aSDavid Howells
1714764c0daSDavid Howells trace_rxrpc_tx_ack(chan->call_debug_id, serial,
172f3f8337cSDavid Howells ntohl(pkt.ack.firstPacket),
173f3f8337cSDavid Howells ntohl(pkt.ack.serial),
174f789bff2SDavid Howells pkt.ack.reason, 0, rxrpc_rx_window_size);
17518bfeba5SDavid Howells break;
1769d35d880SDavid Howells
1779d35d880SDavid Howells default:
1789d35d880SDavid Howells return;
17918bfeba5SDavid Howells }
18018bfeba5SDavid Howells
1812cc80086SDavid Howells ret = kernel_sendmsg(conn->local->socket, &msg, iov, ioc, len);
1822cc80086SDavid Howells conn->peer->last_tx_at = ktime_get_seconds();
1836b47fe1dSDavid Howells if (ret < 0)
1844764c0daSDavid Howells trace_rxrpc_tx_fail(chan->call_debug_id, serial, ret,
1854764c0daSDavid Howells rxrpc_tx_point_call_final_resend);
1864764c0daSDavid Howells else
1874764c0daSDavid Howells trace_rxrpc_tx_packet(chan->call_debug_id, &pkt.whdr,
1884764c0daSDavid Howells rxrpc_tx_point_call_final_resend);
1896b47fe1dSDavid Howells
19018bfeba5SDavid Howells _leave("");
19118bfeba5SDavid Howells }
19218bfeba5SDavid Howells
19318bfeba5SDavid Howells /*
1948c3e34a4SDavid Howells * pass a connection-level abort onto all calls on that connection
1958c3e34a4SDavid Howells */
rxrpc_abort_calls(struct rxrpc_connection * conn)196a00ce28bSDavid Howells static void rxrpc_abort_calls(struct rxrpc_connection *conn)
1978c3e34a4SDavid Howells {
1988c3e34a4SDavid Howells struct rxrpc_call *call;
199248f219cSDavid Howells int i;
2008c3e34a4SDavid Howells
20164753092SDavid Howells _enter("{%d},%x", conn->debug_id, conn->abort_code);
2028c3e34a4SDavid Howells
203a1399f8bSDavid Howells for (i = 0; i < RXRPC_MAXCALLS; i++) {
2049d35d880SDavid Howells call = conn->channels[i].call;
205a00ce28bSDavid Howells if (call)
206a00ce28bSDavid Howells rxrpc_set_call_completion(call,
207a00ce28bSDavid Howells conn->completion,
20864753092SDavid Howells conn->abort_code,
20964753092SDavid Howells conn->error);
210ccbd3dbeSDavid Howells }
2118c3e34a4SDavid Howells
2128c3e34a4SDavid Howells _leave("");
2138c3e34a4SDavid Howells }
2148c3e34a4SDavid Howells
2158c3e34a4SDavid Howells /*
2168c3e34a4SDavid Howells * mark a call as being on a now-secured channel
217248f219cSDavid Howells * - must be called with BH's disabled.
2188c3e34a4SDavid Howells */
rxrpc_call_is_secure(struct rxrpc_call * call)2198c3e34a4SDavid Howells static void rxrpc_call_is_secure(struct rxrpc_call *call)
2208c3e34a4SDavid Howells {
22196b4059fSDavid Howells if (call && __rxrpc_call_state(call) == RXRPC_CALL_SERVER_SECURING) {
22296b4059fSDavid Howells rxrpc_set_call_state(call, RXRPC_CALL_SERVER_RECV_REQUEST);
223248f219cSDavid Howells rxrpc_notify_socket(call);
224248f219cSDavid Howells }
2258c3e34a4SDavid Howells }
2268c3e34a4SDavid Howells
2278c3e34a4SDavid Howells /*
2288c3e34a4SDavid Howells * connection-level Rx packet processor
2298c3e34a4SDavid Howells */
rxrpc_process_event(struct rxrpc_connection * conn,struct sk_buff * skb)2308c3e34a4SDavid Howells static int rxrpc_process_event(struct rxrpc_connection *conn,
231a00ce28bSDavid Howells struct sk_buff *skb)
2328c3e34a4SDavid Howells {
2338c3e34a4SDavid Howells struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
2342953d3b8SDavid Howells int ret;
2358c3e34a4SDavid Howells
236a00ce28bSDavid Howells if (conn->state == RXRPC_CONN_ABORTED)
2378c3e34a4SDavid Howells return -ECONNABORTED;
2388c3e34a4SDavid Howells
2398c3e34a4SDavid Howells _enter("{%d},{%u,%%%u},", conn->debug_id, sp->hdr.type, sp->hdr.serial);
2408c3e34a4SDavid Howells
2418c3e34a4SDavid Howells switch (sp->hdr.type) {
2428c3e34a4SDavid Howells case RXRPC_PACKET_TYPE_CHALLENGE:
243a00ce28bSDavid Howells return conn->security->respond_to_challenge(conn, skb);
2448c3e34a4SDavid Howells
2458c3e34a4SDavid Howells case RXRPC_PACKET_TYPE_RESPONSE:
246a00ce28bSDavid Howells ret = conn->security->verify_response(conn, skb);
2478c3e34a4SDavid Howells if (ret < 0)
2488c3e34a4SDavid Howells return ret;
2498c3e34a4SDavid Howells
25041057ebdSDavid Howells ret = conn->security->init_connection_security(
2512cc80086SDavid Howells conn, conn->key->payload.data[0]);
2528c3e34a4SDavid Howells if (ret < 0)
2538c3e34a4SDavid Howells return ret;
2548c3e34a4SDavid Howells
2553dd9c8b5SDavid Howells spin_lock(&conn->state_lock);
2562953d3b8SDavid Howells if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING)
257bba304dbSDavid Howells conn->state = RXRPC_CONN_SERVICE;
2583dd9c8b5SDavid Howells spin_unlock(&conn->state_lock);
2598c3e34a4SDavid Howells
2602953d3b8SDavid Howells if (conn->state == RXRPC_CONN_SERVICE) {
2612953d3b8SDavid Howells /* Offload call state flipping to the I/O thread. As
2622953d3b8SDavid Howells * we've already received the packet, put it on the
2632953d3b8SDavid Howells * front of the queue.
2642953d3b8SDavid Howells */
2652953d3b8SDavid Howells skb->mark = RXRPC_SKB_MARK_SERVICE_CONN_SECURED;
2662953d3b8SDavid Howells rxrpc_get_skb(skb, rxrpc_skb_get_conn_secured);
2672953d3b8SDavid Howells skb_queue_head(&conn->local->rx_queue, skb);
2682953d3b8SDavid Howells rxrpc_wake_up_io_thread(conn->local);
2692953d3b8SDavid Howells }
2708c3e34a4SDavid Howells return 0;
2718c3e34a4SDavid Howells
2728c3e34a4SDavid Howells default:
27357af281eSDavid Howells WARN_ON_ONCE(1);
2748c3e34a4SDavid Howells return -EPROTO;
2758c3e34a4SDavid Howells }
2768c3e34a4SDavid Howells }
2778c3e34a4SDavid Howells
2788c3e34a4SDavid Howells /*
2798c3e34a4SDavid Howells * set up security and issue a challenge
2808c3e34a4SDavid Howells */
rxrpc_secure_connection(struct rxrpc_connection * conn)2818c3e34a4SDavid Howells static void rxrpc_secure_connection(struct rxrpc_connection *conn)
2828c3e34a4SDavid Howells {
283a00ce28bSDavid Howells if (conn->security->issue_challenge(conn) < 0)
28457af281eSDavid Howells rxrpc_abort_conn(conn, NULL, RX_CALL_DEAD, -ENOMEM,
28557af281eSDavid Howells rxrpc_abort_nomem);
2868c3e34a4SDavid Howells }
2878c3e34a4SDavid Howells
2888c3e34a4SDavid Howells /*
2893136ef49SDavid Howells * Process delayed final ACKs that we haven't subsumed into a subsequent call.
2903136ef49SDavid Howells */
rxrpc_process_delayed_final_acks(struct rxrpc_connection * conn,bool force)291ddc7834aSDavid Howells void rxrpc_process_delayed_final_acks(struct rxrpc_connection *conn, bool force)
2923136ef49SDavid Howells {
2933136ef49SDavid Howells unsigned long j = jiffies, next_j;
2943136ef49SDavid Howells unsigned int channel;
2953136ef49SDavid Howells bool set;
2963136ef49SDavid Howells
2973136ef49SDavid Howells again:
2983136ef49SDavid Howells next_j = j + LONG_MAX;
2993136ef49SDavid Howells set = false;
3003136ef49SDavid Howells for (channel = 0; channel < RXRPC_MAXCALLS; channel++) {
3013136ef49SDavid Howells struct rxrpc_channel *chan = &conn->channels[channel];
3023136ef49SDavid Howells unsigned long ack_at;
3033136ef49SDavid Howells
3043136ef49SDavid Howells if (!test_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags))
3053136ef49SDavid Howells continue;
3063136ef49SDavid Howells
3079d35d880SDavid Howells ack_at = chan->final_ack_at;
308ddc7834aSDavid Howells if (time_before(j, ack_at) && !force) {
3093136ef49SDavid Howells if (time_before(ack_at, next_j)) {
3103136ef49SDavid Howells next_j = ack_at;
3113136ef49SDavid Howells set = true;
3123136ef49SDavid Howells }
3133136ef49SDavid Howells continue;
3143136ef49SDavid Howells }
3153136ef49SDavid Howells
3163136ef49SDavid Howells if (test_and_clear_bit(RXRPC_CONN_FINAL_ACK_0 + channel,
3173136ef49SDavid Howells &conn->flags))
3183136ef49SDavid Howells rxrpc_conn_retransmit_call(conn, NULL, channel);
3193136ef49SDavid Howells }
3203136ef49SDavid Howells
3213136ef49SDavid Howells j = jiffies;
3223136ef49SDavid Howells if (time_before_eq(next_j, j))
3233136ef49SDavid Howells goto again;
3243136ef49SDavid Howells if (set)
3253136ef49SDavid Howells rxrpc_reduce_conn_timer(conn, next_j);
3263136ef49SDavid Howells }
3273136ef49SDavid Howells
3283136ef49SDavid Howells /*
3298c3e34a4SDavid Howells * connection-level event processor
3308c3e34a4SDavid Howells */
rxrpc_do_process_connection(struct rxrpc_connection * conn)33104d36d74SDavid Howells static void rxrpc_do_process_connection(struct rxrpc_connection *conn)
3328c3e34a4SDavid Howells {
3338c3e34a4SDavid Howells struct sk_buff *skb;
3348c3e34a4SDavid Howells int ret;
3358c3e34a4SDavid Howells
3362c4579e4SDavid Howells if (test_and_clear_bit(RXRPC_CONN_EV_CHALLENGE, &conn->events))
3378c3e34a4SDavid Howells rxrpc_secure_connection(conn);
3388c3e34a4SDavid Howells
3398c3e34a4SDavid Howells /* go through the conn-level event packets, releasing the ref on this
3408c3e34a4SDavid Howells * connection that each one has when we've finished with it */
3418c3e34a4SDavid Howells while ((skb = skb_dequeue(&conn->rx_queue))) {
3429a36a6bcSDavid Howells rxrpc_see_skb(skb, rxrpc_skb_see_conn_work);
343a00ce28bSDavid Howells ret = rxrpc_process_event(conn, skb);
3448c3e34a4SDavid Howells switch (ret) {
3458c2f826dSDavid Howells case -ENOMEM:
3468c3e34a4SDavid Howells case -EAGAIN:
347a00ce28bSDavid Howells skb_queue_head(&conn->rx_queue, skb);
348a00ce28bSDavid Howells rxrpc_queue_conn(conn, rxrpc_conn_queue_retry_work);
349a00ce28bSDavid Howells break;
3508c3e34a4SDavid Howells default:
3519a36a6bcSDavid Howells rxrpc_free_skb(skb, rxrpc_skb_put_conn_work);
3528c3e34a4SDavid Howells break;
3538c3e34a4SDavid Howells }
3548c3e34a4SDavid Howells }
35504d36d74SDavid Howells }
35604d36d74SDavid Howells
rxrpc_process_connection(struct work_struct * work)35704d36d74SDavid Howells void rxrpc_process_connection(struct work_struct *work)
35804d36d74SDavid Howells {
35904d36d74SDavid Howells struct rxrpc_connection *conn =
36004d36d74SDavid Howells container_of(work, struct rxrpc_connection, processor);
36104d36d74SDavid Howells
3627fa25105SDavid Howells rxrpc_see_connection(conn, rxrpc_conn_see_work);
36304d36d74SDavid Howells
3640fde882fSDavid Howells if (__rxrpc_use_local(conn->local, rxrpc_local_use_conn_work)) {
36504d36d74SDavid Howells rxrpc_do_process_connection(conn);
3660fde882fSDavid Howells rxrpc_unuse_local(conn->local, rxrpc_local_unuse_conn_work);
36704d36d74SDavid Howells }
3688c3e34a4SDavid Howells }
3695e6ef4f1SDavid Howells
3705e6ef4f1SDavid Howells /*
3715e6ef4f1SDavid Howells * post connection-level events to the connection
3725e6ef4f1SDavid Howells * - this includes challenges, responses, some aborts and call terminal packet
3735e6ef4f1SDavid Howells * retransmission.
3745e6ef4f1SDavid Howells */
rxrpc_post_packet_to_conn(struct rxrpc_connection * conn,struct sk_buff * skb)3755e6ef4f1SDavid Howells static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn,
3765e6ef4f1SDavid Howells struct sk_buff *skb)
3775e6ef4f1SDavid Howells {
3785e6ef4f1SDavid Howells _enter("%p,%p", conn, skb);
3795e6ef4f1SDavid Howells
3805e6ef4f1SDavid Howells rxrpc_get_skb(skb, rxrpc_skb_get_conn_work);
3815e6ef4f1SDavid Howells skb_queue_tail(&conn->rx_queue, skb);
3825e6ef4f1SDavid Howells rxrpc_queue_conn(conn, rxrpc_conn_queue_rx_work);
3835e6ef4f1SDavid Howells }
3845e6ef4f1SDavid Howells
3855e6ef4f1SDavid Howells /*
3865e6ef4f1SDavid Howells * Input a connection-level packet.
3875e6ef4f1SDavid Howells */
rxrpc_input_conn_packet(struct rxrpc_connection * conn,struct sk_buff * skb)38857af281eSDavid Howells bool rxrpc_input_conn_packet(struct rxrpc_connection *conn, struct sk_buff *skb)
3895e6ef4f1SDavid Howells {
3905e6ef4f1SDavid Howells struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
3915e6ef4f1SDavid Howells
3925e6ef4f1SDavid Howells switch (sp->hdr.type) {
3935e6ef4f1SDavid Howells case RXRPC_PACKET_TYPE_BUSY:
3945e6ef4f1SDavid Howells /* Just ignore BUSY packets for now. */
39557af281eSDavid Howells return true;
3965e6ef4f1SDavid Howells
3975e6ef4f1SDavid Howells case RXRPC_PACKET_TYPE_ABORT:
398a00ce28bSDavid Howells if (rxrpc_is_conn_aborted(conn))
399a00ce28bSDavid Howells return true;
400a00ce28bSDavid Howells rxrpc_input_conn_abort(conn, skb);
401a00ce28bSDavid Howells rxrpc_abort_calls(conn);
402a00ce28bSDavid Howells return true;
4035e6ef4f1SDavid Howells
4045e6ef4f1SDavid Howells case RXRPC_PACKET_TYPE_CHALLENGE:
4055e6ef4f1SDavid Howells case RXRPC_PACKET_TYPE_RESPONSE:
406a00ce28bSDavid Howells if (rxrpc_is_conn_aborted(conn)) {
407a00ce28bSDavid Howells if (conn->completion == RXRPC_CALL_LOCALLY_ABORTED)
408a00ce28bSDavid Howells rxrpc_send_conn_abort(conn);
409a00ce28bSDavid Howells return true;
410a00ce28bSDavid Howells }
4115e6ef4f1SDavid Howells rxrpc_post_packet_to_conn(conn, skb);
41257af281eSDavid Howells return true;
4135e6ef4f1SDavid Howells
4145e6ef4f1SDavid Howells default:
41557af281eSDavid Howells WARN_ON_ONCE(1);
41657af281eSDavid Howells return true;
4175e6ef4f1SDavid Howells }
4185e6ef4f1SDavid Howells }
419f2cce89aSDavid Howells
420f2cce89aSDavid Howells /*
421f2cce89aSDavid Howells * Input a connection event.
422f2cce89aSDavid Howells */
rxrpc_input_conn_event(struct rxrpc_connection * conn,struct sk_buff * skb)423f2cce89aSDavid Howells void rxrpc_input_conn_event(struct rxrpc_connection *conn, struct sk_buff *skb)
424f2cce89aSDavid Howells {
4252953d3b8SDavid Howells unsigned int loop;
4262953d3b8SDavid Howells
427a00ce28bSDavid Howells if (test_and_clear_bit(RXRPC_CONN_EV_ABORT_CALLS, &conn->events))
428a00ce28bSDavid Howells rxrpc_abort_calls(conn);
429a00ce28bSDavid Howells
4302953d3b8SDavid Howells switch (skb->mark) {
4312953d3b8SDavid Howells case RXRPC_SKB_MARK_SERVICE_CONN_SECURED:
4322953d3b8SDavid Howells if (conn->state != RXRPC_CONN_SERVICE)
4332953d3b8SDavid Howells break;
4342953d3b8SDavid Howells
4352953d3b8SDavid Howells for (loop = 0; loop < RXRPC_MAXCALLS; loop++)
4369d35d880SDavid Howells rxrpc_call_is_secure(conn->channels[loop].call);
4372953d3b8SDavid Howells break;
4382953d3b8SDavid Howells }
4392953d3b8SDavid Howells
440f2cce89aSDavid Howells /* Process delayed ACKs whose time has come. */
441f2cce89aSDavid Howells if (conn->flags & RXRPC_CONN_FINAL_ACK_MASK)
442f2cce89aSDavid Howells rxrpc_process_delayed_final_acks(conn, false);
443f2cce89aSDavid Howells }
444