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 983136ef49SDavid Howells chan = &conn->channels[channel]; 9918bfeba5SDavid Howells 10018bfeba5SDavid Howells /* If the last call got moved on whilst we were waiting to run, just 10118bfeba5SDavid Howells * ignore this packet. 10218bfeba5SDavid Howells */ 10318bfeba5SDavid Howells call_id = READ_ONCE(chan->last_call); 10418bfeba5SDavid Howells /* Sync with __rxrpc_disconnect_call() */ 10518bfeba5SDavid Howells smp_rmb(); 1063136ef49SDavid Howells if (skb && call_id != sp->hdr.callNumber) 10718bfeba5SDavid Howells return; 10818bfeba5SDavid Howells 1092cc80086SDavid Howells msg.msg_name = &conn->peer->srx.transport; 1102cc80086SDavid Howells msg.msg_namelen = conn->peer->srx.transport_len; 11118bfeba5SDavid Howells msg.msg_control = NULL; 11218bfeba5SDavid Howells msg.msg_controllen = 0; 11318bfeba5SDavid Howells msg.msg_flags = 0; 11418bfeba5SDavid Howells 1155fc62f6aSDavid Howells iov[0].iov_base = &pkt; 1165fc62f6aSDavid Howells iov[0].iov_len = sizeof(pkt.whdr); 1175fc62f6aSDavid Howells iov[1].iov_base = &padding; 1185fc62f6aSDavid Howells iov[1].iov_len = 3; 1195fc62f6aSDavid Howells iov[2].iov_base = &ack_info; 1205fc62f6aSDavid Howells iov[2].iov_len = sizeof(ack_info); 1215fc62f6aSDavid Howells 1223136ef49SDavid Howells pkt.whdr.epoch = htonl(conn->proto.epoch); 123fb1967a6SDavid Howells pkt.whdr.cid = htonl(conn->proto.cid | channel); 1243136ef49SDavid Howells pkt.whdr.callNumber = htonl(call_id); 12518bfeba5SDavid Howells pkt.whdr.seq = 0; 12618bfeba5SDavid Howells pkt.whdr.type = chan->last_type; 12718bfeba5SDavid Howells pkt.whdr.flags = conn->out_clientflag; 12818bfeba5SDavid Howells pkt.whdr.userStatus = 0; 12918bfeba5SDavid Howells pkt.whdr.securityIndex = conn->security_ix; 13018bfeba5SDavid Howells pkt.whdr._rsvd = 0; 13168d6d1aeSDavid Howells pkt.whdr.serviceId = htons(conn->service_id); 13218bfeba5SDavid Howells 13318bfeba5SDavid Howells len = sizeof(pkt.whdr); 13418bfeba5SDavid Howells switch (chan->last_type) { 13518bfeba5SDavid Howells case RXRPC_PACKET_TYPE_ABORT: 1365fc62f6aSDavid Howells pkt.abort_code = htonl(chan->last_abort); 1375fc62f6aSDavid Howells iov[0].iov_len += sizeof(pkt.abort_code); 1385fc62f6aSDavid Howells len += sizeof(pkt.abort_code); 1395fc62f6aSDavid Howells ioc = 1; 14018bfeba5SDavid Howells break; 14118bfeba5SDavid Howells 14218bfeba5SDavid Howells case RXRPC_PACKET_TYPE_ACK: 1432cc80086SDavid Howells mtu = conn->peer->if_mtu; 1442cc80086SDavid Howells mtu -= conn->peer->hdrsize; 14518bfeba5SDavid Howells pkt.ack.bufferSpace = 0; 1463136ef49SDavid Howells pkt.ack.maxSkew = htons(skb ? skb->priority : 0); 1473136ef49SDavid Howells pkt.ack.firstPacket = htonl(chan->last_seq + 1); 1483136ef49SDavid Howells pkt.ack.previousPacket = htonl(chan->last_seq); 1493136ef49SDavid Howells pkt.ack.serial = htonl(skb ? sp->hdr.serial : 0); 1503136ef49SDavid Howells pkt.ack.reason = skb ? RXRPC_ACK_DUPLICATE : RXRPC_ACK_IDLE; 15118bfeba5SDavid Howells pkt.ack.nAcks = 0; 1525fc62f6aSDavid Howells ack_info.rxMTU = htonl(rxrpc_rx_mtu); 1535fc62f6aSDavid Howells ack_info.maxMTU = htonl(mtu); 1545fc62f6aSDavid Howells ack_info.rwind = htonl(rxrpc_rx_window_size); 1555fc62f6aSDavid Howells ack_info.jumbo_max = htonl(rxrpc_rx_jumbo_max); 15657494343SDavid Howells pkt.whdr.flags |= RXRPC_SLOW_START_OK; 1575fc62f6aSDavid Howells padding = 0; 1585fc62f6aSDavid Howells iov[0].iov_len += sizeof(pkt.ack); 1595fc62f6aSDavid Howells len += sizeof(pkt.ack) + 3 + sizeof(ack_info); 1605fc62f6aSDavid Howells ioc = 3; 16118bfeba5SDavid Howells break; 1625fc62f6aSDavid Howells 1635fc62f6aSDavid Howells default: 1645fc62f6aSDavid Howells return; 16518bfeba5SDavid Howells } 16618bfeba5SDavid Howells 16718bfeba5SDavid Howells /* Resync with __rxrpc_disconnect_call() and check that the last call 16818bfeba5SDavid Howells * didn't get advanced whilst we were filling out the packets. 16918bfeba5SDavid Howells */ 17018bfeba5SDavid Howells smp_rmb(); 17118bfeba5SDavid Howells if (READ_ONCE(chan->last_call) != call_id) 17218bfeba5SDavid Howells return; 17318bfeba5SDavid Howells 17418bfeba5SDavid Howells serial = atomic_inc_return(&conn->serial); 17518bfeba5SDavid Howells pkt.whdr.serial = htonl(serial); 17618bfeba5SDavid Howells 17718bfeba5SDavid Howells switch (chan->last_type) { 17818bfeba5SDavid Howells case RXRPC_PACKET_TYPE_ABORT: 17918bfeba5SDavid Howells break; 18018bfeba5SDavid Howells case RXRPC_PACKET_TYPE_ACK: 1814764c0daSDavid Howells trace_rxrpc_tx_ack(chan->call_debug_id, serial, 182f3f8337cSDavid Howells ntohl(pkt.ack.firstPacket), 183f3f8337cSDavid Howells ntohl(pkt.ack.serial), 184f3f8337cSDavid Howells pkt.ack.reason, 0); 18518bfeba5SDavid Howells break; 18618bfeba5SDavid Howells } 18718bfeba5SDavid Howells 1882cc80086SDavid Howells ret = kernel_sendmsg(conn->local->socket, &msg, iov, ioc, len); 1892cc80086SDavid Howells conn->peer->last_tx_at = ktime_get_seconds(); 1906b47fe1dSDavid Howells if (ret < 0) 1914764c0daSDavid Howells trace_rxrpc_tx_fail(chan->call_debug_id, serial, ret, 1924764c0daSDavid Howells rxrpc_tx_point_call_final_resend); 1934764c0daSDavid Howells else 1944764c0daSDavid Howells trace_rxrpc_tx_packet(chan->call_debug_id, &pkt.whdr, 1954764c0daSDavid Howells rxrpc_tx_point_call_final_resend); 1966b47fe1dSDavid Howells 19718bfeba5SDavid Howells _leave(""); 19818bfeba5SDavid Howells } 19918bfeba5SDavid Howells 20018bfeba5SDavid Howells /* 2018c3e34a4SDavid Howells * pass a connection-level abort onto all calls on that connection 2028c3e34a4SDavid Howells */ 203a00ce28bSDavid Howells static void rxrpc_abort_calls(struct rxrpc_connection *conn) 2048c3e34a4SDavid Howells { 2058c3e34a4SDavid Howells struct rxrpc_call *call; 206248f219cSDavid Howells int i; 2078c3e34a4SDavid Howells 20864753092SDavid Howells _enter("{%d},%x", conn->debug_id, conn->abort_code); 2098c3e34a4SDavid Howells 210245500d8SDavid Howells spin_lock(&conn->bundle->channel_lock); 2118c3e34a4SDavid Howells 212a1399f8bSDavid Howells for (i = 0; i < RXRPC_MAXCALLS; i++) { 213a1399f8bSDavid Howells call = rcu_dereference_protected( 214a1399f8bSDavid Howells conn->channels[i].call, 215245500d8SDavid Howells lockdep_is_held(&conn->bundle->channel_lock)); 216a00ce28bSDavid Howells if (call) 217a00ce28bSDavid Howells rxrpc_set_call_completion(call, 218a00ce28bSDavid Howells conn->completion, 21964753092SDavid Howells conn->abort_code, 22064753092SDavid Howells conn->error); 221ccbd3dbeSDavid Howells } 2228c3e34a4SDavid Howells 223245500d8SDavid Howells spin_unlock(&conn->bundle->channel_lock); 2248c3e34a4SDavid Howells _leave(""); 2258c3e34a4SDavid Howells } 2268c3e34a4SDavid Howells 2278c3e34a4SDavid Howells /* 2288c3e34a4SDavid Howells * mark a call as being on a now-secured channel 229248f219cSDavid Howells * - must be called with BH's disabled. 2308c3e34a4SDavid Howells */ 2318c3e34a4SDavid Howells static void rxrpc_call_is_secure(struct rxrpc_call *call) 2328c3e34a4SDavid Howells { 233*96b4059fSDavid Howells if (call && __rxrpc_call_state(call) == RXRPC_CALL_SERVER_SECURING) { 234*96b4059fSDavid Howells rxrpc_set_call_state(call, RXRPC_CALL_SERVER_RECV_REQUEST); 235248f219cSDavid Howells rxrpc_notify_socket(call); 236248f219cSDavid Howells } 2378c3e34a4SDavid Howells } 2388c3e34a4SDavid Howells 2398c3e34a4SDavid Howells /* 2408c3e34a4SDavid Howells * connection-level Rx packet processor 2418c3e34a4SDavid Howells */ 2428c3e34a4SDavid Howells static int rxrpc_process_event(struct rxrpc_connection *conn, 243a00ce28bSDavid Howells struct sk_buff *skb) 2448c3e34a4SDavid Howells { 2458c3e34a4SDavid Howells struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 2462953d3b8SDavid Howells int ret; 2478c3e34a4SDavid Howells 248a00ce28bSDavid Howells if (conn->state == RXRPC_CONN_ABORTED) 2498c3e34a4SDavid Howells return -ECONNABORTED; 2508c3e34a4SDavid Howells 2518c3e34a4SDavid Howells _enter("{%d},{%u,%%%u},", conn->debug_id, sp->hdr.type, sp->hdr.serial); 2528c3e34a4SDavid Howells 2538c3e34a4SDavid Howells switch (sp->hdr.type) { 2548c3e34a4SDavid Howells case RXRPC_PACKET_TYPE_CHALLENGE: 255a00ce28bSDavid Howells return conn->security->respond_to_challenge(conn, skb); 2568c3e34a4SDavid Howells 2578c3e34a4SDavid Howells case RXRPC_PACKET_TYPE_RESPONSE: 258a00ce28bSDavid Howells ret = conn->security->verify_response(conn, skb); 2598c3e34a4SDavid Howells if (ret < 0) 2608c3e34a4SDavid Howells return ret; 2618c3e34a4SDavid Howells 26241057ebdSDavid Howells ret = conn->security->init_connection_security( 2632cc80086SDavid Howells conn, conn->key->payload.data[0]); 2648c3e34a4SDavid Howells if (ret < 0) 2658c3e34a4SDavid Howells return ret; 2668c3e34a4SDavid Howells 2673dd9c8b5SDavid Howells spin_lock(&conn->state_lock); 2682953d3b8SDavid Howells if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING) 269bba304dbSDavid Howells conn->state = RXRPC_CONN_SERVICE; 2703dd9c8b5SDavid Howells spin_unlock(&conn->state_lock); 2718c3e34a4SDavid Howells 2722953d3b8SDavid Howells if (conn->state == RXRPC_CONN_SERVICE) { 2732953d3b8SDavid Howells /* Offload call state flipping to the I/O thread. As 2742953d3b8SDavid Howells * we've already received the packet, put it on the 2752953d3b8SDavid Howells * front of the queue. 2762953d3b8SDavid Howells */ 2772953d3b8SDavid Howells skb->mark = RXRPC_SKB_MARK_SERVICE_CONN_SECURED; 2782953d3b8SDavid Howells rxrpc_get_skb(skb, rxrpc_skb_get_conn_secured); 2792953d3b8SDavid Howells skb_queue_head(&conn->local->rx_queue, skb); 2802953d3b8SDavid Howells rxrpc_wake_up_io_thread(conn->local); 2812953d3b8SDavid Howells } 2828c3e34a4SDavid Howells return 0; 2838c3e34a4SDavid Howells 2848c3e34a4SDavid Howells default: 28557af281eSDavid Howells WARN_ON_ONCE(1); 2868c3e34a4SDavid Howells return -EPROTO; 2878c3e34a4SDavid Howells } 2888c3e34a4SDavid Howells } 2898c3e34a4SDavid Howells 2908c3e34a4SDavid Howells /* 2918c3e34a4SDavid Howells * set up security and issue a challenge 2928c3e34a4SDavid Howells */ 2938c3e34a4SDavid Howells static void rxrpc_secure_connection(struct rxrpc_connection *conn) 2948c3e34a4SDavid Howells { 295a00ce28bSDavid Howells if (conn->security->issue_challenge(conn) < 0) 29657af281eSDavid Howells rxrpc_abort_conn(conn, NULL, RX_CALL_DEAD, -ENOMEM, 29757af281eSDavid Howells rxrpc_abort_nomem); 2988c3e34a4SDavid Howells } 2998c3e34a4SDavid Howells 3008c3e34a4SDavid Howells /* 3013136ef49SDavid Howells * Process delayed final ACKs that we haven't subsumed into a subsequent call. 3023136ef49SDavid Howells */ 303ddc7834aSDavid Howells void rxrpc_process_delayed_final_acks(struct rxrpc_connection *conn, bool force) 3043136ef49SDavid Howells { 3053136ef49SDavid Howells unsigned long j = jiffies, next_j; 3063136ef49SDavid Howells unsigned int channel; 3073136ef49SDavid Howells bool set; 3083136ef49SDavid Howells 3093136ef49SDavid Howells again: 3103136ef49SDavid Howells next_j = j + LONG_MAX; 3113136ef49SDavid Howells set = false; 3123136ef49SDavid Howells for (channel = 0; channel < RXRPC_MAXCALLS; channel++) { 3133136ef49SDavid Howells struct rxrpc_channel *chan = &conn->channels[channel]; 3143136ef49SDavid Howells unsigned long ack_at; 3153136ef49SDavid Howells 3163136ef49SDavid Howells if (!test_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags)) 3173136ef49SDavid Howells continue; 3183136ef49SDavid Howells 3193136ef49SDavid Howells smp_rmb(); /* vs rxrpc_disconnect_client_call */ 3203136ef49SDavid Howells ack_at = READ_ONCE(chan->final_ack_at); 3213136ef49SDavid Howells 322ddc7834aSDavid Howells if (time_before(j, ack_at) && !force) { 3233136ef49SDavid Howells if (time_before(ack_at, next_j)) { 3243136ef49SDavid Howells next_j = ack_at; 3253136ef49SDavid Howells set = true; 3263136ef49SDavid Howells } 3273136ef49SDavid Howells continue; 3283136ef49SDavid Howells } 3293136ef49SDavid Howells 3303136ef49SDavid Howells if (test_and_clear_bit(RXRPC_CONN_FINAL_ACK_0 + channel, 3313136ef49SDavid Howells &conn->flags)) 3323136ef49SDavid Howells rxrpc_conn_retransmit_call(conn, NULL, channel); 3333136ef49SDavid Howells } 3343136ef49SDavid Howells 3353136ef49SDavid Howells j = jiffies; 3363136ef49SDavid Howells if (time_before_eq(next_j, j)) 3373136ef49SDavid Howells goto again; 3383136ef49SDavid Howells if (set) 3393136ef49SDavid Howells rxrpc_reduce_conn_timer(conn, next_j); 3403136ef49SDavid Howells } 3413136ef49SDavid Howells 3423136ef49SDavid Howells /* 3438c3e34a4SDavid Howells * connection-level event processor 3448c3e34a4SDavid Howells */ 34504d36d74SDavid Howells static void rxrpc_do_process_connection(struct rxrpc_connection *conn) 3468c3e34a4SDavid Howells { 3478c3e34a4SDavid Howells struct sk_buff *skb; 3488c3e34a4SDavid Howells int ret; 3498c3e34a4SDavid Howells 3502c4579e4SDavid Howells if (test_and_clear_bit(RXRPC_CONN_EV_CHALLENGE, &conn->events)) 3518c3e34a4SDavid Howells rxrpc_secure_connection(conn); 3528c3e34a4SDavid Howells 3538c3e34a4SDavid Howells /* go through the conn-level event packets, releasing the ref on this 3548c3e34a4SDavid Howells * connection that each one has when we've finished with it */ 3558c3e34a4SDavid Howells while ((skb = skb_dequeue(&conn->rx_queue))) { 3569a36a6bcSDavid Howells rxrpc_see_skb(skb, rxrpc_skb_see_conn_work); 357a00ce28bSDavid Howells ret = rxrpc_process_event(conn, skb); 3588c3e34a4SDavid Howells switch (ret) { 3598c2f826dSDavid Howells case -ENOMEM: 3608c3e34a4SDavid Howells case -EAGAIN: 361a00ce28bSDavid Howells skb_queue_head(&conn->rx_queue, skb); 362a00ce28bSDavid Howells rxrpc_queue_conn(conn, rxrpc_conn_queue_retry_work); 363a00ce28bSDavid Howells break; 3648c3e34a4SDavid Howells default: 3659a36a6bcSDavid Howells rxrpc_free_skb(skb, rxrpc_skb_put_conn_work); 3668c3e34a4SDavid Howells break; 3678c3e34a4SDavid Howells } 3688c3e34a4SDavid Howells } 36904d36d74SDavid Howells } 37004d36d74SDavid Howells 37104d36d74SDavid Howells void rxrpc_process_connection(struct work_struct *work) 37204d36d74SDavid Howells { 37304d36d74SDavid Howells struct rxrpc_connection *conn = 37404d36d74SDavid Howells container_of(work, struct rxrpc_connection, processor); 37504d36d74SDavid Howells 3767fa25105SDavid Howells rxrpc_see_connection(conn, rxrpc_conn_see_work); 37704d36d74SDavid Howells 3780fde882fSDavid Howells if (__rxrpc_use_local(conn->local, rxrpc_local_use_conn_work)) { 37904d36d74SDavid Howells rxrpc_do_process_connection(conn); 3800fde882fSDavid Howells rxrpc_unuse_local(conn->local, rxrpc_local_unuse_conn_work); 38104d36d74SDavid Howells } 3828c3e34a4SDavid Howells } 3835e6ef4f1SDavid Howells 3845e6ef4f1SDavid Howells /* 3855e6ef4f1SDavid Howells * post connection-level events to the connection 3865e6ef4f1SDavid Howells * - this includes challenges, responses, some aborts and call terminal packet 3875e6ef4f1SDavid Howells * retransmission. 3885e6ef4f1SDavid Howells */ 3895e6ef4f1SDavid Howells static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn, 3905e6ef4f1SDavid Howells struct sk_buff *skb) 3915e6ef4f1SDavid Howells { 3925e6ef4f1SDavid Howells _enter("%p,%p", conn, skb); 3935e6ef4f1SDavid Howells 3945e6ef4f1SDavid Howells rxrpc_get_skb(skb, rxrpc_skb_get_conn_work); 3955e6ef4f1SDavid Howells skb_queue_tail(&conn->rx_queue, skb); 3965e6ef4f1SDavid Howells rxrpc_queue_conn(conn, rxrpc_conn_queue_rx_work); 3975e6ef4f1SDavid Howells } 3985e6ef4f1SDavid Howells 3995e6ef4f1SDavid Howells /* 4005e6ef4f1SDavid Howells * Input a connection-level packet. 4015e6ef4f1SDavid Howells */ 40257af281eSDavid Howells bool rxrpc_input_conn_packet(struct rxrpc_connection *conn, struct sk_buff *skb) 4035e6ef4f1SDavid Howells { 4045e6ef4f1SDavid Howells struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 4055e6ef4f1SDavid Howells 4065e6ef4f1SDavid Howells switch (sp->hdr.type) { 4075e6ef4f1SDavid Howells case RXRPC_PACKET_TYPE_BUSY: 4085e6ef4f1SDavid Howells /* Just ignore BUSY packets for now. */ 40957af281eSDavid Howells return true; 4105e6ef4f1SDavid Howells 4115e6ef4f1SDavid Howells case RXRPC_PACKET_TYPE_ABORT: 412a00ce28bSDavid Howells if (rxrpc_is_conn_aborted(conn)) 413a00ce28bSDavid Howells return true; 414a00ce28bSDavid Howells rxrpc_input_conn_abort(conn, skb); 415a00ce28bSDavid Howells rxrpc_abort_calls(conn); 416a00ce28bSDavid Howells return true; 4175e6ef4f1SDavid Howells 4185e6ef4f1SDavid Howells case RXRPC_PACKET_TYPE_CHALLENGE: 4195e6ef4f1SDavid Howells case RXRPC_PACKET_TYPE_RESPONSE: 420a00ce28bSDavid Howells if (rxrpc_is_conn_aborted(conn)) { 421a00ce28bSDavid Howells if (conn->completion == RXRPC_CALL_LOCALLY_ABORTED) 422a00ce28bSDavid Howells rxrpc_send_conn_abort(conn); 423a00ce28bSDavid Howells return true; 424a00ce28bSDavid Howells } 4255e6ef4f1SDavid Howells rxrpc_post_packet_to_conn(conn, skb); 42657af281eSDavid Howells return true; 4275e6ef4f1SDavid Howells 4285e6ef4f1SDavid Howells default: 42957af281eSDavid Howells WARN_ON_ONCE(1); 43057af281eSDavid Howells return true; 4315e6ef4f1SDavid Howells } 4325e6ef4f1SDavid Howells } 433f2cce89aSDavid Howells 434f2cce89aSDavid Howells /* 435f2cce89aSDavid Howells * Input a connection event. 436f2cce89aSDavid Howells */ 437f2cce89aSDavid Howells void rxrpc_input_conn_event(struct rxrpc_connection *conn, struct sk_buff *skb) 438f2cce89aSDavid Howells { 4392953d3b8SDavid Howells unsigned int loop; 4402953d3b8SDavid Howells 441a00ce28bSDavid Howells if (test_and_clear_bit(RXRPC_CONN_EV_ABORT_CALLS, &conn->events)) 442a00ce28bSDavid Howells rxrpc_abort_calls(conn); 443a00ce28bSDavid Howells 4442953d3b8SDavid Howells switch (skb->mark) { 4452953d3b8SDavid Howells case RXRPC_SKB_MARK_SERVICE_CONN_SECURED: 4462953d3b8SDavid Howells if (conn->state != RXRPC_CONN_SERVICE) 4472953d3b8SDavid Howells break; 4482953d3b8SDavid Howells 4492953d3b8SDavid Howells spin_lock(&conn->bundle->channel_lock); 4502953d3b8SDavid Howells 4512953d3b8SDavid Howells for (loop = 0; loop < RXRPC_MAXCALLS; loop++) 4522953d3b8SDavid Howells rxrpc_call_is_secure( 4532953d3b8SDavid Howells rcu_dereference_protected( 4542953d3b8SDavid Howells conn->channels[loop].call, 4552953d3b8SDavid Howells lockdep_is_held(&conn->bundle->channel_lock))); 4562953d3b8SDavid Howells 4572953d3b8SDavid Howells spin_unlock(&conn->bundle->channel_lock); 4582953d3b8SDavid Howells break; 4592953d3b8SDavid Howells } 4602953d3b8SDavid Howells 461f2cce89aSDavid Howells /* Process delayed ACKs whose time has come. */ 462f2cce89aSDavid Howells if (conn->flags & RXRPC_CONN_FINAL_ACK_MASK) 463f2cce89aSDavid Howells rxrpc_process_delayed_final_acks(conn, false); 464f2cce89aSDavid Howells } 465