diff options
-rw-r--r-- | src/vnet/tcp/tcp_input.c | 38 | ||||
-rw-r--r-- | src/vnet/tcp/tcp_output.c | 74 |
2 files changed, 53 insertions, 59 deletions
diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c index ceb00fc3e41..82e676d4654 100644 --- a/src/vnet/tcp/tcp_input.c +++ b/src/vnet/tcp/tcp_input.c @@ -2106,16 +2106,16 @@ tcp46_listen_inline (vlib_main_t * vm, vlib_node_runtime_t * node, /* Create child session. For syn-flood protection use filter */ - /* 1. first check for an RST */ - if (tcp_rst (th0)) - goto drop; + /* 1. first check for an RST: handled in dispatch */ + /* if (tcp_rst (th0)) + goto drop; */ - /* 2. second check for an ACK */ - if (tcp_ack (th0)) - { - tcp_send_reset (b0, is_ip4); - goto drop; - } + /* 2. second check for an ACK: handled in dispatch */ + /* if (tcp_ack (th0)) + { + tcp_send_reset (b0, is_ip4); + goto drop; + } */ /* 3. check for a SYN (did that already) */ @@ -2401,14 +2401,17 @@ tcp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, next0 = tm->dispatch_table[tc0->state][flags0].next; error0 = tm->dispatch_table[tc0->state][flags0].error; - if (PREDICT_FALSE (error0 == TCP_ERROR_DISPATCH)) + if (PREDICT_FALSE (error0 == TCP_ERROR_DISPATCH + || next0 == TCP_INPUT_NEXT_RESET)) { - tcp_state_t state0 = tc0->state; /* Overload tcp flags to store state */ + tcp_state_t state0 = tc0->state; vnet_buffer (b0)->tcp.flags = tc0->state; - clib_warning ("disp error state %U flags %U", - format_tcp_state, &state0, - format_tcp_flags, (int) flags0); + + if (error0 == TCP_ERROR_DISPATCH) + clib_warning ("disp error state %U flags %U", + format_tcp_state, &state0, format_tcp_flags, + (int) flags0); } } else @@ -2517,6 +2520,8 @@ do { \ /* SYNs for new connections -> tcp-listen. */ _(LISTEN, TCP_FLAG_SYN, TCP_INPUT_NEXT_LISTEN, TCP_ERROR_NONE); + _(LISTEN, TCP_FLAG_ACK, TCP_INPUT_NEXT_RESET, TCP_ERROR_NONE); + _(LISTEN, TCP_FLAG_RST, TCP_INPUT_NEXT_DROP, TCP_ERROR_NONE); /* ACK for for a SYN-ACK -> tcp-rcv-process. */ _(SYN_RCVD, TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE); _(SYN_RCVD, TCP_FLAG_RST, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE); @@ -2534,6 +2539,8 @@ do { \ _(ESTABLISHED, TCP_FLAG_FIN | TCP_FLAG_ACK, TCP_INPUT_NEXT_ESTABLISHED, TCP_ERROR_NONE); _(ESTABLISHED, TCP_FLAG_RST, TCP_INPUT_NEXT_ESTABLISHED, TCP_ERROR_NONE); + _(ESTABLISHED, TCP_FLAG_RST | TCP_FLAG_ACK, TCP_INPUT_NEXT_ESTABLISHED, + TCP_ERROR_NONE); /* ACK or FIN-ACK to our FIN */ _(FIN_WAIT_1, TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE); _(FIN_WAIT_1, TCP_FLAG_ACK | TCP_FLAG_FIN, TCP_INPUT_NEXT_RCV_PROCESS, @@ -2546,7 +2553,8 @@ do { \ _(FIN_WAIT_2, TCP_FLAG_FIN | TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE); _(LAST_ACK, TCP_FLAG_ACK, TCP_INPUT_NEXT_RCV_PROCESS, TCP_ERROR_NONE); - _(CLOSED, TCP_FLAG_ACK, TCP_INPUT_NEXT_DROP, TCP_ERROR_CONNECTION_CLOSED); + _(CLOSED, TCP_FLAG_ACK, TCP_INPUT_NEXT_RESET, TCP_ERROR_CONNECTION_CLOSED); + _(CLOSED, TCP_FLAG_RST, TCP_INPUT_NEXT_DROP, TCP_ERROR_CONNECTION_CLOSED); #undef _ } diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c index 33e599ece32..39891fc3fde 100644 --- a/src/vnet/tcp/tcp_output.c +++ b/src/vnet/tcp/tcp_output.c @@ -597,54 +597,41 @@ tcp_enqueue_to_ip_lookup (vlib_main_t * vm, vlib_buffer_t * b, u32 bi, int tcp_make_reset_in_place (vlib_main_t * vm, vlib_buffer_t * b0, - tcp_state_t state, u32 my_thread_index, u8 is_ip4) + tcp_state_t state, u8 thread_index, u8 is_ip4) { - u8 tcp_hdr_len = sizeof (tcp_header_t); ip4_header_t *ih4; ip6_header_t *ih6; tcp_header_t *th0; - ip4_address_t src_ip40; - ip6_address_t src_ip60; - u16 src_port0; + ip4_address_t src_ip40, dst_ip40; + ip6_address_t src_ip60, dst_ip60; + u16 src_port, dst_port; u32 tmp; + u32 seq, ack; + u8 flags; /* Find IP and TCP headers */ - if (is_ip4) - { - ih4 = vlib_buffer_get_current (b0); - th0 = ip4_next_header (ih4); - } - else - { - ih6 = vlib_buffer_get_current (b0); - th0 = ip6_next_header (ih6); - } + th0 = tcp_buffer_hdr (b0); - /* Swap src and dst ip */ + /* Save src and dst ip */ if (is_ip4) { + ih4 = vlib_buffer_get_current (b0); ASSERT ((ih4->ip_version_and_header_length & 0xF0) == 0x40); src_ip40.as_u32 = ih4->src_address.as_u32; - ih4->src_address.as_u32 = ih4->dst_address.as_u32; - ih4->dst_address.as_u32 = src_ip40.as_u32; - - /* Chop the end of the pkt */ - b0->current_length += ip4_header_bytes (ih4) + tcp_hdr_len; + dst_ip40.as_u32 = ih4->dst_address.as_u32; } else { + ih6 = vlib_buffer_get_current (b0); ASSERT ((ih6->ip_version_traffic_class_and_flow_label & 0xF0) == 0x60); clib_memcpy (&src_ip60, &ih6->src_address, sizeof (ip6_address_t)); - clib_memcpy (&ih6->src_address, &ih6->dst_address, - sizeof (ip6_address_t)); - clib_memcpy (&ih6->dst_address, &src_ip60, sizeof (ip6_address_t)); - - /* Chop the end of the pkt */ - b0->current_length += sizeof (ip6_header_t) + tcp_hdr_len; + clib_memcpy (&dst_ip60, &ih6->dst_address, sizeof (ip6_address_t)); } - /* Try to determine what/why we're actually resetting and swap - * src and dst ports */ + src_port = th0->src_port; + dst_port = th0->dst_port; + + /* Try to determine what/why we're actually resetting */ if (state == TCP_STATE_CLOSED) { if (!tcp_syn (th0)) @@ -653,33 +640,32 @@ tcp_make_reset_in_place (vlib_main_t * vm, vlib_buffer_t * b0, tmp = clib_net_to_host_u32 (th0->seq_number); /* Got a SYN for no listener. */ - th0->flags = TCP_FLAG_RST | TCP_FLAG_ACK; - th0->ack_number = clib_host_to_net_u32 (tmp + 1); - th0->seq_number = 0; - + flags = TCP_FLAG_RST | TCP_FLAG_ACK; + ack = clib_host_to_net_u32 (tmp + 1); + seq = 0; } - else if (state >= TCP_STATE_SYN_SENT) + else { - th0->flags = TCP_FLAG_RST | TCP_FLAG_ACK; - th0->seq_number = th0->ack_number; - th0->ack_number = 0; + flags = TCP_FLAG_RST; + seq = th0->ack_number; + ack = 0; } - src_port0 = th0->src_port; - th0->src_port = th0->dst_port; - th0->dst_port = src_port0; - th0->window = 0; - th0->data_offset_and_reserved = (tcp_hdr_len >> 2) << 4; - th0->urgent_pointer = 0; + tcp_reuse_buffer (vm, b0); + th0 = vlib_buffer_push_tcp_net_order (b0, dst_port, src_port, seq, ack, + sizeof (tcp_header_t), flags, 0); - /* Compute checksum */ if (is_ip4) { + ih4 = vlib_buffer_push_ip4 (vm, b0, &dst_ip40, &src_ip40, + IP_PROTOCOL_TCP); th0->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ih4); } else { int bogus = ~0; + ih6 = vlib_buffer_push_ip6 (vm, b0, &dst_ip60, &src_ip60, + IP_PROTOCOL_TCP); th0->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ih6, &bogus); ASSERT (!bogus); } |