1*1000bd0aSYujie Liu#!/bin/bash
29b0b7837SSeth David Schoen# SPDX-License-Identifier: GPL-2.0
39b0b7837SSeth David Schoen#
49b0b7837SSeth David Schoen# By Seth Schoen (c) 2021, for the IPv4 Unicast Extensions Project
59b0b7837SSeth David Schoen# Thanks to David Ahern for help and advice on nettest modifications.
69b0b7837SSeth David Schoen#
79b0b7837SSeth David Schoen# Self-tests for IPv4 address extensions: the kernel's ability to accept
89b0b7837SSeth David Schoen# certain traditionally unused or unallocated IPv4 addresses. For each kind
99b0b7837SSeth David Schoen# of address, we test for interface assignment, ping, TCP, and forwarding.
109b0b7837SSeth David Schoen# Must be run as root (to manipulate network namespaces and virtual
119b0b7837SSeth David Schoen# interfaces).
129b0b7837SSeth David Schoen#
139b0b7837SSeth David Schoen# Things we test for here:
149b0b7837SSeth David Schoen#
159b0b7837SSeth David Schoen# * Currently the kernel accepts addresses in 0/8 and 240/4 as valid.
169b0b7837SSeth David Schoen#
179b0b7837SSeth David Schoen# * Notwithstanding that, 0.0.0.0 and 255.255.255.255 cannot be assigned.
189b0b7837SSeth David Schoen#
199b0b7837SSeth David Schoen# * Currently the kernel DOES NOT accept unicast use of the lowest
209b0b7837SSeth David Schoen#   address in an IPv4 subnet (e.g. 192.168.100.0/32 in 192.168.100.0/24).
219b0b7837SSeth David Schoen#   This is treated as a second broadcast address, for compatibility
229b0b7837SSeth David Schoen#   with 4.2BSD (!).
239b0b7837SSeth David Schoen#
249b0b7837SSeth David Schoen# * Currently the kernel DOES NOT accept unicast use of any of 127/8.
259b0b7837SSeth David Schoen#
269b0b7837SSeth David Schoen# * Currently the kernel DOES NOT accept unicast use of any of 224/4.
279b0b7837SSeth David Schoen#
289b0b7837SSeth David Schoen# These tests provide an easy way to flip the expected result of any
299b0b7837SSeth David Schoen# of these behaviors for testing kernel patches that change them.
309b0b7837SSeth David Schoen
31*1000bd0aSYujie Liusource lib.sh
327844ec21SPo-Hsu Lin
339b0b7837SSeth David Schoen# nettest can be run from PATH or from same directory as this selftest
349b0b7837SSeth David Schoenif ! which nettest >/dev/null; then
359b0b7837SSeth David Schoen	PATH=$PWD:$PATH
369b0b7837SSeth David Schoen	if ! which nettest >/dev/null; then
379b0b7837SSeth David Schoen		echo "'nettest' command not found; skipping tests"
387844ec21SPo-Hsu Lin		exit $ksft_skip
399b0b7837SSeth David Schoen	fi
409b0b7837SSeth David Schoenfi
419b0b7837SSeth David Schoen
429b0b7837SSeth David Schoenresult=0
439b0b7837SSeth David Schoen
449b0b7837SSeth David Schoenhide_output(){ exec 3>&1 4>&2 >/dev/null 2>/dev/null; }
459b0b7837SSeth David Schoenshow_output(){ exec >&3 2>&4; }
469b0b7837SSeth David Schoen
479b0b7837SSeth David Schoenshow_result(){
489b0b7837SSeth David Schoen	if [ $1 -eq 0 ]; then
499b0b7837SSeth David Schoen		printf "TEST: %-60s  [ OK ]\n" "${2}"
509b0b7837SSeth David Schoen	else
519b0b7837SSeth David Schoen		printf "TEST: %-60s  [FAIL]\n" "${2}"
529b0b7837SSeth David Schoen		result=1
539b0b7837SSeth David Schoen	fi
549b0b7837SSeth David Schoen}
559b0b7837SSeth David Schoen
569b0b7837SSeth David Schoen_do_segmenttest(){
579b0b7837SSeth David Schoen	# Perform a simple set of link tests between a pair of
589b0b7837SSeth David Schoen	# IP addresses on a shared (virtual) segment, using
599b0b7837SSeth David Schoen	# ping and nettest.
609b0b7837SSeth David Schoen	# foo --- bar
619b0b7837SSeth David Schoen	# Arguments: ip_a ip_b prefix_length test_description
629b0b7837SSeth David Schoen	#
637be281a4SHangbin Liu	# Caller must set up $foo_ns and $bar_ns namespaces
649b0b7837SSeth David Schoen	# containing linked veth devices foo and bar,
659b0b7837SSeth David Schoen	# respectively.
669b0b7837SSeth David Schoen
677be281a4SHangbin Liu	ip -n $foo_ns address add $1/$3 dev foo || return 1
687be281a4SHangbin Liu	ip -n $foo_ns link set foo up || return 1
697be281a4SHangbin Liu	ip -n $bar_ns address add $2/$3 dev bar || return 1
707be281a4SHangbin Liu	ip -n $bar_ns link set bar up || return 1
719b0b7837SSeth David Schoen
727be281a4SHangbin Liu	ip netns exec $foo_ns timeout 2 ping -c 1 $2 || return 1
737be281a4SHangbin Liu	ip netns exec $bar_ns timeout 2 ping -c 1 $1 || return 1
749b0b7837SSeth David Schoen
757be281a4SHangbin Liu	nettest -B -N $bar_ns -O $foo_ns -r $1 || return 1
767be281a4SHangbin Liu	nettest -B -N $foo_ns -O $bar_ns -r $2 || return 1
779b0b7837SSeth David Schoen
789b0b7837SSeth David Schoen	return 0
799b0b7837SSeth David Schoen}
809b0b7837SSeth David Schoen
819b0b7837SSeth David Schoen_do_route_test(){
829b0b7837SSeth David Schoen	# Perform a simple set of gateway tests.
839b0b7837SSeth David Schoen	#
849b0b7837SSeth David Schoen	# [foo] <---> [foo1]-[bar1] <---> [bar]   /prefix
859b0b7837SSeth David Schoen	#  host          gateway          host
869b0b7837SSeth David Schoen	#
879b0b7837SSeth David Schoen	# Arguments: foo_ip foo1_ip bar1_ip bar_ip prefix_len test_description
889b0b7837SSeth David Schoen	# Displays test result and returns success or failure.
899b0b7837SSeth David Schoen
907be281a4SHangbin Liu	# Caller must set up $foo_ns, $bar_ns, and $router_ns
919b0b7837SSeth David Schoen	# containing linked veth devices foo-foo1, bar1-bar
927be281a4SHangbin Liu	# (foo in $foo_ns, foo1 and bar1 in $router_ns, and
937be281a4SHangbin Liu	# bar in $bar_ns).
949b0b7837SSeth David Schoen
957be281a4SHangbin Liu	ip -n $foo_ns address add $1/$5 dev foo || return 1
967be281a4SHangbin Liu	ip -n $foo_ns link set foo up || return 1
977be281a4SHangbin Liu	ip -n $foo_ns route add default via $2 || return 1
987be281a4SHangbin Liu	ip -n $bar_ns address add $4/$5 dev bar || return 1
997be281a4SHangbin Liu	ip -n $bar_ns link set bar up || return 1
1007be281a4SHangbin Liu	ip -n $bar_ns route add default via $3 || return 1
1017be281a4SHangbin Liu	ip -n $router_ns address add $2/$5 dev foo1 || return 1
1027be281a4SHangbin Liu	ip -n $router_ns link set foo1 up || return 1
1037be281a4SHangbin Liu	ip -n $router_ns address add $3/$5 dev bar1 || return 1
1047be281a4SHangbin Liu	ip -n $router_ns link set bar1 up || return 1
1059b0b7837SSeth David Schoen
1067be281a4SHangbin Liu	echo 1 | ip netns exec $router_ns tee /proc/sys/net/ipv4/ip_forward
1079b0b7837SSeth David Schoen
1087be281a4SHangbin Liu	ip netns exec $foo_ns timeout 2 ping -c 1 $2 || return 1
1097be281a4SHangbin Liu	ip netns exec $foo_ns timeout 2 ping -c 1 $4 || return 1
1107be281a4SHangbin Liu	ip netns exec $bar_ns timeout 2 ping -c 1 $3 || return 1
1117be281a4SHangbin Liu	ip netns exec $bar_ns timeout 2 ping -c 1 $1 || return 1
1129b0b7837SSeth David Schoen
1137be281a4SHangbin Liu	nettest -B -N $bar_ns -O $foo_ns -r $1 || return 1
1147be281a4SHangbin Liu	nettest -B -N $foo_ns -O $bar_ns -r $4 || return 1
1159b0b7837SSeth David Schoen
1169b0b7837SSeth David Schoen	return 0
1179b0b7837SSeth David Schoen}
1189b0b7837SSeth David Schoen
1199b0b7837SSeth David Schoensegmenttest(){
1209b0b7837SSeth David Schoen	# Sets up veth link and tries to connect over it.
1219b0b7837SSeth David Schoen	# Arguments: ip_a ip_b prefix_len test_description
1229b0b7837SSeth David Schoen	hide_output
1237be281a4SHangbin Liu	setup_ns foo_ns bar_ns
1247be281a4SHangbin Liu	ip link add foo netns $foo_ns type veth peer name bar netns $bar_ns
1259b0b7837SSeth David Schoen
1269b0b7837SSeth David Schoen	test_result=0
1279b0b7837SSeth David Schoen	_do_segmenttest "$@" || test_result=1
1289b0b7837SSeth David Schoen
1297be281a4SHangbin Liu	ip netns pids $foo_ns | xargs -r kill -9
1307be281a4SHangbin Liu	ip netns pids $bar_ns | xargs -r kill -9
1317be281a4SHangbin Liu	cleanup_ns $foo_ns $bar_ns
1329b0b7837SSeth David Schoen	show_output
1339b0b7837SSeth David Schoen
1349b0b7837SSeth David Schoen	# inverted tests will expect failure instead of success
1359b0b7837SSeth David Schoen	[ -n "$expect_failure" ] && test_result=`expr 1 - $test_result`
1369b0b7837SSeth David Schoen
1379b0b7837SSeth David Schoen	show_result $test_result "$4"
1389b0b7837SSeth David Schoen}
1399b0b7837SSeth David Schoen
1409b0b7837SSeth David Schoenroute_test(){
1419b0b7837SSeth David Schoen	# Sets up a simple gateway and tries to connect through it.
1429b0b7837SSeth David Schoen	# [foo] <---> [foo1]-[bar1] <---> [bar]   /prefix
1439b0b7837SSeth David Schoen	# Arguments: foo_ip foo1_ip bar1_ip bar_ip prefix_len test_description
1449b0b7837SSeth David Schoen	# Returns success or failure.
1459b0b7837SSeth David Schoen
1469b0b7837SSeth David Schoen	hide_output
1477be281a4SHangbin Liu	setup_ns foo_ns bar_ns router_ns
1487be281a4SHangbin Liu	ip link add foo netns $foo_ns type veth peer name foo1 netns $router_ns
1497be281a4SHangbin Liu	ip link add bar netns $bar_ns type veth peer name bar1 netns $router_ns
1509b0b7837SSeth David Schoen
1519b0b7837SSeth David Schoen	test_result=0
1529b0b7837SSeth David Schoen	_do_route_test "$@" || test_result=1
1539b0b7837SSeth David Schoen
1547be281a4SHangbin Liu	ip netns pids $foo_ns | xargs -r kill -9
1557be281a4SHangbin Liu	ip netns pids $bar_ns | xargs -r kill -9
1567be281a4SHangbin Liu	ip netns pids $router_ns | xargs -r kill -9
1577be281a4SHangbin Liu	cleanup_ns $foo_ns $bar_ns $router_ns
1589b0b7837SSeth David Schoen
1599b0b7837SSeth David Schoen	show_output
1609b0b7837SSeth David Schoen
1619b0b7837SSeth David Schoen	# inverted tests will expect failure instead of success
1629b0b7837SSeth David Schoen	[ -n "$expect_failure" ] && test_result=`expr 1 - $test_result`
1639b0b7837SSeth David Schoen	show_result $test_result "$6"
1649b0b7837SSeth David Schoen}
1659b0b7837SSeth David Schoen
1669b0b7837SSeth David Schoenecho "###########################################################################"
1679b0b7837SSeth David Schoenecho "Unicast address extensions tests (behavior of reserved IPv4 addresses)"
1689b0b7837SSeth David Schoenecho "###########################################################################"
1699b0b7837SSeth David Schoen#
1709b0b7837SSeth David Schoen# Test support for 240/4
1719b0b7837SSeth David Schoensegmenttest 240.1.2.1   240.1.2.4    24 "assign and ping within 240/4 (1 of 2) (is allowed)"
1729b0b7837SSeth David Schoensegmenttest 250.100.2.1 250.100.30.4 16 "assign and ping within 240/4 (2 of 2) (is allowed)"
1739b0b7837SSeth David Schoen#
1749b0b7837SSeth David Schoen# Test support for 0/8
1759b0b7837SSeth David Schoensegmenttest 0.1.2.17    0.1.2.23  24 "assign and ping within 0/8 (1 of 2) (is allowed)"
1769b0b7837SSeth David Schoensegmenttest 0.77.240.17 0.77.2.23 16 "assign and ping within 0/8 (2 of 2) (is allowed)"
1779b0b7837SSeth David Schoen#
1789b0b7837SSeth David Schoen# Even 255.255/16 is OK!
1799b0b7837SSeth David Schoensegmenttest 255.255.3.1 255.255.50.77 16 "assign and ping inside 255.255/16 (is allowed)"
1809b0b7837SSeth David Schoen#
1819b0b7837SSeth David Schoen# Or 255.255.255/24
1829b0b7837SSeth David Schoensegmenttest 255.255.255.1 255.255.255.254 24 "assign and ping inside 255.255.255/24 (is allowed)"
1839b0b7837SSeth David Schoen#
1849b0b7837SSeth David Schoen# Routing between different networks
1859b0b7837SSeth David Schoenroute_test 240.5.6.7 240.5.6.1  255.1.2.1    255.1.2.3      24 "route between 240.5.6/24 and 255.1.2/24 (is allowed)"
1869b0b7837SSeth David Schoenroute_test 0.200.6.7 0.200.38.1 245.99.101.1 245.99.200.111 16 "route between 0.200/16 and 245.99/16 (is allowed)"
1879b0b7837SSeth David Schoen#
1886101ca03SSeth David Schoen# Test support for lowest address ending in .0
1896101ca03SSeth David Schoensegmenttest 5.10.15.20 5.10.15.0 24 "assign and ping lowest address (/24)"
1906101ca03SSeth David Schoen#
1916101ca03SSeth David Schoen# Test support for lowest address not ending in .0
1926101ca03SSeth David Schoensegmenttest 192.168.101.192 192.168.101.193 26 "assign and ping lowest address (/26)"
1936101ca03SSeth David Schoen#
1946101ca03SSeth David Schoen# Routing using lowest address as a gateway/endpoint
1956101ca03SSeth David Schoenroute_test 192.168.42.1 192.168.42.0 9.8.7.6 9.8.7.0 24 "routing using lowest address"
1966101ca03SSeth David Schoen#
1979b0b7837SSeth David Schoen# ==============================================
1989b0b7837SSeth David Schoen# ==== TESTS THAT CURRENTLY EXPECT FAILURE =====
1999b0b7837SSeth David Schoen# ==============================================
2009b0b7837SSeth David Schoenexpect_failure=true
2019b0b7837SSeth David Schoen# It should still not be possible to use 0.0.0.0 or 255.255.255.255
2029b0b7837SSeth David Schoen# as a unicast address.  Thus, these tests expect failure.
2039b0b7837SSeth David Schoensegmenttest 0.0.1.5       0.0.0.0         16 "assigning 0.0.0.0 (is forbidden)"
2049b0b7837SSeth David Schoensegmenttest 255.255.255.1 255.255.255.255 16 "assigning 255.255.255.255 (is forbidden)"
2059b0b7837SSeth David Schoen#
2069b0b7837SSeth David Schoen# Test support for not having all of 127 be loopback
2079b0b7837SSeth David Schoen# Currently Linux does not allow this, so this should fail too
2089b0b7837SSeth David Schoensegmenttest 127.99.4.5 127.99.4.6 16 "assign and ping inside 127/8 (is forbidden)"
2099b0b7837SSeth David Schoen#
2109b0b7837SSeth David Schoen# Test support for unicast use of class D
2119b0b7837SSeth David Schoen# Currently Linux does not allow this, so this should fail too
2129b0b7837SSeth David Schoensegmenttest 225.1.2.3 225.1.2.200 24 "assign and ping class D address (is forbidden)"
2139b0b7837SSeth David Schoen#
2149b0b7837SSeth David Schoen# Routing using class D as a gateway
2159b0b7837SSeth David Schoenroute_test 225.1.42.1 225.1.42.2 9.8.7.6 9.8.7.1 24 "routing using class D (is forbidden)"
2169b0b7837SSeth David Schoen#
2179b0b7837SSeth David Schoen# Routing using 127/8
2189b0b7837SSeth David Schoen# Currently Linux does not allow this, so this should fail too
2199b0b7837SSeth David Schoenroute_test 127.99.2.3 127.99.2.4 200.1.2.3 200.1.2.4 24 "routing using 127/8 (is forbidden)"
2209b0b7837SSeth David Schoen#
2219b0b7837SSeth David Schoenunset expect_failure
2229b0b7837SSeth David Schoen# =====================================================
2239b0b7837SSeth David Schoen# ==== END OF TESTS THAT CURRENTLY EXPECT FAILURE =====
2249b0b7837SSeth David Schoen# =====================================================
2259b0b7837SSeth David Schoenexit ${result}
226