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 */ 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 */ 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 */ 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 */ 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; 915fc62f6aSDavid Howells struct rxrpc_ackinfo ack_info; 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 98*2868b8e4SDavid Howells if (sp && sp->hdr.type == RXRPC_PACKET_TYPE_ACK) { 99*2868b8e4SDavid Howells if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), 100*2868b8e4SDavid Howells &pkt.ack, sizeof(pkt.ack)) < 0) 101*2868b8e4SDavid Howells return; 102*2868b8e4SDavid Howells if (pkt.ack.reason == RXRPC_ACK_PING_RESPONSE) 103*2868b8e4SDavid Howells return; 104*2868b8e4SDavid Howells } 105*2868b8e4SDavid 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; 1255fc62f6aSDavid Howells iov[2].iov_base = &ack_info; 1265fc62f6aSDavid Howells iov[2].iov_len = sizeof(ack_info); 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; 1615fc62f6aSDavid Howells ack_info.rxMTU = htonl(rxrpc_rx_mtu); 1625fc62f6aSDavid Howells ack_info.maxMTU = htonl(mtu); 1635fc62f6aSDavid Howells ack_info.rwind = htonl(rxrpc_rx_window_size); 1645fc62f6aSDavid Howells ack_info.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); 1685fc62f6aSDavid Howells len += sizeof(pkt.ack) + 3 + sizeof(ack_info); 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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