network.subr revision 137070
1# 2# Copyright (c) 2003 The FreeBSD Project. All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions 6# are met: 7# 1. Redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer. 9# 2. Redistributions in binary form must reproduce the above copyright 10# notice, this list of conditions and the following disclaimer in the 11# documentation and/or other materials provided with the distribution. 12# 13# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 14# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 17# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23# SUCH DAMAGE. 24# 25# $FreeBSD: head/etc/network.subr 137070 2004-10-30 13:44:06Z pjd $ 26# 27 28# 29# Subroutines commonly used from network startup scripts. 30# Requires that rc.conf be loaded first. 31# 32 33# ifconfig_up if 34# Evaluate ifconfig(8) arguments for interface $if and 35# run ifconfig(8) with those arguments. It returns 0 if 36# arguments were found and executed or 1 if the interface 37# had no arguments. 38# 39ifconfig_up() 40{ 41 eval ifconfig_args=\$ifconfig_$1 42 if [ -n "${ifconfig_args}" ]; then 43 ifconfig $1 ${ifconfig_args} 44 return 0 45 fi 46 return 1 47} 48 49# ifconfig_down if 50# Remove all inet entries from the $if interface. It returns 51# 0 if inet entries were found and removed. It returns 1 if 52# no entries were found or they could not be removed. 53# 54ifconfig_down() 55{ 56 [ -z "$1" ] && return 1 57 _ifs="^" 58 _ret=1 59 60 inetList="`ifconfig $1 | grep 'inet ' | tr "\n" "$_ifs"`" 61 62 oldifs="$IFS" 63 IFS="$_ifs" 64 for _inet in $inetList ; do 65 # get rid of extraneous line 66 [ -z "$_inet" ] && break 67 68 _inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'` 69 70 IFS="$oldifs" 71 ifconfig $1 ${_inet} delete 72 IFS="$_ifs" 73 _ret=0 74 done 75 IFS="$oldifs" 76 77 return $_ret 78} 79 80# ifalias_up if 81# Configure aliases for network interface $if. 82# It returns 0 if at least one alias was configured or 83# 1 if there were none. 84# 85ifalias_up() 86{ 87 _ret=1 88 alias=0 89 while : ; do 90 eval ifconfig_args=\$ifconfig_$1_alias${alias} 91 if [ -n "${ifconfig_args}" ]; then 92 ifconfig $1 ${ifconfig_args} alias 93 alias=$((${alias} + 1)) 94 _ret=0 95 else 96 break 97 fi 98 done 99 return $_ret 100} 101 102#ifalias_down if 103# Remove aliases for network interface $if. 104# It returns 0 if at least one alias was removed or 105# 1 if there were none. 106# 107ifalias_down() 108{ 109 _ret=1 110 alias=0 111 while : ; do 112 eval ifconfig_args=\$ifconfig_$1_alias${alias} 113 if [ -n "${ifconfig_args}" ]; then 114 ifconfig $1 ${ifconfig_args} -alias 115 alias=$((${alias} + 1)) 116 _ret=0 117 else 118 break 119 fi 120 done 121 return $_ret 122} 123 124# ifscript_up if 125# Evaluate a startup script for the $if interface. 126# It returns 0 if a script was found and processed or 127# 1 if no script was found. 128# 129ifscript_up() 130{ 131 if [ -r /etc/start_if.$1 ]; then 132 . /etc/start_if.$1 133 return 0 134 fi 135 return 1 136} 137 138# ifscript_down if 139# Evaluate a shutdown script for the $if interface. 140# It returns 0 if a script was found and processed or 141# 1 if no script was found. 142# 143ifscript_down() 144{ 145 if [ -r /etc/stop_if.$1 ]; then 146 . /etc/stop_if.$1 147 return 0 148 fi 149 return 1 150} 151 152# Create cloneable interfaces. 153# 154clone_up() 155{ 156 _prefix= 157 _list= 158 for ifn in ${cloned_interfaces}; do 159 ifconfig ${ifn} create 160 if [ $? -eq 0 ]; then 161 _list="${_list}${_prefix}${ifn}" 162 [ -z "$_prefix" ] && _prefix=' ' 163 fi 164 done 165 debug "Cloned: ${_list}" 166} 167 168# Destroy cloned interfaces. Destroyed interfaces are echoed 169# to standard output. 170# 171clone_down() 172{ 173 _prefix= 174 _list= 175 for ifn in ${cloned_interfaces}; do 176 ifconfig ${ifn} destroy 177 if [ $? -eq 0 ]; then 178 _list="${_list}${_prefix}${ifn}" 179 [ -z "$_prefix" ] && _prefix=' ' 180 fi 181 done 182 debug "Destroyed clones: ${_list}" 183} 184 185gif_up() { 186 case ${gif_interfaces} in 187 [Nn][Oo] | '') 188 ;; 189 *) 190 for i in ${gif_interfaces}; do 191 eval peers=\$gifconfig_$i 192 case ${peers} in 193 '') 194 continue 195 ;; 196 *) 197 ifconfig $i create >/dev/null 2>&1 198 ifconfig $i tunnel ${peers} 199 ifconfig $i up 200 ;; 201 esac 202 done 203 ;; 204 esac 205} 206 207# 208# ipx_up ifn 209# Configure any IPX addresses for interface $ifn. Returns 0 if IPX 210# arguments were found and configured; returns 1 otherwise. 211# 212ipx_up() 213{ 214 ifn="$1" 215 eval ifconfig_args=\$ifconfig_${ifn}_ipx 216 if [ -n "${ifconfig_args}" ]; then 217 ifconfig ${ifn} ${ifconfig_args} 218 return 0 219 fi 220 return 1 221} 222 223# ipx_down ifn 224# Remove IPX addresses for interface $ifn. Returns 0 if IPX 225# addresses were found and unconfigured. It returns 1, otherwise. 226# 227ipx_down() 228{ 229 [ -z "$1" ] && return 1 230 _ifs="^" 231 _ret=1 232 233 ipxList="`ifconfig $1 | grep 'ipx ' | tr "\n" "$_ifs"`" 234 235 oldifs="$IFS" 236 IFS="$_ifs" 237 for _ipx in $ipxList ; do 238 # get rid of extraneous line 239 [ -z "$_ipx" ] && break 240 241 _ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'` 242 243 IFS="$oldifs" 244 ifconfig $1 ${_ipx} delete 245 IFS="$_ifs" 246 _ret=0 247 done 248 IFS="$oldifs" 249 250 return $_ret 251} 252 253# ifnet_rename 254# Rename all requested interfaces. 255# 256ifnet_rename() 257{ 258 259 _ifn_list="`list_net_interfaces all`" 260 [ -z "$_ifn_list" ] && return 0 261 for _if in ${_ifn_list} ; do 262 eval _ifname=\$ifconfig_${_if}_name 263 if [ ! -z "$_ifname" ]; then 264 ifconfig $_if name $_ifname 265 fi 266 done 267 return 0 268} 269 270# 271# list_net_interfaces type 272# List all network interfaces. The type of interface returned 273# can be controlled by the type argument. The type 274# argument can be any of the following: 275# nodhcp - all interfaces, excluding DHCP configured interfaces 276# dhcp - list only DHCP configured interfaces 277# all - all interfaces 278# If no argument is specified all network interfaces are output. 279# Note that the list will include cloned interfaces if applicable. 280# Cloned interfaces must already exist to have a chance to appear 281# in the list if ${network_interfaces} is set to `auto'. 282# 283list_net_interfaces() 284{ 285 type=$1 286 287 # Get a list of ALL the interfaces 288 # 289 case ${network_interfaces} in 290 [Aa][Uu][Tt][Oo]) 291 _tmplist="`ifconfig -l`" 292 ;; 293 *) 294 _tmplist="${network_interfaces} ${cloned_interfaces}" 295 ;; 296 esac 297 298 if [ -z "$type" ]; then 299 echo $_tmplist 300 return 0 301 fi 302 303 # Separate out dhcp and non-dhcp intefraces 304 # 305 _aprefix= 306 _bprefix= 307 for _if in ${_tmplist} ; do 308 eval _ifarg="\$ifconfig_${_if}" 309 case "$_ifarg" in 310 [Dd][Hh][Cc][Pp]) 311 _dhcplist="${_dhcplist}${_aprefix}${_if}" 312 [ -z "$_aprefix" ] && _aprefix=' ' 313 ;; 314 ''|*) 315 _nodhcplist="${_nodhcplist}${_bprefix}${_if}" 316 [ -z "$_bprefix" ] && _bprefix=' ' 317 ;; 318 esac 319 done 320 321 case ${pccard_ifconfig} in 322 [Dd][Hh][Cc][Pp]) 323 for _if in ${removable_interfaces} ; do 324 _test_if=`ifconfig ${_if} 2>&1` 325 case "$_test_if" in 326 "ifconfig: interface $_if does not exist") 327 ;; 328 *) 329 _dhcplist="${_dhcplist}${_aprefix}${_if}" 330 [ -z "$_aprefix" ] && _aprefix=' ' 331 ;; 332 esac 333 done 334 ;; 335 *) 336 ;; 337 esac 338 339 case "$type" in 340 nodhcp) 341 echo $_nodhcplist 342 ;; 343 dhcp) 344 echo $_dhcplist 345 ;; 346 all) 347 echo $_nodhcplist $_dhcplist 348 ;; 349 esac 350 return 0 351} 352 353hexdigit() 354{ 355 if [ $1 -lt 10 ]; then 356 echo $1 357 else 358 case $1 in 359 10) echo a ;; 360 11) echo b ;; 361 12) echo c ;; 362 13) echo d ;; 363 14) echo e ;; 364 15) echo f ;; 365 esac 366 fi 367} 368 369hexprint() 370{ 371 val=$1 372 str='' 373 374 dig=`hexdigit $((${val} & 15))` 375 str=${dig}${str} 376 val=$((${val} >> 4)) 377 while [ ${val} -gt 0 ]; do 378 dig=`hexdigit $((${val} & 15))` 379 str=${dig}${str} 380 val=$((${val} >> 4)) 381 done 382 383 echo ${str} 384} 385 386# Setup the interfaces for IPv6 387network6_interface_setup() 388{ 389 interfaces=$* 390 rtsol_interfaces='' 391 case ${ipv6_gateway_enable} in 392 [Yy][Ee][Ss]) 393 rtsol_available=no 394 ;; 395 *) 396 rtsol_available=yes 397 ;; 398 esac 399 for i in $interfaces; do 400 rtsol_interface=yes 401 eval prefix=\$ipv6_prefix_$i 402 if [ -n "${prefix}" ]; then 403 rtsol_available=no 404 rtsol_interface=no 405 laddr=`network6_getladdr $i` 406 hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'` 407 for j in ${prefix}; do 408 address=$j\:${hostid} 409 ifconfig $i inet6 ${address} prefixlen 64 alias 410 411 case ${ipv6_gateway_enable} in 412 [Yy][Ee][Ss]) 413 # subnet-router anycast address 414 # (rfc2373) 415 ifconfig $i inet6 $j:: prefixlen 64 \ 416 alias anycast 417 ;; 418 esac 419 done 420 fi 421 eval ipv6_ifconfig=\$ipv6_ifconfig_$i 422 if [ -n "${ipv6_ifconfig}" ]; then 423 rtsol_available=no 424 rtsol_interface=no 425 ifconfig $i inet6 ${ipv6_ifconfig} alias 426 fi 427 428 if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ] 429 then 430 case ${i} in 431 lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*) 432 ;; 433 *) 434 rtsol_interfaces="${rtsol_interfaces} ${i}" 435 ;; 436 esac 437 else 438 ifconfig $i inet6 439 fi 440 done 441 442 if [ ${rtsol_available} = yes -a -n "${rtsol_interfaces}" ]; then 443 # Act as endhost - automatically configured. 444 # You can configure only single interface, as 445 # specification assumes that autoconfigured host has 446 # single interface only. 447 sysctl net.inet6.ip6.accept_rtadv=1 448 set ${rtsol_interfaces} 449 ifconfig $1 up 450 rtsol ${rtsol_flags} $1 451 fi 452 453 for i in $interfaces; do 454 alias=0 455 while : ; do 456 eval ipv6_ifconfig=\$ipv6_ifconfig_${i}_alias${alias} 457 if [ -z "${ipv6_ifconfig}" ]; then 458 break; 459 fi 460 ifconfig $i inet6 ${ipv6_ifconfig} alias 461 alias=$((${alias} + 1)) 462 done 463 done 464} 465 466# Setup IPv6 to IPv4 mapping 467network6_stf_setup() 468{ 469 case ${stf_interface_ipv4addr} in 470 [Nn][Oo] | '') 471 ;; 472 *) 473 # assign IPv6 addr and interface route for 6to4 interface 474 stf_prefixlen=$((16+${stf_interface_ipv4plen:-0})) 475 OIFS="$IFS" 476 IFS=".$IFS" 477 set ${stf_interface_ipv4addr} 478 IFS="$OIFS" 479 hexfrag1=`hexprint $(($1*256 + $2))` 480 hexfrag2=`hexprint $(($3*256 + $4))` 481 ipv4_in_hexformat="${hexfrag1}:${hexfrag2}" 482 case ${stf_interface_ipv6_ifid} in 483 [Aa][Uu][Tt][Oo] | '') 484 for i in ${ipv6_network_interfaces}; do 485 laddr=`network6_getladdr ${i}` 486 case ${laddr} in 487 '') 488 ;; 489 *) 490 break 491 ;; 492 esac 493 done 494 stf_interface_ipv6_ifid=`expr "${laddr}" : \ 495 'fe80::\(.*\)%\(.*\)'` 496 case ${stf_interface_ipv6_ifid} in 497 '') 498 stf_interface_ipv6_ifid=0:0:0:1 499 ;; 500 esac 501 ;; 502 esac 503 ifconfig stf0 create >/dev/null 2>&1 504 ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \ 505 prefixlen ${stf_prefixlen} 506 # disallow packets to malicious 6to4 prefix 507 route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject 508 route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject 509 route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject 510 route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject 511 ;; 512 esac 513} 514 515# Setup static routes 516network6_static_routes_setup() 517{ 518 # Set up any static routes. 519 case ${ipv6_defaultrouter} in 520 [Nn][Oo] | '') 521 ;; 522 *) 523 ipv6_static_routes="default ${ipv6_static_routes}" 524 ipv6_route_default="default ${ipv6_defaultrouter}" 525 ;; 526 esac 527 case ${ipv6_static_routes} in 528 [Nn][Oo] | '') 529 ;; 530 *) 531 for i in ${ipv6_static_routes}; do 532 eval ipv6_route_args=\$ipv6_route_${i} 533 route add -inet6 ${ipv6_route_args} 534 done 535 ;; 536 esac 537} 538 539# Setup faith 540network6_faith_setup() 541{ 542 case ${ipv6_faith_prefix} in 543 [Nn][Oo] | '') 544 ;; 545 *) 546 sysctl net.inet6.ip6.keepfaith=1 547 ifconfig faith0 create >/dev/null 2>&1 548 ifconfig faith0 up 549 for prefix in ${ipv6_faith_prefix}; do 550 prefixlen=`expr "${prefix}" : ".*/\(.*\)"` 551 case ${prefixlen} in 552 '') 553 prefixlen=96 554 ;; 555 *) 556 prefix=`expr "${prefix}" : \ 557 "\(.*\)/${prefixlen}"` 558 ;; 559 esac 560 route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1 561 route change -inet6 ${prefix} -prefixlen ${prefixlen} \ 562 -ifp faith0 563 done 564 ;; 565 esac 566} 567 568# Install the "default interface" to kernel, which will be used 569# as the default route when there's no router. 570network6_default_interface_setup() 571{ 572 # Choose IPv6 default interface if it is not clearly specified. 573 case ${ipv6_default_interface} in 574 '') 575 for i in ${ipv6_network_interfaces}; do 576 case $i in 577 lo0|faith[0-9]*) 578 continue 579 ;; 580 esac 581 laddr=`network6_getladdr $i exclude_tentative` 582 case ${laddr} in 583 '') 584 ;; 585 *) 586 ipv6_default_interface=$i 587 break 588 ;; 589 esac 590 done 591 ;; 592 esac 593 594 # Disallow unicast packets without outgoing scope identifiers, 595 # or route such packets to a "default" interface, if it is specified. 596 route add -inet6 fe80:: -prefixlen 10 ::1 -reject 597 case ${ipv6_default_interface} in 598 [Nn][Oo] | '') 599 route add -inet6 ff02:: -prefixlen 16 ::1 -reject 600 ;; 601 *) 602 laddr=`network6_getladdr ${ipv6_default_interface}` 603 route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \ 604 -cloning 605 606 # Disable installing the default interface with the 607 # case net.inet6.ip6.forwarding=0 and 608 # net.inet6.ip6.accept_rtadv=0, due to avoid conflict 609 # between the default router list and the manual 610 # configured default route. 611 case ${ipv6_gateway_enable} in 612 [Yy][Ee][Ss]) 613 ;; 614 *) 615 if [ `sysctl -n net.inet6.ip6.accept_rtadv` -eq 1 ] 616 then 617 ndp -I ${ipv6_default_interface} 618 fi 619 ;; 620 esac 621 ;; 622 esac 623} 624 625network6_getladdr() 626{ 627 ifconfig $1 2>/dev/null | while read proto addr rest; do 628 case ${proto} in 629 inet6) 630 case ${addr} in 631 fe80::*) 632 if [ -z "$2" ]; then 633 echo ${addr} 634 return 635 fi 636 case ${rest} in 637 *tentative*) 638 continue 639 ;; 640 *) 641 echo ${addr} 642 return 643 esac 644 esac 645 esac 646 done 647} 648