Home | History | Annotate | Line # | Download | only in arp
t_arp.sh revision 1.48
      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 
     28 SOCKSRC=unix://commsock1
     29 SOCKDST=unix://commsock2
     30 IP4SRC=10.0.1.1
     31 IP4SRC2=10.0.1.5
     32 IP4NET=10.0.1.0
     33 IP4DST=10.0.1.2
     34 IP4DST_PROXYARP1=10.0.1.3
     35 IP4DST_PROXYARP2=10.0.1.4
     36 IP4DST_FAIL1=10.0.1.99
     37 IP4DST_FAIL2=10.0.99.99
     38 
     39 DEBUG=${DEBUG:-false}
     40 TIMEOUT=1
     41 
     42 setup_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 
     56 setup_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 
     84 get_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 
     92 test_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 
    132 check_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 
    149 test_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 
    232 make_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 
    241 test_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 
    352 test_garp()
    353 {
    354 
    355 	test_garp_common false
    356 }
    357 
    358 test_garp_without_dad()
    359 {
    360 
    361 	test_garp_common true
    362 }
    363 
    364 test_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 
    403 make_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 
    412 make_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 
    422 test_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 
    513 test_proxy_arp_pub()
    514 {
    515 
    516 	test_proxy_arp pub
    517 	rump_server_destroy_ifaces
    518 }
    519 
    520 test_proxy_arp_pubproxy()
    521 {
    522 
    523 	test_proxy_arp pubproxy
    524 	rump_server_destroy_ifaces
    525 }
    526 
    527 test_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 
    564 test_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 
    589 test_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 
    667 test_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 
    694 test_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 
    717 test_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 
    740 test_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 
    804 test_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 
    862 test_cache_creation()
    863 {
    864 
    865 	test_cache_creation_common false
    866 }
    867 
    868 test_cache_creation_nodad()
    869 {
    870 
    871 	test_cache_creation_common true
    872 }
    873 
    874 add_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 
    894 atf_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