summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vnet/tcp/tcp_error.def3
-rw-r--r--src/vnet/tcp/tcp_input.c39
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;
}