aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/nat/nat44_hairpinning.c
diff options
context:
space:
mode:
authorElias Rudberg <elias.rudberg@bahnhof.net>2020-12-04 19:32:55 +0100
committerOle Tr�an <otroan@employees.org>2020-12-08 08:49:24 +0000
commit9b8cb5082471dd670066b8ba2872ffbcc35a87f8 (patch)
tree7345bf7e7c5c86cfe7f87ff45bb4c94c42ceacc6 /src/plugins/nat/nat44_hairpinning.c
parent3227e49689974e2dd3aea4d85debdf159d532b42 (diff)
nat: avoid hairpinning infinite loop problem
Fix in nat44 hairpinning code to check if anything was actually changed in the snat_hairpinning() routine, and return 0 if nothing changed. This helps avoid an infinite loop repeating the three nodes nat44-hairpinning-->ip4-lookup-->ip4-local in case there was no change. Also add a corresponding test case. Type: fix Signed-off-by: Elias Rudberg <elias.rudberg@bahnhof.net> Change-Id: I95f48476bd002ac4c6789afe504681f1963e5d38 Signed-off-by: Elias Rudberg <elias.rudberg@bahnhof.net>
Diffstat (limited to 'src/plugins/nat/nat44_hairpinning.c')
-rw-r--r--src/plugins/nat/nat44_hairpinning.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/src/plugins/nat/nat44_hairpinning.c b/src/plugins/nat/nat44_hairpinning.c
index 9eadcf30832..2859046ae05 100644
--- a/src/plugins/nat/nat44_hairpinning.c
+++ b/src/plugins/nat/nat44_hairpinning.c
@@ -108,6 +108,7 @@ snat_hairpinning (vlib_main_t * vm, vlib_node_runtime_t * node,
ip4_address_t sm0_addr;
u16 sm0_port;
u32 sm0_fib_index;
+ u32 old_sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
/* Check if destination is static mappings */
if (!snat_static_mapping_match
(sm, ip0->dst_address, udp0->dst_port, sm->outside_fib_index, proto0,
@@ -159,6 +160,17 @@ snat_hairpinning (vlib_main_t * vm, vlib_node_runtime_t * node,
vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
}
+ /* Check if anything has changed and if not, then return 0. This
+ helps avoid infinite loop, repeating the three nodes
+ nat44-hairpinning-->ip4-lookup-->ip4-local, in case nothing has
+ changed. */
+ old_dst_addr0 = ip0->dst_address.as_u32;
+ old_dst_port0 = tcp0->dst;
+ if (new_dst_addr0 == old_dst_addr0
+ && new_dst_port0 == old_dst_port0
+ && vnet_buffer (b0)->sw_if_index[VLIB_TX] == old_sw_if_index)
+ return 0;
+
/* Destination is behind the same NAT, use internal address and port */
if (new_dst_addr0)
{