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