From: Florin Coras Date: Tue, 29 Dec 2020 17:42:58 +0000 (-0800) Subject: tcp: fix port reuse with multiple listeners X-Git-Tag: v21.10-rc0~590 X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F54%2F30554%2F8;p=vpp.git tcp: fix port reuse with multiple listeners The check in listen state that the listener is not valid is not enough if the time wait session's index overlaps an actual listener's index. Thanks wanghanlin@corp.netease.com for the report! Type: fix Signed-off-by: Florin Coras Change-Id: I3dff0cb134940a8265ff908faa607c67dba5e56b --- diff --git a/src/vnet/tcp/tcp_inlines.h b/src/vnet/tcp/tcp_inlines.h index 25bf7387c69..45762671da8 100644 --- a/src/vnet/tcp/tcp_inlines.h +++ b/src/vnet/tcp/tcp_inlines.h @@ -310,7 +310,6 @@ tcp_input_lookup_buffer (vlib_buffer_t * b, u8 thread_index, u32 * error, vnet_buffer (b)->tcp.data_len = n_data_bytes; vnet_buffer (b)->tcp.seq_end = vnet_buffer (b)->tcp.seq_number + n_data_bytes; - vnet_buffer (b)->tcp.flags = 0; *error = result ? TCP_ERROR_NONE + result : *error; diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c index a159d850728..f5d17eabc36 100644 --- a/src/vnet/tcp/tcp_input.c +++ b/src/vnet/tcp/tcp_input.c @@ -2561,14 +2561,19 @@ tcp46_listen_inline (vlib_main_t * vm, vlib_node_runtime_t * node, b = vlib_get_buffer (vm, bi); - lc = tcp_listener_get (vnet_buffer (b)->tcp.connection_index); - if (PREDICT_FALSE (lc == 0)) + /* Flags initialized with connection state after lookup */ + if (vnet_buffer (b)->tcp.flags == TCP_STATE_LISTEN) + { + lc = tcp_listener_get (vnet_buffer (b)->tcp.connection_index); + } + else { tcp_connection_t *tc; tc = tcp_connection_get (vnet_buffer (b)->tcp.connection_index, thread_index); if (tc->state != TCP_STATE_TIME_WAIT) { + lc = 0; error = TCP_ERROR_CREATE_EXISTS; goto done; } @@ -2802,6 +2807,10 @@ tcp_input_dispatch_buffer (tcp_main_t * tm, tcp_connection_t * tc, error = tm->dispatch_table[tc->state][flags].error; tc->segs_in += 1; + /* Track connection state when packet was received. It helps + * @ref tcp46_listen_inline detect port reuse */ + vnet_buffer (b)->tcp.flags = tc->state; + if (PREDICT_FALSE (error != TCP_ERROR_NONE)) { b->error = error_node->errors[error];