1#!/bin/bash 2# 3# check that ICMP df-needed/pkttoobig icmp are set are set as related 4# state 5# 6# Setup is: 7# 8# nsclient1 -> nsrouter1 -> nsrouter2 -> nsclient2 9# MTU 1500, except for nsrouter2 <-> nsclient2 link (1280). 10# ping nsclient2 from nsclient1, checking that conntrack did set RELATED 11# 'fragmentation needed' icmp packet. 12# 13# In addition, nsrouter1 will perform IP masquerading, i.e. also 14# check the icmp errors are propagated to the correct host as per 15# nat of "established" icmp-echo "connection". 16 17# Kselftest framework requirement - SKIP code is 4. 18ksft_skip=4 19ret=0 20 21nft --version > /dev/null 2>&1 22if [ $? -ne 0 ];then 23 echo "SKIP: Could not run test without nft tool" 24 exit $ksft_skip 25fi 26 27ip -Version > /dev/null 2>&1 28if [ $? -ne 0 ];then 29 echo "SKIP: Could not run test without ip tool" 30 exit $ksft_skip 31fi 32 33cleanup() { 34 for i in 1 2;do ip netns del nsclient$i;done 35 for i in 1 2;do ip netns del nsrouter$i;done 36} 37 38ipv4() { 39 echo -n 192.168.$1.2 40} 41 42ipv6 () { 43 echo -n dead:$1::2 44} 45 46check_counter() 47{ 48 ns=$1 49 name=$2 50 expect=$3 51 local lret=0 52 53 cnt=$(ip netns exec $ns nft list counter inet filter "$name" | grep -q "$expect") 54 if [ $? -ne 0 ]; then 55 echo "ERROR: counter $name in $ns has unexpected value (expected $expect)" 1>&2 56 ip netns exec $ns nft list counter inet filter "$name" 1>&2 57 lret=1 58 fi 59 60 return $lret 61} 62 63check_unknown() 64{ 65 expect="packets 0 bytes 0" 66 for n in nsclient1 nsclient2 nsrouter1 nsrouter2; do 67 check_counter $n "unknown" "$expect" 68 if [ $? -ne 0 ] ;then 69 return 1 70 fi 71 done 72 73 return 0 74} 75 76for n in nsclient1 nsclient2 nsrouter1 nsrouter2; do 77 ip netns add $n 78 ip -net $n link set lo up 79done 80 81DEV=veth0 82ip link add $DEV netns nsclient1 type veth peer name eth1 netns nsrouter1 83DEV=veth0 84ip link add $DEV netns nsclient2 type veth peer name eth1 netns nsrouter2 85 86DEV=veth0 87ip link add $DEV netns nsrouter1 type veth peer name eth2 netns nsrouter2 88 89DEV=veth0 90for i in 1 2; do 91 ip -net nsclient$i link set $DEV up 92 ip -net nsclient$i addr add $(ipv4 $i)/24 dev $DEV 93 ip -net nsclient$i addr add $(ipv6 $i)/64 dev $DEV 94done 95 96ip -net nsrouter1 link set eth1 up 97ip -net nsrouter1 link set veth0 up 98 99ip -net nsrouter2 link set eth1 up 100ip -net nsrouter2 link set eth2 up 101 102ip -net nsclient1 route add default via 192.168.1.1 103ip -net nsclient1 -6 route add default via dead:1::1 104 105ip -net nsclient2 route add default via 192.168.2.1 106ip -net nsclient2 route add default via dead:2::1 107 108i=3 109ip -net nsrouter1 addr add 192.168.1.1/24 dev eth1 110ip -net nsrouter1 addr add 192.168.3.1/24 dev veth0 111ip -net nsrouter1 addr add dead:1::1/64 dev eth1 112ip -net nsrouter1 addr add dead:3::1/64 dev veth0 113ip -net nsrouter1 route add default via 192.168.3.10 114ip -net nsrouter1 -6 route add default via dead:3::10 115 116ip -net nsrouter2 addr add 192.168.2.1/24 dev eth1 117ip -net nsrouter2 addr add 192.168.3.10/24 dev eth2 118ip -net nsrouter2 addr add dead:2::1/64 dev eth1 119ip -net nsrouter2 addr add dead:3::10/64 dev eth2 120ip -net nsrouter2 route add default via 192.168.3.1 121ip -net nsrouter2 route add default via dead:3::1 122 123sleep 2 124for i in 4 6; do 125 ip netns exec nsrouter1 sysctl -q net.ipv$i.conf.all.forwarding=1 126 ip netns exec nsrouter2 sysctl -q net.ipv$i.conf.all.forwarding=1 127done 128 129for netns in nsrouter1 nsrouter2; do 130ip netns exec $netns nft -f - <<EOF 131table inet filter { 132 counter unknown { } 133 counter related { } 134 chain forward { 135 type filter hook forward priority 0; policy accept; 136 meta l4proto icmpv6 icmpv6 type "packet-too-big" ct state "related" counter name "related" accept 137 meta l4proto icmp icmp type "destination-unreachable" ct state "related" counter name "related" accept 138 meta l4proto { icmp, icmpv6 } ct state new,established accept 139 counter name "unknown" drop 140 } 141} 142EOF 143done 144 145ip netns exec nsclient1 nft -f - <<EOF 146table inet filter { 147 counter unknown { } 148 counter related { } 149 chain input { 150 type filter hook input priority 0; policy accept; 151 meta l4proto { icmp, icmpv6 } ct state established,untracked accept 152 153 meta l4proto { icmp, icmpv6 } ct state "related" counter name "related" accept 154 counter name "unknown" drop 155 } 156} 157EOF 158 159ip netns exec nsclient2 nft -f - <<EOF 160table inet filter { 161 counter unknown { } 162 counter new { } 163 counter established { } 164 165 chain input { 166 type filter hook input priority 0; policy accept; 167 meta l4proto { icmp, icmpv6 } ct state established,untracked accept 168 169 meta l4proto { icmp, icmpv6 } ct state "new" counter name "new" accept 170 meta l4proto { icmp, icmpv6 } ct state "established" counter name "established" accept 171 counter name "unknown" drop 172 } 173 chain output { 174 type filter hook output priority 0; policy accept; 175 meta l4proto { icmp, icmpv6 } ct state established,untracked accept 176 177 meta l4proto { icmp, icmpv6 } ct state "new" counter name "new" 178 meta l4proto { icmp, icmpv6 } ct state "established" counter name "established" 179 counter name "unknown" drop 180 } 181} 182EOF 183 184 185# make sure NAT core rewrites adress of icmp error if nat is used according to 186# conntrack nat information (icmp error will be directed at nsrouter1 address, 187# but it needs to be routed to nsclient1 address). 188ip netns exec nsrouter1 nft -f - <<EOF 189table ip nat { 190 chain postrouting { 191 type nat hook postrouting priority 0; policy accept; 192 ip protocol icmp oifname "veth0" counter masquerade 193 } 194} 195table ip6 nat { 196 chain postrouting { 197 type nat hook postrouting priority 0; policy accept; 198 ip6 nexthdr icmpv6 oifname "veth0" counter masquerade 199 } 200} 201EOF 202 203ip netns exec nsrouter2 ip link set eth1 mtu 1280 204ip netns exec nsclient2 ip link set veth0 mtu 1280 205sleep 1 206 207ip netns exec nsclient1 ping -c 1 -s 1000 -q -M do 192.168.2.2 >/dev/null 208if [ $? -ne 0 ]; then 209 echo "ERROR: netns ip routing/connectivity broken" 1>&2 210 cleanup 211 exit 1 212fi 213ip netns exec nsclient1 ping6 -q -c 1 -s 1000 dead:2::2 >/dev/null 214if [ $? -ne 0 ]; then 215 echo "ERROR: netns ipv6 routing/connectivity broken" 1>&2 216 cleanup 217 exit 1 218fi 219 220check_unknown 221if [ $? -ne 0 ]; then 222 ret=1 223fi 224 225expect="packets 0 bytes 0" 226for netns in nsrouter1 nsrouter2 nsclient1;do 227 check_counter "$netns" "related" "$expect" 228 if [ $? -ne 0 ]; then 229 ret=1 230 fi 231done 232 233expect="packets 2 bytes 2076" 234check_counter nsclient2 "new" "$expect" 235if [ $? -ne 0 ]; then 236 ret=1 237fi 238 239ip netns exec nsclient1 ping -q -c 1 -s 1300 -M do 192.168.2.2 > /dev/null 240if [ $? -eq 0 ]; then 241 echo "ERROR: ping should have failed with PMTU too big error" 1>&2 242 ret=1 243fi 244 245# nsrouter2 should have generated the icmp error, so 246# related counter should be 0 (its in forward). 247expect="packets 0 bytes 0" 248check_counter "nsrouter2" "related" "$expect" 249if [ $? -ne 0 ]; then 250 ret=1 251fi 252 253# but nsrouter1 should have seen it, same for nsclient1. 254expect="packets 1 bytes 576" 255for netns in nsrouter1 nsclient1;do 256 check_counter "$netns" "related" "$expect" 257 if [ $? -ne 0 ]; then 258 ret=1 259 fi 260done 261 262ip netns exec nsclient1 ping6 -c 1 -s 1300 dead:2::2 > /dev/null 263if [ $? -eq 0 ]; then 264 echo "ERROR: ping6 should have failed with PMTU too big error" 1>&2 265 ret=1 266fi 267 268expect="packets 2 bytes 1856" 269for netns in nsrouter1 nsclient1;do 270 check_counter "$netns" "related" "$expect" 271 if [ $? -ne 0 ]; then 272 ret=1 273 fi 274done 275 276if [ $ret -eq 0 ];then 277 echo "PASS: icmp mtu error had RELATED state" 278else 279 echo "ERROR: icmp error RELATED state test has failed" 280fi 281 282cleanup 283exit $ret 284