2 # Copyright (c) 2003 The FreeBSD Project. All rights reserved.
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions
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.
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
25 # $FreeBSD: src/etc/network.subr,v 1.163 2005/06/30 04:52:47 brooks Exp $
29 # Subroutines commonly used from network startup scripts.
30 # Requires that /etc/rc.subr be loaded first.
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
42 local _cfg ifconfig_args
45 ifconfig_args=`ifconfig_getargs $1`
46 if [ -n "${ifconfig_args}" ]; then
47 ifconfig $1 ${ifconfig_args}
54 /etc/rc.d/wpa_supplicant start $1
55 # NOTE: wpa_supplicant(8) needs to control the interface's
56 # state in order to perform the SSID scan. But
57 # dhcpcd(8), which may be started by the "dhcp_client"
58 # below, can race against wpa_supplicant(8) and modify
59 # the interface's state, breaking the SSID scan and
60 # preventing the SSID association.
61 # Insert a small delay here to workaround the issue.
63 _cfg=0 # XXX: not sure this should count
67 /etc/rc.d/dhcp_client start $1
75 # Remove all inet entries from the $if interface. It returns
76 # 0 if inet entries were found and removed. It returns 1 if
77 # no entries were found or they could not be removed.
81 local _cfg _ifs oldifs _inet inetList
83 [ -z "$1" ] && return 1
87 inetList="`ifconfig $1 | grep 'inet ' | tr "\n" "$_ifs"`"
91 for _inet in $inetList ; do
92 # get rid of extraneous line
93 [ -z "$_inet" ] && break
95 _inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'`
98 ifconfig $1 ${_inet} delete
105 /etc/rc.d/wpa_supplicant stop $1
109 /etc/rc.d/dhcp_client stop $1
121 # get_if_var if var [default]
122 # Return the value of the pseudo-hash corresponding to $if where
123 # $var is a string containg the sub-string "IF" which will be
124 # replaced with $if after the characters defined in _punct are
125 # replaced with '_'. If the variable is unset, replace it with
130 local _if _punct_c _punct _var _default prefix suffix
132 if [ $# -ne 2 -a $# -ne 3 ]; then
133 err 3 'USAGE: get_if_var name var [default]'
138 for _punct_c in $_punct; do
139 _if=`ltr ${_if} ${_punct_c} '_'`
146 eval echo \${${prefix}${_if}${suffix}-${_default}}
149 # _ifconfig_getargs if [af]
150 # Echos the arguments for the supplied interface to stdout.
151 # Returns 1 if no interface is specified.
152 # In general, the ifconfig_getargs() below should be used outside
157 local _if _ifn _af _args
162 if [ -z "$_ifn" ]; then
166 _args=`get_if_var $_ifn ${_af}ifconfig_IF`
167 if [ -z "$_args" -a -n "${pccard_ifconfig}" ]; then
168 for _if in ${removable_interfaces} ; do
169 if [ "$_if" = "$_ifn" ] ; then
170 _args=${pccard_ifconfig}
179 # ifconfig_getargs if [af]
180 # Takes the result from _ifconfig_getargs() and removes pseudo
181 # args such as DHCP and WPA.
185 local _tmpargs _arg _args is_optarg
187 _tmpargs=`_ifconfig_getargs $1 $2`
188 if [ $? -eq 1 ]; then
194 for _arg in $_tmpargs; do
195 if [ "$is_optarg" = "no" ]; then
220 # Returns 0 if the interface should be configured for IPv6 and
228 # lo0 is always IPv6-enabled
229 if [ "$_if" = "lo0" ]; then
233 case ${ipv6_enable} in
234 [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
239 case "${ipv6_network_interfaces}" in
240 $_if|"$_if "*|*" $_if"|*" $_if "*|[Aa][Uu][Tt][Oo])
241 # True if $ipv6_ifconfig_IF is defined.
242 _tmpargs=`_ifconfig_getargs $_if ipv6`
243 if [ -n "${_tmpargs}" ]; then
247 # True if $ipv6_prefix_IF is defined.
248 _tmpargs=`get_if_var $_if ipv6_prefix_IF`
249 if [ -n "${_tmpargs}" ]; then
259 # dhcpif if [ipv4|ipv6]
260 # Returns 0 if the interface needs DHCP for IPv4/IPv6 and 1 otherwise.
261 # If the second argument is "ipv4" (or "ipv6"), then only IPv4 (or
262 # IPv6) is checked, otherwise both are checked.
266 local _tmpargs _arg _if _af
270 if [ -z "$_af" -o "$_af" = "ipv4" ]; then
271 _tmpargs=`_ifconfig_getargs $_if`
272 for _arg in $_tmpargs; do
281 if [ -z "$_af" -o "$_af" = "ipv6" ] && ipv6if $_if; then
282 _tmpargs=`_ifconfig_getargs $_if ipv6`
283 for _arg in $_tmpargs; do
296 # Returns 0 if the interface is a WPA interface and 1 otherwise.
300 local _tmpargs _arg is_optarg
302 _tmpargs=`_ifconfig_getargs $1`
304 for _arg in $_tmpargs; do
305 if [ "$is_optarg" = "no" ]; then
323 # Returns 0 if the interface exists and 1 otherwise.
327 [ -z "$1" ] && return 1
328 ifconfig -n $1 >/dev/null 2>&1
331 # ifalias_common if action [ipv6]
332 # Helper function for ifalias_up() and ifalias_down().
333 # The $action argument can be either "alias" (to add an
334 # alias) or "-alias" (to remove an alias).
335 # Returns 0 if at least one alias was added/removed or
336 # 1 if there were none.
340 local _if _action _af _af2 _ret _var _args _alias
348 if [ "${_af}" = "ipv6" ]; then
350 _var="ipv6_ifconfig_IF_alias${_alias}"
353 _var="ifconfig_IF_alias${_alias}"
355 _args=`get_if_var $_if $_var`
356 _args="${_args#${_af2} }"
357 if [ -z "${_args}" ]; then
360 ifconfig $_if $_af2 $_args $_action
361 _alias=$((${_alias} + 1))
367 # ifalias_up if [ipv6]
368 # Configure IPv4 aliases for network interface $if or
369 # IPv6 aliases if the second argument is "ipv6".
370 # It returns 0 if at least one alias was configured or
371 # 1 if there were none.
375 ifalias_common $1 alias $2
378 # ifalias_down if [ipv6]
379 # Remove IPv4 aliases for network interface $if or
380 # IPv6 aliases if the second argument is "ipv6".
381 # It returns 0 if at least one alias was removed or
382 # 1 if there were none.
386 ifalias_common $1 -alias $2
390 # Evaluate a startup script for the $if interface.
391 # It returns 0 if a script was found and processed or
392 # 1 if no script was found.
396 if [ -r /etc/start_if.$1 ]; then
404 # Evaluate a shutdown script for the $if interface.
405 # It returns 0 if a script was found and processed or
406 # 1 if no script was found.
410 if [ -r /etc/stop_if.$1 ]; then
418 # Create IEEE 802.11 interfaces.
422 local _prefix _list parent child child_wlans create_args debug_flags
426 for parent in `${SYSCTL_N} -q net.wlan.devices`; do
427 # Parse wlans_$parent="$child ..."
428 child_wlans=`get_if_var $parent wlans_IF`
429 for child in ${child_wlans}; do
430 if ifexists $child; then
434 create_args="wlandev $parent `get_if_var $child create_args_IF`"
435 debug_flags="`get_if_var $child wlandebug_IF`"
436 if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
437 ifconfig $child create ${create_args}
439 ifconfig wlan create ${create_args} name $child
441 if [ $? -eq 0 ]; then
442 _list="${_list}${_prefix}${child}"
443 [ -z "$_prefix" ] && _prefix=' '
445 if [ -n "${debug_flags}" ]; then
446 wlandebug -i $child ${debug_flags}
451 if [ -n "${_list}" ]; then
452 echo "Created wlan interfaces: ${_list}"
454 debug "Created wlan interfaces: ${_list}"
458 # Destroy IEEE 802.11 interfaces.
462 local _prefix _list parent child child_wlans
466 for parent in `${SYSCTL_N} -q net.wlan.devices`; do
467 child_wlans=`get_if_var $parent wlans_IF`
468 for child in ${child_wlans}; do
469 if ! ifexists $child; then
473 ifconfig -n $child destroy
474 if [ $? -eq 0 ]; then
475 _list="${_list}${_prefix}${child}"
476 [ -z "$_prefix" ] && _prefix=' '
481 if [ -n "${_list}" ]; then
482 echo "Destroyed wlan interfaces: ${_list}"
484 debug "Destroyed wlan interfaces: ${_list}"
488 # Create cloneable interfaces.
492 local _prefix _list ifn
496 for ifn in ${cloned_interfaces}; do
497 ifconfig ${ifn} create
498 if [ $? -eq 0 ]; then
499 _list="${_list}${_prefix}${ifn}"
500 [ -z "$_prefix" ] && _prefix=' '
503 if [ -n "${_list}" ]; then
504 echo "Created clone interfaces: ${_list}"
506 debug "Created clone interfaces: ${_list}"
510 # Destroy cloned interfaces.
514 local _prefix _list ifn
518 for ifn in ${cloned_interfaces}; do
519 ifconfig ${ifn} destroy
520 if [ $? -eq 0 ]; then
521 _list="${_list}${_prefix}${ifn}"
522 [ -z "$_prefix" ] && _prefix=' '
525 if [ -n "${_list}" ]; then
526 echo "Destroyed clone interfaces: ${_list}"
528 debug "Destroyed clone interfaces: ${_list}"
532 # Create IPv6<-->IPv4 tunnels
537 case ${gif_interfaces} in
543 for _if in ${gif_interfaces}; do
544 eval _peers=\$gifconfig_${_if}
550 ifconfig $_if create >/dev/null 2>&1
551 ifconfig $_if tunnel ${_peers}
559 # Rename all requested interfaces.
563 local _ifn_list _if _ifname
565 _ifn_list=$(ifconfig -l)
566 [ -z "$_ifn_list" ] && return 0
568 for _if in ${_ifn_list} ; do
569 _ifname=`get_if_var $_if ifconfig_IF_name`
570 if [ -n "$_ifname" ]; then
571 ifconfig $_if name $_ifname
577 # list_net_interfaces
578 # List all network interfaces.
579 # Note that the list will include cloned interfaces if applicable.
580 # Cloned interfaces must already exist to have a chance to appear
581 # in the list if ${network_interfaces} is set to `auto'.
583 list_net_interfaces()
585 local _tmplist _autolist _lo _if
587 case ${network_interfaces} in
589 _autolist=$(ifconfig -l)
591 for _if in ${_autolist} ; do
592 if [ "$_if" = "lo0" ]; then
595 _tmplist="${_tmplist} ${_if}"
598 _tmplist="${_lo} ${_tmplist}"
601 _tmplist="${network_interfaces} ${cloned_interfaces}"
610 if [ $1 -lt 10 ]; then
630 dig=`hexdigit $((${val} & 15))`
633 while [ ${val} -gt 0 ]; do
634 dig=`hexdigit $((${val} & 15))`
644 # IPv6-specific setup subroutines
647 # Setup the interfaces for IPv6
648 network6_interface_setup()
650 local interfaces rtsol_interfaces ipv6_ifconfig
651 local rtsol_available rtsol_interface
652 local prefix laddr hostid address
657 case ${ipv6_gateway_enable} in
665 for _if in $interfaces; do
667 prefix=`get_if_var $_if ipv6_prefix_IF`
668 if [ -n "${prefix}" ]; then
671 laddr=`network6_getladdr $_if`
672 hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'`
673 for j in ${prefix}; do
674 address=$j\:${hostid}
675 ifconfig $_if inet6 ${address} prefixlen 64 alias
677 case ${ipv6_gateway_enable} in
679 # subnet-router anycast address
681 ifconfig $_if inet6 $j:: prefixlen 64 \
687 ipv6_ifconfig=`ifconfig_getargs $_if ipv6`
688 ipv6_ifconfig="${ipv6_ifconfig#inet6 }"
689 if [ -n "${ipv6_ifconfig}" ]; then
692 ifconfig $_if inet6 ${ipv6_ifconfig} alias
695 if [ "${rtsol_available}" = "yes" -a \
696 "${rtsol_interface}" = "yes" ]; then
698 lo0|gif[0-9]*|stf[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*)
701 rtsol_interfaces="${rtsol_interfaces} ${_if}"
709 if [ "${rtsol_available}" = "yes" -a -n "${rtsol_interfaces}" ]; then
710 # Act as endhost - automatically configured.
711 # You can configure only single interface, as
712 # specification assumes that autoconfigured host has
713 # single interface only.
714 ${SYSCTL_W} net.inet6.ip6.accept_rtadv=1
715 set ${rtsol_interfaces}
717 echo "Auto configuring interface $1 ..."
721 for _if in $interfaces; do
726 # Setup IPv6 to IPv4 mapping
729 local stf_prefixlen stf_interface_ipv6_ifid
730 local hexfrag1 hexfrag2 ipv4_in_hexformat laddr
733 case ${stf_interface_ipv4addr} in
737 # assign IPv6 addr and interface route for 6to4 interface
738 stf_prefixlen=$((16+${stf_interface_ipv4plen:-0}))
741 set ${stf_interface_ipv4addr}
743 hexfrag1=`hexprint $(($1*256 + $2))`
744 hexfrag2=`hexprint $(($3*256 + $4))`
745 ipv4_in_hexformat="${hexfrag1}:${hexfrag2}"
746 case ${stf_interface_ipv6_ifid} in
747 [Aa][Uu][Tt][Oo] | '')
748 for _if in ${ipv6_network_interfaces}; do
749 laddr=`network6_getladdr $_if`
758 stf_interface_ipv6_ifid=`expr "${laddr}" : \
759 'fe80::\(.*\)%\(.*\)'`
760 case ${stf_interface_ipv6_ifid} in
762 stf_interface_ipv6_ifid=0:0:0:1
767 ifconfig stf0 create >/dev/null 2>&1
768 ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \
769 prefixlen ${stf_prefixlen}
770 # disallow packets to malicious 6to4 prefix
771 route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
772 route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
773 route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
774 route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
779 # Setup static routes
780 network6_static_routes_setup()
784 # Set up any static routes.
785 case ${ipv6_defaultrouter} in
789 ipv6_static_routes="default ${ipv6_static_routes}"
790 ipv6_route_default="default ${ipv6_defaultrouter}"
793 case ${ipv6_static_routes} in
797 for _rt in ${ipv6_static_routes}; do
798 eval ipv6_route_args=\$ipv6_route_${_rt}
799 route add -inet6 ${ipv6_route_args}
805 # Install the "default interface" to kernel, which will be used
806 # as the default route when there's no router.
807 network6_default_interface_setup()
811 # Choose IPv6 default interface if it is not clearly specified.
812 case ${ipv6_default_interface} in
814 for _if in ${ipv6_network_interfaces}; do
815 if [ "${_if}" = "lo0" ]; then
819 laddr=`network6_getladdr $_if exclude_tentative`
824 ipv6_default_interface=$_if
832 # Disallow unicast packets without outgoing scope identifiers,
833 # or route such packets to a "default" interface, if it is specified.
834 route add -inet6 fe80:: -prefixlen 10 ::1 -reject
835 case ${ipv6_default_interface} in
837 route add -inet6 ff02:: -prefixlen 16 ::1 -reject
840 laddr=`network6_getladdr ${ipv6_default_interface}`
841 route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \
844 # Disable installing the default interface with the
845 # case net.inet6.ip6.forwarding=0 and
846 # net.inet6.ip6.accept_rtadv=0, due to avoid conflict
847 # between the default router list and the manual
848 # configured default route.
849 case ${ipv6_gateway_enable} in
853 if [ `${SYSCTL_N} net.inet6.ip6.accept_rtadv` -eq 1 ]
855 ndp -I ${ipv6_default_interface}
865 local proto addr rest
867 ifconfig $1 2>/dev/null | while read proto addr rest; do