summaryrefslogtreecommitdiffstats
path: root/src/vnet/tcp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/tcp')
-rw-r--r--src/vnet/tcp/tcp_input.c38
-rw-r--r--src/vnet/tcp/tcp_output.c74
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);
}