1*63d1fd59SEnji Cooper# $NetBSD: t_ra.sh,v 1.24 2017/01/13 08:11:01 ozaki-r Exp $ 2640235e2SEnji Cooper# 3640235e2SEnji Cooper# Copyright (c) 2015 Internet Initiative Japan Inc. 4640235e2SEnji Cooper# All rights reserved. 5640235e2SEnji Cooper# 6640235e2SEnji Cooper# Redistribution and use in source and binary forms, with or without 7640235e2SEnji Cooper# modification, are permitted provided that the following conditions 8640235e2SEnji Cooper# are met: 9640235e2SEnji Cooper# 1. Redistributions of source code must retain the above copyright 10640235e2SEnji Cooper# notice, this list of conditions and the following disclaimer. 11640235e2SEnji Cooper# 2. Redistributions in binary form must reproduce the above copyright 12640235e2SEnji Cooper# notice, this list of conditions and the following disclaimer in the 13640235e2SEnji Cooper# documentation and/or other materials provided with the distribution. 14640235e2SEnji Cooper# 15640235e2SEnji Cooper# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16640235e2SEnji Cooper# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17640235e2SEnji Cooper# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18640235e2SEnji Cooper# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19640235e2SEnji Cooper# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20640235e2SEnji Cooper# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21640235e2SEnji Cooper# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22640235e2SEnji Cooper# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23640235e2SEnji Cooper# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24640235e2SEnji Cooper# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25640235e2SEnji Cooper# POSSIBILITY OF SUCH DAMAGE. 26640235e2SEnji Cooper# 27640235e2SEnji Cooper 28640235e2SEnji CooperRUMPSRV=unix://r1 29cdebaff8SEnji CooperRUMPSRV1_2=unix://r12 30640235e2SEnji CooperRUMPCLI=unix://r2 31cdebaff8SEnji CooperRUMPSRV3=unix://r3 32cdebaff8SEnji CooperRUMPSRV4=unix://r4 33640235e2SEnji CooperIP6SRV=fc00:1::1 34cdebaff8SEnji CooperIP6SRV1_2=fc00:1::2 35cdebaff8SEnji CooperIP6SRV_PREFIX=fc00:1: 36640235e2SEnji CooperIP6CLI=fc00:2::2 37cdebaff8SEnji CooperIP6SRV3=fc00:3::1 38cdebaff8SEnji CooperIP6SRV3_PREFIX=fc00:3: 39cdebaff8SEnji CooperIP6SRV4=fc00:4::1 40cdebaff8SEnji CooperIP6SRV4_PREFIX=fc00:4: 41cdebaff8SEnji CooperPIDFILE=./rump.rtadvd.pid 42cdebaff8SEnji CooperPIDFILE1_2=./rump.rtadvd.pid12 43cdebaff8SEnji CooperPIDFILE3=./rump.rtadvd.pid3 44cdebaff8SEnji CooperPIDFILE4=./rump.rtadvd.pid4 45640235e2SEnji CooperCONFIG=./rtadvd.conf 46cdebaff8SEnji CooperWAITTIME=2 47cdebaff8SEnji CooperDEBUG=${DEBUG:-true} 48cdebaff8SEnji Cooper 49cdebaff8SEnji Cooperinit_server() 50cdebaff8SEnji Cooper{ 51cdebaff8SEnji Cooper 52cdebaff8SEnji Cooper export RUMP_SERVER=$1 53cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'0.->.1' rump.sysctl -w net.inet6.ip6.forwarding=1 54cdebaff8SEnji Cooper export LD_PRELOAD=/usr/lib/librumphijack.so 55cdebaff8SEnji Cooper atf_check -s exit:0 mkdir -p /rump/var/chroot/rtadvd 56cdebaff8SEnji Cooper unset LD_PRELOAD 57cdebaff8SEnji Cooper unset RUMP_SERVER 58cdebaff8SEnji Cooper} 59640235e2SEnji Cooper 60640235e2SEnji Coopersetup_shmif0() 61640235e2SEnji Cooper{ 62cdebaff8SEnji Cooper local sock=$1 63cdebaff8SEnji Cooper local IP6ADDR=$2 64640235e2SEnji Cooper 65cdebaff8SEnji Cooper rump_server_add_iface $sock shmif0 bus1 66cdebaff8SEnji Cooper 67cdebaff8SEnji Cooper export RUMP_SERVER=$sock 68640235e2SEnji Cooper atf_check -s exit:0 rump.ifconfig shmif0 inet6 ${IP6ADDR} 69640235e2SEnji Cooper atf_check -s exit:0 rump.ifconfig shmif0 up 70cdebaff8SEnji Cooper atf_check -s exit:0 rump.ifconfig -w 10 71640235e2SEnji Cooper 72640235e2SEnji Cooper $DEBUG && rump.ifconfig 73640235e2SEnji Cooper} 74640235e2SEnji Cooper 75640235e2SEnji Cooperwait_term() 76640235e2SEnji Cooper{ 77640235e2SEnji Cooper local PIDFILE=${1} 78640235e2SEnji Cooper shift 79640235e2SEnji Cooper 80640235e2SEnji Cooper while [ -f ${PIDFILE} ] 81640235e2SEnji Cooper do 82640235e2SEnji Cooper sleep 0.2 83640235e2SEnji Cooper done 84640235e2SEnji Cooper 85640235e2SEnji Cooper return 0 86640235e2SEnji Cooper} 87640235e2SEnji Cooper 88640235e2SEnji Coopercreate_rtadvdconfig() 89640235e2SEnji Cooper{ 90640235e2SEnji Cooper 91640235e2SEnji Cooper cat << _EOF > ${CONFIG} 92640235e2SEnji Coopershmif0:\ 93640235e2SEnji Cooper :mtu#1300:maxinterval#4:mininterval#3: 94640235e2SEnji Cooper_EOF 95640235e2SEnji Cooper} 96640235e2SEnji Cooper 97cdebaff8SEnji Cooperstart_rtadvd() 98cdebaff8SEnji Cooper{ 99cdebaff8SEnji Cooper local sock=$1 100cdebaff8SEnji Cooper local pidfile=$2 101cdebaff8SEnji Cooper 102cdebaff8SEnji Cooper export RUMP_SERVER=$sock 103cdebaff8SEnji Cooper atf_check -s exit:0 rump.rtadvd -c ${CONFIG} -p $pidfile shmif0 104cdebaff8SEnji Cooper while [ ! -f $pidfile ]; do 105cdebaff8SEnji Cooper sleep 0.2 106cdebaff8SEnji Cooper done 107cdebaff8SEnji Cooper unset RUMP_SERVER 108cdebaff8SEnji Cooper} 109cdebaff8SEnji Cooper 110cdebaff8SEnji Coopercheck_entries() 111cdebaff8SEnji Cooper{ 112cdebaff8SEnji Cooper local cli=$1 113cdebaff8SEnji Cooper local srv=$2 114cdebaff8SEnji Cooper local addr_prefix=$3 115cdebaff8SEnji Cooper local mac_srv= ll_srv= 116cdebaff8SEnji Cooper 117cdebaff8SEnji Cooper ll_srv=$(get_linklocal_addr $srv shmif0) 118cdebaff8SEnji Cooper mac_srv=$(get_macaddr $srv shmif0) 119cdebaff8SEnji Cooper 120cdebaff8SEnji Cooper export RUMP_SERVER=$cli 121cdebaff8SEnji Cooper $DEBUG && dump_entries 122cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'if=shmif0' rump.ndp -r 123cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'advertised' rump.ndp -p 124cdebaff8SEnji Cooper atf_check -s exit:0 -o match:"${ll_srv}%shmif0 \(reachable\)" rump.ndp -p 125cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'linkmtu=1300' rump.ndp -n -i shmif0 126cdebaff8SEnji Cooper atf_check -s exit:0 \ 127cdebaff8SEnji Cooper -o match:"$ll_srv%shmif0 +$mac_srv +shmif0 +(23h59m|1d0h0m)..s S R" \ 128cdebaff8SEnji Cooper rump.ndp -n -a 129cdebaff8SEnji Cooper atf_check -s exit:0 -o match:$addr_prefix rump.ndp -n -a 130*63d1fd59SEnji Cooper atf_check -s exit:0 \ 131*63d1fd59SEnji Cooper -o match:"$addr_prefix.+<(TENTATIVE,)?AUTOCONF>" \ 132cdebaff8SEnji Cooper rump.ifconfig shmif0 inet6 133cdebaff8SEnji Cooper unset RUMP_SERVER 134cdebaff8SEnji Cooper} 135cdebaff8SEnji Cooper 136cdebaff8SEnji Cooperdump_entries() 137cdebaff8SEnji Cooper{ 138cdebaff8SEnji Cooper 139cdebaff8SEnji Cooper echo ndp -n -a 140cdebaff8SEnji Cooper rump.ndp -n -a 141cdebaff8SEnji Cooper echo ndp -p 142cdebaff8SEnji Cooper rump.ndp -p 143cdebaff8SEnji Cooper echo ndp -r 144cdebaff8SEnji Cooper rump.ndp -r 145cdebaff8SEnji Cooper} 146cdebaff8SEnji Cooper 147cdebaff8SEnji Cooperatf_test_case ra_basic cleanup 148cdebaff8SEnji Cooperra_basic_head() 149640235e2SEnji Cooper{ 150640235e2SEnji Cooper 151640235e2SEnji Cooper atf_set "descr" "Tests for basic functions of router advaertisement(RA)" 152640235e2SEnji Cooper atf_set "require.progs" "rump_server rump.rtadvd rump.ndp rump.ifconfig" 153640235e2SEnji Cooper} 154640235e2SEnji Cooper 155cdebaff8SEnji Cooperra_basic_body() 156640235e2SEnji Cooper{ 157640235e2SEnji Cooper 158cdebaff8SEnji Cooper rump_server_fs_start $RUMPSRV netinet6 159cdebaff8SEnji Cooper rump_server_start $RUMPCLI netinet6 160640235e2SEnji Cooper 161cdebaff8SEnji Cooper setup_shmif0 ${RUMPSRV} ${IP6SRV} 162cdebaff8SEnji Cooper init_server $RUMPSRV 163640235e2SEnji Cooper 164cdebaff8SEnji Cooper setup_shmif0 ${RUMPCLI} ${IP6CLI} 165640235e2SEnji Cooper export RUMP_SERVER=${RUMPCLI} 166640235e2SEnji Cooper $DEBUG && rump.ndp -n -a 167640235e2SEnji Cooper atf_check -s exit:0 -o match:'= 0' rump.sysctl net.inet6.ip6.accept_rtadv 168640235e2SEnji Cooper unset RUMP_SERVER 169640235e2SEnji Cooper 170640235e2SEnji Cooper create_rtadvdconfig 171cdebaff8SEnji Cooper start_rtadvd $RUMPSRV $PIDFILE 172cdebaff8SEnji Cooper sleep $WAITTIME 173640235e2SEnji Cooper 174640235e2SEnji Cooper export RUMP_SERVER=${RUMPCLI} 175640235e2SEnji Cooper atf_check -s exit:0 -o empty rump.ndp -r 176640235e2SEnji Cooper atf_check -s exit:0 -o not-match:'advertised' rump.ndp -p 177640235e2SEnji Cooper atf_check -s exit:0 -o match:'linkmtu=0' rump.ndp -n -i shmif0 178640235e2SEnji Cooper atf_check -s exit:0 -o not-match:'S R' rump.ndp -n -a 179640235e2SEnji Cooper atf_check -s exit:0 -o not-match:'fc00:1:' rump.ndp -n -a 180640235e2SEnji Cooper atf_check -s exit:0 -o not-match:'fc00:1:' rump.ifconfig shmif0 inet6 181640235e2SEnji Cooper unset RUMP_SERVER 182640235e2SEnji Cooper 183640235e2SEnji Cooper atf_check -s exit:0 kill -TERM `cat ${PIDFILE}` 184640235e2SEnji Cooper wait_term ${PIDFILE} 185640235e2SEnji Cooper 186640235e2SEnji Cooper export RUMP_SERVER=${RUMPCLI} 187640235e2SEnji Cooper atf_check -s exit:0 -o match:'0.->.1' rump.sysctl -w net.inet6.ip6.accept_rtadv=1 188640235e2SEnji Cooper unset RUMP_SERVER 189640235e2SEnji Cooper 190cdebaff8SEnji Cooper start_rtadvd $RUMPSRV $PIDFILE 191cdebaff8SEnji Cooper sleep $WAITTIME 192640235e2SEnji Cooper 193cdebaff8SEnji Cooper check_entries $RUMPCLI $RUMPSRV $IP6SRV_PREFIX 194640235e2SEnji Cooper 195640235e2SEnji Cooper atf_check -s exit:0 kill -TERM `cat ${PIDFILE}` 196640235e2SEnji Cooper wait_term ${PIDFILE} 197640235e2SEnji Cooper 198cdebaff8SEnji Cooper rump_server_destroy_ifaces 199640235e2SEnji Cooper} 200640235e2SEnji Cooper 201cdebaff8SEnji Cooperra_basic_cleanup() 202640235e2SEnji Cooper{ 203640235e2SEnji Cooper 204640235e2SEnji Cooper if [ -f ${PIDFILE} ]; then 205640235e2SEnji Cooper kill -TERM `cat ${PIDFILE}` 206640235e2SEnji Cooper wait_term ${PIDFILE} 207640235e2SEnji Cooper fi 208640235e2SEnji Cooper 209cdebaff8SEnji Cooper $DEBUG && dump 210cdebaff8SEnji Cooper cleanup 211cdebaff8SEnji Cooper} 212cdebaff8SEnji Cooper 213cdebaff8SEnji Cooperatf_test_case ra_flush_prefix_entries cleanup 214cdebaff8SEnji Cooperra_flush_prefix_entries_head() 215cdebaff8SEnji Cooper{ 216cdebaff8SEnji Cooper 217cdebaff8SEnji Cooper atf_set "descr" "Tests for flushing prefixes (ndp -P)" 218cdebaff8SEnji Cooper atf_set "require.progs" "rump_server rump.rtadvd rump.ndp rump.ifconfig" 219cdebaff8SEnji Cooper} 220cdebaff8SEnji Cooper 221cdebaff8SEnji Cooperra_flush_prefix_entries_body() 222cdebaff8SEnji Cooper{ 223cdebaff8SEnji Cooper 224cdebaff8SEnji Cooper rump_server_fs_start $RUMPSRV netinet6 225cdebaff8SEnji Cooper rump_server_start $RUMPCLI netinet6 226cdebaff8SEnji Cooper 227cdebaff8SEnji Cooper setup_shmif0 ${RUMPSRV} ${IP6SRV} 228cdebaff8SEnji Cooper setup_shmif0 ${RUMPCLI} ${IP6CLI} 229cdebaff8SEnji Cooper 230cdebaff8SEnji Cooper init_server $RUMPSRV 231cdebaff8SEnji Cooper 232cdebaff8SEnji Cooper create_rtadvdconfig 233cdebaff8SEnji Cooper 234cdebaff8SEnji Cooper export RUMP_SERVER=${RUMPCLI} 235cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'0.->.1' rump.sysctl -w net.inet6.ip6.accept_rtadv=1 236cdebaff8SEnji Cooper unset RUMP_SERVER 237cdebaff8SEnji Cooper 238cdebaff8SEnji Cooper start_rtadvd $RUMPSRV $PIDFILE 239cdebaff8SEnji Cooper sleep $WAITTIME 240cdebaff8SEnji Cooper 241cdebaff8SEnji Cooper check_entries $RUMPCLI $RUMPSRV $IP6SRV_PREFIX 242cdebaff8SEnji Cooper 243cdebaff8SEnji Cooper export RUMP_SERVER=${RUMPCLI} 244cdebaff8SEnji Cooper 245cdebaff8SEnji Cooper # Terminate rtadvd to prevent new RA messages from coming 246cdebaff8SEnji Cooper # Note that ifconfig down; kill -TERM doesn't work 247cdebaff8SEnji Cooper kill -KILL `cat ${PIDFILE}` 248cdebaff8SEnji Cooper 249cdebaff8SEnji Cooper # Flush all the entries in the prefix list 250cdebaff8SEnji Cooper atf_check -s exit:0 rump.ndp -P 251cdebaff8SEnji Cooper 252cdebaff8SEnji Cooper $DEBUG && dump_entries 253cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'if=shmif0' rump.ndp -r 254cdebaff8SEnji Cooper atf_check -s exit:0 -o empty rump.ndp -p 255cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'linkmtu=1300' rump.ndp -n -i shmif0 256cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'(23h59m|1d0h0m)..s S R' rump.ndp -n -a 257cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'fc00:1:' rump.ndp -n -a 258cdebaff8SEnji Cooper atf_check -s exit:0 -o not-match:'fc00:1:' rump.ifconfig shmif0 inet6 259cdebaff8SEnji Cooper unset RUMP_SERVER 260cdebaff8SEnji Cooper 261cdebaff8SEnji Cooper rump_server_destroy_ifaces 262cdebaff8SEnji Cooper} 263cdebaff8SEnji Cooper 264cdebaff8SEnji Cooperra_flush_prefix_entries_cleanup() 265cdebaff8SEnji Cooper{ 266cdebaff8SEnji Cooper 267cdebaff8SEnji Cooper $DEBUG && dump 268cdebaff8SEnji Cooper cleanup 269cdebaff8SEnji Cooper} 270cdebaff8SEnji Cooper 271cdebaff8SEnji Cooperatf_test_case ra_flush_defrouter_entries cleanup 272cdebaff8SEnji Cooperra_flush_defrouter_entries_head() 273cdebaff8SEnji Cooper{ 274cdebaff8SEnji Cooper 275cdebaff8SEnji Cooper atf_set "descr" "Tests for flushing default routers (ndp -R)" 276cdebaff8SEnji Cooper atf_set "require.progs" "rump_server rump.rtadvd rump.ndp rump.ifconfig" 277cdebaff8SEnji Cooper} 278cdebaff8SEnji Cooper 279cdebaff8SEnji Cooperra_flush_defrouter_entries_body() 280cdebaff8SEnji Cooper{ 281cdebaff8SEnji Cooper 282cdebaff8SEnji Cooper rump_server_fs_start $RUMPSRV netinet6 283cdebaff8SEnji Cooper rump_server_start $RUMPCLI netinet6 284cdebaff8SEnji Cooper 285cdebaff8SEnji Cooper setup_shmif0 ${RUMPSRV} ${IP6SRV} 286cdebaff8SEnji Cooper setup_shmif0 ${RUMPCLI} ${IP6CLI} 287cdebaff8SEnji Cooper 288cdebaff8SEnji Cooper init_server $RUMPSRV 289cdebaff8SEnji Cooper 290cdebaff8SEnji Cooper create_rtadvdconfig 291cdebaff8SEnji Cooper 292cdebaff8SEnji Cooper export RUMP_SERVER=${RUMPCLI} 293cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'0.->.1' rump.sysctl -w net.inet6.ip6.accept_rtadv=1 294cdebaff8SEnji Cooper unset RUMP_SERVER 295cdebaff8SEnji Cooper 296cdebaff8SEnji Cooper start_rtadvd $RUMPSRV $PIDFILE 297cdebaff8SEnji Cooper sleep $WAITTIME 298cdebaff8SEnji Cooper 299cdebaff8SEnji Cooper check_entries $RUMPCLI $RUMPSRV $IP6SRV_PREFIX 300cdebaff8SEnji Cooper 301cdebaff8SEnji Cooper export RUMP_SERVER=${RUMPCLI} 302cdebaff8SEnji Cooper 303cdebaff8SEnji Cooper # Terminate rtadvd to prevent new RA messages from coming 304cdebaff8SEnji Cooper # Note that ifconfig down; kill -TERM doesn't work 305cdebaff8SEnji Cooper kill -KILL `cat ${PIDFILE}` 306cdebaff8SEnji Cooper 307cdebaff8SEnji Cooper # Flush all the entries in the default router list 308cdebaff8SEnji Cooper atf_check -s exit:0 rump.ndp -R 309cdebaff8SEnji Cooper 310cdebaff8SEnji Cooper $DEBUG && dump_entries 311cdebaff8SEnji Cooper atf_check -s exit:0 -o empty rump.ndp -r 312cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'No advertising router' rump.ndp -p 313cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'linkmtu=1300' rump.ndp -n -i shmif0 314cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'(23h59m|1d0h0m)..s S R' rump.ndp -n -a 315cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'fc00:1:' rump.ndp -n -a 316cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'fc00:1:' rump.ifconfig shmif0 inet6 317cdebaff8SEnji Cooper unset RUMP_SERVER 318cdebaff8SEnji Cooper 319cdebaff8SEnji Cooper rump_server_destroy_ifaces 320cdebaff8SEnji Cooper} 321cdebaff8SEnji Cooper 322cdebaff8SEnji Cooperra_flush_defrouter_entries_cleanup() 323cdebaff8SEnji Cooper{ 324cdebaff8SEnji Cooper 325cdebaff8SEnji Cooper $DEBUG && dump 326cdebaff8SEnji Cooper cleanup 327cdebaff8SEnji Cooper} 328cdebaff8SEnji Cooper 329cdebaff8SEnji Cooperatf_test_case ra_delete_address cleanup 330cdebaff8SEnji Cooperra_delete_address_head() 331cdebaff8SEnji Cooper{ 332cdebaff8SEnji Cooper 333cdebaff8SEnji Cooper atf_set "descr" "Tests for deleting auto-configured address" 334cdebaff8SEnji Cooper atf_set "require.progs" "rump_server rump.rtadvd rump.ndp rump.ifconfig" 335cdebaff8SEnji Cooper} 336cdebaff8SEnji Cooper 337cdebaff8SEnji Cooperra_delete_address_body() 338cdebaff8SEnji Cooper{ 339cdebaff8SEnji Cooper 340cdebaff8SEnji Cooper rump_server_fs_start $RUMPSRV netinet6 341cdebaff8SEnji Cooper rump_server_start $RUMPCLI netinet6 342cdebaff8SEnji Cooper 343cdebaff8SEnji Cooper setup_shmif0 ${RUMPSRV} ${IP6SRV} 344cdebaff8SEnji Cooper setup_shmif0 ${RUMPCLI} ${IP6CLI} 345cdebaff8SEnji Cooper 346cdebaff8SEnji Cooper init_server $RUMPSRV 347cdebaff8SEnji Cooper 348cdebaff8SEnji Cooper create_rtadvdconfig 349cdebaff8SEnji Cooper 350cdebaff8SEnji Cooper export RUMP_SERVER=${RUMPCLI} 351cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'0.->.1' rump.sysctl -w net.inet6.ip6.accept_rtadv=1 352cdebaff8SEnji Cooper unset RUMP_SERVER 353cdebaff8SEnji Cooper 354cdebaff8SEnji Cooper start_rtadvd $RUMPSRV $PIDFILE 355cdebaff8SEnji Cooper sleep $WAITTIME 356cdebaff8SEnji Cooper 357cdebaff8SEnji Cooper check_entries $RUMPCLI $RUMPSRV $IP6SRV_PREFIX 358cdebaff8SEnji Cooper 359cdebaff8SEnji Cooper export RUMP_SERVER=${RUMPCLI} 360cdebaff8SEnji Cooper $DEBUG && rump.ifconfig shmif0 361cdebaff8SEnji Cooper atf_check -s exit:0 rump.ifconfig shmif0 inet6 \ 362cdebaff8SEnji Cooper $(rump.ifconfig shmif0 |awk '/AUTOCONF/ {print $2}') delete 363cdebaff8SEnji Cooper unset RUMP_SERVER 364cdebaff8SEnji Cooper 365cdebaff8SEnji Cooper atf_check -s exit:0 kill -TERM `cat ${PIDFILE}` 366cdebaff8SEnji Cooper wait_term ${PIDFILE} 367cdebaff8SEnji Cooper 368cdebaff8SEnji Cooper rump_server_destroy_ifaces 369cdebaff8SEnji Cooper} 370cdebaff8SEnji Cooper 371cdebaff8SEnji Cooperra_delete_address_cleanup() 372cdebaff8SEnji Cooper{ 373cdebaff8SEnji Cooper 374cdebaff8SEnji Cooper if [ -f ${PIDFILE} ]; then 375cdebaff8SEnji Cooper kill -TERM `cat ${PIDFILE}` 376cdebaff8SEnji Cooper wait_term ${PIDFILE} 377cdebaff8SEnji Cooper fi 378cdebaff8SEnji Cooper 379cdebaff8SEnji Cooper $DEBUG && dump 380cdebaff8SEnji Cooper cleanup 381cdebaff8SEnji Cooper} 382cdebaff8SEnji Cooper 383cdebaff8SEnji Cooperatf_test_case ra_multiple_routers cleanup 384cdebaff8SEnji Cooperra_multiple_routers_head() 385cdebaff8SEnji Cooper{ 386cdebaff8SEnji Cooper 387cdebaff8SEnji Cooper atf_set "descr" "Tests for multiple routers" 388cdebaff8SEnji Cooper atf_set "require.progs" "rump_server rump.rtadvd rump.ndp rump.ifconfig" 389cdebaff8SEnji Cooper} 390cdebaff8SEnji Cooper 391cdebaff8SEnji Cooperra_multiple_routers_body() 392cdebaff8SEnji Cooper{ 393cdebaff8SEnji Cooper local n= 394cdebaff8SEnji Cooper 395cdebaff8SEnji Cooper rump_server_fs_start $RUMPSRV netinet6 396cdebaff8SEnji Cooper rump_server_fs_start $RUMPSRV3 netinet6 397cdebaff8SEnji Cooper rump_server_start $RUMPCLI netinet6 398cdebaff8SEnji Cooper 399cdebaff8SEnji Cooper setup_shmif0 ${RUMPSRV} ${IP6SRV} 400cdebaff8SEnji Cooper setup_shmif0 ${RUMPSRV3} ${IP6SRV3} 401cdebaff8SEnji Cooper setup_shmif0 ${RUMPCLI} ${IP6CLI} 402cdebaff8SEnji Cooper 403cdebaff8SEnji Cooper init_server $RUMPSRV 404cdebaff8SEnji Cooper init_server $RUMPSRV3 405cdebaff8SEnji Cooper 406cdebaff8SEnji Cooper create_rtadvdconfig 407cdebaff8SEnji Cooper 408cdebaff8SEnji Cooper export RUMP_SERVER=${RUMPCLI} 409cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'0.->.1' rump.sysctl -w net.inet6.ip6.accept_rtadv=1 410cdebaff8SEnji Cooper unset RUMP_SERVER 411cdebaff8SEnji Cooper 412cdebaff8SEnji Cooper start_rtadvd $RUMPSRV $PIDFILE 413cdebaff8SEnji Cooper start_rtadvd $RUMPSRV3 $PIDFILE3 414cdebaff8SEnji Cooper sleep $WAITTIME 415cdebaff8SEnji Cooper 416cdebaff8SEnji Cooper check_entries $RUMPCLI $RUMPSRV $IP6SRV_PREFIX 417cdebaff8SEnji Cooper check_entries $RUMPCLI $RUMPSRV3 $IP6SRV3_PREFIX 418cdebaff8SEnji Cooper 419cdebaff8SEnji Cooper export RUMP_SERVER=$RUMPCLI 420cdebaff8SEnji Cooper # Two prefixes are advertised by differnt two routers 421cdebaff8SEnji Cooper n=$(rump.ndp -p |grep 'advertised by' |wc -l) 422cdebaff8SEnji Cooper atf_check_equal $n 2 423cdebaff8SEnji Cooper unset RUMP_SERVER 424cdebaff8SEnji Cooper 425cdebaff8SEnji Cooper atf_check -s exit:0 kill -TERM `cat ${PIDFILE}` 426cdebaff8SEnji Cooper wait_term ${PIDFILE} 427cdebaff8SEnji Cooper atf_check -s exit:0 kill -TERM `cat ${PIDFILE3}` 428cdebaff8SEnji Cooper wait_term ${PIDFILE3} 429cdebaff8SEnji Cooper 430cdebaff8SEnji Cooper rump_server_destroy_ifaces 431cdebaff8SEnji Cooper} 432cdebaff8SEnji Cooper 433cdebaff8SEnji Cooperra_multiple_routers_cleanup() 434cdebaff8SEnji Cooper{ 435cdebaff8SEnji Cooper 436cdebaff8SEnji Cooper if [ -f ${PIDFILE} ]; then 437cdebaff8SEnji Cooper kill -TERM `cat ${PIDFILE}` 438cdebaff8SEnji Cooper wait_term ${PIDFILE} 439cdebaff8SEnji Cooper fi 440cdebaff8SEnji Cooper if [ -f ${PIDFILE3} ]; then 441cdebaff8SEnji Cooper kill -TERM `cat ${PIDFILE3}` 442cdebaff8SEnji Cooper wait_term ${PIDFILE3} 443cdebaff8SEnji Cooper fi 444cdebaff8SEnji Cooper 445cdebaff8SEnji Cooper $DEBUG && dump 446cdebaff8SEnji Cooper cleanup 447cdebaff8SEnji Cooper} 448cdebaff8SEnji Cooper 449cdebaff8SEnji Cooperatf_test_case ra_multiple_routers_single_prefix cleanup 450cdebaff8SEnji Cooperra_multiple_routers_single_prefix_head() 451cdebaff8SEnji Cooper{ 452cdebaff8SEnji Cooper 453cdebaff8SEnji Cooper atf_set "descr" "Tests for multiple routers with a single prefix" 454cdebaff8SEnji Cooper atf_set "require.progs" "rump_server rump.rtadvd rump.ndp rump.ifconfig" 455cdebaff8SEnji Cooper} 456cdebaff8SEnji Cooper 457cdebaff8SEnji Cooperra_multiple_routers_single_prefix_body() 458cdebaff8SEnji Cooper{ 459cdebaff8SEnji Cooper local n= 460cdebaff8SEnji Cooper 461cdebaff8SEnji Cooper rump_server_fs_start $RUMPSRV netinet6 462cdebaff8SEnji Cooper rump_server_fs_start $RUMPSRV1_2 netinet6 463cdebaff8SEnji Cooper rump_server_start $RUMPCLI netinet6 464cdebaff8SEnji Cooper 465cdebaff8SEnji Cooper setup_shmif0 ${RUMPSRV} ${IP6SRV} 466cdebaff8SEnji Cooper setup_shmif0 ${RUMPSRV1_2} ${IP6SRV1_2} 467cdebaff8SEnji Cooper setup_shmif0 ${RUMPCLI} ${IP6CLI} 468cdebaff8SEnji Cooper 469cdebaff8SEnji Cooper init_server $RUMPSRV 470cdebaff8SEnji Cooper init_server $RUMPSRV1_2 471cdebaff8SEnji Cooper 472cdebaff8SEnji Cooper create_rtadvdconfig 473cdebaff8SEnji Cooper 474cdebaff8SEnji Cooper export RUMP_SERVER=${RUMPCLI} 475cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'0.->.1' rump.sysctl -w net.inet6.ip6.accept_rtadv=1 476cdebaff8SEnji Cooper unset RUMP_SERVER 477cdebaff8SEnji Cooper 478cdebaff8SEnji Cooper start_rtadvd $RUMPSRV $PIDFILE 479cdebaff8SEnji Cooper start_rtadvd $RUMPSRV1_2 $PIDFILE1_2 480cdebaff8SEnji Cooper sleep $WAITTIME 481cdebaff8SEnji Cooper 482cdebaff8SEnji Cooper check_entries $RUMPCLI $RUMPSRV $IP6SRV_PREFIX 483cdebaff8SEnji Cooper check_entries $RUMPCLI $RUMPSRV1_2 $IP6SRV_PREFIX 484cdebaff8SEnji Cooper 485cdebaff8SEnji Cooper export RUMP_SERVER=$RUMPCLI 486cdebaff8SEnji Cooper # One prefix is advertised by differnt two routers 487cdebaff8SEnji Cooper n=$(rump.ndp -p |grep 'advertised by' |wc -l) 488cdebaff8SEnji Cooper atf_check_equal $n 1 489cdebaff8SEnji Cooper unset RUMP_SERVER 490cdebaff8SEnji Cooper 491cdebaff8SEnji Cooper atf_check -s exit:0 kill -TERM `cat ${PIDFILE}` 492cdebaff8SEnji Cooper wait_term ${PIDFILE} 493cdebaff8SEnji Cooper atf_check -s exit:0 kill -TERM `cat ${PIDFILE1_2}` 494cdebaff8SEnji Cooper wait_term ${PIDFILE1_2} 495cdebaff8SEnji Cooper 496cdebaff8SEnji Cooper rump_server_destroy_ifaces 497cdebaff8SEnji Cooper} 498cdebaff8SEnji Cooper 499cdebaff8SEnji Cooperra_multiple_routers_single_prefix_cleanup() 500cdebaff8SEnji Cooper{ 501cdebaff8SEnji Cooper 502cdebaff8SEnji Cooper if [ -f ${PIDFILE} ]; then 503cdebaff8SEnji Cooper kill -TERM `cat ${PIDFILE}` 504cdebaff8SEnji Cooper wait_term ${PIDFILE} 505cdebaff8SEnji Cooper fi 506cdebaff8SEnji Cooper if [ -f ${PIDFILE1_2} ]; then 507cdebaff8SEnji Cooper kill -TERM `cat ${PIDFILE1_2}` 508cdebaff8SEnji Cooper wait_term ${PIDFILE1_2} 509cdebaff8SEnji Cooper fi 510cdebaff8SEnji Cooper 511cdebaff8SEnji Cooper $DEBUG && dump 512cdebaff8SEnji Cooper cleanup 513cdebaff8SEnji Cooper} 514cdebaff8SEnji Cooper 515cdebaff8SEnji Cooperatf_test_case ra_multiple_routers_maxifprefixes cleanup 516cdebaff8SEnji Cooperra_multiple_routers_maxifprefixes_head() 517cdebaff8SEnji Cooper{ 518cdebaff8SEnji Cooper 519cdebaff8SEnji Cooper atf_set "descr" "Tests for exceeding the number of maximum prefixes" 520cdebaff8SEnji Cooper atf_set "require.progs" "rump_server rump.rtadvd rump.ndp rump.ifconfig" 521cdebaff8SEnji Cooper} 522cdebaff8SEnji Cooper 523cdebaff8SEnji Cooperra_multiple_routers_maxifprefixes_body() 524cdebaff8SEnji Cooper{ 525cdebaff8SEnji Cooper local n= 526cdebaff8SEnji Cooper 527cdebaff8SEnji Cooper rump_server_fs_start $RUMPSRV netinet6 528cdebaff8SEnji Cooper rump_server_fs_start $RUMPSRV3 netinet6 529cdebaff8SEnji Cooper rump_server_fs_start $RUMPSRV4 netinet6 530cdebaff8SEnji Cooper rump_server_start $RUMPCLI netinet6 531cdebaff8SEnji Cooper 532cdebaff8SEnji Cooper setup_shmif0 ${RUMPSRV} ${IP6SRV} 533cdebaff8SEnji Cooper setup_shmif0 ${RUMPSRV3} ${IP6SRV3} 534cdebaff8SEnji Cooper setup_shmif0 ${RUMPSRV4} ${IP6SRV4} 535cdebaff8SEnji Cooper setup_shmif0 ${RUMPCLI} ${IP6CLI} 536cdebaff8SEnji Cooper 537cdebaff8SEnji Cooper init_server $RUMPSRV 538cdebaff8SEnji Cooper init_server $RUMPSRV3 539cdebaff8SEnji Cooper init_server $RUMPSRV4 540cdebaff8SEnji Cooper 541cdebaff8SEnji Cooper create_rtadvdconfig 542cdebaff8SEnji Cooper 543cdebaff8SEnji Cooper export RUMP_SERVER=${RUMPCLI} 544cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'0.->.1' \ 545cdebaff8SEnji Cooper rump.sysctl -w net.inet6.ip6.accept_rtadv=1 546cdebaff8SEnji Cooper # Limit the maximum number of prefix entries to 2 547cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'16.->.2' \ 548cdebaff8SEnji Cooper rump.sysctl -w net.inet6.ip6.maxifprefixes=2 549cdebaff8SEnji Cooper unset RUMP_SERVER 550cdebaff8SEnji Cooper 551cdebaff8SEnji Cooper start_rtadvd $RUMPSRV $PIDFILE 552cdebaff8SEnji Cooper start_rtadvd $RUMPSRV3 $PIDFILE3 553cdebaff8SEnji Cooper sleep $WAITTIME 554cdebaff8SEnji Cooper 555cdebaff8SEnji Cooper check_entries $RUMPCLI $RUMPSRV $IP6SRV_PREFIX 556cdebaff8SEnji Cooper check_entries $RUMPCLI $RUMPSRV3 $IP6SRV3_PREFIX 557cdebaff8SEnji Cooper 558cdebaff8SEnji Cooper start_rtadvd $RUMPSRV4 $PIDFILE4 559cdebaff8SEnji Cooper sleep $WAITTIME 560cdebaff8SEnji Cooper 561cdebaff8SEnji Cooper export RUMP_SERVER=${RUMPCLI} 562cdebaff8SEnji Cooper $DEBUG && dump_entries 563cdebaff8SEnji Cooper # There should remain two prefixes 564cdebaff8SEnji Cooper n=$(rump.ndp -p |grep 'advertised by' |wc -l) 565cdebaff8SEnji Cooper atf_check_equal $n 2 566cdebaff8SEnji Cooper # TODO check other conditions 567cdebaff8SEnji Cooper unset RUMP_SERVER 568cdebaff8SEnji Cooper 569cdebaff8SEnji Cooper atf_check -s exit:0 kill -TERM `cat ${PIDFILE}` 570cdebaff8SEnji Cooper wait_term ${PIDFILE} 571cdebaff8SEnji Cooper atf_check -s exit:0 kill -TERM `cat ${PIDFILE3}` 572cdebaff8SEnji Cooper wait_term ${PIDFILE3} 573cdebaff8SEnji Cooper atf_check -s exit:0 kill -TERM `cat ${PIDFILE4}` 574cdebaff8SEnji Cooper wait_term ${PIDFILE4} 575cdebaff8SEnji Cooper 576cdebaff8SEnji Cooper rump_server_destroy_ifaces 577cdebaff8SEnji Cooper} 578cdebaff8SEnji Cooper 579cdebaff8SEnji Cooperra_multiple_routers_maxifprefixes_cleanup() 580cdebaff8SEnji Cooper{ 581cdebaff8SEnji Cooper 582cdebaff8SEnji Cooper if [ -f ${PIDFILE} ]; then 583cdebaff8SEnji Cooper kill -TERM `cat ${PIDFILE}` 584cdebaff8SEnji Cooper wait_term ${PIDFILE} 585cdebaff8SEnji Cooper fi 586cdebaff8SEnji Cooper if [ -f ${PIDFILE3} ]; then 587cdebaff8SEnji Cooper kill -TERM `cat ${PIDFILE3}` 588cdebaff8SEnji Cooper wait_term ${PIDFILE3} 589cdebaff8SEnji Cooper fi 590cdebaff8SEnji Cooper if [ -f ${PIDFILE4} ]; then 591cdebaff8SEnji Cooper kill -TERM `cat ${PIDFILE4}` 592cdebaff8SEnji Cooper wait_term ${PIDFILE4} 593cdebaff8SEnji Cooper fi 594cdebaff8SEnji Cooper 595cdebaff8SEnji Cooper $DEBUG && dump 596cdebaff8SEnji Cooper cleanup 597cdebaff8SEnji Cooper} 598cdebaff8SEnji Cooper 599cdebaff8SEnji Cooperatf_test_case ra_temporary_address cleanup 600cdebaff8SEnji Cooperra_temporary_address_head() 601cdebaff8SEnji Cooper{ 602cdebaff8SEnji Cooper 603cdebaff8SEnji Cooper atf_set "descr" "Tests for IPv6 temporary address" 604cdebaff8SEnji Cooper atf_set "require.progs" "rump_server rump.rtadvd rump.ndp rump.ifconfig" 605cdebaff8SEnji Cooper} 606cdebaff8SEnji Cooper 607*63d1fd59SEnji Coopercheck_echo_request_pkt() 608*63d1fd59SEnji Cooper{ 609*63d1fd59SEnji Cooper local pkt="$2 > $3: .+ echo request" 610*63d1fd59SEnji Cooper 611*63d1fd59SEnji Cooper extract_new_packets $1 > ./out 612*63d1fd59SEnji Cooper $DEBUG && echo $pkt 613*63d1fd59SEnji Cooper $DEBUG && cat ./out 614*63d1fd59SEnji Cooper atf_check -s exit:0 -o match:"$pkt" cat ./out 615*63d1fd59SEnji Cooper} 616*63d1fd59SEnji Cooper 617cdebaff8SEnji Cooperra_temporary_address_body() 618cdebaff8SEnji Cooper{ 619*63d1fd59SEnji Cooper local ip_auto= ip_temp= 620cdebaff8SEnji Cooper 621cdebaff8SEnji Cooper rump_server_fs_start $RUMPSRV netinet6 622cdebaff8SEnji Cooper rump_server_start $RUMPCLI netinet6 623cdebaff8SEnji Cooper 624*63d1fd59SEnji Cooper setup_shmif0 $RUMPSRV $IP6SRV 625cdebaff8SEnji Cooper init_server $RUMPSRV 626*63d1fd59SEnji Cooper setup_shmif0 $RUMPCLI $IP6CLI 627cdebaff8SEnji Cooper 628*63d1fd59SEnji Cooper export RUMP_SERVER=$RUMPCLI 629cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'0.->.1' \ 630cdebaff8SEnji Cooper rump.sysctl -w net.inet6.ip6.accept_rtadv=1 631cdebaff8SEnji Cooper atf_check -s exit:0 -o match:'0.->.1' \ 632cdebaff8SEnji Cooper rump.sysctl -w net.inet6.ip6.use_tempaddr=1 633cdebaff8SEnji Cooper unset RUMP_SERVER 634cdebaff8SEnji Cooper 635*63d1fd59SEnji Cooper create_rtadvdconfig 636cdebaff8SEnji Cooper start_rtadvd $RUMPSRV $PIDFILE 637cdebaff8SEnji Cooper sleep $WAITTIME 638cdebaff8SEnji Cooper 639cdebaff8SEnji Cooper check_entries $RUMPCLI $RUMPSRV $IP6SRV_PREFIX 640cdebaff8SEnji Cooper 641*63d1fd59SEnji Cooper export RUMP_SERVER=$RUMPCLI 642*63d1fd59SEnji Cooper 643cdebaff8SEnji Cooper # Check temporary address 644*63d1fd59SEnji Cooper atf_check -s exit:0 \ 645*63d1fd59SEnji Cooper -o match:"$IP6SRV_PREFIX.+<(TENTATIVE,)?AUTOCONF,TEMPORARY>" \ 646cdebaff8SEnji Cooper rump.ifconfig shmif0 inet6 647*63d1fd59SEnji Cooper 648*63d1fd59SEnji Cooper # 649*63d1fd59SEnji Cooper # Testing net.inet6.ip6.prefer_tempaddr 650*63d1fd59SEnji Cooper # 651*63d1fd59SEnji Cooper atf_check -s exit:0 rump.ifconfig -w 10 652*63d1fd59SEnji Cooper $DEBUG && rump.ifconfig shmif0 653*63d1fd59SEnji Cooper ip_auto=$(rump.ifconfig shmif0 |awk '/<AUTOCONF>/ {sub(/\/[0-9]*/, ""); print $2;}') 654*63d1fd59SEnji Cooper ip_temp=$(rump.ifconfig shmif0 |awk '/<AUTOCONF,TEMPORARY>/ {sub(/\/[0-9]*/, ""); print $2;}') 655*63d1fd59SEnji Cooper $DEBUG && echo $ip_auto $ip_temp 656*63d1fd59SEnji Cooper 657*63d1fd59SEnji Cooper # Ignore old packets 658*63d1fd59SEnji Cooper extract_new_packets bus1 > /dev/null 659*63d1fd59SEnji Cooper 660*63d1fd59SEnji Cooper atf_check -s exit:0 -o ignore rump.ping6 -n -X 2 -c 1 $IP6SRV 661*63d1fd59SEnji Cooper # autoconf (non-temporal) address should be used as the source address 662*63d1fd59SEnji Cooper check_echo_request_pkt bus1 $ip_auto $IP6SRV 663*63d1fd59SEnji Cooper 664*63d1fd59SEnji Cooper # Enable net.inet6.ip6.prefer_tempaddr 665*63d1fd59SEnji Cooper atf_check -s exit:0 -o match:'0.->.1' \ 666*63d1fd59SEnji Cooper rump.sysctl -w net.inet6.ip6.prefer_tempaddr=1 667*63d1fd59SEnji Cooper 668*63d1fd59SEnji Cooper atf_check -s exit:0 -o ignore rump.ping6 -n -X 2 -c 1 $IP6SRV 669*63d1fd59SEnji Cooper # autoconf, temporal address should be used as the source address 670*63d1fd59SEnji Cooper check_echo_request_pkt bus1 $ip_temp $IP6SRV 671*63d1fd59SEnji Cooper 672cdebaff8SEnji Cooper unset RUMP_SERVER 673cdebaff8SEnji Cooper 674cdebaff8SEnji Cooper atf_check -s exit:0 kill -TERM `cat ${PIDFILE}` 675*63d1fd59SEnji Cooper wait_term $PIDFILE 676cdebaff8SEnji Cooper 677cdebaff8SEnji Cooper rump_server_destroy_ifaces 678cdebaff8SEnji Cooper} 679cdebaff8SEnji Cooper 680cdebaff8SEnji Cooperra_temporary_address_cleanup() 681cdebaff8SEnji Cooper{ 682cdebaff8SEnji Cooper 683cdebaff8SEnji Cooper if [ -f ${PIDFILE} ]; then 684cdebaff8SEnji Cooper kill -TERM `cat ${PIDFILE}` 685cdebaff8SEnji Cooper wait_term ${PIDFILE} 686cdebaff8SEnji Cooper fi 687cdebaff8SEnji Cooper 688cdebaff8SEnji Cooper $DEBUG && dump 689cdebaff8SEnji Cooper cleanup 690640235e2SEnji Cooper} 691640235e2SEnji Cooper 692640235e2SEnji Cooperatf_init_test_cases() 693640235e2SEnji Cooper{ 694640235e2SEnji Cooper 695cdebaff8SEnji Cooper atf_add_test_case ra_basic 696cdebaff8SEnji Cooper atf_add_test_case ra_flush_prefix_entries 697cdebaff8SEnji Cooper atf_add_test_case ra_flush_defrouter_entries 698cdebaff8SEnji Cooper atf_add_test_case ra_delete_address 699cdebaff8SEnji Cooper atf_add_test_case ra_multiple_routers 700cdebaff8SEnji Cooper atf_add_test_case ra_multiple_routers_single_prefix 701cdebaff8SEnji Cooper atf_add_test_case ra_multiple_routers_maxifprefixes 702cdebaff8SEnji Cooper atf_add_test_case ra_temporary_address 703640235e2SEnji Cooper} 704