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 /* 20*a00ce28bSDavid Howells * Set the completion state on an aborted connection. 21*a00ce28bSDavid Howells */ 22*a00ce28bSDavid Howells static bool rxrpc_set_conn_aborted(struct rxrpc_connection *conn, struct sk_buff *skb, 23*a00ce28bSDavid Howells s32 abort_code, int err, 24*a00ce28bSDavid Howells enum rxrpc_call_completion compl) 25*a00ce28bSDavid Howells { 26*a00ce28bSDavid Howells bool aborted = false; 27*a00ce28bSDavid Howells 28*a00ce28bSDavid Howells if (conn->state != RXRPC_CONN_ABORTED) { 29*a00ce28bSDavid Howells spin_lock(&conn->state_lock); 30*a00ce28bSDavid Howells if (conn->state != RXRPC_CONN_ABORTED) { 31*a00ce28bSDavid Howells conn->abort_code = abort_code; 32*a00ce28bSDavid Howells conn->error = err; 33*a00ce28bSDavid Howells conn->completion = compl; 34*a00ce28bSDavid Howells /* Order the abort info before the state change. */ 35*a00ce28bSDavid Howells smp_store_release(&conn->state, RXRPC_CONN_ABORTED); 36*a00ce28bSDavid Howells set_bit(RXRPC_CONN_DONT_REUSE, &conn->flags); 37*a00ce28bSDavid Howells set_bit(RXRPC_CONN_EV_ABORT_CALLS, &conn->events); 38*a00ce28bSDavid Howells aborted = true; 39*a00ce28bSDavid Howells } 40*a00ce28bSDavid Howells spin_unlock(&conn->state_lock); 41*a00ce28bSDavid Howells } 42*a00ce28bSDavid Howells 43*a00ce28bSDavid Howells return aborted; 44*a00ce28bSDavid Howells } 45*a00ce28bSDavid Howells 46*a00ce28bSDavid Howells /* 47*a00ce28bSDavid Howells * Mark a socket buffer to indicate that the connection it's on should be aborted. 48*a00ce28bSDavid Howells */ 49*a00ce28bSDavid Howells int rxrpc_abort_conn(struct rxrpc_connection *conn, struct sk_buff *skb, 50*a00ce28bSDavid Howells s32 abort_code, int err, const char *why) 51*a00ce28bSDavid Howells { 52*a00ce28bSDavid Howells struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 53*a00ce28bSDavid Howells 54*a00ce28bSDavid Howells if (rxrpc_set_conn_aborted(conn, skb, abort_code, err, 55*a00ce28bSDavid Howells RXRPC_CALL_LOCALLY_ABORTED)) { 56*a00ce28bSDavid Howells trace_rxrpc_abort(0, why, sp->hdr.cid, sp->hdr.callNumber, 57*a00ce28bSDavid Howells sp->hdr.seq, abort_code, err); 58*a00ce28bSDavid Howells rxrpc_poke_conn(conn, rxrpc_conn_get_poke_abort); 59*a00ce28bSDavid Howells } 60*a00ce28bSDavid Howells return -EPROTO; 61*a00ce28bSDavid Howells } 62*a00ce28bSDavid Howells 63*a00ce28bSDavid Howells /* 64*a00ce28bSDavid Howells * Mark a connection as being remotely aborted. 65*a00ce28bSDavid Howells */ 66*a00ce28bSDavid Howells static bool rxrpc_input_conn_abort(struct rxrpc_connection *conn, 67*a00ce28bSDavid Howells struct sk_buff *skb) 68*a00ce28bSDavid Howells { 69*a00ce28bSDavid Howells return rxrpc_set_conn_aborted(conn, skb, skb->priority, -ECONNABORTED, 70*a00ce28bSDavid Howells RXRPC_CALL_REMOTELY_ABORTED); 71*a00ce28bSDavid Howells } 72*a00ce28bSDavid Howells 73*a00ce28bSDavid 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 */ 203*a00ce28bSDavid 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)); 216*a00ce28bSDavid Howells if (call) 217*a00ce28bSDavid Howells rxrpc_set_call_completion(call, 218*a00ce28bSDavid 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 { 2338c3e34a4SDavid Howells _enter("%p", call); 2348c3e34a4SDavid Howells if (call) { 2353dd9c8b5SDavid Howells write_lock(&call->state_lock); 236248f219cSDavid Howells if (call->state == RXRPC_CALL_SERVER_SECURING) { 2372d914c1bSDavid Howells call->state = RXRPC_CALL_SERVER_RECV_REQUEST; 238248f219cSDavid Howells rxrpc_notify_socket(call); 239248f219cSDavid Howells } 2403dd9c8b5SDavid Howells write_unlock(&call->state_lock); 2418c3e34a4SDavid Howells } 2428c3e34a4SDavid Howells } 2438c3e34a4SDavid Howells 2448c3e34a4SDavid Howells /* 2458c3e34a4SDavid Howells * connection-level Rx packet processor 2468c3e34a4SDavid Howells */ 2478c3e34a4SDavid Howells static int rxrpc_process_event(struct rxrpc_connection *conn, 248*a00ce28bSDavid Howells struct sk_buff *skb) 2498c3e34a4SDavid Howells { 2508c3e34a4SDavid Howells struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 2518c3e34a4SDavid Howells int loop, ret; 2528c3e34a4SDavid Howells 253*a00ce28bSDavid Howells if (conn->state == RXRPC_CONN_ABORTED) 2548c3e34a4SDavid Howells return -ECONNABORTED; 2558c3e34a4SDavid Howells 2568c3e34a4SDavid Howells _enter("{%d},{%u,%%%u},", conn->debug_id, sp->hdr.type, sp->hdr.serial); 2578c3e34a4SDavid Howells 2588c3e34a4SDavid Howells switch (sp->hdr.type) { 2598c3e34a4SDavid Howells case RXRPC_PACKET_TYPE_CHALLENGE: 260*a00ce28bSDavid Howells return conn->security->respond_to_challenge(conn, skb); 2618c3e34a4SDavid Howells 2628c3e34a4SDavid Howells case RXRPC_PACKET_TYPE_RESPONSE: 263*a00ce28bSDavid Howells ret = conn->security->verify_response(conn, skb); 2648c3e34a4SDavid Howells if (ret < 0) 2658c3e34a4SDavid Howells return ret; 2668c3e34a4SDavid Howells 26741057ebdSDavid Howells ret = conn->security->init_connection_security( 2682cc80086SDavid Howells conn, conn->key->payload.data[0]); 2698c3e34a4SDavid Howells if (ret < 0) 2708c3e34a4SDavid Howells return ret; 2718c3e34a4SDavid Howells 272245500d8SDavid Howells spin_lock(&conn->bundle->channel_lock); 2733dd9c8b5SDavid Howells spin_lock(&conn->state_lock); 2748c3e34a4SDavid Howells 275bba304dbSDavid Howells if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING) { 276bba304dbSDavid Howells conn->state = RXRPC_CONN_SERVICE; 2773dd9c8b5SDavid Howells spin_unlock(&conn->state_lock); 2788c3e34a4SDavid Howells for (loop = 0; loop < RXRPC_MAXCALLS; loop++) 279dee46364SDavid Howells rxrpc_call_is_secure( 280dee46364SDavid Howells rcu_dereference_protected( 281a1399f8bSDavid Howells conn->channels[loop].call, 282245500d8SDavid Howells lockdep_is_held(&conn->bundle->channel_lock))); 283248f219cSDavid Howells } else { 2843dd9c8b5SDavid Howells spin_unlock(&conn->state_lock); 2858c3e34a4SDavid Howells } 2868c3e34a4SDavid Howells 287245500d8SDavid Howells spin_unlock(&conn->bundle->channel_lock); 2888c3e34a4SDavid Howells return 0; 2898c3e34a4SDavid Howells 2908c3e34a4SDavid Howells default: 291fb46f6eeSDavid Howells trace_rxrpc_rx_eproto(NULL, sp->hdr.serial, 292fb46f6eeSDavid Howells tracepoint_string("bad_conn_pkt")); 2938c3e34a4SDavid Howells return -EPROTO; 2948c3e34a4SDavid Howells } 2958c3e34a4SDavid Howells } 2968c3e34a4SDavid Howells 2978c3e34a4SDavid Howells /* 2988c3e34a4SDavid Howells * set up security and issue a challenge 2998c3e34a4SDavid Howells */ 3008c3e34a4SDavid Howells static void rxrpc_secure_connection(struct rxrpc_connection *conn) 3018c3e34a4SDavid Howells { 302*a00ce28bSDavid Howells if (conn->security->issue_challenge(conn) < 0) 303*a00ce28bSDavid Howells rxrpc_abort_conn(conn, NULL, RX_CALL_DEAD, -ENOMEM, "OOM"); 3048c3e34a4SDavid Howells } 3058c3e34a4SDavid Howells 3068c3e34a4SDavid Howells /* 3073136ef49SDavid Howells * Process delayed final ACKs that we haven't subsumed into a subsequent call. 3083136ef49SDavid Howells */ 309ddc7834aSDavid Howells void rxrpc_process_delayed_final_acks(struct rxrpc_connection *conn, bool force) 3103136ef49SDavid Howells { 3113136ef49SDavid Howells unsigned long j = jiffies, next_j; 3123136ef49SDavid Howells unsigned int channel; 3133136ef49SDavid Howells bool set; 3143136ef49SDavid Howells 3153136ef49SDavid Howells again: 3163136ef49SDavid Howells next_j = j + LONG_MAX; 3173136ef49SDavid Howells set = false; 3183136ef49SDavid Howells for (channel = 0; channel < RXRPC_MAXCALLS; channel++) { 3193136ef49SDavid Howells struct rxrpc_channel *chan = &conn->channels[channel]; 3203136ef49SDavid Howells unsigned long ack_at; 3213136ef49SDavid Howells 3223136ef49SDavid Howells if (!test_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags)) 3233136ef49SDavid Howells continue; 3243136ef49SDavid Howells 3253136ef49SDavid Howells smp_rmb(); /* vs rxrpc_disconnect_client_call */ 3263136ef49SDavid Howells ack_at = READ_ONCE(chan->final_ack_at); 3273136ef49SDavid Howells 328ddc7834aSDavid Howells if (time_before(j, ack_at) && !force) { 3293136ef49SDavid Howells if (time_before(ack_at, next_j)) { 3303136ef49SDavid Howells next_j = ack_at; 3313136ef49SDavid Howells set = true; 3323136ef49SDavid Howells } 3333136ef49SDavid Howells continue; 3343136ef49SDavid Howells } 3353136ef49SDavid Howells 3363136ef49SDavid Howells if (test_and_clear_bit(RXRPC_CONN_FINAL_ACK_0 + channel, 3373136ef49SDavid Howells &conn->flags)) 3383136ef49SDavid Howells rxrpc_conn_retransmit_call(conn, NULL, channel); 3393136ef49SDavid Howells } 3403136ef49SDavid Howells 3413136ef49SDavid Howells j = jiffies; 3423136ef49SDavid Howells if (time_before_eq(next_j, j)) 3433136ef49SDavid Howells goto again; 3443136ef49SDavid Howells if (set) 3453136ef49SDavid Howells rxrpc_reduce_conn_timer(conn, next_j); 3463136ef49SDavid Howells } 3473136ef49SDavid Howells 3483136ef49SDavid Howells /* 3498c3e34a4SDavid Howells * connection-level event processor 3508c3e34a4SDavid Howells */ 35104d36d74SDavid Howells static void rxrpc_do_process_connection(struct rxrpc_connection *conn) 3528c3e34a4SDavid Howells { 3538c3e34a4SDavid Howells struct sk_buff *skb; 3548c3e34a4SDavid Howells int ret; 3558c3e34a4SDavid Howells 3562c4579e4SDavid Howells if (test_and_clear_bit(RXRPC_CONN_EV_CHALLENGE, &conn->events)) 3578c3e34a4SDavid Howells rxrpc_secure_connection(conn); 3588c3e34a4SDavid Howells 3598c3e34a4SDavid Howells /* go through the conn-level event packets, releasing the ref on this 3608c3e34a4SDavid Howells * connection that each one has when we've finished with it */ 3618c3e34a4SDavid Howells while ((skb = skb_dequeue(&conn->rx_queue))) { 3629a36a6bcSDavid Howells rxrpc_see_skb(skb, rxrpc_skb_see_conn_work); 363*a00ce28bSDavid Howells ret = rxrpc_process_event(conn, skb); 3648c3e34a4SDavid Howells switch (ret) { 3658c2f826dSDavid Howells case -ENOMEM: 3668c3e34a4SDavid Howells case -EAGAIN: 367*a00ce28bSDavid Howells skb_queue_head(&conn->rx_queue, skb); 368*a00ce28bSDavid Howells rxrpc_queue_conn(conn, rxrpc_conn_queue_retry_work); 369*a00ce28bSDavid Howells break; 3708c3e34a4SDavid Howells default: 3719a36a6bcSDavid Howells rxrpc_free_skb(skb, rxrpc_skb_put_conn_work); 3728c3e34a4SDavid Howells break; 3738c3e34a4SDavid Howells } 3748c3e34a4SDavid Howells } 37504d36d74SDavid Howells } 37604d36d74SDavid Howells 37704d36d74SDavid Howells void rxrpc_process_connection(struct work_struct *work) 37804d36d74SDavid Howells { 37904d36d74SDavid Howells struct rxrpc_connection *conn = 38004d36d74SDavid Howells container_of(work, struct rxrpc_connection, processor); 38104d36d74SDavid Howells 3827fa25105SDavid Howells rxrpc_see_connection(conn, rxrpc_conn_see_work); 38304d36d74SDavid Howells 3840fde882fSDavid Howells if (__rxrpc_use_local(conn->local, rxrpc_local_use_conn_work)) { 38504d36d74SDavid Howells rxrpc_do_process_connection(conn); 3860fde882fSDavid Howells rxrpc_unuse_local(conn->local, rxrpc_local_unuse_conn_work); 38704d36d74SDavid Howells } 3888c3e34a4SDavid Howells } 3895e6ef4f1SDavid Howells 3905e6ef4f1SDavid Howells /* 3915e6ef4f1SDavid Howells * post connection-level events to the connection 3925e6ef4f1SDavid Howells * - this includes challenges, responses, some aborts and call terminal packet 3935e6ef4f1SDavid Howells * retransmission. 3945e6ef4f1SDavid Howells */ 3955e6ef4f1SDavid Howells static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn, 3965e6ef4f1SDavid Howells struct sk_buff *skb) 3975e6ef4f1SDavid Howells { 3985e6ef4f1SDavid Howells _enter("%p,%p", conn, skb); 3995e6ef4f1SDavid Howells 4005e6ef4f1SDavid Howells rxrpc_get_skb(skb, rxrpc_skb_get_conn_work); 4015e6ef4f1SDavid Howells skb_queue_tail(&conn->rx_queue, skb); 4025e6ef4f1SDavid Howells rxrpc_queue_conn(conn, rxrpc_conn_queue_rx_work); 4035e6ef4f1SDavid Howells } 4045e6ef4f1SDavid Howells 4055e6ef4f1SDavid Howells /* 4065e6ef4f1SDavid Howells * Input a connection-level packet. 4075e6ef4f1SDavid Howells */ 4085e6ef4f1SDavid Howells int rxrpc_input_conn_packet(struct rxrpc_connection *conn, struct sk_buff *skb) 4095e6ef4f1SDavid Howells { 4105e6ef4f1SDavid Howells struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 4115e6ef4f1SDavid Howells 4125e6ef4f1SDavid Howells switch (sp->hdr.type) { 4135e6ef4f1SDavid Howells case RXRPC_PACKET_TYPE_BUSY: 4145e6ef4f1SDavid Howells /* Just ignore BUSY packets for now. */ 4155e6ef4f1SDavid Howells return 0; 4165e6ef4f1SDavid Howells 4175e6ef4f1SDavid Howells case RXRPC_PACKET_TYPE_ABORT: 418*a00ce28bSDavid Howells if (rxrpc_is_conn_aborted(conn)) 419*a00ce28bSDavid Howells return true; 420*a00ce28bSDavid Howells rxrpc_input_conn_abort(conn, skb); 421*a00ce28bSDavid Howells rxrpc_abort_calls(conn); 422*a00ce28bSDavid Howells return true; 4235e6ef4f1SDavid Howells 4245e6ef4f1SDavid Howells case RXRPC_PACKET_TYPE_CHALLENGE: 4255e6ef4f1SDavid Howells case RXRPC_PACKET_TYPE_RESPONSE: 426*a00ce28bSDavid Howells if (rxrpc_is_conn_aborted(conn)) { 427*a00ce28bSDavid Howells if (conn->completion == RXRPC_CALL_LOCALLY_ABORTED) 428*a00ce28bSDavid Howells rxrpc_send_conn_abort(conn); 429*a00ce28bSDavid Howells return true; 430*a00ce28bSDavid Howells } 4315e6ef4f1SDavid Howells rxrpc_post_packet_to_conn(conn, skb); 4325e6ef4f1SDavid Howells return 0; 4335e6ef4f1SDavid Howells 4345e6ef4f1SDavid Howells default: 4355e6ef4f1SDavid Howells trace_rxrpc_rx_eproto(NULL, sp->hdr.serial, 4365e6ef4f1SDavid Howells tracepoint_string("bad_conn_pkt")); 4375e6ef4f1SDavid Howells return -EPROTO; 4385e6ef4f1SDavid Howells } 4395e6ef4f1SDavid Howells } 440f2cce89aSDavid Howells 441f2cce89aSDavid Howells /* 442f2cce89aSDavid Howells * Input a connection event. 443f2cce89aSDavid Howells */ 444f2cce89aSDavid Howells void rxrpc_input_conn_event(struct rxrpc_connection *conn, struct sk_buff *skb) 445f2cce89aSDavid Howells { 446*a00ce28bSDavid Howells if (test_and_clear_bit(RXRPC_CONN_EV_ABORT_CALLS, &conn->events)) 447*a00ce28bSDavid Howells rxrpc_abort_calls(conn); 448*a00ce28bSDavid Howells 449f2cce89aSDavid Howells /* Process delayed ACKs whose time has come. */ 450f2cce89aSDavid Howells if (conn->flags & RXRPC_CONN_FINAL_ACK_MASK) 451f2cce89aSDavid Howells rxrpc_process_delayed_final_acks(conn, false); 452f2cce89aSDavid Howells } 453