network.subr revision 116029
125184Sjkh# 2113674Smtm# Copyright (c) 2003 The FreeBSD Project. All rights reserved. 3113674Smtm# 4113674Smtm# Redistribution and use in source and binary forms, with or without 5113674Smtm# modification, are permitted provided that the following conditions 6113674Smtm# are met: 7113674Smtm# 1. Redistributions of source code must retain the above copyright 8113674Smtm# notice, this list of conditions and the following disclaimer. 9113674Smtm# 2. Redistributions in binary form must reproduce the above copyright 10113674Smtm# notice, this list of conditions and the following disclaimer in the 11113674Smtm# documentation and/or other materials provided with the distribution. 12113674Smtm# 13113674Smtm# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 14113674Smtm# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15113674Smtm# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16113674Smtm# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 17113674Smtm# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18113674Smtm# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19113674Smtm# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20113674Smtm# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21113674Smtm# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22113674Smtm# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23113674Smtm# SUCH DAMAGE. 24113674Smtm# 2550472Speter# $FreeBSD: head/etc/network.subr 116029 2003-06-08 10:34:40Z mtm $ 2666830Sobrien# 2725184Sjkh 28113674Smtm# 29113674Smtm# Subroutines commonly used from network startup scripts. 30113674Smtm# Requires that rc.conf be loaded first. 31113674Smtm# 3225184Sjkh 33113674Smtm# ifconfig_up if 34113674Smtm# Evaluate ifconfig(8) arguments for interface $if and 35113674Smtm# run ifconfig(8) with those arguments. It returns 0 if 36113674Smtm# arguments were found and executed or 1 if the interface 37113674Smtm# had no arguments. 38113674Smtm# 39113674Smtmifconfig_up() 40113674Smtm{ 41113674Smtm eval ifconfig_args=\$ifconfig_$1 42113674Smtm if [ -n "${ifconfig_args}" ]; then 43113674Smtm ifconfig $1 ${ifconfig_args} 44113674Smtm return 0 45113674Smtm fi 46113674Smtm return 1 47113674Smtm} 4825184Sjkh 49116029Smtm# ifconfig_down if 50116029Smtm# Remove all inet entries from the $if interface. It returns 51116029Smtm# 0 if inet entries were found and removed. It returns 1 if 52116100Smtm# no entries were found or the could not be removed. 53116029Smtm# 54116029Smtmifconfig_down() 55116029Smtm{ 56116029Smtm [ -z "$1" ] && return 1 57116029Smtm _ifs="^" 58116029Smtm _ret=1 59116029Smtm 60116029Smtm inetList="`ifconfig $1 | grep 'inet ' | tr "\n" "$_ifs"`" 61116029Smtm 62116029Smtm oldifs="$IFS" 63116029Smtm IFS="$_ifs" 64116029Smtm for _inet in $inetList ; do 65116029Smtm # get rid of extraneous line 66116029Smtm [ -z "$_inet" ] && break 67116029Smtm 68116029Smtm _inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'` 69116029Smtm 70116032Smtm echo ifconfig $1 ${_inet} delete 71116032Smtm _ret=0 72116032Smtm done 73116029Smtm IFS="$oldifs" 74116029Smtm 75116029Smtm return $_ret 76116029Smtm} 77116029Smtm 78116029Smtm# ifalias_up if 79116029Smtm# Configure aliases for network interface $if. 80113674Smtm# It returns 0 if at least one alias was configured or 81113674Smtm# 1 if there were none. 82113674Smtm# 83113674Smtmifalias_up() 84113674Smtm{ 85113674Smtm _ret=1 86113674Smtm alias=0 87113674Smtm while : ; do 88113674Smtm eval ifconfig_args=\$ifconfig_$1_alias${alias} 89113674Smtm if [ -n "${ifconfig_args}" ]; then 90113674Smtm ifconfig $1 ${ifconfig_args} alias 91113674Smtm alias=$((${alias} + 1)) 92113674Smtm _ret=0 93113674Smtm else 94113674Smtm break 95113674Smtm fi 96113674Smtm done 97113674Smtm return $_ret 98113674Smtm} 99113674Smtm 100113674Smtm#ifalias_down if 101100280Sgordon# Remove aliases for network interface $if. 102116029Smtm# It returns 0 if at least one alias was removed or 103116029Smtm# 1 if there were none. 104116029Smtm# 105116029Smtmifalias_down() 106116029Smtm{ 107116029Smtm _ret=1 108116029Smtm alias=0 109116029Smtm while : ; do 110116029Smtm eval ifconfig_args=\$ifconfig_$1_alias${alias} 111116029Smtm if [ -n "${ifconfig_args}" ]; then 112116029Smtm ifconfig $1 ${ifconfig_args} -alias 113116029Smtm alias=$((${alias} + 1)) 114116029Smtm _ret=0 115116029Smtm else 116116029Smtm break 117116029Smtm fi 118116029Smtm done 119116029Smtm return $_ret 120116029Smtm} 121116029Smtm 122116029Smtm# ifscript_up if 123116029Smtm# Evaluate a startup script for the $if interface. 124113674Smtm# It returns 0 if a script was found and processed or 125113674Smtm# 1 if no script was found. 126113674Smtm# 127113674Smtmifscript_up() 128113674Smtm{ 129113674Smtm if [ -r /etc/start_if.$1 ]; then 130100280Sgordon . /etc/start_if.$1 131113674Smtm return 0 132113674Smtm fi 133113674Smtm return 1 134113674Smtm} 135113674Smtm 136100280Sgordon# ifscript_down if 137100280Sgordon# Evaluate a shutdown script for the $if interface. 138116029Smtm# It returns 0 if a script was found and processed or 139116029Smtm# 1 if no script was found. 140116029Smtm# 141116029Smtmifscript_down() 142116029Smtm{ 143116029Smtm if [ -r /etc/stop_if.$1 ]; then 144116029Smtm . /etc/stop_if.$1 145116029Smtm return 0 146116029Smtm fi 147116029Smtm return 1 148116029Smtm} 149116029Smtm 150116029Smtm# Create cloneable interfaces. 151116029Smtm# 152113674Smtmclone_up() 153113674Smtm{ 154113674Smtm _prefix= 155100280Sgordon _list= 156113674Smtm for ifn in ${cloned_interfaces}; do 157113674Smtm ifconfig ${ifn} create 158113674Smtm if $? ; then 159113674Smtm _list="${_list}${_prefix}${ifn}" 160113674Smtm [ -z "$_prefix" ] && _prefix=' ' 161113674Smtm fi 162113674Smtm done 163113674Smtm debug "Cloned: ${_list}" 164113674Smtm} 165113674Smtm 166113674Smtm# Destroy cloned interfaces. Destroyed interfaces are echoed 167100280Sgordon# to standard output. 168113674Smtm# 169113674Smtmclone_down() 170113674Smtm{ 171113674Smtm _prefix= 172113674Smtm _list= 173113674Smtm for ifn in ${cloned_interfaces}; do 174113674Smtm ifconfig ${ifn} destroy 175113674Smtm if $? ; then 176113674Smtm _list="${_list}${_prefix}${ifn}" 177113674Smtm [ -z "$_prefix" ] && _prefix=' ' 178113674Smtm fi 179113674Smtm done 180113674Smtm debug "Destroyed clones: ${_list}" 181113674Smtm} 182113674Smtm 183100280Sgordongif_up() { 184100280Sgordon case ${gif_interfaces} in 185113674Smtm [Nn][Oo] | '') 186100282Sdougb ;; 187100282Sdougb *) 188100282Sdougb for i in ${gif_interfaces}; do 189100282Sdougb eval peers=\$gifconfig_$i 190100282Sdougb case ${peers} in 191100282Sdougb '') 192100282Sdougb continue 193100282Sdougb ;; 194100282Sdougb *) 195100282Sdougb ifconfig $i create >/dev/null 2>&1 196100282Sdougb ifconfig $i tunnel ${peers} 197100282Sdougb ifconfig $i up 198100282Sdougb ;; 199103710Sume esac 200100282Sdougb done 201100282Sdougb ;; 202100282Sdougb esac 203100282Sdougb} 204100282Sdougb 205100282Sdougb# 206100282Sdougb# ipx_up ifn 207113674Smtm# Configure any IPX addresses for interface $ifn. Returns 0 if IPX 208113674Smtm# arguments were found and configured; returns 1 otherwise. 209113674Smtm# 210113674Smtmipx_up() 211113674Smtm{ 212113674Smtm ifn="$1" 213100280Sgordon eval ifconfig_args=\$ifconfig_${ifn}_ipx 214113674Smtm if [ -n "${ifconfig_args}" ]; then 215113674Smtm ifconfig ${ifn} ${ifconfig_args} 216113674Smtm return 0 217113674Smtm fi 218113674Smtm return 1 21985831Sdes} 220113674Smtm 221113674Smtm# ipx_down ifn 22285831Sdes# Remove IPX addresses for interface $ifn. Returns 0 if IPX 223116029Smtm# addresses were found and unconfigured. It returns 1, otherwise. 224116029Smtm# 225116029Smtmipx_down() 226113674Smtm{ 227116029Smtm # XXX - So, who's an IPX expert ? 228116029Smtm return 1 229116100Smtm} 230116100Smtm 231116100Smtm# 232116100Smtm# list_net_interfaces type 233116100Smtm# List all network interfaces. The type of interface returned 234116100Smtm# can be controlled by the type argument. The type 235116100Smtm# argument can be any of the following: 236116100Smtm# nodhcp - all interfaces, excluding DHCP configured interfaces 237116100Smtm# dhcp - list only DHCP configured interfaces 238116100Smtm# If no argument is specified all network interfaces are output. 239116100Smtm# Note that the list always includes cloned interfaces. 240116100Smtm# 241116100Smtmlist_net_interfaces() 242116100Smtm{ 243116100Smtm type=$1 244116100Smtm 245116100Smtm # Get a list of ALL the interfaces 246116100Smtm # 247116100Smtm case ${network_interfaces} in 248116100Smtm [Aa][Uu][Tt][Oo]) 249116100Smtm _tmplist="`ifconfig -l`" 250116100Smtm ;; 251116029Smtm *) 252116029Smtm _tmplist="${network_interfaces}" 253116029Smtm ;; 254113674Smtm esac 255113674Smtm _tmplist="${_tmplist} ${cloned_interfaces}" 256113674Smtm 257113674Smtm if [ -z "$type" ]; then 258113674Smtm echo $_tmplist 259113674Smtm return 0 260113674Smtm fi 261113674Smtm 262113674Smtm # Separate out dhcp and non-dhcp intefraces 263113674Smtm # 264113674Smtm _aprefix= 265113674Smtm _brefix= 26665532Snectar for _if in ${_tmplist} ; do 267113674Smtm eval _ifarg="\$ifconfig_${_if}" 26851231Ssheldonh case "$_ifarg" in 26951231Ssheldonh [Dd][Hh][Cc][Pp]) 27051231Ssheldonh _dhcplist="${_dhcplist}${_aprefix}${_if}" 271113674Smtm [ -z "$_aprefix" ] && _aprefix=' ' 27251231Ssheldonh ;; 27383677Sbrooks ''|*) 274113674Smtm _nodhcplist="${_nodhcplist}${_bprefix}${_if}" 27583677Sbrooks [ -z "$_bprefix" ] && _bprefix=' ' 27651231Ssheldonh ;; 277113674Smtm esac 27849122Sbrian done 279113674Smtm 280113674Smtm case "$type" in 281113674Smtm nodhcp) 282113674Smtm echo $_nodhcplist 28349122Sbrian ;; 284113674Smtm dhcp) 285113674Smtm echo $_dhcplist 286113674Smtm ;; 287113674Smtm esac 288113674Smtm return 0 289113674Smtm} 290113674Smtm 29151231Ssheldonhhexdigit() 292113674Smtm{ 293113674Smtm if [ $1 -lt 10 ]; then 29451231Ssheldonh echo $1 295113674Smtm else 296113674Smtm case $1 in 297113674Smtm 10) echo a ;; 29851231Ssheldonh 11) echo b ;; 29951231Ssheldonh 12) echo c ;; 30054458Sobrien 13) echo d ;; 30151231Ssheldonh 14) echo e ;; 302113674Smtm 15) echo f ;; 303113674Smtm esac 304113674Smtm fi 305113674Smtm} 306113674Smtm 307113674Smtmhexprint() 308113674Smtm{ 309113674Smtm val=$1 310113674Smtm str='' 31125184Sjkh 312114942Sume dig=`hexdigit $((${val} & 15))` 313114942Sume str=${dig}${str} 314114942Sume val=$((${val} >> 4)) 315114942Sume while [ ${val} -gt 0 ]; do 316114942Sume dig=`hexdigit $((${val} & 15))` 317114942Sume str=${dig}${str} 318114942Sume val=$((${val} >> 4)) 319114942Sume done 320114942Sume 321114942Sume echo ${str} 322114942Sume} 323114942Sume 324114942Sume# Setup the interfaces for IPv6 325114942Sumenetwork6_interface_setup() 326114942Sume{ 327114942Sume interfaces=$* 328114942Sume rtsol_interfaces='' 329114942Sume case ${ipv6_gateway_enable} in 330114942Sume [Yy][Ee][Ss]) 331114942Sume rtsol_available=no 332114942Sume ;; 333114942Sume *) 334114942Sume rtsol_available=yes 335114942Sume ;; 336114942Sume esac 337114942Sume for i in $interfaces; do 338114942Sume rtsol_interface=yes 339114942Sume eval prefix=\$ipv6_prefix_$i 340114942Sume if [ -n "${prefix}" ]; then 341114942Sume rtsol_available=no 342114942Sume rtsol_interface=no 343114942Sume laddr=`network6_getladdr $i` 344114942Sume hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'` 345114942Sume for j in ${prefix}; do 346114942Sume address=$j\:${hostid} 347114942Sume ifconfig $i inet6 ${address} prefixlen 64 alias 348114942Sume 349114942Sume case ${ipv6_gateway_enable} in 350114942Sume [Yy][Ee][Ss]) 351114942Sume # subnet-router anycast address 352114942Sume # (rfc2373) 353114942Sume ifconfig $i inet6 $j:: prefixlen 64 \ 354114942Sume alias anycast 355114942Sume ;; 356114942Sume esac 357114942Sume done 358114942Sume fi 359114942Sume eval ipv6_ifconfig=\$ipv6_ifconfig_$i 360114942Sume if [ -n "${ipv6_ifconfig}" ]; then 361114942Sume rtsol_available=no 362114942Sume rtsol_interface=no 363114942Sume ifconfig $i inet6 ${ipv6_ifconfig} alias 364114942Sume fi 365114942Sume 366114942Sume if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ] 367114942Sume then 368114942Sume case ${i} in 369114942Sume lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*) 370114942Sume ;; 371114942Sume *) 372114942Sume rtsol_interfaces="${rtsol_interfaces} ${i}" 373114942Sume ;; 374114942Sume esac 375114942Sume else 376114942Sume ifconfig $i inet6 377114942Sume fi 378114942Sume done 379114942Sume 380114942Sume if [ ${rtsol_available} = yes -a -n "${rtsol_interfaces}" ]; then 381114942Sume # Act as endhost - automatically configured. 382114942Sume # You can configure only single interface, as 383114942Sume # specification assumes that autoconfigured host has 384114942Sume # single interface only. 385114942Sume sysctl net.inet6.ip6.accept_rtadv=1 386114942Sume set ${rtsol_interfaces} 387114942Sume ifconfig $1 up 388114942Sume rtsol $1 389114942Sume fi 390114942Sume 391114942Sume for i in $interfaces; do 392114942Sume alias=0 393114942Sume while : ; do 394114942Sume eval ipv6_ifconfig=\$ipv6_ifconfig_${i}_alias${alias} 395114942Sume if [ -z "${ipv6_ifconfig}" ]; then 396114942Sume break; 397114942Sume fi 398114942Sume ifconfig $i inet6 ${ipv6_ifconfig} alias 399114942Sume alias=$((${alias} + 1)) 400114942Sume done 401114942Sume done 402114942Sume} 403114942Sume 404114942Sume# Setup IPv6 to IPv4 mapping 405114942Sumenetwork6_stf_setup() 406114942Sume{ 407114942Sume case ${stf_interface_ipv4addr} in 408114942Sume [Nn][Oo] | '') 409114942Sume ;; 410114942Sume *) 411114942Sume # assign IPv6 addr and interface route for 6to4 interface 412114942Sume stf_prefixlen=$((16+${stf_interface_ipv4plen:-0})) 413114942Sume OIFS="$IFS" 414114942Sume IFS=".$IFS" 415114942Sume set ${stf_interface_ipv4addr} 416114942Sume IFS="$OIFS" 417114942Sume hexfrag1=`hexprint $(($1*256 + $2))` 418114942Sume hexfrag2=`hexprint $(($3*256 + $4))` 419114942Sume ipv4_in_hexformat="${hexfrag1}:${hexfrag2}" 420114942Sume case ${stf_interface_ipv6_ifid} in 421114942Sume [Aa][Uu][Tt][Oo] | '') 422114942Sume for i in ${ipv6_network_interfaces}; do 423114942Sume laddr=`network6_getladdr ${i}` 424114942Sume case ${laddr} in 425114942Sume '') 426114942Sume ;; 427114942Sume *) 428114942Sume break 429114942Sume ;; 430114942Sume esac 431114942Sume done 432114942Sume stf_interface_ipv6_ifid=`expr "${laddr}" : \ 433114942Sume 'fe80::\(.*\)%\(.*\)'` 434114942Sume case ${stf_interface_ipv6_ifid} in 435114942Sume '') 436114942Sume stf_interface_ipv6_ifid=0:0:0:1 437114942Sume ;; 438114942Sume esac 439114942Sume ;; 440114942Sume esac 441114942Sume ifconfig stf0 create >/dev/null 2>&1 442114942Sume ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \ 443114942Sume prefixlen ${stf_prefixlen} 444114942Sume # disallow packets to malicious 6to4 prefix 445114942Sume route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject 446114942Sume route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject 447114942Sume route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject 448114942Sume route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject 449114942Sume ;; 450114942Sume esac 451114942Sume} 452114942Sume 453114942Sume# Setup static routes 454114942Sumenetwork6_static_routes_setup() 455114942Sume{ 456114942Sume # Set up any static routes. 457114942Sume case ${ipv6_defaultrouter} in 458114942Sume [Nn][Oo] | '') 459114942Sume ;; 460114942Sume *) 461114942Sume ipv6_static_routes="default ${ipv6_static_routes}" 462114942Sume ipv6_route_default="default ${ipv6_defaultrouter}" 463114942Sume ;; 464114942Sume esac 465114942Sume case ${ipv6_static_routes} in 466114942Sume [Nn][Oo] | '') 467114942Sume ;; 468114942Sume *) 469114942Sume for i in ${ipv6_static_routes}; do 470114942Sume eval ipv6_route_args=\$ipv6_route_${i} 471114942Sume route add -inet6 ${ipv6_route_args} 472114942Sume done 473114942Sume ;; 474114942Sume esac 475114942Sume} 476114942Sume 477114942Sume# Setup faith 478114942Sumenetwork6_faith_setup() 479114942Sume{ 480114942Sume case ${ipv6_faith_prefix} in 481114942Sume [Nn][Oo] | '') 482114942Sume ;; 483114942Sume *) 484114942Sume sysctl net.inet6.ip6.keepfaith=1 485114942Sume ifconfig faith0 create >/dev/null 2>&1 486114942Sume ifconfig faith0 up 487114942Sume for prefix in ${ipv6_faith_prefix}; do 488114942Sume prefixlen=`expr "${prefix}" : ".*/\(.*\)"` 489114942Sume case ${prefixlen} in 490114942Sume '') 491114942Sume prefixlen=96 492114942Sume ;; 493114942Sume *) 494114942Sume prefix=`expr "${prefix}" : \ 495114942Sume "\(.*\)/${prefixlen}"` 496114942Sume ;; 497114942Sume esac 498114942Sume route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1 499114942Sume route change -inet6 ${prefix} -prefixlen ${prefixlen} \ 500114942Sume -ifp faith0 501114942Sume done 502114942Sume ;; 503114942Sume esac 504114942Sume} 505114942Sume 506114942Sume# Install the "default interface" to kernel, which will be used 507114942Sume# as the default route when there's no router. 508114942Sumenetwork6_default_interface_setup() 509114942Sume{ 510114942Sume # Choose IPv6 default interface if it is not clearly specified. 511114942Sume case ${ipv6_default_interface} in 512114942Sume '') 513114942Sume for i in ${ipv6_network_interfaces}; do 514114942Sume case $i in 515114942Sume lo0|faith[0-9]*) 516114942Sume continue 517114942Sume ;; 518114942Sume esac 519114942Sume laddr=`network6_getladdr $i exclude_tentative` 520114942Sume case ${laddr} in 521114942Sume '') 522114942Sume ;; 523114942Sume *) 524114942Sume ipv6_default_interface=$i 525114942Sume break 526114942Sume ;; 527114942Sume esac 528114942Sume done 529114942Sume ;; 530114942Sume esac 531114942Sume 532114942Sume # Disallow unicast packets without outgoing scope identifiers, 533114942Sume # or route such packets to a "default" interface, if it is specified. 534114942Sume route add -inet6 fe80:: -prefixlen 10 ::1 -reject 535114942Sume case ${ipv6_default_interface} in 536114942Sume [Nn][Oo] | '') 537114942Sume route add -inet6 ff02:: -prefixlen 16 ::1 -reject 538114942Sume ;; 539114942Sume *) 540114942Sume laddr=`network6_getladdr ${ipv6_default_interface}` 541114942Sume route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \ 542114942Sume -cloning 543114942Sume 544114942Sume # Disable installing the default interface with the 545114942Sume # case net.inet6.ip6.forwarding=0 and 546114942Sume # net.inet6.ip6.accept_rtadv=0, due to avoid conflict 547114942Sume # between the default router list and the manual 548114942Sume # configured default route. 549114942Sume case ${ipv6_gateway_enable} in 550114942Sume [Yy][Ee][Ss]) 551114942Sume ;; 552114942Sume *) 553114942Sume if [ `sysctl -n net.inet6.ip6.accept_rtadv` -eq 1 ] 554114942Sume then 555114942Sume ndp -I ${ipv6_default_interface} 556114942Sume fi 557114942Sume ;; 558114942Sume esac 559114942Sume ;; 560114942Sume esac 561114942Sume} 562114942Sume 563114942Sumenetwork6_getladdr() 564114942Sume{ 565114942Sume ifconfig $1 2>/dev/null | while read proto addr rest; do 566114942Sume case ${proto} in 567114942Sume inet6) 568114942Sume case ${addr} in 569114942Sume fe80::*) 570114942Sume if [ -z "$2" ]; then 571114942Sume echo ${addr} 572114942Sume return 573114942Sume fi 574114942Sume case ${rest} in 575114942Sume *tentative*) 576114942Sume continue 577114942Sume ;; 578114942Sume *) 579114942Sume echo ${addr} 580114942Sume return 581114942Sume esac 582114942Sume esac 583114942Sume esac 584114942Sume done 585114942Sume} 586114942Sume