162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* connection-level event handling 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 562306a36Sopenharmony_ci * Written by David Howells (dhowells@redhat.com) 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/net.h> 1262306a36Sopenharmony_ci#include <linux/skbuff.h> 1362306a36Sopenharmony_ci#include <linux/errqueue.h> 1462306a36Sopenharmony_ci#include <net/sock.h> 1562306a36Sopenharmony_ci#include <net/af_rxrpc.h> 1662306a36Sopenharmony_ci#include <net/ip.h> 1762306a36Sopenharmony_ci#include "ar-internal.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* 2062306a36Sopenharmony_ci * Set the completion state on an aborted connection. 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_cistatic bool rxrpc_set_conn_aborted(struct rxrpc_connection *conn, struct sk_buff *skb, 2362306a36Sopenharmony_ci s32 abort_code, int err, 2462306a36Sopenharmony_ci enum rxrpc_call_completion compl) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci bool aborted = false; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci if (conn->state != RXRPC_CONN_ABORTED) { 2962306a36Sopenharmony_ci spin_lock(&conn->state_lock); 3062306a36Sopenharmony_ci if (conn->state != RXRPC_CONN_ABORTED) { 3162306a36Sopenharmony_ci conn->abort_code = abort_code; 3262306a36Sopenharmony_ci conn->error = err; 3362306a36Sopenharmony_ci conn->completion = compl; 3462306a36Sopenharmony_ci /* Order the abort info before the state change. */ 3562306a36Sopenharmony_ci smp_store_release(&conn->state, RXRPC_CONN_ABORTED); 3662306a36Sopenharmony_ci set_bit(RXRPC_CONN_DONT_REUSE, &conn->flags); 3762306a36Sopenharmony_ci set_bit(RXRPC_CONN_EV_ABORT_CALLS, &conn->events); 3862306a36Sopenharmony_ci aborted = true; 3962306a36Sopenharmony_ci } 4062306a36Sopenharmony_ci spin_unlock(&conn->state_lock); 4162306a36Sopenharmony_ci } 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci return aborted; 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* 4762306a36Sopenharmony_ci * Mark a socket buffer to indicate that the connection it's on should be aborted. 4862306a36Sopenharmony_ci */ 4962306a36Sopenharmony_ciint rxrpc_abort_conn(struct rxrpc_connection *conn, struct sk_buff *skb, 5062306a36Sopenharmony_ci s32 abort_code, int err, enum rxrpc_abort_reason why) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci if (rxrpc_set_conn_aborted(conn, skb, abort_code, err, 5562306a36Sopenharmony_ci RXRPC_CALL_LOCALLY_ABORTED)) { 5662306a36Sopenharmony_ci trace_rxrpc_abort(0, why, sp->hdr.cid, sp->hdr.callNumber, 5762306a36Sopenharmony_ci sp->hdr.seq, abort_code, err); 5862306a36Sopenharmony_ci rxrpc_poke_conn(conn, rxrpc_conn_get_poke_abort); 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci return -EPROTO; 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/* 6462306a36Sopenharmony_ci * Mark a connection as being remotely aborted. 6562306a36Sopenharmony_ci */ 6662306a36Sopenharmony_cistatic bool rxrpc_input_conn_abort(struct rxrpc_connection *conn, 6762306a36Sopenharmony_ci struct sk_buff *skb) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci return rxrpc_set_conn_aborted(conn, skb, skb->priority, -ECONNABORTED, 7062306a36Sopenharmony_ci RXRPC_CALL_REMOTELY_ABORTED); 7162306a36Sopenharmony_ci} 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci/* 7462306a36Sopenharmony_ci * Retransmit terminal ACK or ABORT of the previous call. 7562306a36Sopenharmony_ci */ 7662306a36Sopenharmony_civoid rxrpc_conn_retransmit_call(struct rxrpc_connection *conn, 7762306a36Sopenharmony_ci struct sk_buff *skb, 7862306a36Sopenharmony_ci unsigned int channel) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci struct rxrpc_skb_priv *sp = skb ? rxrpc_skb(skb) : NULL; 8162306a36Sopenharmony_ci struct rxrpc_channel *chan; 8262306a36Sopenharmony_ci struct msghdr msg; 8362306a36Sopenharmony_ci struct kvec iov[3]; 8462306a36Sopenharmony_ci struct { 8562306a36Sopenharmony_ci struct rxrpc_wire_header whdr; 8662306a36Sopenharmony_ci union { 8762306a36Sopenharmony_ci __be32 abort_code; 8862306a36Sopenharmony_ci struct rxrpc_ackpacket ack; 8962306a36Sopenharmony_ci }; 9062306a36Sopenharmony_ci } __attribute__((packed)) pkt; 9162306a36Sopenharmony_ci struct rxrpc_ackinfo ack_info; 9262306a36Sopenharmony_ci size_t len; 9362306a36Sopenharmony_ci int ret, ioc; 9462306a36Sopenharmony_ci u32 serial, mtu, call_id, padding; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci _enter("%d", conn->debug_id); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci if (sp && sp->hdr.type == RXRPC_PACKET_TYPE_ACK) { 9962306a36Sopenharmony_ci if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), 10062306a36Sopenharmony_ci &pkt.ack, sizeof(pkt.ack)) < 0) 10162306a36Sopenharmony_ci return; 10262306a36Sopenharmony_ci if (pkt.ack.reason == RXRPC_ACK_PING_RESPONSE) 10362306a36Sopenharmony_ci return; 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci chan = &conn->channels[channel]; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci /* If the last call got moved on whilst we were waiting to run, just 10962306a36Sopenharmony_ci * ignore this packet. 11062306a36Sopenharmony_ci */ 11162306a36Sopenharmony_ci call_id = chan->last_call; 11262306a36Sopenharmony_ci if (skb && call_id != sp->hdr.callNumber) 11362306a36Sopenharmony_ci return; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci msg.msg_name = &conn->peer->srx.transport; 11662306a36Sopenharmony_ci msg.msg_namelen = conn->peer->srx.transport_len; 11762306a36Sopenharmony_ci msg.msg_control = NULL; 11862306a36Sopenharmony_ci msg.msg_controllen = 0; 11962306a36Sopenharmony_ci msg.msg_flags = 0; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci iov[0].iov_base = &pkt; 12262306a36Sopenharmony_ci iov[0].iov_len = sizeof(pkt.whdr); 12362306a36Sopenharmony_ci iov[1].iov_base = &padding; 12462306a36Sopenharmony_ci iov[1].iov_len = 3; 12562306a36Sopenharmony_ci iov[2].iov_base = &ack_info; 12662306a36Sopenharmony_ci iov[2].iov_len = sizeof(ack_info); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci serial = rxrpc_get_next_serial(conn); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci pkt.whdr.epoch = htonl(conn->proto.epoch); 13162306a36Sopenharmony_ci pkt.whdr.cid = htonl(conn->proto.cid | channel); 13262306a36Sopenharmony_ci pkt.whdr.callNumber = htonl(call_id); 13362306a36Sopenharmony_ci pkt.whdr.serial = htonl(serial); 13462306a36Sopenharmony_ci pkt.whdr.seq = 0; 13562306a36Sopenharmony_ci pkt.whdr.type = chan->last_type; 13662306a36Sopenharmony_ci pkt.whdr.flags = conn->out_clientflag; 13762306a36Sopenharmony_ci pkt.whdr.userStatus = 0; 13862306a36Sopenharmony_ci pkt.whdr.securityIndex = conn->security_ix; 13962306a36Sopenharmony_ci pkt.whdr._rsvd = 0; 14062306a36Sopenharmony_ci pkt.whdr.serviceId = htons(conn->service_id); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci len = sizeof(pkt.whdr); 14362306a36Sopenharmony_ci switch (chan->last_type) { 14462306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_ABORT: 14562306a36Sopenharmony_ci pkt.abort_code = htonl(chan->last_abort); 14662306a36Sopenharmony_ci iov[0].iov_len += sizeof(pkt.abort_code); 14762306a36Sopenharmony_ci len += sizeof(pkt.abort_code); 14862306a36Sopenharmony_ci ioc = 1; 14962306a36Sopenharmony_ci break; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_ACK: 15262306a36Sopenharmony_ci mtu = conn->peer->if_mtu; 15362306a36Sopenharmony_ci mtu -= conn->peer->hdrsize; 15462306a36Sopenharmony_ci pkt.ack.bufferSpace = 0; 15562306a36Sopenharmony_ci pkt.ack.maxSkew = htons(skb ? skb->priority : 0); 15662306a36Sopenharmony_ci pkt.ack.firstPacket = htonl(chan->last_seq + 1); 15762306a36Sopenharmony_ci pkt.ack.previousPacket = htonl(chan->last_seq); 15862306a36Sopenharmony_ci pkt.ack.serial = htonl(skb ? sp->hdr.serial : 0); 15962306a36Sopenharmony_ci pkt.ack.reason = skb ? RXRPC_ACK_DUPLICATE : RXRPC_ACK_IDLE; 16062306a36Sopenharmony_ci pkt.ack.nAcks = 0; 16162306a36Sopenharmony_ci ack_info.rxMTU = htonl(rxrpc_rx_mtu); 16262306a36Sopenharmony_ci ack_info.maxMTU = htonl(mtu); 16362306a36Sopenharmony_ci ack_info.rwind = htonl(rxrpc_rx_window_size); 16462306a36Sopenharmony_ci ack_info.jumbo_max = htonl(rxrpc_rx_jumbo_max); 16562306a36Sopenharmony_ci pkt.whdr.flags |= RXRPC_SLOW_START_OK; 16662306a36Sopenharmony_ci padding = 0; 16762306a36Sopenharmony_ci iov[0].iov_len += sizeof(pkt.ack); 16862306a36Sopenharmony_ci len += sizeof(pkt.ack) + 3 + sizeof(ack_info); 16962306a36Sopenharmony_ci ioc = 3; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci trace_rxrpc_tx_ack(chan->call_debug_id, serial, 17262306a36Sopenharmony_ci ntohl(pkt.ack.firstPacket), 17362306a36Sopenharmony_ci ntohl(pkt.ack.serial), 17462306a36Sopenharmony_ci pkt.ack.reason, 0, rxrpc_rx_window_size); 17562306a36Sopenharmony_ci break; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci default: 17862306a36Sopenharmony_ci return; 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci ret = kernel_sendmsg(conn->local->socket, &msg, iov, ioc, len); 18262306a36Sopenharmony_ci conn->peer->last_tx_at = ktime_get_seconds(); 18362306a36Sopenharmony_ci if (ret < 0) 18462306a36Sopenharmony_ci trace_rxrpc_tx_fail(chan->call_debug_id, serial, ret, 18562306a36Sopenharmony_ci rxrpc_tx_point_call_final_resend); 18662306a36Sopenharmony_ci else 18762306a36Sopenharmony_ci trace_rxrpc_tx_packet(chan->call_debug_id, &pkt.whdr, 18862306a36Sopenharmony_ci rxrpc_tx_point_call_final_resend); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci _leave(""); 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci/* 19462306a36Sopenharmony_ci * pass a connection-level abort onto all calls on that connection 19562306a36Sopenharmony_ci */ 19662306a36Sopenharmony_cistatic void rxrpc_abort_calls(struct rxrpc_connection *conn) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci struct rxrpc_call *call; 19962306a36Sopenharmony_ci int i; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci _enter("{%d},%x", conn->debug_id, conn->abort_code); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci for (i = 0; i < RXRPC_MAXCALLS; i++) { 20462306a36Sopenharmony_ci call = conn->channels[i].call; 20562306a36Sopenharmony_ci if (call) 20662306a36Sopenharmony_ci rxrpc_set_call_completion(call, 20762306a36Sopenharmony_ci conn->completion, 20862306a36Sopenharmony_ci conn->abort_code, 20962306a36Sopenharmony_ci conn->error); 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci _leave(""); 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci/* 21662306a36Sopenharmony_ci * mark a call as being on a now-secured channel 21762306a36Sopenharmony_ci * - must be called with BH's disabled. 21862306a36Sopenharmony_ci */ 21962306a36Sopenharmony_cistatic void rxrpc_call_is_secure(struct rxrpc_call *call) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci if (call && __rxrpc_call_state(call) == RXRPC_CALL_SERVER_SECURING) { 22262306a36Sopenharmony_ci rxrpc_set_call_state(call, RXRPC_CALL_SERVER_RECV_REQUEST); 22362306a36Sopenharmony_ci rxrpc_notify_socket(call); 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci/* 22862306a36Sopenharmony_ci * connection-level Rx packet processor 22962306a36Sopenharmony_ci */ 23062306a36Sopenharmony_cistatic int rxrpc_process_event(struct rxrpc_connection *conn, 23162306a36Sopenharmony_ci struct sk_buff *skb) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 23462306a36Sopenharmony_ci int ret; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci if (conn->state == RXRPC_CONN_ABORTED) 23762306a36Sopenharmony_ci return -ECONNABORTED; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci _enter("{%d},{%u,%%%u},", conn->debug_id, sp->hdr.type, sp->hdr.serial); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci switch (sp->hdr.type) { 24262306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_CHALLENGE: 24362306a36Sopenharmony_ci return conn->security->respond_to_challenge(conn, skb); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_RESPONSE: 24662306a36Sopenharmony_ci ret = conn->security->verify_response(conn, skb); 24762306a36Sopenharmony_ci if (ret < 0) 24862306a36Sopenharmony_ci return ret; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci ret = conn->security->init_connection_security( 25162306a36Sopenharmony_ci conn, conn->key->payload.data[0]); 25262306a36Sopenharmony_ci if (ret < 0) 25362306a36Sopenharmony_ci return ret; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci spin_lock(&conn->state_lock); 25662306a36Sopenharmony_ci if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING) 25762306a36Sopenharmony_ci conn->state = RXRPC_CONN_SERVICE; 25862306a36Sopenharmony_ci spin_unlock(&conn->state_lock); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci if (conn->state == RXRPC_CONN_SERVICE) { 26162306a36Sopenharmony_ci /* Offload call state flipping to the I/O thread. As 26262306a36Sopenharmony_ci * we've already received the packet, put it on the 26362306a36Sopenharmony_ci * front of the queue. 26462306a36Sopenharmony_ci */ 26562306a36Sopenharmony_ci skb->mark = RXRPC_SKB_MARK_SERVICE_CONN_SECURED; 26662306a36Sopenharmony_ci rxrpc_get_skb(skb, rxrpc_skb_get_conn_secured); 26762306a36Sopenharmony_ci skb_queue_head(&conn->local->rx_queue, skb); 26862306a36Sopenharmony_ci rxrpc_wake_up_io_thread(conn->local); 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci return 0; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci default: 27362306a36Sopenharmony_ci WARN_ON_ONCE(1); 27462306a36Sopenharmony_ci return -EPROTO; 27562306a36Sopenharmony_ci } 27662306a36Sopenharmony_ci} 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci/* 27962306a36Sopenharmony_ci * set up security and issue a challenge 28062306a36Sopenharmony_ci */ 28162306a36Sopenharmony_cistatic void rxrpc_secure_connection(struct rxrpc_connection *conn) 28262306a36Sopenharmony_ci{ 28362306a36Sopenharmony_ci if (conn->security->issue_challenge(conn) < 0) 28462306a36Sopenharmony_ci rxrpc_abort_conn(conn, NULL, RX_CALL_DEAD, -ENOMEM, 28562306a36Sopenharmony_ci rxrpc_abort_nomem); 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci/* 28962306a36Sopenharmony_ci * Process delayed final ACKs that we haven't subsumed into a subsequent call. 29062306a36Sopenharmony_ci */ 29162306a36Sopenharmony_civoid rxrpc_process_delayed_final_acks(struct rxrpc_connection *conn, bool force) 29262306a36Sopenharmony_ci{ 29362306a36Sopenharmony_ci unsigned long j = jiffies, next_j; 29462306a36Sopenharmony_ci unsigned int channel; 29562306a36Sopenharmony_ci bool set; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ciagain: 29862306a36Sopenharmony_ci next_j = j + LONG_MAX; 29962306a36Sopenharmony_ci set = false; 30062306a36Sopenharmony_ci for (channel = 0; channel < RXRPC_MAXCALLS; channel++) { 30162306a36Sopenharmony_ci struct rxrpc_channel *chan = &conn->channels[channel]; 30262306a36Sopenharmony_ci unsigned long ack_at; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci if (!test_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags)) 30562306a36Sopenharmony_ci continue; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci ack_at = chan->final_ack_at; 30862306a36Sopenharmony_ci if (time_before(j, ack_at) && !force) { 30962306a36Sopenharmony_ci if (time_before(ack_at, next_j)) { 31062306a36Sopenharmony_ci next_j = ack_at; 31162306a36Sopenharmony_ci set = true; 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci continue; 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci if (test_and_clear_bit(RXRPC_CONN_FINAL_ACK_0 + channel, 31762306a36Sopenharmony_ci &conn->flags)) 31862306a36Sopenharmony_ci rxrpc_conn_retransmit_call(conn, NULL, channel); 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci j = jiffies; 32262306a36Sopenharmony_ci if (time_before_eq(next_j, j)) 32362306a36Sopenharmony_ci goto again; 32462306a36Sopenharmony_ci if (set) 32562306a36Sopenharmony_ci rxrpc_reduce_conn_timer(conn, next_j); 32662306a36Sopenharmony_ci} 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci/* 32962306a36Sopenharmony_ci * connection-level event processor 33062306a36Sopenharmony_ci */ 33162306a36Sopenharmony_cistatic void rxrpc_do_process_connection(struct rxrpc_connection *conn) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci struct sk_buff *skb; 33462306a36Sopenharmony_ci int ret; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci if (test_and_clear_bit(RXRPC_CONN_EV_CHALLENGE, &conn->events)) 33762306a36Sopenharmony_ci rxrpc_secure_connection(conn); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci /* go through the conn-level event packets, releasing the ref on this 34062306a36Sopenharmony_ci * connection that each one has when we've finished with it */ 34162306a36Sopenharmony_ci while ((skb = skb_dequeue(&conn->rx_queue))) { 34262306a36Sopenharmony_ci rxrpc_see_skb(skb, rxrpc_skb_see_conn_work); 34362306a36Sopenharmony_ci ret = rxrpc_process_event(conn, skb); 34462306a36Sopenharmony_ci switch (ret) { 34562306a36Sopenharmony_ci case -ENOMEM: 34662306a36Sopenharmony_ci case -EAGAIN: 34762306a36Sopenharmony_ci skb_queue_head(&conn->rx_queue, skb); 34862306a36Sopenharmony_ci rxrpc_queue_conn(conn, rxrpc_conn_queue_retry_work); 34962306a36Sopenharmony_ci break; 35062306a36Sopenharmony_ci default: 35162306a36Sopenharmony_ci rxrpc_free_skb(skb, rxrpc_skb_put_conn_work); 35262306a36Sopenharmony_ci break; 35362306a36Sopenharmony_ci } 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_civoid rxrpc_process_connection(struct work_struct *work) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci struct rxrpc_connection *conn = 36062306a36Sopenharmony_ci container_of(work, struct rxrpc_connection, processor); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci rxrpc_see_connection(conn, rxrpc_conn_see_work); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci if (__rxrpc_use_local(conn->local, rxrpc_local_use_conn_work)) { 36562306a36Sopenharmony_ci rxrpc_do_process_connection(conn); 36662306a36Sopenharmony_ci rxrpc_unuse_local(conn->local, rxrpc_local_unuse_conn_work); 36762306a36Sopenharmony_ci } 36862306a36Sopenharmony_ci} 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci/* 37162306a36Sopenharmony_ci * post connection-level events to the connection 37262306a36Sopenharmony_ci * - this includes challenges, responses, some aborts and call terminal packet 37362306a36Sopenharmony_ci * retransmission. 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_cistatic void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn, 37662306a36Sopenharmony_ci struct sk_buff *skb) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci _enter("%p,%p", conn, skb); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci rxrpc_get_skb(skb, rxrpc_skb_get_conn_work); 38162306a36Sopenharmony_ci skb_queue_tail(&conn->rx_queue, skb); 38262306a36Sopenharmony_ci rxrpc_queue_conn(conn, rxrpc_conn_queue_rx_work); 38362306a36Sopenharmony_ci} 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci/* 38662306a36Sopenharmony_ci * Input a connection-level packet. 38762306a36Sopenharmony_ci */ 38862306a36Sopenharmony_cibool rxrpc_input_conn_packet(struct rxrpc_connection *conn, struct sk_buff *skb) 38962306a36Sopenharmony_ci{ 39062306a36Sopenharmony_ci struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci switch (sp->hdr.type) { 39362306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_BUSY: 39462306a36Sopenharmony_ci /* Just ignore BUSY packets for now. */ 39562306a36Sopenharmony_ci return true; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_ABORT: 39862306a36Sopenharmony_ci if (rxrpc_is_conn_aborted(conn)) 39962306a36Sopenharmony_ci return true; 40062306a36Sopenharmony_ci rxrpc_input_conn_abort(conn, skb); 40162306a36Sopenharmony_ci rxrpc_abort_calls(conn); 40262306a36Sopenharmony_ci return true; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_CHALLENGE: 40562306a36Sopenharmony_ci case RXRPC_PACKET_TYPE_RESPONSE: 40662306a36Sopenharmony_ci if (rxrpc_is_conn_aborted(conn)) { 40762306a36Sopenharmony_ci if (conn->completion == RXRPC_CALL_LOCALLY_ABORTED) 40862306a36Sopenharmony_ci rxrpc_send_conn_abort(conn); 40962306a36Sopenharmony_ci return true; 41062306a36Sopenharmony_ci } 41162306a36Sopenharmony_ci rxrpc_post_packet_to_conn(conn, skb); 41262306a36Sopenharmony_ci return true; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci default: 41562306a36Sopenharmony_ci WARN_ON_ONCE(1); 41662306a36Sopenharmony_ci return true; 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci} 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci/* 42162306a36Sopenharmony_ci * Input a connection event. 42262306a36Sopenharmony_ci */ 42362306a36Sopenharmony_civoid rxrpc_input_conn_event(struct rxrpc_connection *conn, struct sk_buff *skb) 42462306a36Sopenharmony_ci{ 42562306a36Sopenharmony_ci unsigned int loop; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci if (test_and_clear_bit(RXRPC_CONN_EV_ABORT_CALLS, &conn->events)) 42862306a36Sopenharmony_ci rxrpc_abort_calls(conn); 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci switch (skb->mark) { 43162306a36Sopenharmony_ci case RXRPC_SKB_MARK_SERVICE_CONN_SECURED: 43262306a36Sopenharmony_ci if (conn->state != RXRPC_CONN_SERVICE) 43362306a36Sopenharmony_ci break; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci for (loop = 0; loop < RXRPC_MAXCALLS; loop++) 43662306a36Sopenharmony_ci rxrpc_call_is_secure(conn->channels[loop].call); 43762306a36Sopenharmony_ci break; 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci /* Process delayed ACKs whose time has come. */ 44162306a36Sopenharmony_ci if (conn->flags & RXRPC_CONN_FINAL_ACK_MASK) 44262306a36Sopenharmony_ci rxrpc_process_delayed_final_acks(conn, false); 44362306a36Sopenharmony_ci} 444