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.5 2007/07/10 22:36:01 swildner 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 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. NOTE: cloned interfaces 391 # have already been configured so they should show up in the 392 # ifconfig -l output. 393 # 394 case ${network_interfaces} in 395 [Aa][Uu][Tt][Oo]) 396 _tmplist="`ifconfig -l`" 397 ;; 398 *) 399 _tmplist="${network_interfaces} ${cloned_interfaces}" 400 ;; 401 esac 402 403 if [ -z "$type" ]; then 404 echo $_tmplist 405 return 0 406 fi 407 408 # Separate out dhcp and non-dhcp interfaces 409 # 410 _aprefix= 411 _bprefix= 412 for _if in ${_tmplist} ; do 413 eval _ifarg="\$ifconfig_${_if}" 414 case "$_ifarg" in 415 [Dd][Hh][Cc][Pp]) 416 _dhcplist="${_dhcplist}${_aprefix}${_if}" 417 [ -z "$_aprefix" ] && _aprefix=' ' 418 ;; 419 ''|*) 420 _nodhcplist="${_nodhcplist}${_bprefix}${_if}" 421 [ -z "$_bprefix" ] && _bprefix=' ' 422 ;; 423 esac 424 done 425 426 case "$type" in 427 nodhcp) 428 echo $_nodhcplist 429 ;; 430 dhcp) 431 echo $_dhcplist 432 ;; 433 esac 434 return 0 435} 436 437hexdigit() 438{ 439 if [ $1 -lt 10 ]; then 440 echo $1 441 else 442 case $1 in 443 10) echo a ;; 444 11) echo b ;; 445 12) echo c ;; 446 13) echo d ;; 447 14) echo e ;; 448 15) echo f ;; 449 esac 450 fi 451} 452 453hexprint() 454{ 455 val=$1 456 str='' 457 458 dig=`hexdigit $((${val} & 15))` 459 str=${dig}${str} 460 val=$((${val} >> 4)) 461 while [ ${val} -gt 0 ]; do 462 dig=`hexdigit $((${val} & 15))` 463 str=${dig}${str} 464 val=$((${val} >> 4)) 465 done 466 467 echo ${str} 468} 469 470# Setup the interfaces for IPv6 471network6_interface_setup() 472{ 473 interfaces=$* 474 rtsol_interfaces='' 475 case ${ipv6_gateway_enable} in 476 [Yy][Ee][Ss]) 477 rtsol_available=no 478 ;; 479 *) 480 rtsol_available=yes 481 ;; 482 esac 483 for i in $interfaces; do 484 rtsol_interface=yes 485 eval prefix=\$ipv6_prefix_$i 486 if [ -n "${prefix}" ]; then 487 rtsol_available=no 488 rtsol_interface=no 489 laddr=`network6_getladdr $i` 490 hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'` 491 for j in ${prefix}; do 492 address=$j\:${hostid} 493 ifconfig $i inet6 ${address} prefixlen 64 alias 494 495 case ${ipv6_gateway_enable} in 496 [Yy][Ee][Ss]) 497 # subnet-router anycast address 498 # (rfc2373) 499 ifconfig $i inet6 $j:: prefixlen 64 \ 500 alias anycast 501 ;; 502 esac 503 done 504 fi 505 eval ipv6_ifconfig=\$ipv6_ifconfig_$i 506 if [ -n "${ipv6_ifconfig}" ]; then 507 rtsol_available=no 508 rtsol_interface=no 509 ifconfig $i inet6 ${ipv6_ifconfig} alias 510 fi 511 512 if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ] 513 then 514 case ${i} in 515 lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*) 516 ;; 517 *) 518 rtsol_interfaces="${rtsol_interfaces} ${i}" 519 ;; 520 esac 521 else 522 ifconfig $i inet6 523 fi 524 done 525 526 if [ ${rtsol_available} = yes -a -n "${rtsol_interfaces}" ]; then 527 # Act as endhost - automatically configured. 528 # You can configure only single interface, as 529 # specification assumes that autoconfigured host has 530 # single interface only. 531 sysctl net.inet6.ip6.accept_rtadv=1 532 set ${rtsol_interfaces} 533 ifconfig $1 up 534 rtsol $1 535 fi 536 537 for i in $interfaces; do 538 alias=0 539 while : ; do 540 eval ipv6_ifconfig=\$ipv6_ifconfig_${i}_alias${alias} 541 if [ -z "${ipv6_ifconfig}" ]; then 542 break; 543 fi 544 ifconfig $i inet6 ${ipv6_ifconfig} alias 545 alias=$((${alias} + 1)) 546 done 547 done 548} 549 550# Setup IPv6 to IPv4 mapping 551network6_stf_setup() 552{ 553 case ${stf_interface_ipv4addr} in 554 [Nn][Oo] | '') 555 ;; 556 *) 557 # assign IPv6 addr and interface route for 6to4 interface 558 stf_prefixlen=$((16+${stf_interface_ipv4plen:-0})) 559 OIFS="$IFS" 560 IFS=".$IFS" 561 set ${stf_interface_ipv4addr} 562 IFS="$OIFS" 563 hexfrag1=`hexprint $(($1*256 + $2))` 564 hexfrag2=`hexprint $(($3*256 + $4))` 565 ipv4_in_hexformat="${hexfrag1}:${hexfrag2}" 566 case ${stf_interface_ipv6_ifid} in 567 [Aa][Uu][Tt][Oo] | '') 568 for i in ${ipv6_network_interfaces}; do 569 laddr=`network6_getladdr ${i}` 570 case ${laddr} in 571 '') 572 ;; 573 *) 574 break 575 ;; 576 esac 577 done 578 stf_interface_ipv6_ifid=`expr "${laddr}" : \ 579 'fe80::\(.*\)%\(.*\)'` 580 case ${stf_interface_ipv6_ifid} in 581 '') 582 stf_interface_ipv6_ifid=0:0:0:1 583 ;; 584 esac 585 ;; 586 esac 587 ifconfig stf0 create >/dev/null 2>&1 588 ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \ 589 prefixlen ${stf_prefixlen} 590 # disallow packets to malicious 6to4 prefix 591 route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject 592 route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject 593 route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject 594 route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject 595 ;; 596 esac 597} 598 599# Setup static routes 600network6_static_routes_setup() 601{ 602 # Set up any static routes. 603 case ${ipv6_defaultrouter} in 604 [Nn][Oo] | '') 605 ;; 606 *) 607 ipv6_static_routes="default ${ipv6_static_routes}" 608 ipv6_route_default="default ${ipv6_defaultrouter}" 609 ;; 610 esac 611 case ${ipv6_static_routes} in 612 [Nn][Oo] | '') 613 ;; 614 *) 615 for i in ${ipv6_static_routes}; do 616 eval ipv6_route_args=\$ipv6_route_${i} 617 route add -inet6 ${ipv6_route_args} 618 done 619 ;; 620 esac 621} 622 623# Setup faith 624network6_faith_setup() 625{ 626 case ${ipv6_faith_prefix} in 627 [Nn][Oo] | '') 628 ;; 629 *) 630 sysctl net.inet6.ip6.keepfaith=1 631 ifconfig faith0 create >/dev/null 2>&1 632 ifconfig faith0 up 633 for prefix in ${ipv6_faith_prefix}; do 634 prefixlen=`expr "${prefix}" : ".*/\(.*\)"` 635 case ${prefixlen} in 636 '') 637 prefixlen=96 638 ;; 639 *) 640 prefix=`expr "${prefix}" : \ 641 "\(.*\)/${prefixlen}"` 642 ;; 643 esac 644 route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1 645 route change -inet6 ${prefix} -prefixlen ${prefixlen} \ 646 -ifp faith0 647 done 648 ;; 649 esac 650} 651 652# Install the "default interface" to kernel, which will be used 653# as the default route when there's no router. 654network6_default_interface_setup() 655{ 656 # Choose IPv6 default interface if it is not clearly specified. 657 case ${ipv6_default_interface} in 658 '') 659 for i in ${ipv6_network_interfaces}; do 660 case $i in 661 lo0|faith[0-9]*) 662 continue 663 ;; 664 esac 665 laddr=`network6_getladdr $i exclude_tentative` 666 case ${laddr} in 667 '') 668 ;; 669 *) 670 ipv6_default_interface=$i 671 break 672 ;; 673 esac 674 done 675 ;; 676 esac 677 678 # Disallow unicast packets without outgoing scope identifiers, 679 # or route such packets to a "default" interface, if it is specified. 680 route add -inet6 fe80:: -prefixlen 10 ::1 -reject 681 case ${ipv6_default_interface} in 682 [Nn][Oo] | '') 683 route add -inet6 ff02:: -prefixlen 16 ::1 -reject 684 ;; 685 *) 686 laddr=`network6_getladdr ${ipv6_default_interface}` 687 route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \ 688 -cloning 689 690 # Disable installing the default interface with the 691 # case net.inet6.ip6.forwarding=0 and 692 # net.inet6.ip6.accept_rtadv=0, due to avoid conflict 693 # between the default router list and the manual 694 # configured default route. 695 case ${ipv6_gateway_enable} in 696 [Yy][Ee][Ss]) 697 ;; 698 *) 699 if [ `sysctl -n net.inet6.ip6.accept_rtadv` -eq 1 ] 700 then 701 ndp -I ${ipv6_default_interface} 702 fi 703 ;; 704 esac 705 ;; 706 esac 707} 708 709network6_getladdr() 710{ 711 ifconfig $1 2>/dev/null | while read proto addr rest; do 712 case ${proto} in 713 inet6) 714 case ${addr} in 715 fe80::*) 716 if [ -z "$2" ]; then 717 echo ${addr} 718 return 719 fi 720 case ${rest} in 721 *tentative*) 722 continue 723 ;; 724 *) 725 echo ${addr} 726 return 727 esac 728 esac 729 esac 730 done 731} 732