network.subr revision 116029
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 116029 2003-06-08 10:34:40Z 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 the 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 echo ifconfig $1 ${_inet} delete 71 _ret=0 72 done 73 IFS="$oldifs" 74 75 return $_ret 76} 77 78# ifalias_up if 79# Configure aliases for network interface $if. 80# It returns 0 if at least one alias was configured or 81# 1 if there were none. 82# 83ifalias_up() 84{ 85 _ret=1 86 alias=0 87 while : ; do 88 eval ifconfig_args=\$ifconfig_$1_alias${alias} 89 if [ -n "${ifconfig_args}" ]; then 90 ifconfig $1 ${ifconfig_args} alias 91 alias=$((${alias} + 1)) 92 _ret=0 93 else 94 break 95 fi 96 done 97 return $_ret 98} 99 100#ifalias_down if 101# Remove aliases for network interface $if. 102# It returns 0 if at least one alias was removed or 103# 1 if there were none. 104# 105ifalias_down() 106{ 107 _ret=1 108 alias=0 109 while : ; do 110 eval ifconfig_args=\$ifconfig_$1_alias${alias} 111 if [ -n "${ifconfig_args}" ]; then 112 ifconfig $1 ${ifconfig_args} -alias 113 alias=$((${alias} + 1)) 114 _ret=0 115 else 116 break 117 fi 118 done 119 return $_ret 120} 121 122# ifscript_up if 123# Evaluate a startup script for the $if interface. 124# It returns 0 if a script was found and processed or 125# 1 if no script was found. 126# 127ifscript_up() 128{ 129 if [ -r /etc/start_if.$1 ]; then 130 . /etc/start_if.$1 131 return 0 132 fi 133 return 1 134} 135 136# ifscript_down if 137# Evaluate a shutdown script for the $if interface. 138# It returns 0 if a script was found and processed or 139# 1 if no script was found. 140# 141ifscript_down() 142{ 143 if [ -r /etc/stop_if.$1 ]; then 144 . /etc/stop_if.$1 145 return 0 146 fi 147 return 1 148} 149 150# Create cloneable interfaces. 151# 152clone_up() 153{ 154 _prefix= 155 _list= 156 for ifn in ${cloned_interfaces}; do 157 ifconfig ${ifn} create 158 if $? ; then 159 _list="${_list}${_prefix}${ifn}" 160 [ -z "$_prefix" ] && _prefix=' ' 161 fi 162 done 163 debug "Cloned: ${_list}" 164} 165 166# Destroy cloned interfaces. Destroyed interfaces are echoed 167# to standard output. 168# 169clone_down() 170{ 171 _prefix= 172 _list= 173 for ifn in ${cloned_interfaces}; do 174 ifconfig ${ifn} destroy 175 if $? ; then 176 _list="${_list}${_prefix}${ifn}" 177 [ -z "$_prefix" ] && _prefix=' ' 178 fi 179 done 180 debug "Destroyed clones: ${_list}" 181} 182 183gif_up() { 184 case ${gif_interfaces} in 185 [Nn][Oo] | '') 186 ;; 187 *) 188 for i in ${gif_interfaces}; do 189 eval peers=\$gifconfig_$i 190 case ${peers} in 191 '') 192 continue 193 ;; 194 *) 195 ifconfig $i create >/dev/null 2>&1 196 ifconfig $i tunnel ${peers} 197 ifconfig $i up 198 ;; 199 esac 200 done 201 ;; 202 esac 203} 204 205# 206# ipx_up ifn 207# Configure any IPX addresses for interface $ifn. Returns 0 if IPX 208# arguments were found and configured; returns 1 otherwise. 209# 210ipx_up() 211{ 212 ifn="$1" 213 eval ifconfig_args=\$ifconfig_${ifn}_ipx 214 if [ -n "${ifconfig_args}" ]; then 215 ifconfig ${ifn} ${ifconfig_args} 216 return 0 217 fi 218 return 1 219} 220 221# ipx_down ifn 222# Remove IPX addresses for interface $ifn. Returns 0 if IPX 223# addresses were found and unconfigured. It returns 1, otherwise. 224# 225ipx_down() 226{ 227 # XXX - So, who's an IPX expert ? 228 return 1 229} 230 231# 232# list_net_interfaces type 233# List all network interfaces. The type of interface returned 234# can be controlled by the type argument. The type 235# argument can be any of the following: 236# nodhcp - all interfaces, excluding DHCP configured interfaces 237# dhcp - list only DHCP configured interfaces 238# If no argument is specified all network interfaces are output. 239# Note that the list always includes cloned interfaces. 240# 241list_net_interfaces() 242{ 243 type=$1 244 245 # Get a list of ALL the interfaces 246 # 247 case ${network_interfaces} in 248 [Aa][Uu][Tt][Oo]) 249 _tmplist="`ifconfig -l`" 250 ;; 251 *) 252 _tmplist="${network_interfaces}" 253 ;; 254 esac 255 _tmplist="${_tmplist} ${cloned_interfaces}" 256 257 if [ -z "$type" ]; then 258 echo $_tmplist 259 return 0 260 fi 261 262 # Separate out dhcp and non-dhcp intefraces 263 # 264 _aprefix= 265 _brefix= 266 for _if in ${_tmplist} ; do 267 eval _ifarg="\$ifconfig_${_if}" 268 case "$_ifarg" in 269 [Dd][Hh][Cc][Pp]) 270 _dhcplist="${_dhcplist}${_aprefix}${_if}" 271 [ -z "$_aprefix" ] && _aprefix=' ' 272 ;; 273 ''|*) 274 _nodhcplist="${_nodhcplist}${_bprefix}${_if}" 275 [ -z "$_bprefix" ] && _bprefix=' ' 276 ;; 277 esac 278 done 279 280 case "$type" in 281 nodhcp) 282 echo $_nodhcplist 283 ;; 284 dhcp) 285 echo $_dhcplist 286 ;; 287 esac 288 return 0 289} 290 291hexdigit() 292{ 293 if [ $1 -lt 10 ]; then 294 echo $1 295 else 296 case $1 in 297 10) echo a ;; 298 11) echo b ;; 299 12) echo c ;; 300 13) echo d ;; 301 14) echo e ;; 302 15) echo f ;; 303 esac 304 fi 305} 306 307hexprint() 308{ 309 val=$1 310 str='' 311 312 dig=`hexdigit $((${val} & 15))` 313 str=${dig}${str} 314 val=$((${val} >> 4)) 315 while [ ${val} -gt 0 ]; do 316 dig=`hexdigit $((${val} & 15))` 317 str=${dig}${str} 318 val=$((${val} >> 4)) 319 done 320 321 echo ${str} 322} 323 324# Setup the interfaces for IPv6 325network6_interface_setup() 326{ 327 interfaces=$* 328 rtsol_interfaces='' 329 case ${ipv6_gateway_enable} in 330 [Yy][Ee][Ss]) 331 rtsol_available=no 332 ;; 333 *) 334 rtsol_available=yes 335 ;; 336 esac 337 for i in $interfaces; do 338 rtsol_interface=yes 339 eval prefix=\$ipv6_prefix_$i 340 if [ -n "${prefix}" ]; then 341 rtsol_available=no 342 rtsol_interface=no 343 laddr=`network6_getladdr $i` 344 hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'` 345 for j in ${prefix}; do 346 address=$j\:${hostid} 347 ifconfig $i inet6 ${address} prefixlen 64 alias 348 349 case ${ipv6_gateway_enable} in 350 [Yy][Ee][Ss]) 351 # subnet-router anycast address 352 # (rfc2373) 353 ifconfig $i inet6 $j:: prefixlen 64 \ 354 alias anycast 355 ;; 356 esac 357 done 358 fi 359 eval ipv6_ifconfig=\$ipv6_ifconfig_$i 360 if [ -n "${ipv6_ifconfig}" ]; then 361 rtsol_available=no 362 rtsol_interface=no 363 ifconfig $i inet6 ${ipv6_ifconfig} alias 364 fi 365 366 if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ] 367 then 368 case ${i} in 369 lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*) 370 ;; 371 *) 372 rtsol_interfaces="${rtsol_interfaces} ${i}" 373 ;; 374 esac 375 else 376 ifconfig $i inet6 377 fi 378 done 379 380 if [ ${rtsol_available} = yes -a -n "${rtsol_interfaces}" ]; then 381 # Act as endhost - automatically configured. 382 # You can configure only single interface, as 383 # specification assumes that autoconfigured host has 384 # single interface only. 385 sysctl net.inet6.ip6.accept_rtadv=1 386 set ${rtsol_interfaces} 387 ifconfig $1 up 388 rtsol $1 389 fi 390 391 for i in $interfaces; do 392 alias=0 393 while : ; do 394 eval ipv6_ifconfig=\$ipv6_ifconfig_${i}_alias${alias} 395 if [ -z "${ipv6_ifconfig}" ]; then 396 break; 397 fi 398 ifconfig $i inet6 ${ipv6_ifconfig} alias 399 alias=$((${alias} + 1)) 400 done 401 done 402} 403 404# Setup IPv6 to IPv4 mapping 405network6_stf_setup() 406{ 407 case ${stf_interface_ipv4addr} in 408 [Nn][Oo] | '') 409 ;; 410 *) 411 # assign IPv6 addr and interface route for 6to4 interface 412 stf_prefixlen=$((16+${stf_interface_ipv4plen:-0})) 413 OIFS="$IFS" 414 IFS=".$IFS" 415 set ${stf_interface_ipv4addr} 416 IFS="$OIFS" 417 hexfrag1=`hexprint $(($1*256 + $2))` 418 hexfrag2=`hexprint $(($3*256 + $4))` 419 ipv4_in_hexformat="${hexfrag1}:${hexfrag2}" 420 case ${stf_interface_ipv6_ifid} in 421 [Aa][Uu][Tt][Oo] | '') 422 for i in ${ipv6_network_interfaces}; do 423 laddr=`network6_getladdr ${i}` 424 case ${laddr} in 425 '') 426 ;; 427 *) 428 break 429 ;; 430 esac 431 done 432 stf_interface_ipv6_ifid=`expr "${laddr}" : \ 433 'fe80::\(.*\)%\(.*\)'` 434 case ${stf_interface_ipv6_ifid} in 435 '') 436 stf_interface_ipv6_ifid=0:0:0:1 437 ;; 438 esac 439 ;; 440 esac 441 ifconfig stf0 create >/dev/null 2>&1 442 ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \ 443 prefixlen ${stf_prefixlen} 444 # disallow packets to malicious 6to4 prefix 445 route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject 446 route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject 447 route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject 448 route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject 449 ;; 450 esac 451} 452 453# Setup static routes 454network6_static_routes_setup() 455{ 456 # Set up any static routes. 457 case ${ipv6_defaultrouter} in 458 [Nn][Oo] | '') 459 ;; 460 *) 461 ipv6_static_routes="default ${ipv6_static_routes}" 462 ipv6_route_default="default ${ipv6_defaultrouter}" 463 ;; 464 esac 465 case ${ipv6_static_routes} in 466 [Nn][Oo] | '') 467 ;; 468 *) 469 for i in ${ipv6_static_routes}; do 470 eval ipv6_route_args=\$ipv6_route_${i} 471 route add -inet6 ${ipv6_route_args} 472 done 473 ;; 474 esac 475} 476 477# Setup faith 478network6_faith_setup() 479{ 480 case ${ipv6_faith_prefix} in 481 [Nn][Oo] | '') 482 ;; 483 *) 484 sysctl net.inet6.ip6.keepfaith=1 485 ifconfig faith0 create >/dev/null 2>&1 486 ifconfig faith0 up 487 for prefix in ${ipv6_faith_prefix}; do 488 prefixlen=`expr "${prefix}" : ".*/\(.*\)"` 489 case ${prefixlen} in 490 '') 491 prefixlen=96 492 ;; 493 *) 494 prefix=`expr "${prefix}" : \ 495 "\(.*\)/${prefixlen}"` 496 ;; 497 esac 498 route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1 499 route change -inet6 ${prefix} -prefixlen ${prefixlen} \ 500 -ifp faith0 501 done 502 ;; 503 esac 504} 505 506# Install the "default interface" to kernel, which will be used 507# as the default route when there's no router. 508network6_default_interface_setup() 509{ 510 # Choose IPv6 default interface if it is not clearly specified. 511 case ${ipv6_default_interface} in 512 '') 513 for i in ${ipv6_network_interfaces}; do 514 case $i in 515 lo0|faith[0-9]*) 516 continue 517 ;; 518 esac 519 laddr=`network6_getladdr $i exclude_tentative` 520 case ${laddr} in 521 '') 522 ;; 523 *) 524 ipv6_default_interface=$i 525 break 526 ;; 527 esac 528 done 529 ;; 530 esac 531 532 # Disallow unicast packets without outgoing scope identifiers, 533 # or route such packets to a "default" interface, if it is specified. 534 route add -inet6 fe80:: -prefixlen 10 ::1 -reject 535 case ${ipv6_default_interface} in 536 [Nn][Oo] | '') 537 route add -inet6 ff02:: -prefixlen 16 ::1 -reject 538 ;; 539 *) 540 laddr=`network6_getladdr ${ipv6_default_interface}` 541 route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \ 542 -cloning 543 544 # Disable installing the default interface with the 545 # case net.inet6.ip6.forwarding=0 and 546 # net.inet6.ip6.accept_rtadv=0, due to avoid conflict 547 # between the default router list and the manual 548 # configured default route. 549 case ${ipv6_gateway_enable} in 550 [Yy][Ee][Ss]) 551 ;; 552 *) 553 if [ `sysctl -n net.inet6.ip6.accept_rtadv` -eq 1 ] 554 then 555 ndp -I ${ipv6_default_interface} 556 fi 557 ;; 558 esac 559 ;; 560 esac 561} 562 563network6_getladdr() 564{ 565 ifconfig $1 2>/dev/null | while read proto addr rest; do 566 case ${proto} in 567 inet6) 568 case ${addr} in 569 fe80::*) 570 if [ -z "$2" ]; then 571 echo ${addr} 572 return 573 fi 574 case ${rest} in 575 *tentative*) 576 continue 577 ;; 578 *) 579 echo ${addr} 580 return 581 esac 582 esac 583 esac 584 done 585} 586