diff options
author | Florin Coras <fcoras@cisco.com> | 2020-12-29 09:42:58 -0800 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2021-02-05 20:50:11 +0000 |
commit | ee1cb469b2ddc4e9cb611413ff9e7c2c29e6a064 (patch) | |
tree | 62f59e64edc5f1d500f5961194dffe195318b50d /src/vnet/tcp/tcp_input.c | |
parent | ffc6bdcd38b8209050671d3d86f943c37887a7b7 (diff) |
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 <fcoras@cisco.com>
Change-Id: I3dff0cb134940a8265ff908faa607c67dba5e56b
Diffstat (limited to 'src/vnet/tcp/tcp_input.c')
-rw-r--r-- | src/vnet/tcp/tcp_input.c | 13 |
1 files changed, 11 insertions, 2 deletions
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]; |