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 38trap cleanup EXIT 39 40ipv4() { 41 echo -n 192.168.$1.2 42} 43 44ipv6 () { 45 echo -n dead:$1::2 46} 47 48check_counter() 49{ 50 ns=$1 51 name=$2 52 expect=$3 53 local lret=0 54 55 cnt=$(ip netns exec $ns nft list counter inet filter "$name" | grep -q "$expect") 56 if [ $? -ne 0 ]; then 57 echo "ERROR: counter $name in $ns has unexpected value (expected $expect)" 1>&2 58 ip netns exec $ns nft list counter inet filter "$name" 1>&2 59 lret=1 60 fi 61 62 return $lret 63} 64 65check_unknown() 66{ 67 expect="packets 0 bytes 0" 68 for n in nsclient1 nsclient2 nsrouter1 nsrouter2; do 69 check_counter $n "unknown" "$expect" 70 if [ $? -ne 0 ] ;then 71 return 1 72 fi 73 done 74 75 return 0 76} 77 78for n in nsclient1 nsclient2 nsrouter1 nsrouter2; do 79 ip netns add $n 80 ip -net $n link set lo up 81done 82 83DEV=veth0 84ip link add $DEV netns nsclient1 type veth peer name eth1 netns nsrouter1 85DEV=veth0 86ip link add $DEV netns nsclient2 type veth peer name eth1 netns nsrouter2 87 88DEV=veth0 89ip link add $DEV netns nsrouter1 type veth peer name eth2 netns nsrouter2 90 91DEV=veth0 92for i in 1 2; do 93 ip -net nsclient$i link set $DEV up 94 ip -net nsclient$i addr add $(ipv4 $i)/24 dev $DEV 95 ip -net nsclient$i addr add $(ipv6 $i)/64 dev $DEV 96done 97 98ip -net nsrouter1 link set eth1 up 99ip -net nsrouter1 link set veth0 up 100 101ip -net nsrouter2 link set eth1 up 102ip -net nsrouter2 link set eth2 up 103 104ip -net nsclient1 route add default via 192.168.1.1 105ip -net nsclient1 -6 route add default via dead:1::1 106 107ip -net nsclient2 route add default via 192.168.2.1 108ip -net nsclient2 route add default via dead:2::1 109 110i=3 111ip -net nsrouter1 addr add 192.168.1.1/24 dev eth1 112ip -net nsrouter1 addr add 192.168.3.1/24 dev veth0 113ip -net nsrouter1 addr add dead:1::1/64 dev eth1 114ip -net nsrouter1 addr add dead:3::1/64 dev veth0 115ip -net nsrouter1 route add default via 192.168.3.10 116ip -net nsrouter1 -6 route add default via dead:3::10 117 118ip -net nsrouter2 addr add 192.168.2.1/24 dev eth1 119ip -net nsrouter2 addr add 192.168.3.10/24 dev eth2 120ip -net nsrouter2 addr add dead:2::1/64 dev eth1 121ip -net nsrouter2 addr add dead:3::10/64 dev eth2 122ip -net nsrouter2 route add default via 192.168.3.1 123ip -net nsrouter2 route add default via dead:3::1 124 125sleep 2 126for i in 4 6; do 127 ip netns exec nsrouter1 sysctl -q net.ipv$i.conf.all.forwarding=1 128 ip netns exec nsrouter2 sysctl -q net.ipv$i.conf.all.forwarding=1 129done 130 131for netns in nsrouter1 nsrouter2; do 132ip netns exec $netns nft -f - <<EOF 133table inet filter { 134 counter unknown { } 135 counter related { } 136 chain forward { 137 type filter hook forward priority 0; policy accept; 138 meta l4proto icmpv6 icmpv6 type "packet-too-big" ct state "related" counter name "related" accept 139 meta l4proto icmp icmp type "destination-unreachable" ct state "related" counter name "related" accept 140 meta l4proto { icmp, icmpv6 } ct state new,established accept 141 counter name "unknown" drop 142 } 143} 144EOF 145done 146 147ip netns exec nsclient1 nft -f - <<EOF 148table inet filter { 149 counter unknown { } 150 counter related { } 151 counter redir4 { } 152 counter redir6 { } 153 chain input { 154 type filter hook input priority 0; policy accept; 155 156 icmp type "redirect" ct state "related" counter name "redir4" accept 157 icmpv6 type "nd-redirect" ct state "related" counter name "redir6" accept 158 159 meta l4proto { icmp, icmpv6 } ct state established,untracked accept 160 meta l4proto { icmp, icmpv6 } ct state "related" counter name "related" accept 161 162 counter name "unknown" drop 163 } 164} 165EOF 166 167ip netns exec nsclient2 nft -f - <<EOF 168table inet filter { 169 counter unknown { } 170 counter new { } 171 counter established { } 172 173 chain input { 174 type filter hook input 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" accept 178 meta l4proto { icmp, icmpv6 } ct state "established" counter name "established" accept 179 counter name "unknown" drop 180 } 181 chain output { 182 type filter hook output priority 0; policy accept; 183 meta l4proto { icmp, icmpv6 } ct state established,untracked accept 184 185 meta l4proto { icmp, icmpv6 } ct state "new" counter name "new" 186 meta l4proto { icmp, icmpv6 } ct state "established" counter name "established" 187 counter name "unknown" drop 188 } 189} 190EOF 191 192 193# make sure NAT core rewrites adress of icmp error if nat is used according to 194# conntrack nat information (icmp error will be directed at nsrouter1 address, 195# but it needs to be routed to nsclient1 address). 196ip netns exec nsrouter1 nft -f - <<EOF 197table ip nat { 198 chain postrouting { 199 type nat hook postrouting priority 0; policy accept; 200 ip protocol icmp oifname "veth0" counter masquerade 201 } 202} 203table ip6 nat { 204 chain postrouting { 205 type nat hook postrouting priority 0; policy accept; 206 ip6 nexthdr icmpv6 oifname "veth0" counter masquerade 207 } 208} 209EOF 210 211ip netns exec nsrouter2 ip link set eth1 mtu 1280 212ip netns exec nsclient2 ip link set veth0 mtu 1280 213sleep 1 214 215ip netns exec nsclient1 ping -c 1 -s 1000 -q -M do 192.168.2.2 >/dev/null 216if [ $? -ne 0 ]; then 217 echo "ERROR: netns ip routing/connectivity broken" 1>&2 218 cleanup 219 exit 1 220fi 221ip netns exec nsclient1 ping6 -q -c 1 -s 1000 dead:2::2 >/dev/null 222if [ $? -ne 0 ]; then 223 echo "ERROR: netns ipv6 routing/connectivity broken" 1>&2 224 cleanup 225 exit 1 226fi 227 228check_unknown 229if [ $? -ne 0 ]; then 230 ret=1 231fi 232 233expect="packets 0 bytes 0" 234for netns in nsrouter1 nsrouter2 nsclient1;do 235 check_counter "$netns" "related" "$expect" 236 if [ $? -ne 0 ]; then 237 ret=1 238 fi 239done 240 241expect="packets 2 bytes 2076" 242check_counter nsclient2 "new" "$expect" 243if [ $? -ne 0 ]; then 244 ret=1 245fi 246 247ip netns exec nsclient1 ping -q -c 1 -s 1300 -M do 192.168.2.2 > /dev/null 248if [ $? -eq 0 ]; then 249 echo "ERROR: ping should have failed with PMTU too big error" 1>&2 250 ret=1 251fi 252 253# nsrouter2 should have generated the icmp error, so 254# related counter should be 0 (its in forward). 255expect="packets 0 bytes 0" 256check_counter "nsrouter2" "related" "$expect" 257if [ $? -ne 0 ]; then 258 ret=1 259fi 260 261# but nsrouter1 should have seen it, same for nsclient1. 262expect="packets 1 bytes 576" 263for netns in nsrouter1 nsclient1;do 264 check_counter "$netns" "related" "$expect" 265 if [ $? -ne 0 ]; then 266 ret=1 267 fi 268done 269 270ip netns exec nsclient1 ping6 -c 1 -s 1300 dead:2::2 > /dev/null 271if [ $? -eq 0 ]; then 272 echo "ERROR: ping6 should have failed with PMTU too big error" 1>&2 273 ret=1 274fi 275 276expect="packets 2 bytes 1856" 277for netns in nsrouter1 nsclient1;do 278 check_counter "$netns" "related" "$expect" 279 if [ $? -ne 0 ]; then 280 ret=1 281 fi 282done 283 284if [ $ret -eq 0 ];then 285 echo "PASS: icmp mtu error had RELATED state" 286else 287 echo "ERROR: icmp error RELATED state test has failed" 288fi 289 290# add 'bad' route, expect icmp REDIRECT to be generated 291ip netns exec nsclient1 ip route add 192.168.1.42 via 192.168.1.1 292ip netns exec nsclient1 ip route add dead:1::42 via dead:1::1 293 294ip netns exec "nsclient1" ping -q -c 2 192.168.1.42 > /dev/null 295 296expect="packets 1 bytes 112" 297check_counter nsclient1 "redir4" "$expect" 298if [ $? -ne 0 ];then 299 ret=1 300fi 301 302ip netns exec "nsclient1" ping -c 1 dead:1::42 > /dev/null 303expect="packets 1 bytes 192" 304check_counter nsclient1 "redir6" "$expect" 305if [ $? -ne 0 ];then 306 ret=1 307fi 308 309if [ $ret -eq 0 ];then 310 echo "PASS: icmp redirects had RELATED state" 311else 312 echo "ERROR: icmp redirect RELATED state test has failed" 313fi 314 315exit $ret 316