aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/tcp/tcp_input.c
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2020-12-29 09:42:58 -0800
committerDave Barach <openvpp@barachs.net>2021-02-05 20:50:11 +0000
commitee1cb469b2ddc4e9cb611413ff9e7c2c29e6a064 (patch)
tree62f59e64edc5f1d500f5961194dffe195318b50d /src/vnet/tcp/tcp_input.c
parentffc6bdcd38b8209050671d3d86f943c37887a7b7 (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.c13
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];