19b0b7837SSeth David Schoen#!/bin/sh
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*7844ec21SPo-Hsu Lin# Kselftest framework requirement - SKIP code is 4.
32*7844ec21SPo-Hsu Linksft_skip=4
33*7844ec21SPo-Hsu Lin
349b0b7837SSeth David Schoen# nettest can be run from PATH or from same directory as this selftest
359b0b7837SSeth David Schoenif ! which nettest >/dev/null; then
369b0b7837SSeth David Schoen	PATH=$PWD:$PATH
379b0b7837SSeth David Schoen	if ! which nettest >/dev/null; then
389b0b7837SSeth David Schoen		echo "'nettest' command not found; skipping tests"
39*7844ec21SPo-Hsu Lin		exit $ksft_skip
409b0b7837SSeth David Schoen	fi
419b0b7837SSeth David Schoenfi
429b0b7837SSeth David Schoen
439b0b7837SSeth David Schoenresult=0
449b0b7837SSeth David Schoen
459b0b7837SSeth David Schoenhide_output(){ exec 3>&1 4>&2 >/dev/null 2>/dev/null; }
469b0b7837SSeth David Schoenshow_output(){ exec >&3 2>&4; }
479b0b7837SSeth David Schoen
489b0b7837SSeth David Schoenshow_result(){
499b0b7837SSeth David Schoen	if [ $1 -eq 0 ]; then
509b0b7837SSeth David Schoen		printf "TEST: %-60s  [ OK ]\n" "${2}"
519b0b7837SSeth David Schoen	else
529b0b7837SSeth David Schoen		printf "TEST: %-60s  [FAIL]\n" "${2}"
539b0b7837SSeth David Schoen		result=1
549b0b7837SSeth David Schoen	fi
559b0b7837SSeth David Schoen}
569b0b7837SSeth David Schoen
579b0b7837SSeth David Schoen_do_segmenttest(){
589b0b7837SSeth David Schoen	# Perform a simple set of link tests between a pair of
599b0b7837SSeth David Schoen	# IP addresses on a shared (virtual) segment, using
609b0b7837SSeth David Schoen	# ping and nettest.
619b0b7837SSeth David Schoen	# foo --- bar
629b0b7837SSeth David Schoen	# Arguments: ip_a ip_b prefix_length test_description
639b0b7837SSeth David Schoen	#
649b0b7837SSeth David Schoen	# Caller must set up foo-ns and bar-ns namespaces
659b0b7837SSeth David Schoen	# containing linked veth devices foo and bar,
669b0b7837SSeth David Schoen	# respectively.
679b0b7837SSeth David Schoen
689b0b7837SSeth David Schoen	ip -n foo-ns address add $1/$3 dev foo || return 1
699b0b7837SSeth David Schoen	ip -n foo-ns link set foo up || return 1
709b0b7837SSeth David Schoen	ip -n bar-ns address add $2/$3 dev bar || return 1
719b0b7837SSeth David Schoen	ip -n bar-ns link set bar up || return 1
729b0b7837SSeth David Schoen
739b0b7837SSeth David Schoen	ip netns exec foo-ns timeout 2 ping -c 1 $2 || return 1
749b0b7837SSeth David Schoen	ip netns exec bar-ns timeout 2 ping -c 1 $1 || return 1
759b0b7837SSeth David Schoen
769b0b7837SSeth David Schoen	nettest -B -N bar-ns -O foo-ns -r $1 || return 1
779b0b7837SSeth David Schoen	nettest -B -N foo-ns -O bar-ns -r $2 || return 1
789b0b7837SSeth David Schoen
799b0b7837SSeth David Schoen	return 0
809b0b7837SSeth David Schoen}
819b0b7837SSeth David Schoen
829b0b7837SSeth David Schoen_do_route_test(){
839b0b7837SSeth David Schoen	# Perform a simple set of gateway tests.
849b0b7837SSeth David Schoen	#
859b0b7837SSeth David Schoen	# [foo] <---> [foo1]-[bar1] <---> [bar]   /prefix
869b0b7837SSeth David Schoen	#  host          gateway          host
879b0b7837SSeth David Schoen	#
889b0b7837SSeth David Schoen	# Arguments: foo_ip foo1_ip bar1_ip bar_ip prefix_len test_description
899b0b7837SSeth David Schoen	# Displays test result and returns success or failure.
909b0b7837SSeth David Schoen
919b0b7837SSeth David Schoen	# Caller must set up foo-ns, bar-ns, and router-ns
929b0b7837SSeth David Schoen	# containing linked veth devices foo-foo1, bar1-bar
939b0b7837SSeth David Schoen	# (foo in foo-ns, foo1 and bar1 in router-ns, and
949b0b7837SSeth David Schoen	# bar in bar-ns).
959b0b7837SSeth David Schoen
969b0b7837SSeth David Schoen	ip -n foo-ns address add $1/$5 dev foo || return 1
979b0b7837SSeth David Schoen	ip -n foo-ns link set foo up || return 1
989b0b7837SSeth David Schoen	ip -n foo-ns route add default via $2 || return 1
999b0b7837SSeth David Schoen	ip -n bar-ns address add $4/$5 dev bar || return 1
1009b0b7837SSeth David Schoen	ip -n bar-ns link set bar up || return 1
1019b0b7837SSeth David Schoen	ip -n bar-ns route add default via $3 || return 1
1029b0b7837SSeth David Schoen	ip -n router-ns address add $2/$5 dev foo1 || return 1
1039b0b7837SSeth David Schoen	ip -n router-ns link set foo1 up || return 1
1049b0b7837SSeth David Schoen	ip -n router-ns address add $3/$5 dev bar1 || return 1
1059b0b7837SSeth David Schoen	ip -n router-ns link set bar1 up || return 1
1069b0b7837SSeth David Schoen
1079b0b7837SSeth David Schoen	echo 1 | ip netns exec router-ns tee /proc/sys/net/ipv4/ip_forward
1089b0b7837SSeth David Schoen
1099b0b7837SSeth David Schoen	ip netns exec foo-ns timeout 2 ping -c 1 $2 || return 1
1109b0b7837SSeth David Schoen	ip netns exec foo-ns timeout 2 ping -c 1 $4 || return 1
1119b0b7837SSeth David Schoen	ip netns exec bar-ns timeout 2 ping -c 1 $3 || return 1
1129b0b7837SSeth David Schoen	ip netns exec bar-ns timeout 2 ping -c 1 $1 || return 1
1139b0b7837SSeth David Schoen
1149b0b7837SSeth David Schoen	nettest -B -N bar-ns -O foo-ns -r $1 || return 1
1159b0b7837SSeth David Schoen	nettest -B -N foo-ns -O bar-ns -r $4 || return 1
1169b0b7837SSeth David Schoen
1179b0b7837SSeth David Schoen	return 0
1189b0b7837SSeth David Schoen}
1199b0b7837SSeth David Schoen
1209b0b7837SSeth David Schoensegmenttest(){
1219b0b7837SSeth David Schoen	# Sets up veth link and tries to connect over it.
1229b0b7837SSeth David Schoen	# Arguments: ip_a ip_b prefix_len test_description
1239b0b7837SSeth David Schoen	hide_output
1249b0b7837SSeth David Schoen	ip netns add foo-ns
1259b0b7837SSeth David Schoen	ip netns add bar-ns
1269b0b7837SSeth David Schoen	ip link add foo netns foo-ns type veth peer name bar netns bar-ns
1279b0b7837SSeth David Schoen
1289b0b7837SSeth David Schoen	test_result=0
1299b0b7837SSeth David Schoen	_do_segmenttest "$@" || test_result=1
1309b0b7837SSeth David Schoen
1319b0b7837SSeth David Schoen	ip netns pids foo-ns | xargs -r kill -9
1329b0b7837SSeth David Schoen	ip netns pids bar-ns | xargs -r kill -9
1339b0b7837SSeth David Schoen	ip netns del foo-ns
1349b0b7837SSeth David Schoen	ip netns del bar-ns
1359b0b7837SSeth David Schoen	show_output
1369b0b7837SSeth David Schoen
1379b0b7837SSeth David Schoen	# inverted tests will expect failure instead of success
1389b0b7837SSeth David Schoen	[ -n "$expect_failure" ] && test_result=`expr 1 - $test_result`
1399b0b7837SSeth David Schoen
1409b0b7837SSeth David Schoen	show_result $test_result "$4"
1419b0b7837SSeth David Schoen}
1429b0b7837SSeth David Schoen
1439b0b7837SSeth David Schoenroute_test(){
1449b0b7837SSeth David Schoen	# Sets up a simple gateway and tries to connect through it.
1459b0b7837SSeth David Schoen	# [foo] <---> [foo1]-[bar1] <---> [bar]   /prefix
1469b0b7837SSeth David Schoen	# Arguments: foo_ip foo1_ip bar1_ip bar_ip prefix_len test_description
1479b0b7837SSeth David Schoen	# Returns success or failure.
1489b0b7837SSeth David Schoen
1499b0b7837SSeth David Schoen	hide_output
1509b0b7837SSeth David Schoen	ip netns add foo-ns
1519b0b7837SSeth David Schoen	ip netns add bar-ns
1529b0b7837SSeth David Schoen	ip netns add router-ns
1539b0b7837SSeth David Schoen	ip link add foo netns foo-ns type veth peer name foo1 netns router-ns
1549b0b7837SSeth David Schoen	ip link add bar netns bar-ns type veth peer name bar1 netns router-ns
1559b0b7837SSeth David Schoen
1569b0b7837SSeth David Schoen	test_result=0
1579b0b7837SSeth David Schoen	_do_route_test "$@" || test_result=1
1589b0b7837SSeth David Schoen
1599b0b7837SSeth David Schoen	ip netns pids foo-ns | xargs -r kill -9
1609b0b7837SSeth David Schoen	ip netns pids bar-ns | xargs -r kill -9
1619b0b7837SSeth David Schoen	ip netns pids router-ns | xargs -r kill -9
1629b0b7837SSeth David Schoen	ip netns del foo-ns
1639b0b7837SSeth David Schoen	ip netns del bar-ns
1649b0b7837SSeth David Schoen	ip netns del router-ns
1659b0b7837SSeth David Schoen
1669b0b7837SSeth David Schoen	show_output
1679b0b7837SSeth David Schoen
1689b0b7837SSeth David Schoen	# inverted tests will expect failure instead of success
1699b0b7837SSeth David Schoen	[ -n "$expect_failure" ] && test_result=`expr 1 - $test_result`
1709b0b7837SSeth David Schoen	show_result $test_result "$6"
1719b0b7837SSeth David Schoen}
1729b0b7837SSeth David Schoen
1739b0b7837SSeth David Schoenecho "###########################################################################"
1749b0b7837SSeth David Schoenecho "Unicast address extensions tests (behavior of reserved IPv4 addresses)"
1759b0b7837SSeth David Schoenecho "###########################################################################"
1769b0b7837SSeth David Schoen#
1779b0b7837SSeth David Schoen# Test support for 240/4
1789b0b7837SSeth David Schoensegmenttest 240.1.2.1   240.1.2.4    24 "assign and ping within 240/4 (1 of 2) (is allowed)"
1799b0b7837SSeth David Schoensegmenttest 250.100.2.1 250.100.30.4 16 "assign and ping within 240/4 (2 of 2) (is allowed)"
1809b0b7837SSeth David Schoen#
1819b0b7837SSeth David Schoen# Test support for 0/8
1829b0b7837SSeth David Schoensegmenttest 0.1.2.17    0.1.2.23  24 "assign and ping within 0/8 (1 of 2) (is allowed)"
1839b0b7837SSeth David Schoensegmenttest 0.77.240.17 0.77.2.23 16 "assign and ping within 0/8 (2 of 2) (is allowed)"
1849b0b7837SSeth David Schoen#
1859b0b7837SSeth David Schoen# Even 255.255/16 is OK!
1869b0b7837SSeth David Schoensegmenttest 255.255.3.1 255.255.50.77 16 "assign and ping inside 255.255/16 (is allowed)"
1879b0b7837SSeth David Schoen#
1889b0b7837SSeth David Schoen# Or 255.255.255/24
1899b0b7837SSeth David Schoensegmenttest 255.255.255.1 255.255.255.254 24 "assign and ping inside 255.255.255/24 (is allowed)"
1909b0b7837SSeth David Schoen#
1919b0b7837SSeth David Schoen# Routing between different networks
1929b0b7837SSeth 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)"
1939b0b7837SSeth 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)"
1949b0b7837SSeth David Schoen#
1956101ca03SSeth David Schoen# Test support for lowest address ending in .0
1966101ca03SSeth David Schoensegmenttest 5.10.15.20 5.10.15.0 24 "assign and ping lowest address (/24)"
1976101ca03SSeth David Schoen#
1986101ca03SSeth David Schoen# Test support for lowest address not ending in .0
1996101ca03SSeth David Schoensegmenttest 192.168.101.192 192.168.101.193 26 "assign and ping lowest address (/26)"
2006101ca03SSeth David Schoen#
2016101ca03SSeth David Schoen# Routing using lowest address as a gateway/endpoint
2026101ca03SSeth David Schoenroute_test 192.168.42.1 192.168.42.0 9.8.7.6 9.8.7.0 24 "routing using lowest address"
2036101ca03SSeth David Schoen#
2049b0b7837SSeth David Schoen# ==============================================
2059b0b7837SSeth David Schoen# ==== TESTS THAT CURRENTLY EXPECT FAILURE =====
2069b0b7837SSeth David Schoen# ==============================================
2079b0b7837SSeth David Schoenexpect_failure=true
2089b0b7837SSeth David Schoen# It should still not be possible to use 0.0.0.0 or 255.255.255.255
2099b0b7837SSeth David Schoen# as a unicast address.  Thus, these tests expect failure.
2109b0b7837SSeth David Schoensegmenttest 0.0.1.5       0.0.0.0         16 "assigning 0.0.0.0 (is forbidden)"
2119b0b7837SSeth David Schoensegmenttest 255.255.255.1 255.255.255.255 16 "assigning 255.255.255.255 (is forbidden)"
2129b0b7837SSeth David Schoen#
2139b0b7837SSeth David Schoen# Test support for not having all of 127 be loopback
2149b0b7837SSeth David Schoen# Currently Linux does not allow this, so this should fail too
2159b0b7837SSeth David Schoensegmenttest 127.99.4.5 127.99.4.6 16 "assign and ping inside 127/8 (is forbidden)"
2169b0b7837SSeth David Schoen#
2179b0b7837SSeth David Schoen# Test support for unicast use of class D
2189b0b7837SSeth David Schoen# Currently Linux does not allow this, so this should fail too
2199b0b7837SSeth David Schoensegmenttest 225.1.2.3 225.1.2.200 24 "assign and ping class D address (is forbidden)"
2209b0b7837SSeth David Schoen#
2219b0b7837SSeth David Schoen# Routing using class D as a gateway
2229b0b7837SSeth 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)"
2239b0b7837SSeth David Schoen#
2249b0b7837SSeth David Schoen# Routing using 127/8
2259b0b7837SSeth David Schoen# Currently Linux does not allow this, so this should fail too
2269b0b7837SSeth 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)"
2279b0b7837SSeth David Schoen#
2289b0b7837SSeth David Schoenunset expect_failure
2299b0b7837SSeth David Schoen# =====================================================
2309b0b7837SSeth David Schoen# ==== END OF TESTS THAT CURRENTLY EXPECT FAILURE =====
2319b0b7837SSeth David Schoen# =====================================================
2329b0b7837SSeth David Schoenexit ${result}
233