diff options
author | David S. Miller <davem@davemloft.net> | 2022-05-22 21:03:02 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2022-05-22 21:03:02 +0100 |
commit | baea40de321b35c7eefb6afbe34ac49caece76cf (patch) | |
tree | be291a9ee3bb46a3189a6da5e054521062b65b38 /net/rxrpc/input.c | |
parent | 0598cec957abbdd47b8eb7dceb51d54ac465417d (diff) | |
parent | adc9613ff66c26ebaff9814973181ac178beb90b (diff) |
Merge branch 'rxrpc-misc'
David Howells says:
====================
rxrpc: Miscellaneous changes
Here are some miscellaneous changes for AF_RXRPC:
(1) Allow the list of local endpoints to be viewed through /proc.
(2) Switch to using refcount_t for refcounting.
(3) Fix a locking issue found by lockdep.
(4) Autogenerate tracing symbol enums from symbol->string maps to make it
easier to keep them in sync.
(5) Return an error to sendmsg() if a call it tried to set up failed.
Because it failed at this point, no notification will be generated for
recvmsg to pick up - but userspace still needs to know about the
failure.
(6) Fix the selection of abort codes generated by internal events. In
particular, rxrpc and kafs shouldn't be generating RX_USER_ABORT
unless it's because userspace did something to cancel a call.
(7) Adjust the interpretation and handling of certain ACK types to try and
detect NAT changes causing a call to seem to start mid-flow from a
different peer.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/rxrpc/input.c')
-rw-r--r-- | net/rxrpc/input.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c index dc201363f2c4..16c0af41c202 100644 --- a/net/rxrpc/input.c +++ b/net/rxrpc/input.c @@ -903,6 +903,33 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) rxrpc_propose_ack_respond_to_ack); } + /* If we get an EXCEEDS_WINDOW ACK from the server, it probably + * indicates that the client address changed due to NAT. The server + * lost the call because it switched to a different peer. + */ + if (unlikely(buf.ack.reason == RXRPC_ACK_EXCEEDS_WINDOW) && + first_soft_ack == 1 && + prev_pkt == 0 && + rxrpc_is_client_call(call)) { + rxrpc_set_call_completion(call, RXRPC_CALL_REMOTELY_ABORTED, + 0, -ENETRESET); + return; + } + + /* If we get an OUT_OF_SEQUENCE ACK from the server, that can also + * indicate a change of address. However, we can retransmit the call + * if we still have it buffered to the beginning. + */ + if (unlikely(buf.ack.reason == RXRPC_ACK_OUT_OF_SEQUENCE) && + first_soft_ack == 1 && + prev_pkt == 0 && + call->tx_hard_ack == 0 && + rxrpc_is_client_call(call)) { + rxrpc_set_call_completion(call, RXRPC_CALL_REMOTELY_ABORTED, + 0, -ENETRESET); + return; + } + /* Discard any out-of-order or duplicate ACKs (outside lock). */ if (!rxrpc_is_ack_valid(call, first_soft_ack, prev_pkt)) { trace_rxrpc_rx_discard_ack(call->debug_id, ack_serial, @@ -1154,8 +1181,6 @@ static void rxrpc_post_packet_to_local(struct rxrpc_local *local, */ static void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb) { - CHECK_SLAB_OKAY(&local->usage); - if (rxrpc_get_local_maybe(local)) { skb_queue_tail(&local->reject_queue, skb); rxrpc_queue_local(local); @@ -1413,7 +1438,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb) } } - if (!call || atomic_read(&call->usage) == 0) { + if (!call || refcount_read(&call->ref) == 0) { if (rxrpc_to_client(sp) || sp->hdr.type != RXRPC_PACKET_TYPE_DATA) goto bad_message; |