-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
selftests: netfilter: add fib test case
There is a bug report on netfilter.org bugzilla pointing to fib expression dropping ipv6 DAD packets. Add a test case that demonstrates this problem. Next patch excludes icmpv6 packets coming from any to linklocal. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
- Loading branch information
Florian Westphal
authored and
Pablo Neira Ayuso
committed
Jun 9, 2021
1 parent
ad9f151
commit 8294442
Showing
2 changed files
with
222 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
#!/bin/bash | ||
# | ||
# This tests the fib expression. | ||
# | ||
# Kselftest framework requirement - SKIP code is 4. | ||
ksft_skip=4 | ||
ret=0 | ||
|
||
sfx=$(mktemp -u "XXXXXXXX") | ||
ns1="ns1-$sfx" | ||
ns2="ns2-$sfx" | ||
nsrouter="nsrouter-$sfx" | ||
timeout=4 | ||
|
||
log_netns=$(sysctl -n net.netfilter.nf_log_all_netns) | ||
|
||
cleanup() | ||
{ | ||
ip netns del ${ns1} | ||
ip netns del ${ns2} | ||
ip netns del ${nsrouter} | ||
|
||
[ $log_netns -eq 0 ] && sysctl -q net.netfilter.nf_log_all_netns=$log_netns | ||
} | ||
|
||
nft --version > /dev/null 2>&1 | ||
if [ $? -ne 0 ];then | ||
echo "SKIP: Could not run test without nft tool" | ||
exit $ksft_skip | ||
fi | ||
|
||
ip -Version > /dev/null 2>&1 | ||
if [ $? -ne 0 ];then | ||
echo "SKIP: Could not run test without ip tool" | ||
exit $ksft_skip | ||
fi | ||
|
||
ip netns add ${nsrouter} | ||
if [ $? -ne 0 ];then | ||
echo "SKIP: Could not create net namespace" | ||
exit $ksft_skip | ||
fi | ||
|
||
trap cleanup EXIT | ||
|
||
dmesg | grep -q ' nft_rpfilter: ' | ||
if [ $? -eq 0 ]; then | ||
dmesg -c | grep ' nft_rpfilter: ' | ||
echo "WARN: a previous test run has failed" 1>&2 | ||
fi | ||
|
||
sysctl -q net.netfilter.nf_log_all_netns=1 | ||
ip netns add ${ns1} | ||
ip netns add ${ns2} | ||
|
||
load_ruleset() { | ||
local netns=$1 | ||
|
||
ip netns exec ${netns} nft -f /dev/stdin <<EOF | ||
table inet filter { | ||
chain prerouting { | ||
type filter hook prerouting priority 0; policy accept; | ||
fib saddr . iif oif missing counter log prefix "$netns nft_rpfilter: " drop | ||
} | ||
} | ||
EOF | ||
} | ||
|
||
load_ruleset_count() { | ||
local netns=$1 | ||
|
||
ip netns exec ${netns} nft -f /dev/stdin <<EOF | ||
table inet filter { | ||
chain prerouting { | ||
type filter hook prerouting priority 0; policy accept; | ||
ip daddr 1.1.1.1 fib saddr . iif oif missing counter drop | ||
ip6 daddr 1c3::c01d fib saddr . iif oif missing counter drop | ||
} | ||
} | ||
EOF | ||
} | ||
|
||
check_drops() { | ||
dmesg | grep -q ' nft_rpfilter: ' | ||
if [ $? -eq 0 ]; then | ||
dmesg | grep ' nft_rpfilter: ' | ||
echo "FAIL: rpfilter did drop packets" | ||
return 1 | ||
fi | ||
|
||
return 0 | ||
} | ||
|
||
check_fib_counter() { | ||
local want=$1 | ||
local ns=$2 | ||
local address=$3 | ||
|
||
line=$(ip netns exec ${ns} nft list table inet filter | grep 'fib saddr . iif' | grep $address | grep "packets $want" ) | ||
ret=$? | ||
|
||
if [ $ret -ne 0 ];then | ||
echo "Netns $ns fib counter doesn't match expected packet count of $want for $address" 1>&2 | ||
ip netns exec ${ns} nft list table inet filter | ||
return 1 | ||
fi | ||
|
||
if [ $want -gt 0 ]; then | ||
echo "PASS: fib expression did drop packets for $address" | ||
fi | ||
|
||
return 0 | ||
} | ||
|
||
load_ruleset ${nsrouter} | ||
load_ruleset ${ns1} | ||
load_ruleset ${ns2} | ||
|
||
ip link add veth0 netns ${nsrouter} type veth peer name eth0 netns ${ns1} > /dev/null 2>&1 | ||
if [ $? -ne 0 ];then | ||
echo "SKIP: No virtual ethernet pair device support in kernel" | ||
exit $ksft_skip | ||
fi | ||
ip link add veth1 netns ${nsrouter} type veth peer name eth0 netns ${ns2} | ||
|
||
ip -net ${nsrouter} link set lo up | ||
ip -net ${nsrouter} link set veth0 up | ||
ip -net ${nsrouter} addr add 10.0.1.1/24 dev veth0 | ||
ip -net ${nsrouter} addr add dead:1::1/64 dev veth0 | ||
|
||
ip -net ${nsrouter} link set veth1 up | ||
ip -net ${nsrouter} addr add 10.0.2.1/24 dev veth1 | ||
ip -net ${nsrouter} addr add dead:2::1/64 dev veth1 | ||
|
||
ip -net ${ns1} link set lo up | ||
ip -net ${ns1} link set eth0 up | ||
|
||
ip -net ${ns2} link set lo up | ||
ip -net ${ns2} link set eth0 up | ||
|
||
ip -net ${ns1} addr add 10.0.1.99/24 dev eth0 | ||
ip -net ${ns1} addr add dead:1::99/64 dev eth0 | ||
ip -net ${ns1} route add default via 10.0.1.1 | ||
ip -net ${ns1} route add default via dead:1::1 | ||
|
||
ip -net ${ns2} addr add 10.0.2.99/24 dev eth0 | ||
ip -net ${ns2} addr add dead:2::99/64 dev eth0 | ||
ip -net ${ns2} route add default via 10.0.2.1 | ||
ip -net ${ns2} route add default via dead:2::1 | ||
|
||
test_ping() { | ||
local daddr4=$1 | ||
local daddr6=$2 | ||
|
||
ip netns exec ${ns1} ping -c 1 -q $daddr4 > /dev/null | ||
ret=$? | ||
if [ $ret -ne 0 ];then | ||
check_drops | ||
echo "FAIL: ${ns1} cannot reach $daddr4, ret $ret" 1>&2 | ||
return 1 | ||
fi | ||
|
||
ip netns exec ${ns1} ping -c 3 -q $daddr6 > /dev/null | ||
ret=$? | ||
if [ $ret -ne 0 ];then | ||
check_drops | ||
echo "FAIL: ${ns1} cannot reach $daddr6, ret $ret" 1>&2 | ||
return 1 | ||
fi | ||
|
||
return 0 | ||
} | ||
|
||
ip netns exec ${nsrouter} sysctl net.ipv6.conf.all.forwarding=1 > /dev/null | ||
ip netns exec ${nsrouter} sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null | ||
ip netns exec ${nsrouter} sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null | ||
|
||
sleep 3 | ||
|
||
test_ping 10.0.2.1 dead:2::1 || exit 1 | ||
check_drops || exit 1 | ||
|
||
test_ping 10.0.2.99 dead:2::99 || exit 1 | ||
check_drops || exit 1 | ||
|
||
echo "PASS: fib expression did not cause unwanted packet drops" | ||
|
||
ip netns exec ${nsrouter} nft flush table inet filter | ||
|
||
ip -net ${ns1} route del default | ||
ip -net ${ns1} -6 route del default | ||
|
||
ip -net ${ns1} addr del 10.0.1.99/24 dev eth0 | ||
ip -net ${ns1} addr del dead:1::99/64 dev eth0 | ||
|
||
ip -net ${ns1} addr add 10.0.2.99/24 dev eth0 | ||
ip -net ${ns1} addr add dead:2::99/64 dev eth0 | ||
|
||
ip -net ${ns1} route add default via 10.0.2.1 | ||
ip -net ${ns1} -6 route add default via dead:2::1 | ||
|
||
ip -net ${nsrouter} addr add dead:2::1/64 dev veth0 | ||
|
||
# switch to ruleset that doesn't log, this time | ||
# its expected that this does drop the packets. | ||
load_ruleset_count ${nsrouter} | ||
|
||
# ns1 has a default route, but nsrouter does not. | ||
# must not check return value, ping to 1.1.1.1 will | ||
# fail. | ||
check_fib_counter 0 ${nsrouter} 1.1.1.1 || exit 1 | ||
check_fib_counter 0 ${nsrouter} 1c3::c01d || exit 1 | ||
|
||
ip netns exec ${ns1} ping -c 1 -W 1 -q 1.1.1.1 > /dev/null | ||
check_fib_counter 1 ${nsrouter} 1.1.1.1 || exit 1 | ||
|
||
sleep 2 | ||
ip netns exec ${ns1} ping -c 3 -q 1c3::c01d > /dev/null | ||
check_fib_counter 3 ${nsrouter} 1c3::c01d || exit 1 | ||
|
||
exit 0 |