tcp: cleanup connections if handshake fails
[vpp.git] / src / vnet / tcp / tcp_input.c
index 3959437..91876fe 100644 (file)
@@ -316,18 +316,18 @@ tcp_segment_validate (tcp_worker_ctx_t * wrk, tcp_connection_t * tc0,
                        tcp_time_now_w_thread (tc0->c_thread_index)))
        {
          tc0->tsval_recent = tc0->rcv_opts.tsval;
-         clib_warning ("paws failed - really old segment. REALLY?");
+         clib_warning ("paws failed: 24-day old segment");
        }
-      else
+      /* Drop after ack if not rst. Resets can fail paws check as per
+       * RFC 7323 sec. 5.2: When an <RST> segment is received, it MUST NOT
+       * be subjected to the PAWS check by verifying an acceptable value in
+       * SEG.TSval */
+      else if (!tcp_rst (th0))
        {
-         /* Drop after ack if not rst */
-         if (!tcp_rst (th0))
-           {
-             tcp_program_ack (wrk, tc0);
-             TCP_EVT_DBG (TCP_EVT_DUPACK_SENT, tc0, vnet_buffer (b0)->tcp);
-           }
+         tcp_program_ack (wrk, tc0);
+         TCP_EVT_DBG (TCP_EVT_DUPACK_SENT, tc0, vnet_buffer (b0)->tcp);
+         goto error;
        }
-      goto error;
     }
 
   /* 1st: check sequence number */
@@ -2480,6 +2480,8 @@ tcp46_syn_sent_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
 
       if (tcp_opts_wscale (&new_tc0->rcv_opts))
        new_tc0->snd_wscale = new_tc0->rcv_opts.wscale;
+      else
+       new_tc0->rcv_wscale = 0;
 
       new_tc0->snd_wnd = clib_net_to_host_u16 (tcp0->window)
        << new_tc0->snd_wscale;
@@ -2718,17 +2720,16 @@ tcp46_rcv_process_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
           */
          if (!tcp_rcv_ack_is_acceptable (tc0, b0))
            {
-             TCP_DBG ("connection not accepted");
-             tcp_send_reset_w_pkt (tc0, b0, is_ip4);
+             tcp_connection_reset (tc0);
              error0 = TCP_ERROR_ACK_INVALID;
              goto drop;
            }
 
          /* Make sure the ack is exactly right */
-         if (tc0->rcv_nxt != vnet_buffer (b0)->tcp.seq_number)
+         if (tc0->rcv_nxt != vnet_buffer (b0)->tcp.seq_number || is_fin0)
            {
+             tcp_connection_reset (tc0);
              error0 = TCP_ERROR_SEGMENT_INVALID;
-             tcp_send_reset_w_pkt (tc0, b0, is_ip4);
              goto drop;
            }
 
@@ -3095,7 +3096,7 @@ tcp46_listen_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
        }
 
       /* Create child session and send SYN-ACK */
-      child0 = tcp_connection_new (my_thread_index);
+      child0 = tcp_connection_alloc (my_thread_index);
       child0->c_lcl_port = th0->dst_port;
       child0->c_rmt_port = th0->src_port;
       child0->c_is_ip4 = is_ip4;
@@ -3117,7 +3118,8 @@ tcp46_listen_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
 
       if (tcp_options_parse (th0, &child0->rcv_opts, 1))
        {
-         clib_warning ("options parse fail");
+         error0 = TCP_ERROR_OPTIONS;
+         tcp_connection_free (child0);
          goto drop;
        }