@@ -885,6 +885,144 @@ EOF
885885 ip netns exec " $ns0 " nft delete table $family nat
886886}
887887
888+ test_stateless_nat_ip ()
889+ {
890+ local lret=0
891+
892+ ip netns exec " $ns0 " sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
893+ ip netns exec " $ns0 " sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
894+
895+ ip netns exec " $ns2 " ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
896+ if [ $? -ne 0 ] ; then
897+ echo " ERROR: cannot ping $ns1 from $ns2 before loading stateless rules"
898+ return 1
899+ fi
900+
901+ ip netns exec " $ns0 " nft -f /dev/stdin << EOF
902+ table ip stateless {
903+ map xlate_in {
904+ typeof meta iifname . ip saddr . ip daddr : ip daddr
905+ elements = {
906+ "veth1" . 10.0.2.99 . 10.0.1.99 : 10.0.2.2,
907+ }
908+ }
909+ map xlate_out {
910+ typeof meta iifname . ip saddr . ip daddr : ip daddr
911+ elements = {
912+ "veth0" . 10.0.1.99 . 10.0.2.2 : 10.0.2.99
913+ }
914+ }
915+
916+ chain prerouting {
917+ type filter hook prerouting priority -400; policy accept;
918+ ip saddr set meta iifname . ip saddr . ip daddr map @xlate_in
919+ ip daddr set meta iifname . ip saddr . ip daddr map @xlate_out
920+ }
921+ }
922+ EOF
923+ if [ $? -ne 0 ]; then
924+ echo " SKIP: Could not add ip statless rules"
925+ return $ksft_skip
926+ fi
927+
928+ reset_counters
929+
930+ ip netns exec " $ns2 " ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
931+ if [ $? -ne 0 ] ; then
932+ echo " ERROR: cannot ping $ns1 from $ns2 with stateless rules"
933+ lret=1
934+ fi
935+
936+ # ns1 should have seen packets from .2.2, due to stateless rewrite.
937+ expect=" packets 1 bytes 84"
938+ cnt=$( ip netns exec " $ns1 " nft list counter inet filter ns0insl | grep -q " $expect " )
939+ if [ $? -ne 0 ]; then
940+ bad_counter " $ns1 " ns0insl " $expect " " test_stateless 1"
941+ lret=1
942+ fi
943+
944+ for dir in " in" " out" ; do
945+ cnt=$( ip netns exec " $ns2 " nft list counter inet filter ns1${dir} | grep -q " $expect " )
946+ if [ $? -ne 0 ]; then
947+ bad_counter " $ns2 " ns1$dir " $expect " " test_stateless 2"
948+ lret=1
949+ fi
950+ done
951+
952+ # ns1 should not have seen packets from ns2, due to masquerade
953+ expect=" packets 0 bytes 0"
954+ for dir in " in" " out" ; do
955+ cnt=$( ip netns exec " $ns1 " nft list counter inet filter ns2${dir} | grep -q " $expect " )
956+ if [ $? -ne 0 ]; then
957+ bad_counter " $ns1 " ns0$dir " $expect " " test_stateless 3"
958+ lret=1
959+ fi
960+
961+ cnt=$( ip netns exec " $ns0 " nft list counter inet filter ns1${dir} | grep -q " $expect " )
962+ if [ $? -ne 0 ]; then
963+ bad_counter " $ns0 " ns1$dir " $expect " " test_stateless 4"
964+ lret=1
965+ fi
966+ done
967+
968+ reset_counters
969+
970+ socat -h > /dev/null 2>&1
971+ if [ $? -ne 0 ]; then
972+ echo " SKIP: Could not run stateless nat frag test without socat tool"
973+ if [ $lret -eq 0 ]; then
974+ return $ksft_skip
975+ fi
976+
977+ ip netns exec " $ns0 " nft delete table ip stateless
978+ return $lret
979+ fi
980+
981+ local tmpfile=$( mktemp)
982+ dd if=/dev/urandom of=$tmpfile bs=4096 count=1 2> /dev/null
983+
984+ local outfile=$( mktemp)
985+ ip netns exec " $ns1 " timeout 3 socat -u UDP4-RECV:4233 OPEN:$outfile < /dev/null &
986+ sc_r=$!
987+
988+ sleep 1
989+ # re-do with large ping -> ip fragmentation
990+ ip netns exec " $ns2 " timeout 3 socat - UDP4-SENDTO:" 10.0.1.99:4233" < " $tmpfile " > /dev/null
991+ if [ $? -ne 0 ] ; then
992+ echo " ERROR: failed to test udp $ns1 to $ns2 with stateless ip nat" 1>&2
993+ lret=1
994+ fi
995+
996+ wait
997+
998+ cmp " $tmpfile " " $outfile "
999+ if [ $? -ne 0 ]; then
1000+ ls -l " $tmpfile " " $outfile "
1001+ echo " ERROR: in and output file mismatch when checking udp with stateless nat" 1>&2
1002+ lret=1
1003+ fi
1004+
1005+ rm -f " $tmpfile " " $outfile "
1006+
1007+ # ns1 should have seen packets from 2.2, due to stateless rewrite.
1008+ expect=" packets 3 bytes 4164"
1009+ cnt=$( ip netns exec " $ns1 " nft list counter inet filter ns0insl | grep -q " $expect " )
1010+ if [ $? -ne 0 ]; then
1011+ bad_counter " $ns1 " ns0insl " $expect " " test_stateless 5"
1012+ lret=1
1013+ fi
1014+
1015+ ip netns exec " $ns0 " nft delete table ip stateless
1016+ if [ $? -ne 0 ]; then
1017+ echo " ERROR: Could not delete table ip stateless" 1>&2
1018+ lret=1
1019+ fi
1020+
1021+ test $lret -eq 0 && echo " PASS: IP statless for $ns2 "
1022+
1023+ return $lret
1024+ }
1025+
8881026# ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99
8891027for i in 0 1 2; do
8901028ip netns exec ns$i -$sfx nft -f /dev/stdin << EOF
@@ -951,6 +1089,19 @@ table inet filter {
9511089EOF
9521090done
9531091
1092+ # special case for stateless nat check, counter needs to
1093+ # be done before (input) ip defragmentation
1094+ ip netns exec ns1-$sfx nft -f /dev/stdin << EOF
1095+ table inet filter {
1096+ counter ns0insl {}
1097+
1098+ chain pre {
1099+ type filter hook prerouting priority -400; policy accept;
1100+ ip saddr 10.0.2.2 counter name "ns0insl"
1101+ }
1102+ }
1103+ EOF
1104+
9541105sleep 3
9551106# test basic connectivity
9561107for i in 1 2; do
@@ -1005,6 +1156,7 @@ $test_inet_nat && test_redirect inet
10051156$test_inet_nat && test_redirect6 inet
10061157
10071158test_port_shadowing
1159+ test_stateless_nat_ip
10081160
10091161if [ $ret -ne 0 ]; then
10101162 echo -n " FAIL: "
0 commit comments