@@ -899,6 +899,144 @@ EOF
899899 ip netns exec " $ns0 " nft delete table $family nat
900900}
901901
902+ test_stateless_nat_ip ()
903+ {
904+ local lret=0
905+
906+ ip netns exec " $ns0 " sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
907+ ip netns exec " $ns0 " sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
908+
909+ ip netns exec " $ns2 " ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
910+ if [ $? -ne 0 ] ; then
911+ echo " ERROR: cannot ping $ns1 from $ns2 before loading stateless rules"
912+ return 1
913+ fi
914+
915+ ip netns exec " $ns0 " nft -f /dev/stdin << EOF
916+ table ip stateless {
917+ map xlate_in {
918+ typeof meta iifname . ip saddr . ip daddr : ip daddr
919+ elements = {
920+ "veth1" . 10.0.2.99 . 10.0.1.99 : 10.0.2.2,
921+ }
922+ }
923+ map xlate_out {
924+ typeof meta iifname . ip saddr . ip daddr : ip daddr
925+ elements = {
926+ "veth0" . 10.0.1.99 . 10.0.2.2 : 10.0.2.99
927+ }
928+ }
929+
930+ chain prerouting {
931+ type filter hook prerouting priority -400; policy accept;
932+ ip saddr set meta iifname . ip saddr . ip daddr map @xlate_in
933+ ip daddr set meta iifname . ip saddr . ip daddr map @xlate_out
934+ }
935+ }
936+ EOF
937+ if [ $? -ne 0 ]; then
938+ echo " SKIP: Could not add ip statless rules"
939+ return $ksft_skip
940+ fi
941+
942+ reset_counters
943+
944+ ip netns exec " $ns2 " ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
945+ if [ $? -ne 0 ] ; then
946+ echo " ERROR: cannot ping $ns1 from $ns2 with stateless rules"
947+ lret=1
948+ fi
949+
950+ # ns1 should have seen packets from .2.2, due to stateless rewrite.
951+ expect=" packets 1 bytes 84"
952+ cnt=$( ip netns exec " $ns1 " nft list counter inet filter ns0insl | grep -q " $expect " )
953+ if [ $? -ne 0 ]; then
954+ bad_counter " $ns1 " ns0insl " $expect " " test_stateless 1"
955+ lret=1
956+ fi
957+
958+ for dir in " in" " out" ; do
959+ cnt=$( ip netns exec " $ns2 " nft list counter inet filter ns1${dir} | grep -q " $expect " )
960+ if [ $? -ne 0 ]; then
961+ bad_counter " $ns2 " ns1$dir " $expect " " test_stateless 2"
962+ lret=1
963+ fi
964+ done
965+
966+ # ns1 should not have seen packets from ns2, due to masquerade
967+ expect=" packets 0 bytes 0"
968+ for dir in " in" " out" ; do
969+ cnt=$( ip netns exec " $ns1 " nft list counter inet filter ns2${dir} | grep -q " $expect " )
970+ if [ $? -ne 0 ]; then
971+ bad_counter " $ns1 " ns0$dir " $expect " " test_stateless 3"
972+ lret=1
973+ fi
974+
975+ cnt=$( ip netns exec " $ns0 " nft list counter inet filter ns1${dir} | grep -q " $expect " )
976+ if [ $? -ne 0 ]; then
977+ bad_counter " $ns0 " ns1$dir " $expect " " test_stateless 4"
978+ lret=1
979+ fi
980+ done
981+
982+ reset_counters
983+
984+ socat -h > /dev/null 2>&1
985+ if [ $? -ne 0 ]; then
986+ echo " SKIP: Could not run stateless nat frag test without socat tool"
987+ if [ $lret -eq 0 ]; then
988+ return $ksft_skip
989+ fi
990+
991+ ip netns exec " $ns0 " nft delete table ip stateless
992+ return $lret
993+ fi
994+
995+ local tmpfile=$( mktemp)
996+ dd if=/dev/urandom of=$tmpfile bs=4096 count=1 2> /dev/null
997+
998+ local outfile=$( mktemp)
999+ ip netns exec " $ns1 " timeout 3 socat -u UDP4-RECV:4233 OPEN:$outfile < /dev/null &
1000+ sc_r=$!
1001+
1002+ sleep 1
1003+ # re-do with large ping -> ip fragmentation
1004+ ip netns exec " $ns2 " timeout 3 socat - UDP4-SENDTO:" 10.0.1.99:4233" < " $tmpfile " > /dev/null
1005+ if [ $? -ne 0 ] ; then
1006+ echo " ERROR: failed to test udp $ns1 to $ns2 with stateless ip nat" 1>&2
1007+ lret=1
1008+ fi
1009+
1010+ wait
1011+
1012+ cmp " $tmpfile " " $outfile "
1013+ if [ $? -ne 0 ]; then
1014+ ls -l " $tmpfile " " $outfile "
1015+ echo " ERROR: in and output file mismatch when checking udp with stateless nat" 1>&2
1016+ lret=1
1017+ fi
1018+
1019+ rm -f " $tmpfile " " $outfile "
1020+
1021+ # ns1 should have seen packets from 2.2, due to stateless rewrite.
1022+ expect=" packets 3 bytes 4164"
1023+ cnt=$( ip netns exec " $ns1 " nft list counter inet filter ns0insl | grep -q " $expect " )
1024+ if [ $? -ne 0 ]; then
1025+ bad_counter " $ns1 " ns0insl " $expect " " test_stateless 5"
1026+ lret=1
1027+ fi
1028+
1029+ ip netns exec " $ns0 " nft delete table ip stateless
1030+ if [ $? -ne 0 ]; then
1031+ echo " ERROR: Could not delete table ip stateless" 1>&2
1032+ lret=1
1033+ fi
1034+
1035+ test $lret -eq 0 && echo " PASS: IP statless for $ns2 "
1036+
1037+ return $lret
1038+ }
1039+
9021040# ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99
9031041for i in 0 1 2; do
9041042ip netns exec ns$i -$sfx nft -f /dev/stdin << EOF
@@ -965,6 +1103,19 @@ table inet filter {
9651103EOF
9661104done
9671105
1106+ # special case for stateless nat check, counter needs to
1107+ # be done before (input) ip defragmentation
1108+ ip netns exec ns1-$sfx nft -f /dev/stdin << EOF
1109+ table inet filter {
1110+ counter ns0insl {}
1111+
1112+ chain pre {
1113+ type filter hook prerouting priority -400; policy accept;
1114+ ip saddr 10.0.2.2 counter name "ns0insl"
1115+ }
1116+ }
1117+ EOF
1118+
9681119sleep 3
9691120# test basic connectivity
9701121for i in 1 2; do
@@ -1019,6 +1170,7 @@ $test_inet_nat && test_redirect inet
10191170$test_inet_nat && test_redirect6 inet
10201171
10211172test_port_shadowing
1173+ test_stateless_nat_ip
10221174
10231175if [ $ret -ne 0 ]; then
10241176 echo -n " FAIL: "
0 commit comments