xref: /netbsd-src/tests/net/arp/t_arp.sh (revision e781f1b0f718d190e8c0bb85c26b6c7e8178130f)
1#	$NetBSD: t_arp.sh,v 1.48 2024/09/09 07:26:42 ozaki-r Exp $
2#
3# Copyright (c) 2015 The NetBSD Foundation, Inc.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25# POSSIBILITY OF SUCH DAMAGE.
26#
27
28SOCKSRC=unix://commsock1
29SOCKDST=unix://commsock2
30IP4SRC=10.0.1.1
31IP4SRC2=10.0.1.5
32IP4NET=10.0.1.0
33IP4DST=10.0.1.2
34IP4DST_PROXYARP1=10.0.1.3
35IP4DST_PROXYARP2=10.0.1.4
36IP4DST_FAIL1=10.0.1.99
37IP4DST_FAIL2=10.0.99.99
38
39DEBUG=${DEBUG:-false}
40TIMEOUT=1
41
42setup_dst_server()
43{
44
45	rump_server_add_iface $SOCKDST shmif0 bus1
46	export RUMP_SERVER=$SOCKDST
47	atf_check -s exit:0 rump.ifconfig shmif0 inet $IP4DST/24
48	atf_check -s exit:0 rump.ifconfig shmif0 up
49	atf_check -s exit:0 rump.ifconfig -w 10
50
51	$DEBUG && rump.ifconfig shmif0
52	$DEBUG && rump.arp -n -a
53	$DEBUG && rump.netstat -nr -f inet
54}
55
56setup_src_server()
57{
58	local keep=${1:-0}
59
60	export RUMP_SERVER=$SOCKSRC
61
62	# Shorten the expire time of cache entries
63	if [ $keep != 0 ]; then
64		# Convert to ms
65		keep=$(($keep * 1000))
66		atf_check -s exit:0 -o ignore \
67		    rump.sysctl -w net.inet.arp.nd_reachable=$keep
68	fi
69
70	# Setup an interface
71	rump_server_add_iface $SOCKSRC shmif0 bus1
72	atf_check -s exit:0 rump.ifconfig shmif0 inet $IP4SRC/24
73	atf_check -s exit:0 rump.ifconfig shmif0 up
74	atf_check -s exit:0 rump.ifconfig -w 10
75
76	# Sanity check
77	$DEBUG && rump.ifconfig shmif0
78	$DEBUG && rump.arp -n -a
79	$DEBUG && rump.netstat -nr -f inet
80	atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4SRC
81	atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST
82}
83
84get_timeout()
85{
86	local addr="$1"
87	local timeout=$(env RUMP_SERVER=$SOCKSRC rump.arp -n $addr |grep $addr|awk '{print $7;}')
88	timeout=${timeout%s}
89	echo $timeout
90}
91
92test_cache_expiration()
93{
94	local arp_keep=7
95
96	rump_server_start $SOCKSRC
97	rump_server_start $SOCKDST
98
99	setup_dst_server
100	setup_src_server $arp_keep
101
102	# Make a permanent cache entry to avoid sending an NS packet disturbing
103	# the test
104	macaddr=$(get_macaddr $SOCKSRC shmif0)
105	export RUMP_SERVER=$SOCKDST
106	atf_check -s exit:0 -o ignore rump.arp -s $IP4SRC $macaddr
107
108	export RUMP_SERVER=$SOCKSRC
109
110	#
111	# Check if a cache is expired expectedly
112	#
113	atf_check -s exit:0 -o ignore rump.ping -n -w $TIMEOUT -c 1 $IP4DST
114
115	$DEBUG && rump.arp -n -a
116	atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.arp -n $IP4SRC
117	# Should be cached
118	atf_check -s exit:0 -o not-match:'permanent' rump.arp -n $IP4DST
119
120	timeout=$(get_timeout $IP4DST)
121
122	atf_check -s exit:0 sleep $(($timeout + 1))
123
124	$DEBUG && rump.arp -n -a
125	atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.arp -n $IP4SRC
126	# Expired but remains until GC sweaps it (1 day)
127	atf_check -s exit:0 -o match:"$ONEDAYISH" rump.arp -n $IP4DST
128
129	rump_server_destroy_ifaces
130}
131
132check_arp_static_entry()
133{
134	local ip=$1
135	local mac=$2
136	local type=$3
137	local flags=
138
139	atf_check -s exit:0 -o match:"$mac" rump.arp -n $ip
140	if [ $type = 'permanent' ]; then
141		atf_check -s exit:0 -o match:'permanent' rump.arp -n $ip
142		check_route $ip "$mac" UHLS shmif0
143	else
144		atf_check -s exit:0 -o not-match:'permanent' rump.arp -n $ip
145		check_route $ip "$mac" UHL shmif0
146	fi
147}
148
149test_command()
150{
151	local arp_keep=5
152	local bonus=2
153
154	rump_server_start $SOCKSRC
155	rump_server_start $SOCKDST
156
157	setup_dst_server
158	setup_src_server $arp_keep
159
160	export RUMP_SERVER=$SOCKSRC
161
162	# Add and delete a static entry
163	$DEBUG && rump.arp -n -a
164	atf_check -s exit:0 -o ignore rump.arp -s 10.0.1.10 b2:a0:20:00:00:10
165	$DEBUG && rump.arp -n -a
166	$DEBUG && rump.netstat -nr -f inet
167	check_arp_static_entry 10.0.1.10 'b2:a0:20:00:00:10' permanent
168	atf_check -s exit:0 -o ignore rump.arp -d 10.0.1.10
169	$DEBUG && rump.arp -n -a
170	$DEBUG && rump.netstat -nr -f inet
171	atf_check -s not-exit:0 -e ignore rump.arp -n 10.0.1.10
172	check_route_no_entry 10.0.1.10
173
174	# Add multiple entries via a file
175	cat - > ./list <<-EOF
176	10.0.1.11 b2:a0:20:00:00:11
177	10.0.1.12 b2:a0:20:00:00:12
178	10.0.1.13 b2:a0:20:00:00:13
179	10.0.1.14 b2:a0:20:00:00:14
180	10.0.1.15 b2:a0:20:00:00:15
181	EOF
182	$DEBUG && rump.arp -n -a
183	$DEBUG && rump.netstat -nr -f inet
184	atf_check -s exit:0 -o ignore rump.arp -f ./list
185	$DEBUG && rump.arp -n -a
186	$DEBUG && rump.netstat -nr -f inet
187	check_arp_static_entry 10.0.1.11 'b2:a0:20:00:00:11' permanent
188	check_arp_static_entry 10.0.1.12 'b2:a0:20:00:00:12' permanent
189	check_arp_static_entry 10.0.1.13 'b2:a0:20:00:00:13' permanent
190	check_arp_static_entry 10.0.1.14 'b2:a0:20:00:00:14' permanent
191	check_arp_static_entry 10.0.1.15 'b2:a0:20:00:00:15' permanent
192
193	# Test arp -a
194	atf_check -s exit:0 -o match:'10.0.1.11' rump.arp -n -a
195	atf_check -s exit:0 -o match:'10.0.1.12' rump.arp -n -a
196	atf_check -s exit:0 -o match:'10.0.1.13' rump.arp -n -a
197	atf_check -s exit:0 -o match:'10.0.1.14' rump.arp -n -a
198	atf_check -s exit:0 -o match:'10.0.1.15' rump.arp -n -a
199
200	# Flush all entries
201	$DEBUG && rump.arp -n -a
202	$DEBUG && rump.netstat -nr -f inet
203	atf_check -s exit:0 -o ignore rump.arp -d -a
204	atf_check -s not-exit:0 -e ignore rump.arp -n 10.0.1.11
205	atf_check -s not-exit:0 -e ignore rump.arp -n 10.0.1.12
206	atf_check -s not-exit:0 -e ignore rump.arp -n 10.0.1.13
207	atf_check -s not-exit:0 -e ignore rump.arp -n 10.0.1.14
208	atf_check -s not-exit:0 -e ignore rump.arp -n 10.0.1.15
209	atf_check -s not-exit:0 -e ignore rump.arp -n 10.0.1.1
210	check_route_no_entry 10.0.1.11
211	check_route_no_entry 10.0.1.12
212	check_route_no_entry 10.0.1.13
213	check_route_no_entry 10.0.1.14
214	check_route_no_entry 10.0.1.15
215
216	# Test temp option
217	$DEBUG && rump.arp -n -a
218	atf_check -s exit:0 -o ignore rump.arp -s 10.0.1.10 b2:a0:20:00:00:10 temp
219	$DEBUG && rump.arp -n -a
220	$DEBUG && rump.netstat -nr -f inet
221	check_arp_static_entry 10.0.1.10 'b2:a0:20:00:00:10' temp
222
223	# Hm? the cache doesn't expire...
224	#atf_check -s exit:0 sleep $(($arp_keep + $bonus))
225	#$DEBUG && rump.arp -n -a
226	#$DEBUG && rump.netstat -nr -f inet
227	#atf_check -s not-exit:0 -e ignore rump.arp -n 10.0.1.10
228
229	rump_server_destroy_ifaces
230}
231
232make_pkt_str_arpreq()
233{
234	local target=$1
235	local sender=$2
236	pkt="> ff:ff:ff:ff:ff:ff, ethertype ARP \(0x0806\), length 42:"
237	pkt="$pkt Request who-has $target tell $sender, length 28"
238	echo $pkt
239}
240
241test_garp_common()
242{
243	local no_dad=$1
244	local pkt=
245
246	rump_server_start $SOCKSRC
247
248	export RUMP_SERVER=$SOCKSRC
249
250	if $no_dad; then
251		atf_check -s exit:0 -o match:'3 -> 0' \
252		    rump.sysctl -w net.inet.ip.dad_count=0
253	fi
254
255	# Setup an interface
256	rump_server_add_iface $SOCKSRC shmif0 bus1
257	atf_check -s exit:0 rump.ifconfig shmif0 inet 10.0.0.1/24
258	atf_check -s exit:0 rump.ifconfig shmif0 up
259	$DEBUG && rump.ifconfig shmif0
260
261	atf_check -s exit:0 sleep 1
262	extract_new_packets bus1 > ./out
263
264	#
265	# Assign an address to an interface without IFF_UP
266	#
267	# A GARP packet is sent for the primary address
268	pkt=$(make_pkt_str_arpreq 10.0.0.1 10.0.0.1)
269	atf_check -s exit:0 -o match:"$pkt" cat ./out
270
271	atf_check -s exit:0 rump.ifconfig shmif0 down
272	atf_check -s exit:0 rump.ifconfig shmif0 inet 10.0.0.2/24 alias
273
274	atf_check -s exit:0 sleep 1
275	extract_new_packets bus1 > ./out
276
277	# A GARP packet is sent for the alias address
278	pkt=$(make_pkt_str_arpreq 10.0.0.2 10.0.0.2)
279	atf_check -s exit:0 -o match:"$pkt" cat ./out
280
281	# Clean up
282	atf_check -s exit:0 rump.ifconfig shmif0 inet 10.0.0.1/24 delete
283	atf_check -s exit:0 rump.ifconfig shmif0 inet 10.0.0.2/24 delete
284
285	#
286	# Assign an address to an interface with IFF_UP
287	#
288	atf_check -s exit:0 rump.ifconfig shmif0 up
289
290	# Primary address
291	atf_check -s exit:0 rump.ifconfig shmif0 inet 10.0.0.3/24
292
293	atf_check -s exit:0 sleep 1
294	extract_new_packets bus1 > ./out
295
296	pkt=$(make_pkt_str_arpreq 10.0.0.3 10.0.0.3)
297	if $no_dad; then
298		# A GARP packet is sent
299		atf_check -s exit:0 -o match:"$pkt" cat ./out
300	else
301		# No GARP packet is sent
302		atf_check -s exit:0 -o not-match:"$pkt" cat ./out
303	fi
304
305	# Alias address
306	atf_check -s exit:0 rump.ifconfig shmif0 inet 10.0.0.4/24 alias
307
308	atf_check -s exit:0 sleep 1
309	extract_new_packets bus1 > ./out
310
311	pkt=$(make_pkt_str_arpreq 10.0.0.4 10.0.0.4)
312	if $no_dad; then
313		# A GARP packet is sent
314		atf_check -s exit:0 -o match:"$pkt" cat ./out
315	else
316		# No GARP packet is sent
317		atf_check -s exit:0 -o not-match:"$pkt" cat ./out
318	fi
319
320	#
321	# GARP on Link up
322	#
323	atf_check -s exit:0 rump.ifconfig shmif0 media none
324	extract_new_packets bus1 > ./out
325	atf_check -s exit:0 rump.ifconfig shmif0 media auto
326
327	atf_check -s exit:0 sleep 1
328	extract_new_packets bus1 > ./out
329
330	if $no_dad; then
331		# A GARP packet is sent for both primary and alias addresses.
332		pkt=$(make_pkt_str_arpreq 10.0.0.3 10.0.0.3)
333		atf_check -s exit:0 -o match:"$pkt" cat ./out
334		pkt=$(make_pkt_str_arpreq 10.0.0.4 10.0.0.4)
335		atf_check -s exit:0 -o match:"$pkt" cat ./out
336	else
337		# No GARP is sent.
338		pkt=$(make_pkt_str_arpreq 10.0.0.3 10.0.0.3)
339		atf_check -s exit:0 -o not-match:"$pkt" cat ./out
340		pkt=$(make_pkt_str_arpreq 10.0.0.4 10.0.0.4)
341		atf_check -s exit:0 -o not-match:"$pkt" cat ./out
342		# DAD packets are sent instead.
343		pkt=$(make_pkt_str_arpreq 10.0.0.3 0.0.0.0)
344		atf_check -s exit:0 -o match:"$pkt" cat ./out
345		pkt=$(make_pkt_str_arpreq 10.0.0.4 0.0.0.0)
346		atf_check -s exit:0 -o match:"$pkt" cat ./out
347	fi
348
349	rump_server_destroy_ifaces
350}
351
352test_garp()
353{
354
355	test_garp_common false
356}
357
358test_garp_without_dad()
359{
360
361	test_garp_common true
362}
363
364test_cache_overwriting()
365{
366
367	rump_server_start $SOCKSRC
368	rump_server_start $SOCKDST
369
370	setup_dst_server
371	setup_src_server
372
373	export RUMP_SERVER=$SOCKSRC
374
375	# Cannot overwrite a permanent cache
376	atf_check -s exit:0 rump.arp -s $IP4DST b2:a0:20:00:00:ff
377	$DEBUG && rump.arp -n -a
378	atf_check -s not-exit:0 -e match:'File exists' \
379	    rump.arp -s $IP4DST b2:a0:20:00:00:fe
380	# cleanup
381	atf_check -s exit:0 rump.arp -d $IP4DST
382
383	atf_check -s exit:0 -o ignore rump.ping -n -w $TIMEOUT -c 1 $IP4DST
384	$DEBUG && rump.arp -n -a
385	# Can overwrite a dynamic cache
386	atf_check -s exit:0 -o ignore rump.arp -s $IP4DST b2:a0:20:00:00:00
387	$DEBUG && rump.arp -n -a
388	atf_check -s exit:0 -o match:'b2:a0:20:00:00:00' rump.arp -n $IP4DST
389	atf_check -s exit:0 -o match:'permanent' rump.arp -n $IP4DST
390
391	atf_check -s exit:0 -o ignore rump.arp -s 10.0.1.10 b2:a0:20:00:00:10 temp
392	$DEBUG && rump.arp -n -a
393	atf_check -s exit:0 -o match:'b2:a0:20:00:00:10' rump.arp -n 10.0.1.10
394	atf_check -s exit:0 -o not-match:'permanent' rump.arp -n 10.0.1.10
395	# Can overwrite a temp cache
396	atf_check -s exit:0 -o ignore rump.arp -s 10.0.1.10 b2:a0:20:00:00:ff
397	atf_check -s exit:0 -o match:'b2:a0:20:00:00:ff' rump.arp -n 10.0.1.10
398	$DEBUG && rump.arp -n -a
399
400	rump_server_destroy_ifaces
401}
402
403make_pkt_str_arprep()
404{
405	local ip=$1
406	local mac=$2
407	pkt="ethertype ARP (0x0806), length 42: "
408	pkt="Reply $ip is-at $mac, length 28"
409	echo $pkt
410}
411
412make_pkt_str_garp()
413{
414	local ip=$1
415	local mac=$2
416	local pkt=
417	pkt="$mac > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806),"
418	pkt="$pkt length 42: Request who-has $ip tell $ip, length 28"
419	echo $pkt
420}
421
422test_proxy_arp()
423{
424	local opts= title= flags=
425	local type=$1
426
427	rump_server_start $SOCKSRC
428	rump_server_fs_start $SOCKDST tap
429
430	setup_dst_server
431	setup_src_server
432
433	export RUMP_SERVER=$SOCKDST
434	atf_check -s exit:0 -o ignore rump.sysctl -w net.inet.ip.forwarding=1
435	macaddr_dst=$(get_macaddr $SOCKDST shmif0)
436
437	if [ "$type" = "pub" ]; then
438		opts="pub"
439	else
440		opts="pub proxy"
441	fi
442	# Always proxy only since migrating to lltable/llentry
443	title='published \(proxy only\)'
444
445	#
446	# Test#1: First setup an endpoint then create proxy arp entry
447	#
448	export RUMP_SERVER=$SOCKDST
449	rump_server_add_iface $SOCKDST tap1
450	atf_check -s exit:0 rump.ifconfig tap1 $IP4DST_PROXYARP1/24 up
451	atf_check -s exit:0 rump.ifconfig -w 10
452
453	# Try to ping (should fail w/o proxy arp)
454	export RUMP_SERVER=$SOCKSRC
455	atf_check -s not-exit:0 -o ignore -e ignore \
456	    rump.ping -n -w 1 -c 1 $IP4DST_PROXYARP1
457	# Remove ARP entry as it may hang around in WAITDELETE a few seconds
458	atf_check -s ignore rump.arp -d $IP4DST_PROXYARP1
459
460	# Flushing
461	extract_new_packets bus1 > ./out
462
463	# Set up proxy ARP entry
464	export RUMP_SERVER=$SOCKDST
465	atf_check -s exit:0 -o ignore \
466	    rump.arp -s $IP4DST_PROXYARP1 $macaddr_dst $opts
467	atf_check -s exit:0 -o match:"$title" rump.arp -n $IP4DST_PROXYARP1
468
469	# Try to ping
470	export RUMP_SERVER=$SOCKSRC
471	atf_check -s exit:0 -o ignore rump.ping -n -w 1 -c 1 $IP4DST_PROXYARP1
472
473	extract_new_packets bus1 > ./out
474	$DEBUG && cat ./out
475
476	pkt1=$(make_pkt_str_arprep $IP4DST_PROXYARP1 $macaddr_dst)
477	pkt2=$(make_pkt_str_garp $IP4DST_PROXYARP1 $macaddr_dst)
478	atf_check -s exit:0 -x "cat ./out |grep -q -e '$pkt1' -e '$pkt2'"
479
480	#
481	# Test#2: Create proxy arp entry then set up an endpoint
482	#
483	export RUMP_SERVER=$SOCKDST
484	atf_check -s exit:0 -o ignore \
485	    rump.arp -s $IP4DST_PROXYARP2 $macaddr_dst $opts
486	atf_check -s exit:0 -o match:"$title" rump.arp -n $IP4DST_PROXYARP2
487	$DEBUG && rump.netstat -nr -f inet
488
489	# Try to ping (should fail because no endpoint exists)
490	export RUMP_SERVER=$SOCKSRC
491	atf_check -s not-exit:0 -o ignore -e ignore \
492	    rump.ping -n -w 1 -c 1 $IP4DST_PROXYARP2
493	# Remove ARP entry as it may hang around in WAITDELETE a few seconds
494	atf_check -s ignore rump.arp -d $IP4DST_PROXYARP2
495
496	extract_new_packets bus1 > ./out
497	$DEBUG && cat ./out
498
499	# ARP reply should be sent
500	pkt=$(make_pkt_str_arprep $IP4DST_PROXYARP2 $macaddr_dst)
501	atf_check -s exit:0 -x "cat ./out |grep -q '$pkt'"
502
503	export RUMP_SERVER=$SOCKDST
504	rump_server_add_iface $SOCKDST tap2
505	atf_check -s exit:0 rump.ifconfig tap2 $IP4DST_PROXYARP2/24 up
506	atf_check -s exit:0 rump.ifconfig -w 10
507
508	# Try to ping
509	export RUMP_SERVER=$SOCKSRC
510	atf_check -s exit:0 -o ignore rump.ping -n -w 1 -c 1 $IP4DST_PROXYARP2
511}
512
513test_proxy_arp_pub()
514{
515
516	test_proxy_arp pub
517	rump_server_destroy_ifaces
518}
519
520test_proxy_arp_pubproxy()
521{
522
523	test_proxy_arp pubproxy
524	rump_server_destroy_ifaces
525}
526
527test_link_activation()
528{
529
530	rump_server_start $SOCKSRC
531	rump_server_start $SOCKDST
532
533	setup_dst_server
534	setup_src_server
535
536	# flush old packets
537	extract_new_packets bus1 > ./out
538
539	export RUMP_SERVER=$SOCKSRC
540
541	atf_check -s exit:0 -o ignore rump.ifconfig shmif0 link \
542	    b2:a1:00:00:00:01
543
544	atf_check -s exit:0 sleep 1
545	extract_new_packets bus1 > ./out
546	$DEBUG && cat ./out
547
548	pkt=$(make_pkt_str_arpreq $IP4SRC $IP4SRC)
549	atf_check -s exit:0 -o not-match:"$pkt" cat ./out
550
551	atf_check -s exit:0 -o ignore rump.ifconfig shmif0 link \
552	    b2:a1:00:00:00:02 active
553
554	atf_check -s exit:0 sleep 1
555	extract_new_packets bus1 > ./out
556	$DEBUG && cat ./out
557
558	pkt=$(make_pkt_str_arpreq $IP4SRC $IP4SRC)
559	atf_check -s exit:0 -o match:"b2:a1:00:00:00:02 $pkt" cat ./out
560
561	rump_server_destroy_ifaces
562}
563
564test_static()
565{
566	local macaddr_src=
567
568	rump_server_start $SOCKSRC
569	rump_server_start $SOCKDST
570
571	setup_dst_server
572	setup_src_server
573
574	macaddr_src=$(get_macaddr $SOCKSRC shmif0)
575
576	# Set a (valid) static ARP entry for the src server
577	export RUMP_SERVER=$SOCKDST
578	$DEBUG && rump.arp -n -a
579	atf_check -s exit:0 -o ignore rump.arp -s $IP4SRC $macaddr_src
580	$DEBUG && rump.arp -n -a
581
582	# Test receiving an ARP request with the static ARP entry (as spa/sha)
583	export RUMP_SERVER=$SOCKSRC
584	atf_check -s exit:0 -o ignore rump.ping -n -w 1 -c 1 $IP4DST
585
586	rump_server_destroy_ifaces
587}
588
589test_rtm()
590{
591	local macaddr_src= macaddr_dst=
592	local file=./tmp
593	local pid= hdr= what= addr=
594
595	rump_server_start $SOCKSRC
596	rump_server_start $SOCKDST
597
598	setup_dst_server
599	setup_src_server
600
601	macaddr_src=$(get_macaddr $SOCKSRC shmif0)
602	macaddr_dst=$(get_macaddr $SOCKDST shmif0)
603
604	export RUMP_SERVER=$SOCKSRC
605
606	# Test ping and a resulting routing message (RTM_ADD)
607	rump.route -n monitor -c 1 > $file &
608	pid=$!
609	sleep 1
610	atf_check -s exit:0 -o ignore rump.ping -n -w 1 -c 1 $IP4DST
611	wait $pid
612	$DEBUG && cat $file
613
614	hdr="RTM_ADD.+<UP,HOST,DONE,LLINFO,CLONED>"
615	what="<DST,GATEWAY>"
616	addr="$IP4DST $macaddr_dst"
617	atf_check -s exit:0 -o match:"$hdr" -o match:"$what" -o match:"$addr" \
618		cat $file
619
620	# Test ping and a resulting routing message (RTM_MISS) on subnet
621	rump.route -n monitor -c 1 > $file &
622	pid=$!
623	sleep 1
624	atf_check -s exit:2 -o ignore -e ignore \
625		rump.ping -n -w 1 -c 1 $IP4DST_FAIL1
626	wait $pid
627	$DEBUG && cat $file
628
629	hdr="RTM_MISS.+<DONE>"
630	what="<DST,GATEWAY,AUTHOR>"
631	addr="$IP4DST_FAIL1 link#2 $IP4SRC"
632	atf_check -s exit:0 -o match:"$hdr" -o match:"$what" -o match:"$addr" \
633		cat $file
634
635	# Test ping and a resulting routing message (RTM_MISS) off subnet
636	rump.route -n monitor -c 1 > $file &
637	pid=$!
638	sleep 1
639	atf_check -s exit:2 -o ignore -e ignore \
640		rump.ping -n -w 1 -c 1 $IP4DST_FAIL2
641	wait $pid
642	$DEBUG && cat $file
643
644	hdr="RTM_MISS.+<DONE>"
645	what="<DST>"
646	addr="$IP4DST_FAIL2"
647	atf_check -s exit:0 -o match:"$hdr" -o match:"$what" -o match:"$addr" \
648		cat $file
649
650	# Test arp -d and resulting routing messages (RTM_DELETE)
651	rump.route -n monitor -c 1 > $file &
652	pid=$!
653	sleep 1
654	atf_check -s exit:0 -o ignore rump.arp -d $IP4DST
655	wait $pid
656	$DEBUG && cat $file
657
658	hdr="RTM_DELETE.+<HOST,DONE,LLINFO,CLONED>"
659	what="<DST,GATEWAY>"
660	addr="$IP4DST $macaddr_dst"
661	atf_check -s exit:0 -o match:"$hdr" -o match:"$what" -o match:"$addr" \
662		grep -A 3 RTM_DELETE $file
663
664	rump_server_destroy_ifaces
665}
666
667test_purge_on_route_change()
668{
669
670	rump_server_start $SOCKSRC
671	rump_server_start $SOCKDST
672
673	setup_dst_server
674	setup_src_server
675
676	rump_server_add_iface $SOCKSRC shmif1 bus1
677	export RUMP_SERVER=$SOCKSRC
678	atf_check -s exit:0 rump.ifconfig shmif1 inet $IP4SRC2/24
679	atf_check -s exit:0 rump.ifconfig -w 10
680
681	$DEBUG && rump.netstat -nr -f inet
682	atf_check -s exit:0 -o ignore rump.ping -n -w 1 -c 1 $IP4DST
683	$DEBUG && rump.arp -na
684	atf_check -s exit:0 -o ignore \
685	    rump.route change -net $IP4NET -ifp shmif1
686	$DEBUG && rump.netstat -nr -f inet
687	$DEBUG && rump.arp -na
688	# The entry was already removed on route change
689	atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST
690
691	rump_server_destroy_ifaces
692}
693
694test_purge_on_route_delete()
695{
696
697	rump_server_start $SOCKSRC
698	rump_server_start $SOCKDST
699
700	setup_dst_server
701	setup_src_server
702
703	$DEBUG && rump.netstat -nr -f inet
704	atf_check -s exit:0 -o ignore rump.ping -n -w 1 -c 1 $IP4DST
705	$DEBUG && rump.arp -na
706
707	atf_check -s exit:0 -o ignore rump.route delete -net $IP4NET
708	$DEBUG && rump.netstat -nr -f inet
709	$DEBUG && rump.arp -na
710
711	# The entry was already removed on route delete
712	atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST
713
714	rump_server_destroy_ifaces
715}
716
717test_purge_on_ifdown()
718{
719
720	rump_server_start $SOCKSRC
721	rump_server_start $SOCKDST
722
723	setup_dst_server
724	setup_src_server
725
726	$DEBUG && rump.netstat -nr -f inet
727	atf_check -s exit:0 -o ignore rump.ping -n -w 1 -c 1 $IP4DST
728	atf_check -s exit:0 -o match:'shmif0' rump.arp -n $IP4DST
729
730	# Shutdown the interface
731	atf_check -s exit:0 rump.ifconfig shmif0 down
732	$DEBUG && rump.netstat -nr -f inet
733	$DEBUG && rump.arp -na
734
735	atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST
736
737	rump_server_destroy_ifaces
738}
739
740test_stray_entries()
741{
742
743	rump_server_start $SOCKSRC
744	rump_server_start $SOCKDST
745
746	setup_dst_server
747	setup_src_server
748
749	rump_server_add_iface $SOCKSRC shmif1 bus1
750
751	export RUMP_SERVER=$SOCKSRC
752	atf_check -s exit:0 rump.ifconfig shmif1 inet $IP4SRC2/24
753	atf_check -s exit:0 rump.ifconfig -w 10
754
755	$DEBUG && rump.netstat -nr -f inet
756	atf_check -s exit:0 -o ignore rump.ping -n -w 1 -c 1 $IP4DST
757	$DEBUG && rump.arp -na
758	atf_check -s exit:0 -o match:'shmif0' rump.arp -n $IP4DST
759	atf_check -s exit:0 -o not-match:'shmif1' rump.arp -n $IP4DST
760
761	# Clean up
762	atf_check -s exit:0 -o ignore rump.arp -da
763	atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST
764
765	# ping from a different source address
766	atf_check -s exit:0 -o ignore \
767	    rump.ping -n -w 1 -c 1 -I $IP4SRC2 $IP4DST
768	$DEBUG && rump.arp -na
769	atf_check -s exit:0 -o match:'shmif0' rump.arp -n $IP4DST
770	# ARP reply goes back via shmif1, so a cache is created on shmif1
771	atf_check -s exit:0 -o match:'shmif1' rump.arp -n $IP4DST
772
773	# Clean up by arp -da
774	atf_check -s exit:0 -o ignore rump.arp -da
775	atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST
776
777	# ping from a different source address again
778	atf_check -s exit:0 -o ignore \
779	    rump.ping -n -w 1 -c 1 -I $IP4SRC2 $IP4DST
780	atf_check -s exit:0 -o match:'shmif0' rump.arp -n $IP4DST
781	# ARP reply doen't come
782	atf_check -s exit:0 -o not-match:'shmif1' rump.arp -n $IP4DST
783
784	# Cleanup caches on the destination
785	export RUMP_SERVER=$SOCKDST
786	atf_check -s exit:0 -o ignore rump.arp -da
787	export RUMP_SERVER=$SOCKSRC
788
789	# ping from a different source address again
790	atf_check -s exit:0 -o ignore \
791	    rump.ping -n -w 1 -c 1 -I $IP4SRC2 $IP4DST
792	atf_check -s exit:0 -o match:'shmif0' rump.arp -n $IP4DST
793	# ARP reply goes back via shmif1
794	atf_check -s exit:0 -o match:'shmif1' rump.arp -n $IP4DST
795
796	# Clean up by arp -d <ip>
797	atf_check -s exit:0 -o ignore rump.arp -d $IP4DST
798	# Both entries should be deleted
799	atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST
800
801	rump_server_destroy_ifaces
802}
803
804test_cache_creation_common()
805{
806	local no_dad=$1
807
808	rump_server_start $SOCKSRC
809	rump_server_start $SOCKDST
810
811	if $no_dad; then
812		export RUMP_SERVER=$SOCKSRC
813		atf_check -s exit:0 -o match:'3 -> 0' \
814		    rump.sysctl -w net.inet.ip.dad_count=0
815		export RUMP_SERVER=$SOCKDST
816		atf_check -s exit:0 -o match:'3 -> 0' \
817		    rump.sysctl -w net.inet.ip.dad_count=0
818	fi
819
820	setup_dst_server
821	setup_src_server
822
823	macaddr_src=$(get_macaddr $SOCKSRC shmif0)
824	macaddr_dst=$(get_macaddr $SOCKDST shmif0)
825
826	# ARP cache entries are not created for DAD/GARP packets.
827	export RUMP_SERVER=$SOCKSRC
828	atf_check -s exit:0 -o empty rump.arp -n -a
829	export RUMP_SERVER=$SOCKDST
830	atf_check -s exit:0 -o empty rump.arp -n -a
831
832	export RUMP_SERVER=$SOCKSRC
833
834	extract_new_packets bus1 > ./out
835
836	atf_check -s exit:0 -o ignore rump.ping -n -w $TIMEOUT -c 1 $IP4DST
837	$DEBUG && rump.arp -n -a
838
839	extract_new_packets bus1 > ./out
840
841	atf_check -s exit:0 -o match:"\? \(10.0.1.2\) at $macaddr_dst on shmif0 [0-9]+s R" \
842	    rump.arp -n -a
843
844	export RUMP_SERVER=$SOCKDST
845
846	# An entry was first created as stale then sending an ARP reply made it delay.
847	atf_check -s exit:0 -o match:"\? \(10.0.1.1\) at $macaddr_src on shmif0 [0-9]+s D" \
848	    rump.arp -n -a
849
850	# The sender resolves the receiver's address.
851	pkt=$(make_pkt_str_arpreq 10.0.1.2 10.0.1.1)
852	atf_check -s exit:0 -o match:"$pkt" cat ./out
853
854	# The receiver doesn't resolv the sender's address because the ARP request
855	# from the sender has let make an entry already.
856	pkt=$(make_pkt_str_arpreq 10.0.1.1 10.0.1.2)
857	atf_check -s exit:0 -o not-match:"$pkt" cat ./out
858
859	rump_server_destroy_ifaces
860}
861
862test_cache_creation()
863{
864
865	test_cache_creation_common false
866}
867
868test_cache_creation_nodad()
869{
870
871	test_cache_creation_common true
872}
873
874add_test()
875{
876	local name=$1
877	local desc="$2"
878
879	atf_test_case "arp_${name}" cleanup
880	eval "arp_${name}_head() {
881			atf_set descr \"${desc}\"
882			atf_set require.progs rump_server
883		}
884	    arp_${name}_body() {
885			test_${name}
886		}
887	    arp_${name}_cleanup() {
888			\$DEBUG && dump
889			cleanup
890		}"
891	atf_add_test_case "arp_${name}"
892}
893
894atf_init_test_cases()
895{
896
897	add_test cache_expiration      "Tests for ARP cache expiration"
898	add_test command               "Tests for arp_commands of arp(8)"
899	add_test garp                  "Tests for GARP"
900	add_test garp_without_dad      "Tests for GARP with DAD disabled"
901	add_test cache_overwriting     "Tests for behavior of overwriting ARP caches"
902	add_test proxy_arp_pub         "Tests for Proxy ARP (pub)"
903	add_test proxy_arp_pubproxy    "Tests for Proxy ARP (pub proxy)"
904	add_test link_activation       "Tests for activating a new MAC address"
905	add_test static                "Tests for static ARP entries"
906	add_test rtm                   "Tests for routing messages on operations of ARP entries"
907	add_test purge_on_route_change "Tests if ARP entries are removed on route change"
908	add_test purge_on_route_delete "Tests if ARP entries are removed on route delete"
909	add_test purge_on_ifdown       "Tests if ARP entries are removed on interface down"
910	add_test stray_entries         "Tests if ARP entries are removed on route change"
911	add_test cache_creation        "Tests for ARP cache creation"
912	add_test cache_creation_nodad  "Tests for ARP cache creation without DAD"
913}
914