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