network.subr revision 147682
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 147682 2005-06-30 04:52:47Z brooks $ 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. Pseudo arguments DHCP and WPA are handled 38# here. 39# 40ifconfig_up() 41{ 42 _cfg=1 43 44 ifconfig_args=`ifconfig_getargs $1` 45 if [ -n "${ifconfig_args}" ]; then 46 ifconfig $1 ${ifconfig_args} 47 _cfg=0 48 fi 49 50 if wpaif $1; then 51 /etc/rc.d/wpa_supplicant start $1 52 _cfg=0 # XXX: not sure this should count 53 fi 54 55 if dhcpif $1; then 56 /etc/rc.d/dhclient start $1 57 _cfg=0 58 fi 59 60 return $_cfg 61} 62 63# ifconfig_down if 64# Remove all inet entries from the $if interface. It returns 65# 0 if inet entries were found and removed. It returns 1 if 66# no entries were found or they could not be removed. 67# 68ifconfig_down() 69{ 70 [ -z "$1" ] && return 1 71 _ifs="^" 72 _cfg=1 73 74 inetList="`ifconfig $1 | grep 'inet ' | tr "\n" "$_ifs"`" 75 76 oldifs="$IFS" 77 IFS="$_ifs" 78 for _inet in $inetList ; do 79 # get rid of extraneous line 80 [ -z "$_inet" ] && break 81 82 _inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'` 83 84 IFS="$oldifs" 85 ifconfig $1 ${_inet} delete 86 IFS="$_ifs" 87 _cfg=0 88 done 89 IFS="$oldifs" 90 91 if wpaif $1; then 92 /etc/rc.d/wpa_supplicant stop $1 93 _cfg=0 94 fi 95 96 if dhcpif $1; then 97 /etc/rc.d/dhclient stop $1 98 _cfg=0 99 fi 100 101 return $_cfg 102} 103 104# _ifconfig_getargs if 105# Echos the arguments for the supplied interface to stdout. 106# returns 1 if empty. In general, ifconfig_getargs should be used 107# outside this file. 108_ifconfig_getargs() 109{ 110 _ifn=$1 111 if [ -z "$_ifn" ]; then 112 return 1 113 fi 114 115 eval _args=\$ifconfig_$1 116 if [ -z "$_args" -a -n "${pccard_ifconfig}" ]; then 117 for _if in ${removable_interfaces} ; do 118 if [ "$_if" = "$_ifn" ] ; then 119 _args=${pccard_ifconfig} 120 break 121 fi 122 done 123 fi 124 125 echo $_args 126} 127 128# ifconfig_getargs if 129# Takes the result from _ifconfig_getargs and removes pseudo 130# args such as DHCP and WPA. 131ifconfig_getargs() 132{ 133 _tmpargs=`_ifconfig_getargs $1` 134 if [ $? -eq 1 ]; then 135 return 1 136 fi 137 _args= 138 139 for _arg in $_tmpargs; do 140 case $_arg in 141 [Dd][Hh][Cc][Pp]) 142 ;; 143 [Ww][Pp][Aa]) 144 ;; 145 *) 146 _args="$_args $_arg" 147 ;; 148 esac 149 done 150 151 echo $_args 152} 153 154# dhcpif if 155# Returns 0 if the interface is a DHCP interface and 1 otherwise. 156dhcpif() 157{ 158 _tmpargs=`_ifconfig_getargs $1` 159 for _arg in $_tmpargs; do 160 case $_arg in 161 [Dd][Hh][Cc][Pp]) 162 return 0 163 ;; 164 esac 165 done 166 return 1 167} 168 169# wpaif if 170# Returns 0 if the interface is a WPA interface and 1 otherwise. 171wpaif() 172{ 173 _tmpargs=`_ifconfig_getargs $1` 174 for _arg in $_tmpargs; do 175 case $_arg in 176 [Ww][Pp][Aa]) 177 return 0 178 ;; 179 esac 180 done 181 return 1 182} 183 184# ifalias_up if 185# Configure aliases for network interface $if. 186# It returns 0 if at least one alias was configured or 187# 1 if there were none. 188# 189ifalias_up() 190{ 191 _ret=1 192 alias=0 193 while : ; do 194 eval ifconfig_args=\$ifconfig_$1_alias${alias} 195 if [ -n "${ifconfig_args}" ]; then 196 ifconfig $1 ${ifconfig_args} alias 197 alias=$((${alias} + 1)) 198 _ret=0 199 else 200 break 201 fi 202 done 203 return $_ret 204} 205 206#ifalias_down if 207# Remove aliases for network interface $if. 208# It returns 0 if at least one alias was removed or 209# 1 if there were none. 210# 211ifalias_down() 212{ 213 _ret=1 214 alias=0 215 while : ; do 216 eval ifconfig_args=\$ifconfig_$1_alias${alias} 217 if [ -n "${ifconfig_args}" ]; then 218 ifconfig $1 ${ifconfig_args} -alias 219 alias=$((${alias} + 1)) 220 _ret=0 221 else 222 break 223 fi 224 done 225 return $_ret 226} 227 228# ifscript_up if 229# Evaluate a startup script for the $if interface. 230# It returns 0 if a script was found and processed or 231# 1 if no script was found. 232# 233ifscript_up() 234{ 235 if [ -r /etc/start_if.$1 ]; then 236 . /etc/start_if.$1 237 return 0 238 fi 239 return 1 240} 241 242# ifscript_down if 243# Evaluate a shutdown script for the $if interface. 244# It returns 0 if a script was found and processed or 245# 1 if no script was found. 246# 247ifscript_down() 248{ 249 if [ -r /etc/stop_if.$1 ]; then 250 . /etc/stop_if.$1 251 return 0 252 fi 253 return 1 254} 255 256# Create cloneable interfaces. 257# 258clone_up() 259{ 260 _prefix= 261 _list= 262 for ifn in ${cloned_interfaces}; do 263 ifconfig ${ifn} create 264 if [ $? -eq 0 ]; then 265 _list="${_list}${_prefix}${ifn}" 266 [ -z "$_prefix" ] && _prefix=' ' 267 fi 268 done 269 debug "Cloned: ${_list}" 270} 271 272# Destroy cloned interfaces. Destroyed interfaces are echoed 273# to standard output. 274# 275clone_down() 276{ 277 _prefix= 278 _list= 279 for ifn in ${cloned_interfaces}; do 280 ifconfig ${ifn} destroy 281 if [ $? -eq 0 ]; then 282 _list="${_list}${_prefix}${ifn}" 283 [ -z "$_prefix" ] && _prefix=' ' 284 fi 285 done 286 debug "Destroyed clones: ${_list}" 287} 288 289gif_up() { 290 case ${gif_interfaces} in 291 [Nn][Oo] | '') 292 ;; 293 *) 294 for i in ${gif_interfaces}; do 295 eval peers=\$gifconfig_$i 296 case ${peers} in 297 '') 298 continue 299 ;; 300 *) 301 ifconfig $i create >/dev/null 2>&1 302 ifconfig $i tunnel ${peers} 303 ifconfig $i up 304 ;; 305 esac 306 done 307 ;; 308 esac 309} 310 311# 312# ipx_up ifn 313# Configure any IPX addresses for interface $ifn. Returns 0 if IPX 314# arguments were found and configured; returns 1 otherwise. 315# 316ipx_up() 317{ 318 ifn="$1" 319 eval ifconfig_args=\$ifconfig_${ifn}_ipx 320 if [ -n "${ifconfig_args}" ]; then 321 ifconfig ${ifn} ${ifconfig_args} 322 return 0 323 fi 324 return 1 325} 326 327# ipx_down ifn 328# Remove IPX addresses for interface $ifn. Returns 0 if IPX 329# addresses were found and unconfigured. It returns 1, otherwise. 330# 331ipx_down() 332{ 333 [ -z "$1" ] && return 1 334 _ifs="^" 335 _ret=1 336 337 ipxList="`ifconfig $1 | grep 'ipx ' | tr "\n" "$_ifs"`" 338 339 oldifs="$IFS" 340 IFS="$_ifs" 341 for _ipx in $ipxList ; do 342 # get rid of extraneous line 343 [ -z "$_ipx" ] && break 344 345 _ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'` 346 347 IFS="$oldifs" 348 ifconfig $1 ${_ipx} delete 349 IFS="$_ifs" 350 _ret=0 351 done 352 IFS="$oldifs" 353 354 return $_ret 355} 356 357# ifnet_rename 358# Rename all requested interfaces. 359# 360ifnet_rename() 361{ 362 363 _ifn_list="`ifconfig -l`" 364 [ -z "$_ifn_list" ] && return 0 365 for _if in ${_ifn_list} ; do 366 eval _ifname=\$ifconfig_${_if}_name 367 if [ ! -z "$_ifname" ]; then 368 ifconfig $_if name $_ifname 369 fi 370 done 371 return 0 372} 373 374# 375# list_net_interfaces type 376# List all network interfaces. The type of interface returned 377# can be controlled by the type argument. The type 378# argument can be any of the following: 379# nodhcp - all interfaces, excluding DHCP configured interfaces 380# dhcp - list only DHCP configured interfaces 381# If no argument is specified all network interfaces are output. 382# Note that the list will include cloned interfaces if applicable. 383# Cloned interfaces must already exist to have a chance to appear 384# in the list if ${network_interfaces} is set to `auto'. 385# 386list_net_interfaces() 387{ 388 type=$1 389 390 # Get a list of ALL the interfaces 391 # 392 case ${network_interfaces} in 393 [Aa][Uu][Tt][Oo]) 394 _tmplist="`ifconfig -l`" 395 ;; 396 *) 397 _tmplist="${network_interfaces} ${cloned_interfaces}" 398 ;; 399 esac 400 401 if [ -z "$type" ]; then 402 echo $_tmplist 403 return 0 404 fi 405 406 # Separate out dhcp and non-dhcp interfaces 407 # 408 _aprefix= 409 _bprefix= 410 for _if in ${_tmplist} ; do 411 eval _ifarg="\$ifconfig_${_if}" 412 case "$_ifarg" in 413 [Dd][Hh][Cc][Pp]) 414 _dhcplist="${_dhcplist}${_aprefix}${_if}" 415 [ -z "$_aprefix" ] && _aprefix=' ' 416 ;; 417 ''|*) 418 _nodhcplist="${_nodhcplist}${_bprefix}${_if}" 419 [ -z "$_bprefix" ] && _bprefix=' ' 420 ;; 421 esac 422 done 423 424 case ${pccard_ifconfig} in 425 [Dd][Hh][Cc][Pp]) 426 for _if in ${removable_interfaces} ; do 427 _test_if=`ifconfig ${_if} 2>&1` 428 case "$_test_if" in 429 "ifconfig: interface $_if does not exist") 430 ;; 431 *) 432 _dhcplist="${_dhcplist}${_aprefix}${_if}" 433 [ -z "$_aprefix" ] && _aprefix=' ' 434 ;; 435 esac 436 done 437 ;; 438 *) 439 ;; 440 esac 441 442 case "$type" in 443 nodhcp) 444 echo $_nodhcplist 445 ;; 446 dhcp) 447 echo $_dhcplist 448 ;; 449 esac 450 return 0 451} 452 453hexdigit() 454{ 455 if [ $1 -lt 10 ]; then 456 echo $1 457 else 458 case $1 in 459 10) echo a ;; 460 11) echo b ;; 461 12) echo c ;; 462 13) echo d ;; 463 14) echo e ;; 464 15) echo f ;; 465 esac 466 fi 467} 468 469hexprint() 470{ 471 val=$1 472 str='' 473 474 dig=`hexdigit $((${val} & 15))` 475 str=${dig}${str} 476 val=$((${val} >> 4)) 477 while [ ${val} -gt 0 ]; do 478 dig=`hexdigit $((${val} & 15))` 479 str=${dig}${str} 480 val=$((${val} >> 4)) 481 done 482 483 echo ${str} 484} 485 486# Setup the interfaces for IPv6 487network6_interface_setup() 488{ 489 interfaces=$* 490 rtsol_interfaces='' 491 case ${ipv6_gateway_enable} in 492 [Yy][Ee][Ss]) 493 rtsol_available=no 494 ;; 495 *) 496 rtsol_available=yes 497 ;; 498 esac 499 for i in $interfaces; do 500 rtsol_interface=yes 501 eval prefix=\$ipv6_prefix_$i 502 if [ -n "${prefix}" ]; then 503 rtsol_available=no 504 rtsol_interface=no 505 laddr=`network6_getladdr $i` 506 hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'` 507 for j in ${prefix}; do 508 address=$j\:${hostid} 509 ifconfig $i inet6 ${address} prefixlen 64 alias 510 511 case ${ipv6_gateway_enable} in 512 [Yy][Ee][Ss]) 513 # subnet-router anycast address 514 # (rfc2373) 515 ifconfig $i inet6 $j:: prefixlen 64 \ 516 alias anycast 517 ;; 518 esac 519 done 520 fi 521 eval ipv6_ifconfig=\$ipv6_ifconfig_$i 522 if [ -n "${ipv6_ifconfig}" ]; then 523 rtsol_available=no 524 rtsol_interface=no 525 ifconfig $i inet6 ${ipv6_ifconfig} alias 526 fi 527 528 if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ] 529 then 530 case ${i} in 531 lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*) 532 ;; 533 *) 534 rtsol_interfaces="${rtsol_interfaces} ${i}" 535 ;; 536 esac 537 else 538 ifconfig $i inet6 539 fi 540 done 541 542 if [ ${rtsol_available} = yes -a -n "${rtsol_interfaces}" ]; then 543 # Act as endhost - automatically configured. 544 # You can configure only single interface, as 545 # specification assumes that autoconfigured host has 546 # single interface only. 547 sysctl net.inet6.ip6.accept_rtadv=1 548 set ${rtsol_interfaces} 549 ifconfig $1 up 550 rtsol ${rtsol_flags} $1 551 fi 552 553 for i in $interfaces; do 554 alias=0 555 while : ; do 556 eval ipv6_ifconfig=\$ipv6_ifconfig_${i}_alias${alias} 557 if [ -z "${ipv6_ifconfig}" ]; then 558 break; 559 fi 560 ifconfig $i inet6 ${ipv6_ifconfig} alias 561 alias=$((${alias} + 1)) 562 done 563 done 564} 565 566# Setup IPv6 to IPv4 mapping 567network6_stf_setup() 568{ 569 case ${stf_interface_ipv4addr} in 570 [Nn][Oo] | '') 571 ;; 572 *) 573 # assign IPv6 addr and interface route for 6to4 interface 574 stf_prefixlen=$((16+${stf_interface_ipv4plen:-0})) 575 OIFS="$IFS" 576 IFS=".$IFS" 577 set ${stf_interface_ipv4addr} 578 IFS="$OIFS" 579 hexfrag1=`hexprint $(($1*256 + $2))` 580 hexfrag2=`hexprint $(($3*256 + $4))` 581 ipv4_in_hexformat="${hexfrag1}:${hexfrag2}" 582 case ${stf_interface_ipv6_ifid} in 583 [Aa][Uu][Tt][Oo] | '') 584 for i in ${ipv6_network_interfaces}; do 585 laddr=`network6_getladdr ${i}` 586 case ${laddr} in 587 '') 588 ;; 589 *) 590 break 591 ;; 592 esac 593 done 594 stf_interface_ipv6_ifid=`expr "${laddr}" : \ 595 'fe80::\(.*\)%\(.*\)'` 596 case ${stf_interface_ipv6_ifid} in 597 '') 598 stf_interface_ipv6_ifid=0:0:0:1 599 ;; 600 esac 601 ;; 602 esac 603 ifconfig stf0 create >/dev/null 2>&1 604 ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \ 605 prefixlen ${stf_prefixlen} 606 # disallow packets to malicious 6to4 prefix 607 route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject 608 route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject 609 route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject 610 route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject 611 ;; 612 esac 613} 614 615# Setup static routes 616network6_static_routes_setup() 617{ 618 # Set up any static routes. 619 case ${ipv6_defaultrouter} in 620 [Nn][Oo] | '') 621 ;; 622 *) 623 ipv6_static_routes="default ${ipv6_static_routes}" 624 ipv6_route_default="default ${ipv6_defaultrouter}" 625 ;; 626 esac 627 case ${ipv6_static_routes} in 628 [Nn][Oo] | '') 629 ;; 630 *) 631 for i in ${ipv6_static_routes}; do 632 eval ipv6_route_args=\$ipv6_route_${i} 633 route add -inet6 ${ipv6_route_args} 634 done 635 ;; 636 esac 637} 638 639# Setup faith 640network6_faith_setup() 641{ 642 case ${ipv6_faith_prefix} in 643 [Nn][Oo] | '') 644 ;; 645 *) 646 sysctl net.inet6.ip6.keepfaith=1 647 ifconfig faith0 create >/dev/null 2>&1 648 ifconfig faith0 up 649 for prefix in ${ipv6_faith_prefix}; do 650 prefixlen=`expr "${prefix}" : ".*/\(.*\)"` 651 case ${prefixlen} in 652 '') 653 prefixlen=96 654 ;; 655 *) 656 prefix=`expr "${prefix}" : \ 657 "\(.*\)/${prefixlen}"` 658 ;; 659 esac 660 route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1 661 route change -inet6 ${prefix} -prefixlen ${prefixlen} \ 662 -ifp faith0 663 done 664 ;; 665 esac 666} 667 668# Install the "default interface" to kernel, which will be used 669# as the default route when there's no router. 670network6_default_interface_setup() 671{ 672 # Choose IPv6 default interface if it is not clearly specified. 673 case ${ipv6_default_interface} in 674 '') 675 for i in ${ipv6_network_interfaces}; do 676 case $i in 677 lo0|faith[0-9]*) 678 continue 679 ;; 680 esac 681 laddr=`network6_getladdr $i exclude_tentative` 682 case ${laddr} in 683 '') 684 ;; 685 *) 686 ipv6_default_interface=$i 687 break 688 ;; 689 esac 690 done 691 ;; 692 esac 693 694 # Disallow unicast packets without outgoing scope identifiers, 695 # or route such packets to a "default" interface, if it is specified. 696 route add -inet6 fe80:: -prefixlen 10 ::1 -reject 697 case ${ipv6_default_interface} in 698 [Nn][Oo] | '') 699 route add -inet6 ff02:: -prefixlen 16 ::1 -reject 700 ;; 701 *) 702 laddr=`network6_getladdr ${ipv6_default_interface}` 703 route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \ 704 -cloning 705 706 # Disable installing the default interface with the 707 # case net.inet6.ip6.forwarding=0 and 708 # net.inet6.ip6.accept_rtadv=0, due to avoid conflict 709 # between the default router list and the manual 710 # configured default route. 711 case ${ipv6_gateway_enable} in 712 [Yy][Ee][Ss]) 713 ;; 714 *) 715 if [ `sysctl -n net.inet6.ip6.accept_rtadv` -eq 1 ] 716 then 717 ndp -I ${ipv6_default_interface} 718 fi 719 ;; 720 esac 721 ;; 722 esac 723} 724 725network6_getladdr() 726{ 727 ifconfig $1 2>/dev/null | while read proto addr rest; do 728 case ${proto} in 729 inet6) 730 case ${addr} in 731 fe80::*) 732 if [ -z "$2" ]; then 733 echo ${addr} 734 return 735 fi 736 case ${rest} in 737 *tentative*) 738 continue 739 ;; 740 *) 741 echo ${addr} 742 return 743 esac 744 esac 745 esac 746 done 747} 748