network.subr revision 134376
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 134376 2004-08-27 12:11:47Z yar $ 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# 254# list_net_interfaces type 255# List all network interfaces. The type of interface returned 256# can be controlled by the type argument. The type 257# argument can be any of the following: 258# nodhcp - all interfaces, excluding DHCP configured interfaces 259# dhcp - list only DHCP configured interfaces 260# If no argument is specified all network interfaces are output. 261# Note that the list always includes cloned interfaces. 262# 263list_net_interfaces() 264{ 265 type=$1 266 267 # Get a list of ALL the interfaces 268 # 269 case ${network_interfaces} in 270 [Aa][Uu][Tt][Oo]) 271 _tmplist="`ifconfig -l`" 272 ;; 273 *) 274 _tmplist="${network_interfaces}" 275 ;; 276 esac 277 _tmplist="${_tmplist} ${cloned_interfaces}" 278 279 if [ -z "$type" ]; then 280 echo $_tmplist 281 return 0 282 fi 283 284 # Separate out dhcp and non-dhcp intefraces 285 # 286 _aprefix= 287 _bprefix= 288 for _if in ${_tmplist} ; do 289 eval _ifarg="\$ifconfig_${_if}" 290 case "$_ifarg" in 291 [Dd][Hh][Cc][Pp]) 292 _dhcplist="${_dhcplist}${_aprefix}${_if}" 293 [ -z "$_aprefix" ] && _aprefix=' ' 294 ;; 295 ''|*) 296 _nodhcplist="${_nodhcplist}${_bprefix}${_if}" 297 [ -z "$_bprefix" ] && _bprefix=' ' 298 ;; 299 esac 300 done 301 302 case ${pccard_ifconfig} in 303 [Dd][Hh][Cc][Pp]) 304 for _if in ${removable_interfaces} ; do 305 _test_if=`ifconfig ${_if} 2>&1` 306 case "$_test_if" in 307 "ifconfig: interface $_if does not exist") 308 ;; 309 *) 310 _dhcplist="${_dhcplist}${_aprefix}${_if}" 311 [ -z "$_aprefix" ] && _aprefix=' ' 312 ;; 313 esac 314 done 315 ;; 316 *) 317 ;; 318 esac 319 320 case "$type" in 321 nodhcp) 322 echo $_nodhcplist 323 ;; 324 dhcp) 325 echo $_dhcplist 326 ;; 327 esac 328 return 0 329} 330 331hexdigit() 332{ 333 if [ $1 -lt 10 ]; then 334 echo $1 335 else 336 case $1 in 337 10) echo a ;; 338 11) echo b ;; 339 12) echo c ;; 340 13) echo d ;; 341 14) echo e ;; 342 15) echo f ;; 343 esac 344 fi 345} 346 347hexprint() 348{ 349 val=$1 350 str='' 351 352 dig=`hexdigit $((${val} & 15))` 353 str=${dig}${str} 354 val=$((${val} >> 4)) 355 while [ ${val} -gt 0 ]; do 356 dig=`hexdigit $((${val} & 15))` 357 str=${dig}${str} 358 val=$((${val} >> 4)) 359 done 360 361 echo ${str} 362} 363 364# Setup the interfaces for IPv6 365network6_interface_setup() 366{ 367 interfaces=$* 368 rtsol_interfaces='' 369 case ${ipv6_gateway_enable} in 370 [Yy][Ee][Ss]) 371 rtsol_available=no 372 ;; 373 *) 374 rtsol_available=yes 375 ;; 376 esac 377 for i in $interfaces; do 378 rtsol_interface=yes 379 eval prefix=\$ipv6_prefix_$i 380 if [ -n "${prefix}" ]; then 381 rtsol_available=no 382 rtsol_interface=no 383 laddr=`network6_getladdr $i` 384 hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'` 385 for j in ${prefix}; do 386 address=$j\:${hostid} 387 ifconfig $i inet6 ${address} prefixlen 64 alias 388 389 case ${ipv6_gateway_enable} in 390 [Yy][Ee][Ss]) 391 # subnet-router anycast address 392 # (rfc2373) 393 ifconfig $i inet6 $j:: prefixlen 64 \ 394 alias anycast 395 ;; 396 esac 397 done 398 fi 399 eval ipv6_ifconfig=\$ipv6_ifconfig_$i 400 if [ -n "${ipv6_ifconfig}" ]; then 401 rtsol_available=no 402 rtsol_interface=no 403 ifconfig $i inet6 ${ipv6_ifconfig} alias 404 fi 405 406 if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ] 407 then 408 case ${i} in 409 lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*) 410 ;; 411 *) 412 rtsol_interfaces="${rtsol_interfaces} ${i}" 413 ;; 414 esac 415 else 416 ifconfig $i inet6 417 fi 418 done 419 420 if [ ${rtsol_available} = yes -a -n "${rtsol_interfaces}" ]; then 421 # Act as endhost - automatically configured. 422 # You can configure only single interface, as 423 # specification assumes that autoconfigured host has 424 # single interface only. 425 sysctl net.inet6.ip6.accept_rtadv=1 426 set ${rtsol_interfaces} 427 ifconfig $1 up 428 rtsol ${rtsol_flags} $1 429 fi 430 431 for i in $interfaces; do 432 alias=0 433 while : ; do 434 eval ipv6_ifconfig=\$ipv6_ifconfig_${i}_alias${alias} 435 if [ -z "${ipv6_ifconfig}" ]; then 436 break; 437 fi 438 ifconfig $i inet6 ${ipv6_ifconfig} alias 439 alias=$((${alias} + 1)) 440 done 441 done 442} 443 444# Setup IPv6 to IPv4 mapping 445network6_stf_setup() 446{ 447 case ${stf_interface_ipv4addr} in 448 [Nn][Oo] | '') 449 ;; 450 *) 451 # assign IPv6 addr and interface route for 6to4 interface 452 stf_prefixlen=$((16+${stf_interface_ipv4plen:-0})) 453 OIFS="$IFS" 454 IFS=".$IFS" 455 set ${stf_interface_ipv4addr} 456 IFS="$OIFS" 457 hexfrag1=`hexprint $(($1*256 + $2))` 458 hexfrag2=`hexprint $(($3*256 + $4))` 459 ipv4_in_hexformat="${hexfrag1}:${hexfrag2}" 460 case ${stf_interface_ipv6_ifid} in 461 [Aa][Uu][Tt][Oo] | '') 462 for i in ${ipv6_network_interfaces}; do 463 laddr=`network6_getladdr ${i}` 464 case ${laddr} in 465 '') 466 ;; 467 *) 468 break 469 ;; 470 esac 471 done 472 stf_interface_ipv6_ifid=`expr "${laddr}" : \ 473 'fe80::\(.*\)%\(.*\)'` 474 case ${stf_interface_ipv6_ifid} in 475 '') 476 stf_interface_ipv6_ifid=0:0:0:1 477 ;; 478 esac 479 ;; 480 esac 481 ifconfig stf0 create >/dev/null 2>&1 482 ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \ 483 prefixlen ${stf_prefixlen} 484 # disallow packets to malicious 6to4 prefix 485 route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject 486 route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject 487 route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject 488 route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject 489 ;; 490 esac 491} 492 493# Setup static routes 494network6_static_routes_setup() 495{ 496 # Set up any static routes. 497 case ${ipv6_defaultrouter} in 498 [Nn][Oo] | '') 499 ;; 500 *) 501 ipv6_static_routes="default ${ipv6_static_routes}" 502 ipv6_route_default="default ${ipv6_defaultrouter}" 503 ;; 504 esac 505 case ${ipv6_static_routes} in 506 [Nn][Oo] | '') 507 ;; 508 *) 509 for i in ${ipv6_static_routes}; do 510 eval ipv6_route_args=\$ipv6_route_${i} 511 route add -inet6 ${ipv6_route_args} 512 done 513 ;; 514 esac 515} 516 517# Setup faith 518network6_faith_setup() 519{ 520 case ${ipv6_faith_prefix} in 521 [Nn][Oo] | '') 522 ;; 523 *) 524 sysctl net.inet6.ip6.keepfaith=1 525 ifconfig faith0 create >/dev/null 2>&1 526 ifconfig faith0 up 527 for prefix in ${ipv6_faith_prefix}; do 528 prefixlen=`expr "${prefix}" : ".*/\(.*\)"` 529 case ${prefixlen} in 530 '') 531 prefixlen=96 532 ;; 533 *) 534 prefix=`expr "${prefix}" : \ 535 "\(.*\)/${prefixlen}"` 536 ;; 537 esac 538 route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1 539 route change -inet6 ${prefix} -prefixlen ${prefixlen} \ 540 -ifp faith0 541 done 542 ;; 543 esac 544} 545 546# Install the "default interface" to kernel, which will be used 547# as the default route when there's no router. 548network6_default_interface_setup() 549{ 550 # Choose IPv6 default interface if it is not clearly specified. 551 case ${ipv6_default_interface} in 552 '') 553 for i in ${ipv6_network_interfaces}; do 554 case $i in 555 lo0|faith[0-9]*) 556 continue 557 ;; 558 esac 559 laddr=`network6_getladdr $i exclude_tentative` 560 case ${laddr} in 561 '') 562 ;; 563 *) 564 ipv6_default_interface=$i 565 break 566 ;; 567 esac 568 done 569 ;; 570 esac 571 572 # Disallow unicast packets without outgoing scope identifiers, 573 # or route such packets to a "default" interface, if it is specified. 574 route add -inet6 fe80:: -prefixlen 10 ::1 -reject 575 case ${ipv6_default_interface} in 576 [Nn][Oo] | '') 577 route add -inet6 ff02:: -prefixlen 16 ::1 -reject 578 ;; 579 *) 580 laddr=`network6_getladdr ${ipv6_default_interface}` 581 route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \ 582 -cloning 583 584 # Disable installing the default interface with the 585 # case net.inet6.ip6.forwarding=0 and 586 # net.inet6.ip6.accept_rtadv=0, due to avoid conflict 587 # between the default router list and the manual 588 # configured default route. 589 case ${ipv6_gateway_enable} in 590 [Yy][Ee][Ss]) 591 ;; 592 *) 593 if [ `sysctl -n net.inet6.ip6.accept_rtadv` -eq 1 ] 594 then 595 ndp -I ${ipv6_default_interface} 596 fi 597 ;; 598 esac 599 ;; 600 esac 601} 602 603network6_getladdr() 604{ 605 ifconfig $1 2>/dev/null | while read proto addr rest; do 606 case ${proto} in 607 inet6) 608 case ${addr} in 609 fe80::*) 610 if [ -z "$2" ]; then 611 echo ${addr} 612 return 613 fi 614 case ${rest} in 615 *tentative*) 616 continue 617 ;; 618 *) 619 echo ${addr} 620 return 621 esac 622 esac 623 esac 624 done 625} 626