diff options
-rw-r--r-- | src/vnet/tcp/tcp_error.def | 3 | ||||
-rw-r--r-- | src/vnet/tcp/tcp_input.c | 39 |
2 files changed, 26 insertions, 16 deletions
diff --git a/src/vnet/tcp/tcp_error.def b/src/vnet/tcp/tcp_error.def index 0d6c44b5402..7bed10f1840 100644 --- a/src/vnet/tcp/tcp_error.def +++ b/src/vnet/tcp/tcp_error.def @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Cisco and/or its affiliates. + * Copyright (c) 2016-2019 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -26,6 +26,7 @@ tcp_error (PARTIALLY_ENQUEUED, "Packets partially pushed into rx fifo") tcp_error (SEGMENT_OLD, "Old segment") tcp_error (SEGMENT_INVALID, "Invalid segments") tcp_error (SYNS_RCVD, "SYNs received") +tcp_error (SPURIOUS_SYN, "Spurious SYNs received") tcp_error (SYN_ACKS_RCVD, "SYN-ACKs received") tcp_error (MSG_QUEUE_FULL, "Events not sent for lack of msg queue space") tcp_error (CREATE_SESSION_FAIL, "Sessions couldn't be allocated") diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c index da03cababb7..6514dca4b4a 100644 --- a/src/vnet/tcp/tcp_input.c +++ b/src/vnet/tcp/tcp_input.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Cisco and/or its affiliates. + * Copyright (c) 2016-2019 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -330,6 +330,26 @@ tcp_segment_validate (tcp_worker_ctx_t * wrk, tcp_connection_t * tc0, if (!tcp_segment_in_rcv_wnd (tc0, vnet_buffer (b0)->tcp.seq_number, vnet_buffer (b0)->tcp.seq_end)) { + /* SYN/SYN-ACK retransmit */ + if (tcp_syn (th0) + && vnet_buffer (b0)->tcp.seq_number == tc0->rcv_nxt - 1) + { + tcp_options_parse (th0, &tc0->rcv_opts, 1); + if (tc0->state == TCP_STATE_SYN_RCVD) + { + tcp_send_synack (tc0); + TCP_EVT_DBG (TCP_EVT_SYN_RCVD, tc0, 0); + *error0 = TCP_ERROR_SYNS_RCVD; + } + else + { + tcp_program_ack (wrk, tc0); + TCP_EVT_DBG (TCP_EVT_SYNACK_RCVD, tc0); + *error0 = TCP_ERROR_SYN_ACKS_RCVD; + } + goto error; + } + *error0 = TCP_ERROR_RCV_WND; /* If our window is 0 and the packet is in sequence, let it pass * through for ack processing. It should be dropped later. */ @@ -356,22 +376,11 @@ tcp_segment_validate (tcp_worker_ctx_t * wrk, tcp_connection_t * tc0, /* 3rd: check security and precedence (skip) */ - /* 4th: check the SYN bit */ + /* 4th: check the SYN bit (in window) */ if (PREDICT_FALSE (tcp_syn (th0))) { - *error0 = tcp_ack (th0) ? TCP_ERROR_SYN_ACKS_RCVD : TCP_ERROR_SYNS_RCVD; - /* TODO implement RFC 5961 */ - if (tc0->state == TCP_STATE_SYN_RCVD) - { - tcp_options_parse (th0, &tc0->rcv_opts, 1); - tcp_send_synack (tc0); - TCP_EVT_DBG (TCP_EVT_SYN_RCVD, tc0, 0); - } - else - { - tcp_program_ack (wrk, tc0); - TCP_EVT_DBG (TCP_EVT_SYNACK_RCVD, tc0); - } + *error0 = TCP_ERROR_SPURIOUS_SYN; + tcp_send_reset (tc0); goto error; } |