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