xref: /linux/tools/testing/selftests/net/exception_cache.sh (revision adf50c47a47f0f0f0b79dd58ffade9919cddebea)
1*c923c149SIdo Schimmel#!/bin/bash
2*c923c149SIdo Schimmel# SPDX-License-Identifier: GPL-2.0
3*c923c149SIdo Schimmel#
4*c923c149SIdo Schimmel# Test that the state of the route exception cache after an ICMP error is
5*c923c149SIdo Schimmel# processed does not depend on whether the quoted packet was matched to a
6*c923c149SIdo Schimmel# socket. Otherwise, an off-path attacker can probe the cache to discover the
7*c923c149SIdo Schimmel# ephemeral port used by a connected UDP socket.
8*c923c149SIdo Schimmel#
9*c923c149SIdo Schimmel# When the quoted packet is not matched to a socket, the same exception is
10*c923c149SIdo Schimmel# created as when it is matched, so that neither its presence nor its contents
11*c923c149SIdo Schimmel# reveal the result of socket matching.
12*c923c149SIdo Schimmel#
13*c923c149SIdo Schimmel#                              +----+
14*c923c149SIdo Schimmel#                    +---------| r1 |
15*c923c149SIdo Schimmel#                    |         +----+
16*c923c149SIdo Schimmel#  +----+   +--------+            | .1
17*c923c149SIdo Schimmel#  | h1 |---| bridge |            |    198.51.100.0/30
18*c923c149SIdo Schimmel#  +----+   +--------+            |    2001:db8:2::/64
19*c923c149SIdo Schimmel#      .1            |            | .2
20*c923c149SIdo Schimmel#                    |         +----+           +----+
21*c923c149SIdo Schimmel#                    +---------| r2 |-----------| h2 |
22*c923c149SIdo Schimmel#                    .2   .3   +----+ .1     .2 +----+
23*c923c149SIdo Schimmel#                                   203.0.113.0/24
24*c923c149SIdo Schimmel#                                   2001:db8:3::/64
25*c923c149SIdo Schimmel#         192.0.2.0/24
26*c923c149SIdo Schimmel#         2001:db8:1::/64
27*c923c149SIdo Schimmel#
28*c923c149SIdo Schimmel# Traffic from h1 to h2 is routed via r1, which reaches h2's network via r2
29*c923c149SIdo Schimmel# over the point-to-point link. The MTU of the r2 - h2 link is lowered so that
30*c923c149SIdo Schimmel# r2 emits ICMP errors towards h1.
31*c923c149SIdo Schimmel#
32*c923c149SIdo Schimmel# For the redirect tests r1's route to h2's network is replaced with one via r2
33*c923c149SIdo Schimmel# on the shared segment, so that r1 forwards the packet back to the segment it
34*c923c149SIdo Schimmel# arrived from and emits a redirect towards h1.
35*c923c149SIdo Schimmel#
36*c923c149SIdo Schimmel# The packets that provoke the ICMP errors are injected with a packet socket so
37*c923c149SIdo Schimmel# that no socket is ever associated with them. A socket is created separately,
38*c923c149SIdo Schimmel# with socat, when a test needs the ICMP error to be matched.
39*c923c149SIdo Schimmel
40*c923c149SIdo Schimmel# shellcheck disable=SC1091,SC2034,SC2154,SC2329
41*c923c149SIdo Schimmelsource lib.sh
42*c923c149SIdo Schimmel
43*c923c149SIdo Schimmelrequire_command jq
44*c923c149SIdo Schimmelrequire_command mausezahn
45*c923c149SIdo Schimmelrequire_command nstat
46*c923c149SIdo Schimmelrequire_command socat
47*c923c149SIdo Schimmel
48*c923c149SIdo SchimmelALL_TESTS="
49*c923c149SIdo Schimmel	pmtu_no_socket_ipv4
50*c923c149SIdo Schimmel	pmtu_no_socket_ipv6
51*c923c149SIdo Schimmel	pmtu_socket_ipv4
52*c923c149SIdo Schimmel	pmtu_socket_ipv6
53*c923c149SIdo Schimmel	pmtu_omit_ipv4
54*c923c149SIdo Schimmel	pmtu_omit_ipv6
55*c923c149SIdo Schimmel	redirect_no_socket_ipv4
56*c923c149SIdo Schimmel	redirect_no_socket_ipv6
57*c923c149SIdo Schimmel	redirect_socket_ipv4
58*c923c149SIdo Schimmel	redirect_socket_ipv6
59*c923c149SIdo Schimmel"
60*c923c149SIdo Schimmel
61*c923c149SIdo Schimmel# Shared segment.
62*c923c149SIdo SchimmelH1_ADDR4=192.0.2.1
63*c923c149SIdo SchimmelR1_ADDR4=192.0.2.2
64*c923c149SIdo SchimmelR2_ADDR4=192.0.2.3
65*c923c149SIdo SchimmelH1_ADDR6=2001:db8:1::1
66*c923c149SIdo SchimmelR1_ADDR6=2001:db8:1::2
67*c923c149SIdo SchimmelR2_ADDR6=2001:db8:1::3
68*c923c149SIdo Schimmel
69*c923c149SIdo Schimmel# r1 - r2 link.
70*c923c149SIdo SchimmelR2_R1_ADDR4=198.51.100.2
71*c923c149SIdo SchimmelR2_R1_ADDR6=2001:db8:2::2
72*c923c149SIdo Schimmel
73*c923c149SIdo Schimmel# r2 - h2 link.
74*c923c149SIdo SchimmelH2_ADDR4=203.0.113.2
75*c923c149SIdo SchimmelH2_NET4=203.0.113.0/24
76*c923c149SIdo SchimmelH2_ADDR6=2001:db8:3::2
77*c923c149SIdo SchimmelH2_NET6=2001:db8:3::/64
78*c923c149SIdo Schimmel
79*c923c149SIdo SchimmelSPORT=12345
80*c923c149SIdo SchimmelDPORT=54321
81*c923c149SIdo Schimmel
82*c923c149SIdo Schimmel# The MTU of the shared segment and of the r1 - r2 link. Large enough for the
83*c923c149SIdo Schimmel# injected packets to reach r2 intact.
84*c923c149SIdo SchimmelSEGMENT_MTU=2000
85*c923c149SIdo Schimmel# Size of the injected packets. The PMTU tests need a size that exceeds every
86*c923c149SIdo Schimmel# MTU used for the r2 - h2 link, so that r2 responds with an ICMP error. The
87*c923c149SIdo Schimmel# redirect tests need a size that does not, otherwise r2 would respond with an
88*c923c149SIdo Schimmel# ICMP error in addition to the redirect emitted by r1.
89*c923c149SIdo SchimmelPMTU_PACKET_SIZE=1800
90*c923c149SIdo SchimmelREDIRECT_PACKET_SIZE=100
91*c923c149SIdo Schimmel
92*c923c149SIdo Schimmel# The MTUs used for the r2 - h2 link. All of them must be at least
93*c923c149SIdo Schimmel# IPV6_MIN_MTU, otherwise IPv6 silently ignores the error instead of creating
94*c923c149SIdo Schimmel# an exception.
95*c923c149SIdo SchimmelMTU_MID=1400
96*c923c149SIdo SchimmelMTU_LOW=1300
97*c923c149SIdo Schimmel
98*c923c149SIdo Schimmel# Values for the IP{,V6}_MTU_DISCOVER socket option.
99*c923c149SIdo SchimmelPMTUDISC_DONT=0
100*c923c149SIdo SchimmelPMTUDISC_OMIT=5
101*c923c149SIdo Schimmel
102*c923c149SIdo SchimmelSOCAT_PID=
103*c923c149SIdo Schimmel
104*c923c149SIdo Schimmellinklocal_get()
105*c923c149SIdo Schimmel{
106*c923c149SIdo Schimmel	local ns=$1; shift
107*c923c149SIdo Schimmel	local dev=$1; shift
108*c923c149SIdo Schimmel
109*c923c149SIdo Schimmel	ip -n "$ns" -j -6 addr show dev "$dev" | \
110*c923c149SIdo Schimmel		jq -r '.[]["addr_info"][] | select(.scope == "link") | .local'
111*c923c149SIdo Schimmel}
112*c923c149SIdo Schimmel
113*c923c149SIdo Schimmellinklocal_exists()
114*c923c149SIdo Schimmel{
115*c923c149SIdo Schimmel	local ns=$1; shift
116*c923c149SIdo Schimmel	local dev=$1; shift
117*c923c149SIdo Schimmel
118*c923c149SIdo Schimmel	[ -n "$(linklocal_get "$ns" "$dev")" ]
119*c923c149SIdo Schimmel}
120*c923c149SIdo Schimmel
121*c923c149SIdo Schimmelfamily_vars_set()
122*c923c149SIdo Schimmel{
123*c923c149SIdo Schimmel	local family=$1; shift
124*c923c149SIdo Schimmel
125*c923c149SIdo Schimmel	FAMILY=$family
126*c923c149SIdo Schimmel
127*c923c149SIdo Schimmel	if [ "$family" -eq 4 ]; then
128*c923c149SIdo Schimmel		H1_ADDR=$H1_ADDR4
129*c923c149SIdo Schimmel		H2_ADDR=$H2_ADDR4
130*c923c149SIdo Schimmel		MZ_FAMILY_OPT=()
131*c923c149SIdo Schimmel		# Without the Don't Fragment bit set r2 fragments the packet
132*c923c149SIdo Schimmel		# instead of reporting the MTU of the next hop.
133*c923c149SIdo Schimmel		MZ_IP_OPTS="df,"
134*c923c149SIdo Schimmel		SOCAT_DST="UDP4-CONNECT:$H2_ADDR4:$DPORT"
135*c923c149SIdo Schimmel		SOCAT_BIND="bind=$H1_ADDR4:$SPORT"
136*c923c149SIdo Schimmel		SOCAT_PMTUDISC="ip-mtu-discover"
137*c923c149SIdo Schimmel	else
138*c923c149SIdo Schimmel		H1_ADDR=$H1_ADDR6
139*c923c149SIdo Schimmel		H2_ADDR=$H2_ADDR6
140*c923c149SIdo Schimmel		MZ_FAMILY_OPT=(-6)
141*c923c149SIdo Schimmel		MZ_IP_OPTS=
142*c923c149SIdo Schimmel		SOCAT_DST="UDP6-CONNECT:[$H2_ADDR6]:$DPORT"
143*c923c149SIdo Schimmel		SOCAT_BIND="bind=[$H1_ADDR6]:$SPORT"
144*c923c149SIdo Schimmel		SOCAT_PMTUDISC="ipv6-mtu-discover"
145*c923c149SIdo Schimmel	fi
146*c923c149SIdo Schimmel}
147*c923c149SIdo Schimmel
148*c923c149SIdo Schimmeltopology_setup()
149*c923c149SIdo Schimmel{
150*c923c149SIdo Schimmel	local ns
151*c923c149SIdo Schimmel
152*c923c149SIdo Schimmel	setup_ns h1 r1 r2 h2 sw
153*c923c149SIdo Schimmel	defer cleanup_all_ns
154*c923c149SIdo Schimmel
155*c923c149SIdo Schimmel	# Link-local addresses are generated from the MAC address and read
156*c923c149SIdo Schimmel	# back during setup, so request that generation mode explicitly and
157*c923c149SIdo Schimmel	# make the addresses available as soon as the devices are brought up.
158*c923c149SIdo Schimmel	for ns in "$h1" "$r1" "$r2" "$h2" "$sw"; do
159*c923c149SIdo Schimmel		ip netns exec "$ns" sysctl -qw \
160*c923c149SIdo Schimmel			net.ipv6.conf.default.addr_gen_mode=0 \
161*c923c149SIdo Schimmel			net.ipv6.conf.default.accept_dad=0 \
162*c923c149SIdo Schimmel			net.ipv6.conf.all.accept_dad=0
163*c923c149SIdo Schimmel	done
164*c923c149SIdo Schimmel
165*c923c149SIdo Schimmel	ip -n "$sw" link add name br0 type bridge
166*c923c149SIdo Schimmel	ip -n "$sw" link set dev br0 mtu "$SEGMENT_MTU" up
167*c923c149SIdo Schimmel
168*c923c149SIdo Schimmel	ip -n "$h1" link add name eth0 mtu "$SEGMENT_MTU" type veth \
169*c923c149SIdo Schimmel		peer name swp1 mtu "$SEGMENT_MTU" netns "$sw"
170*c923c149SIdo Schimmel	ip -n "$r1" link add name eth0 mtu "$SEGMENT_MTU" type veth \
171*c923c149SIdo Schimmel		peer name swp2 mtu "$SEGMENT_MTU" netns "$sw"
172*c923c149SIdo Schimmel	ip -n "$r2" link add name eth0 mtu "$SEGMENT_MTU" type veth \
173*c923c149SIdo Schimmel		peer name swp3 mtu "$SEGMENT_MTU" netns "$sw"
174*c923c149SIdo Schimmel	ip -n "$r1" link add name eth1 mtu "$SEGMENT_MTU" type veth \
175*c923c149SIdo Schimmel		peer name eth1 mtu "$SEGMENT_MTU" netns "$r2"
176*c923c149SIdo Schimmel	ip -n "$r2" link add name eth2 type veth peer name eth0 netns "$h2"
177*c923c149SIdo Schimmel
178*c923c149SIdo Schimmel	ip -n "$sw" link set dev swp1 master br0 up
179*c923c149SIdo Schimmel	ip -n "$sw" link set dev swp2 master br0 up
180*c923c149SIdo Schimmel	ip -n "$sw" link set dev swp3 master br0 up
181*c923c149SIdo Schimmel
182*c923c149SIdo Schimmel	ip -n "$h1" link set dev eth0 up
183*c923c149SIdo Schimmel	ip -n "$r1" link set dev eth0 up
184*c923c149SIdo Schimmel	ip -n "$r1" link set dev eth1 up
185*c923c149SIdo Schimmel	ip -n "$r2" link set dev eth0 up
186*c923c149SIdo Schimmel	ip -n "$r2" link set dev eth1 up
187*c923c149SIdo Schimmel	ip -n "$r2" link set dev eth2 up
188*c923c149SIdo Schimmel	ip -n "$h2" link set dev eth0 up
189*c923c149SIdo Schimmel
190*c923c149SIdo Schimmel	ip -n "$h1" address add "$H1_ADDR4/24" dev eth0
191*c923c149SIdo Schimmel	ip -n "$r1" address add "$R1_ADDR4/24" dev eth0
192*c923c149SIdo Schimmel	ip -n "$r2" address add "$R2_ADDR4/24" dev eth0
193*c923c149SIdo Schimmel	ip -n "$r1" address add 198.51.100.1/30 dev eth1
194*c923c149SIdo Schimmel	ip -n "$r2" address add "$R2_R1_ADDR4/30" dev eth1
195*c923c149SIdo Schimmel	ip -n "$r2" address add 203.0.113.1/24 dev eth2
196*c923c149SIdo Schimmel	ip -n "$h2" address add "$H2_ADDR4/24" dev eth0
197*c923c149SIdo Schimmel
198*c923c149SIdo Schimmel	ip -n "$h1" -6 address add "$H1_ADDR6/64" dev eth0 nodad
199*c923c149SIdo Schimmel	ip -n "$r1" -6 address add "$R1_ADDR6/64" dev eth0 nodad
200*c923c149SIdo Schimmel	ip -n "$r2" -6 address add "$R2_ADDR6/64" dev eth0 nodad
201*c923c149SIdo Schimmel	ip -n "$r1" -6 address add 2001:db8:2::1/64 dev eth1 nodad
202*c923c149SIdo Schimmel	ip -n "$r2" -6 address add "$R2_R1_ADDR6/64" dev eth1 nodad
203*c923c149SIdo Schimmel	ip -n "$r2" -6 address add 2001:db8:3::1/64 dev eth2 nodad
204*c923c149SIdo Schimmel	ip -n "$h2" -6 address add "$H2_ADDR6/64" dev eth0 nodad
205*c923c149SIdo Schimmel
206*c923c149SIdo Schimmel	ip netns exec "$r1" sysctl -qw net.ipv4.ip_forward=1
207*c923c149SIdo Schimmel	ip netns exec "$r1" sysctl -qw net.ipv4.conf.all.send_redirects=1
208*c923c149SIdo Schimmel	ip netns exec "$r1" sysctl -qw net.ipv6.conf.all.forwarding=1
209*c923c149SIdo Schimmel	ip netns exec "$r2" sysctl -qw net.ipv4.ip_forward=1
210*c923c149SIdo Schimmel	ip netns exec "$r2" sysctl -qw net.ipv6.conf.all.forwarding=1
211*c923c149SIdo Schimmel
212*c923c149SIdo Schimmel	ip netns exec "$h1" sysctl -qw net.ipv4.conf.all.accept_redirects=1
213*c923c149SIdo Schimmel	ip netns exec "$h1" sysctl -qw net.ipv4.conf.eth0.accept_redirects=1
214*c923c149SIdo Schimmel	ip netns exec "$h1" sysctl -qw net.ipv6.conf.all.accept_redirects=1
215*c923c149SIdo Schimmel	ip netns exec "$h1" sysctl -qw net.ipv6.conf.eth0.accept_redirects=1
216*c923c149SIdo Schimmel
217*c923c149SIdo Schimmel	slowwait 5 linklocal_exists "$r1" eth0
218*c923c149SIdo Schimmel	check_err $? "r1: link-local address was not generated"
219*c923c149SIdo Schimmel	slowwait 5 linklocal_exists "$r2" eth0
220*c923c149SIdo Schimmel	check_err $? "r2: link-local address was not generated"
221*c923c149SIdo Schimmel
222*c923c149SIdo Schimmel	R1_LLADDR=$(linklocal_get "$r1" eth0)
223*c923c149SIdo Schimmel	R2_LLADDR=$(linklocal_get "$r2" eth0)
224*c923c149SIdo Schimmel	R1_MAC=$(ip -n "$r1" -j link show dev eth0 | jq -r '.[]["address"]')
225*c923c149SIdo Schimmel	R2_MAC=$(ip -n "$r2" -j link show dev eth0 | jq -r '.[]["address"]')
226*c923c149SIdo Schimmel
227*c923c149SIdo Schimmel	ip -n "$h1" route add "$H2_NET4" via "$R1_ADDR4" dev eth0
228*c923c149SIdo Schimmel	ip -n "$h1" -6 route add "$H2_NET6" via "$R1_LLADDR" dev eth0
229*c923c149SIdo Schimmel	ip -n "$r1" route add "$H2_NET4" via "$R2_R1_ADDR4" dev eth1
230*c923c149SIdo Schimmel	ip -n "$r1" -6 route add "$H2_NET6" via "$R2_R1_ADDR6" dev eth1
231*c923c149SIdo Schimmel	ip -n "$h2" route add default via 203.0.113.1 dev eth0
232*c923c149SIdo Schimmel	ip -n "$h2" -6 route add default via 2001:db8:3::1 dev eth0
233*c923c149SIdo Schimmel
234*c923c149SIdo Schimmel	far_mtu_set "$MTU_MID"
235*c923c149SIdo Schimmel}
236*c923c149SIdo Schimmel
237*c923c149SIdo Schimmel# Make r1 forward towards h2's network over the segment it receives the packet
238*c923c149SIdo Schimmel# from, so that it emits a redirect towards h1.
239*c923c149SIdo Schimmelredirect_route_set()
240*c923c149SIdo Schimmel{
241*c923c149SIdo Schimmel	ip -n "$r1" route replace "$H2_NET4" via "$R2_ADDR4" dev eth0
242*c923c149SIdo Schimmel	ip -n "$r1" -6 route replace "$H2_NET6" via "$R2_LLADDR" dev eth0
243*c923c149SIdo Schimmel
244*c923c149SIdo Schimmel	# __ip_do_redirect() only creates an exception if the new gateway is
245*c923c149SIdo Schimmel	# already a valid neighbour. Otherwise it merely triggers address
246*c923c149SIdo Schimmel	# resolution. IPv6 resolves the target itself, in rt6_do_redirect().
247*c923c149SIdo Schimmel	ip -n "$h1" neigh replace "$R2_ADDR4" lladdr "$R2_MAC" dev eth0 \
248*c923c149SIdo Schimmel		nud permanent
249*c923c149SIdo Schimmel}
250*c923c149SIdo Schimmel
251*c923c149SIdo Schimmelfar_mtu_set()
252*c923c149SIdo Schimmel{
253*c923c149SIdo Schimmel	local mtu=$1; shift
254*c923c149SIdo Schimmel
255*c923c149SIdo Schimmel	ip -n "$r2" link set dev eth2 mtu "$mtu"
256*c923c149SIdo Schimmel	ip -n "$h2" link set dev eth0 mtu "$mtu"
257*c923c149SIdo Schimmel}
258*c923c149SIdo Schimmel
259*c923c149SIdo Schimmelsocket_is_open()
260*c923c149SIdo Schimmel{
261*c923c149SIdo Schimmel	ip netns exec "$h1" ss -uHn "sport = :$SPORT" | grep -q .
262*c923c149SIdo Schimmel}
263*c923c149SIdo Schimmel
264*c923c149SIdo Schimmelsocket_start()
265*c923c149SIdo Schimmel{
266*c923c149SIdo Schimmel	# Disable PMTU discovery by default so that ICMP errors are not
267*c923c149SIdo Schimmel	# reported to the socket. Otherwise socat would exit when the first one
268*c923c149SIdo Schimmel	# arrives and later packets in the same test would not be matched to a
269*c923c149SIdo Schimmel	# socket. The exception is still created, as ip{,6}_sk_accept_pmtu()
270*c923c149SIdo Schimmel	# only rejects IP{,V6}_PMTUDISC_{INTERFACE,OMIT}.
271*c923c149SIdo Schimmel	local pmtudisc=${1:-$PMTUDISC_DONT}
272*c923c149SIdo Schimmel
273*c923c149SIdo Schimmel	# Send socat's diagnostics to /dev/null. It reports the ICMP errors
274*c923c149SIdo Schimmel	# that reach the socket, which is exactly what the tests provoke.
275*c923c149SIdo Schimmel	ip netns exec "$h1" socat -u -lf/dev/null \
276*c923c149SIdo Schimmel		"$SOCAT_DST,$SOCAT_BIND,$SOCAT_PMTUDISC=$pmtudisc" \
277*c923c149SIdo Schimmel		OPEN:/dev/null,wronly=1 &
278*c923c149SIdo Schimmel	SOCAT_PID=$!
279*c923c149SIdo Schimmel	defer socket_stop
280*c923c149SIdo Schimmel
281*c923c149SIdo Schimmel	slowwait 5 socket_is_open
282*c923c149SIdo Schimmel	check_err $? "socket did not open"
283*c923c149SIdo Schimmel}
284*c923c149SIdo Schimmel
285*c923c149SIdo Schimmelsocket_stop()
286*c923c149SIdo Schimmel{
287*c923c149SIdo Schimmel	[ -z "$SOCAT_PID" ] && return 0
288*c923c149SIdo Schimmel
289*c923c149SIdo Schimmel	kill "$SOCAT_PID" &> /dev/null
290*c923c149SIdo Schimmel	wait "$SOCAT_PID" 2> /dev/null
291*c923c149SIdo Schimmel	SOCAT_PID=
292*c923c149SIdo Schimmel}
293*c923c149SIdo Schimmel
294*c923c149SIdo Schimmel# Inject a packet towards h2 with a packet socket. No socket is associated with
295*c923c149SIdo Schimmel# it, so an ICMP error quoting it is matched to a socket only if one was
296*c923c149SIdo Schimmel# created separately with the same source port.
297*c923c149SIdo Schimmelpacket_send()
298*c923c149SIdo Schimmel{
299*c923c149SIdo Schimmel	local size=$1; shift
300*c923c149SIdo Schimmel
301*c923c149SIdo Schimmel	ip netns exec "$h1" mausezahn "${MZ_FAMILY_OPT[@]}" eth0 \
302*c923c149SIdo Schimmel		-a own -b "$R1_MAC" -A "$H1_ADDR" -B "$H2_ADDR" \
303*c923c149SIdo Schimmel		-t udp "${MZ_IP_OPTS}sp=$SPORT,dp=$DPORT" \
304*c923c149SIdo Schimmel		-p "$size" -c 1 -q
305*c923c149SIdo Schimmel}
306*c923c149SIdo Schimmel
307*c923c149SIdo Schimmelexception_show()
308*c923c149SIdo Schimmel{
309*c923c149SIdo Schimmel	if [ "$FAMILY" -eq 4 ]; then
310*c923c149SIdo Schimmel		# IPv4 exceptions without a bound route are not dumped, but
311*c923c149SIdo Schimmel		# "route get" reports the exception and binds a route to it.
312*c923c149SIdo Schimmel		ip -n "$h1" route get "$H2_ADDR"
313*c923c149SIdo Schimmel	else
314*c923c149SIdo Schimmel		# IPv6 does not report a cache indication in "route get"
315*c923c149SIdo Schimmel		# output, so dump the exceptions instead.
316*c923c149SIdo Schimmel		ip -n "$h1" -6 route show cache | grep -F "$H2_ADDR" || true
317*c923c149SIdo Schimmel	fi
318*c923c149SIdo Schimmel}
319*c923c149SIdo Schimmel
320*c923c149SIdo Schimmelexception_mtu_get()
321*c923c149SIdo Schimmel{
322*c923c149SIdo Schimmel	exception_show | grep -o "mtu [0-9]*" | cut -d ' ' -f 2
323*c923c149SIdo Schimmel}
324*c923c149SIdo Schimmel
325*c923c149SIdo Schimmelexception_gw_get()
326*c923c149SIdo Schimmel{
327*c923c149SIdo Schimmel	exception_show | grep -o "via [0-9a-f.:]*" | cut -d ' ' -f 2
328*c923c149SIdo Schimmel}
329*c923c149SIdo Schimmel
330*c923c149SIdo Schimmelexception_mtu_check()
331*c923c149SIdo Schimmel{
332*c923c149SIdo Schimmel	local expected=$1; shift
333*c923c149SIdo Schimmel
334*c923c149SIdo Schimmel	[ "$(exception_mtu_get)" = "$expected" ]
335*c923c149SIdo Schimmel}
336*c923c149SIdo Schimmel
337*c923c149SIdo Schimmelicmp_errors_get()
338*c923c149SIdo Schimmel{
339*c923c149SIdo Schimmel	local ctr=IcmpInDestUnreachs
340*c923c149SIdo Schimmel
341*c923c149SIdo Schimmel	[ "$FAMILY" -eq 6 ] && ctr=Icmp6InPktTooBigs
342*c923c149SIdo Schimmel
343*c923c149SIdo Schimmel	ip netns exec "$h1" nstat -asz "$ctr" | \
344*c923c149SIdo Schimmel		awk -v ctr="$ctr" '$1 == ctr { print $2 }'
345*c923c149SIdo Schimmel}
346*c923c149SIdo Schimmel
347*c923c149SIdo Schimmelexception_pmtu_check()
348*c923c149SIdo Schimmel{
349*c923c149SIdo Schimmel	local mtu=$1; shift
350*c923c149SIdo Schimmel	local desc=$1; shift
351*c923c149SIdo Schimmel
352*c923c149SIdo Schimmel	busywait "$BUSYWAIT_TIMEOUT" exception_mtu_check "$mtu"
353*c923c149SIdo Schimmel	check_err $? "$desc: exception does not carry an MTU of $mtu"
354*c923c149SIdo Schimmel}
355*c923c149SIdo Schimmel
356*c923c149SIdo Schimmelpmtu_no_socket()
357*c923c149SIdo Schimmel{
358*c923c149SIdo Schimmel	local family=$1; shift
359*c923c149SIdo Schimmel
360*c923c149SIdo Schimmel	RET=0
361*c923c149SIdo Schimmel	family_vars_set "$family"
362*c923c149SIdo Schimmel	topology_setup
363*c923c149SIdo Schimmel
364*c923c149SIdo Schimmel	packet_send "$PMTU_PACKET_SIZE"
365*c923c149SIdo Schimmel	exception_pmtu_check "$MTU_MID" "No socket"
366*c923c149SIdo Schimmel
367*c923c149SIdo Schimmel	log_test "IPv$family: PMTU: exception without a matching socket"
368*c923c149SIdo Schimmel}
369*c923c149SIdo Schimmel
370*c923c149SIdo Schimmelpmtu_no_socket_ipv4()
371*c923c149SIdo Schimmel{
372*c923c149SIdo Schimmel	pmtu_no_socket 4
373*c923c149SIdo Schimmel}
374*c923c149SIdo Schimmel
375*c923c149SIdo Schimmelpmtu_no_socket_ipv6()
376*c923c149SIdo Schimmel{
377*c923c149SIdo Schimmel	pmtu_no_socket 6
378*c923c149SIdo Schimmel}
379*c923c149SIdo Schimmel
380*c923c149SIdo Schimmelpmtu_socket()
381*c923c149SIdo Schimmel{
382*c923c149SIdo Schimmel	local family=$1; shift
383*c923c149SIdo Schimmel	local t0
384*c923c149SIdo Schimmel
385*c923c149SIdo Schimmel	RET=0
386*c923c149SIdo Schimmel	family_vars_set "$family"
387*c923c149SIdo Schimmel	topology_setup
388*c923c149SIdo Schimmel	socket_start
389*c923c149SIdo Schimmel
390*c923c149SIdo Schimmel	packet_send "$PMTU_PACKET_SIZE"
391*c923c149SIdo Schimmel	exception_pmtu_check "$MTU_MID" "Matching socket"
392*c923c149SIdo Schimmel
393*c923c149SIdo Schimmel	# A lower PMTU replaces the one currently stored in the exception.
394*c923c149SIdo Schimmel	far_mtu_set "$MTU_LOW"
395*c923c149SIdo Schimmel	packet_send "$PMTU_PACKET_SIZE"
396*c923c149SIdo Schimmel	exception_pmtu_check "$MTU_LOW" "Lower PMTU"
397*c923c149SIdo Schimmel
398*c923c149SIdo Schimmel	# A higher PMTU is ignored, so the exception is left as it is. Wait
399*c923c149SIdo Schimmel	# for the error to be received, as otherwise the check below would
400*c923c149SIdo Schimmel	# pass even if it never was.
401*c923c149SIdo Schimmel	far_mtu_set "$MTU_MID"
402*c923c149SIdo Schimmel	t0=$(icmp_errors_get)
403*c923c149SIdo Schimmel	packet_send "$PMTU_PACKET_SIZE"
404*c923c149SIdo Schimmel	busywait "$BUSYWAIT_TIMEOUT" until_counter_is ">= $((t0 + 1))" \
405*c923c149SIdo Schimmel		icmp_errors_get > /dev/null
406*c923c149SIdo Schimmel	check_err $? "Higher PMTU: ICMP error was not received"
407*c923c149SIdo Schimmel
408*c923c149SIdo Schimmel	exception_mtu_check "$MTU_LOW"
409*c923c149SIdo Schimmel	check_err $? "Higher PMTU: exception does not carry an MTU of $MTU_LOW"
410*c923c149SIdo Schimmel
411*c923c149SIdo Schimmel	log_test "IPv$family: PMTU: exception with a matching socket"
412*c923c149SIdo Schimmel}
413*c923c149SIdo Schimmel
414*c923c149SIdo Schimmelpmtu_socket_ipv4()
415*c923c149SIdo Schimmel{
416*c923c149SIdo Schimmel	pmtu_socket 4
417*c923c149SIdo Schimmel}
418*c923c149SIdo Schimmel
419*c923c149SIdo Schimmelpmtu_socket_ipv6()
420*c923c149SIdo Schimmel{
421*c923c149SIdo Schimmel	pmtu_socket 6
422*c923c149SIdo Schimmel}
423*c923c149SIdo Schimmel
424*c923c149SIdo Schimmelpmtu_omit()
425*c923c149SIdo Schimmel{
426*c923c149SIdo Schimmel	local family=$1; shift
427*c923c149SIdo Schimmel
428*c923c149SIdo Schimmel	RET=0
429*c923c149SIdo Schimmel	family_vars_set "$family"
430*c923c149SIdo Schimmel	topology_setup
431*c923c149SIdo Schimmel	socket_start "$PMTUDISC_OMIT"
432*c923c149SIdo Schimmel
433*c923c149SIdo Schimmel	packet_send "$PMTU_PACKET_SIZE"
434*c923c149SIdo Schimmel	exception_pmtu_check "$MTU_MID" "PMTU discovery disabled"
435*c923c149SIdo Schimmel
436*c923c149SIdo Schimmel	log_test "IPv$family: PMTU: exception with a socket ignoring it"
437*c923c149SIdo Schimmel}
438*c923c149SIdo Schimmel
439*c923c149SIdo Schimmelpmtu_omit_ipv4()
440*c923c149SIdo Schimmel{
441*c923c149SIdo Schimmel	pmtu_omit 4
442*c923c149SIdo Schimmel}
443*c923c149SIdo Schimmel
444*c923c149SIdo Schimmelpmtu_omit_ipv6()
445*c923c149SIdo Schimmel{
446*c923c149SIdo Schimmel	pmtu_omit 6
447*c923c149SIdo Schimmel}
448*c923c149SIdo Schimmel
449*c923c149SIdo Schimmelexception_gw_check()
450*c923c149SIdo Schimmel{
451*c923c149SIdo Schimmel	local expected=$1; shift
452*c923c149SIdo Schimmel
453*c923c149SIdo Schimmel	[ -n "$expected" ] && [ "$(exception_gw_get)" = "$expected" ]
454*c923c149SIdo Schimmel}
455*c923c149SIdo Schimmel
456*c923c149SIdo Schimmelredirect_gw_new()
457*c923c149SIdo Schimmel{
458*c923c149SIdo Schimmel	if [ "$FAMILY" -eq 4 ]; then
459*c923c149SIdo Schimmel		echo "$R2_ADDR4"
460*c923c149SIdo Schimmel	else
461*c923c149SIdo Schimmel		echo "$R2_LLADDR"
462*c923c149SIdo Schimmel	fi
463*c923c149SIdo Schimmel}
464*c923c149SIdo Schimmel
465*c923c149SIdo Schimmelredirect_no_socket()
466*c923c149SIdo Schimmel{
467*c923c149SIdo Schimmel	local family=$1; shift
468*c923c149SIdo Schimmel
469*c923c149SIdo Schimmel	RET=0
470*c923c149SIdo Schimmel	family_vars_set "$family"
471*c923c149SIdo Schimmel	topology_setup
472*c923c149SIdo Schimmel	redirect_route_set
473*c923c149SIdo Schimmel
474*c923c149SIdo Schimmel	packet_send "$REDIRECT_PACKET_SIZE"
475*c923c149SIdo Schimmel	busywait "$BUSYWAIT_TIMEOUT" exception_gw_check "$(redirect_gw_new)"
476*c923c149SIdo Schimmel	check_err $? "No socket: exception does not carry the new gateway"
477*c923c149SIdo Schimmel
478*c923c149SIdo Schimmel	log_test "IPv$family: Redirect: exception without a matching socket"
479*c923c149SIdo Schimmel}
480*c923c149SIdo Schimmel
481*c923c149SIdo Schimmelredirect_no_socket_ipv4()
482*c923c149SIdo Schimmel{
483*c923c149SIdo Schimmel	redirect_no_socket 4
484*c923c149SIdo Schimmel}
485*c923c149SIdo Schimmel
486*c923c149SIdo Schimmelredirect_no_socket_ipv6()
487*c923c149SIdo Schimmel{
488*c923c149SIdo Schimmel	redirect_no_socket 6
489*c923c149SIdo Schimmel}
490*c923c149SIdo Schimmel
491*c923c149SIdo Schimmelredirect_socket()
492*c923c149SIdo Schimmel{
493*c923c149SIdo Schimmel	local family=$1; shift
494*c923c149SIdo Schimmel
495*c923c149SIdo Schimmel	RET=0
496*c923c149SIdo Schimmel	family_vars_set "$family"
497*c923c149SIdo Schimmel	topology_setup
498*c923c149SIdo Schimmel	redirect_route_set
499*c923c149SIdo Schimmel	socket_start
500*c923c149SIdo Schimmel
501*c923c149SIdo Schimmel	packet_send "$REDIRECT_PACKET_SIZE"
502*c923c149SIdo Schimmel	busywait "$BUSYWAIT_TIMEOUT" exception_gw_check "$(redirect_gw_new)"
503*c923c149SIdo Schimmel	check_err $? "Matching socket: exception does not carry the new gateway"
504*c923c149SIdo Schimmel
505*c923c149SIdo Schimmel	log_test "IPv$family: Redirect: exception with a matching socket"
506*c923c149SIdo Schimmel}
507*c923c149SIdo Schimmel
508*c923c149SIdo Schimmelredirect_socket_ipv4()
509*c923c149SIdo Schimmel{
510*c923c149SIdo Schimmel	redirect_socket 4
511*c923c149SIdo Schimmel}
512*c923c149SIdo Schimmel
513*c923c149SIdo Schimmelredirect_socket_ipv6()
514*c923c149SIdo Schimmel{
515*c923c149SIdo Schimmel	redirect_socket 6
516*c923c149SIdo Schimmel}
517*c923c149SIdo Schimmel
518*c923c149SIdo Schimmeltrap defer_scopes_cleanup EXIT
519*c923c149SIdo Schimmeltests_run
520*c923c149SIdo Schimmel
521*c923c149SIdo Schimmelexit "$EXIT_STATUS"
522