From ee1cb469b2ddc4e9cb611413ff9e7c2c29e6a064 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Tue, 29 Dec 2020 09:42:58 -0800 Subject: 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 --- src/vnet/tcp/tcp_input.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src/vnet/tcp/tcp_input.c') 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]; -- cgit 1.2.3-korg