summaryrefslogtreecommitdiffstats
path: root/src/vnet
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
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')
-rw-r--r--src/vnet/tcp/tcp_inlines.h1
-rw-r--r--src/vnet/tcp/tcp_input.c13
2 files changed, 11 insertions, 3 deletions
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];