tcp: fix handling of retransmitted syns 28/17628/4
authorFlorin Coras <fcoras@cisco.com>
Sat, 16 Feb 2019 02:20:58 +0000 (18:20 -0800)
committerDamjan Marion <dmarion@me.com>
Mon, 18 Feb 2019 07:03:06 +0000 (07:03 +0000)
Change-Id: I88fdeb0ca56d3a5d9c0f36def13c6de8142f59f0
Signed-off-by: Florin Coras <fcoras@cisco.com>
src/vnet/tcp/tcp_error.def
src/vnet/tcp/tcp_input.c

index 0d6c44b..7bed10f 100644 (file)
@@ -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")
index da03cab..6514dca 100644 (file)
@@ -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;
     }