Commit 3c3c3248 authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso
Browse files

selftests: netfilter: nft_nat.sh: add test for reverse clash with nat

This will fail without the previous bug fix because we erronously
believe that the clashing entry went way.

However, the clash exists in the opposite direction due to an
existing nat mapping:
 PASS: IP statless for ns2-LgTIuS
 ERROR: failed to test udp ns1-x4iyOW to ns2-LgTIuS with dnat rule step 2, result: ""

This is partially adapted from test instructions from the below
ubuntu tracker.

Link: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2109889


Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Tested-by: default avatarShaun Brady <brady.1345@gmail.com>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 50d9ce96
Loading
Loading
Loading
Loading
+76 −5
Original line number Diff line number Diff line
@@ -866,6 +866,24 @@ EOF
	ip netns exec "$ns0" nft delete table $family nat
}

file_cmp()
{
	local infile="$1"
	local outfile="$2"

	if ! cmp "$infile" "$outfile";then
		echo -n "Infile "
		ls -l "$infile"
		echo -n "Outfile "
		ls -l "$outfile"
		echo "ERROR: in and output file mismatch when checking $msg" 1>&1
		ret=1
		return 1
	fi

	return 0
}

test_stateless_nat_ip()
{
	local lret=0
@@ -966,11 +984,7 @@ EOF

	wait

	if ! cmp "$INFILE" "$OUTFILE";then
		ls -l "$INFILE" "$OUTFILE"
		echo "ERROR: in and output file mismatch when checking udp with stateless nat" 1>&2
		lret=1
	fi
	file_cmp "$INFILE" "$OUTFILE" "udp with stateless nat" || lret=1

	:> "$OUTFILE"

@@ -991,6 +1005,62 @@ EOF
	return $lret
}

test_dnat_clash()
{
	local lret=0

	if ! socat -h > /dev/null 2>&1;then
		echo "SKIP: Could not run dnat clash test without socat tool"
		[ $ret -eq 0 ] && ret=$ksft_skip
		return $ksft_skip
	fi

ip netns exec "$ns0" nft -f /dev/stdin <<EOF
flush ruleset
table ip dnat-test {
 chain prerouting {
  type nat hook prerouting priority dstnat; policy accept;
  ip daddr 10.0.2.1 udp dport 1234 counter dnat to 10.0.1.1:1234
 }
}
EOF
	if [ $? -ne 0 ]; then
		echo "SKIP: Could not add dnat rules"
		[ $ret -eq 0 ] && ret=$ksft_skip
		return $ksft_skip
	fi

	local udpdaddr="10.0.2.1"
	for i in 1 2;do
		echo "PING $udpdaddr" > "$INFILE"
		echo "PONG 10.0.1.1 step $i" | ip netns exec "$ns0" timeout 3 socat STDIO UDP4-LISTEN:1234,bind=10.0.1.1 > "$OUTFILE" 2>/dev/null &
		local lpid=$!

		busywait $BUSYWAIT_TIMEOUT listener_ready "$ns0" 1234 "-u"

		result=$(ip netns exec "$ns1" timeout 3 socat STDIO UDP4-SENDTO:"$udpdaddr:1234,sourceport=4321" < "$INFILE")
		udpdaddr="10.0.1.1"

		if [ "$result" != "PONG 10.0.1.1 step $i" ] ; then
			echo "ERROR: failed to test udp $ns1 to $ns2 with dnat rule step $i, result: \"$result\"" 1>&2
			lret=1
			ret=1
		fi

		wait

		file_cmp "$INFILE" "$OUTFILE" "udp dnat step $i" || lret=1

		:> "$OUTFILE"
	done

	test $lret -eq 0 && echo "PASS: IP dnat clash $ns1:$ns2"

	ip netns exec "$ns0" nft flush ruleset

	return $lret
}

# ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99
for i in "$ns0" "$ns1" "$ns2" ;do
ip netns exec "$i" nft -f /dev/stdin <<EOF
@@ -1147,6 +1217,7 @@ $test_inet_nat && test_redirect6 inet

test_port_shadowing
test_stateless_nat_ip
test_dnat_clash

if [ $ret -ne 0 ];then
	echo -n "FAIL: "