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 # walk through net.wlan and find unused device that can be created
427 if ! ${SYSCTL_N} -q net.wlan.${idx}.%parent >/dev/null; then
436 # check if given interface is parent for any existing wlan device
440 sysctl -q net.wlan | grep -q "%parent: ${1}"
444 # Create IEEE 802.11 interfaces.
448 local _prefix _list parent child child_wlans create_args debug_flags
456 # Order detected devices so that interfaces configured via rc.conf are
457 # created first, and then all other devices are automatically assigned
458 for parent in `${SYSCTL_N} -q net.wlan.devices`; do
459 child_wlans=`get_if_var $parent wlans_IF`
460 if [ -n "${child_wlans}" ]; then
461 _rcconf="${_rcconf} ${parent}"
463 _auto="${_auto} ${parent}"
467 for parent in ${_rcconf} ${_auto}; do
468 if wlan_is_parent $parent; then
471 # Parse wlans_$parent="$child ..."
472 child_wlans=`get_if_var $parent wlans_IF`
473 # Or find first unused wlan device to create
474 if [ -z "${child_wlans}" ]; then
475 child_wlans=`wlan_get_unused`
477 for child in ${child_wlans}; do
478 if ifexists $child; then
482 create_args="wlandev $parent `get_if_var $child create_args_IF`"
483 debug_flags="`get_if_var $child wlandebug_IF`"
484 if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
485 ifconfig $child create ${create_args}
487 ifconfig wlan create ${create_args} name $child
489 if [ $? -eq 0 ]; then
490 _list="${_list}${_prefix}${child}"
491 [ -z "$_prefix" ] && _prefix=' '
493 if [ -n "${debug_flags}" ]; then
494 wlandebug -i $child ${debug_flags}
499 if [ -n "${_list}" ]; then
500 echo "Created wlan interfaces: ${_list}"
502 debug "Created wlan interfaces: ${_list}"
506 # Destroy IEEE 802.11 interfaces.
510 local _prefix _list parent child child_wlans
514 for parent in `${SYSCTL_N} -q net.wlan.devices`; do
515 child_wlans=`get_if_var $parent wlans_IF`
516 for child in ${child_wlans}; do
517 if ! ifexists $child; then
521 ifconfig -n $child destroy
522 if [ $? -eq 0 ]; then
523 _list="${_list}${_prefix}${child}"
524 [ -z "$_prefix" ] && _prefix=' '
529 if [ -n "${_list}" ]; then
530 echo "Destroyed wlan interfaces: ${_list}"
532 debug "Destroyed wlan interfaces: ${_list}"
536 # Create cloneable interfaces.
540 local _prefix _list ifn
544 for ifn in ${cloned_interfaces}; do
545 ifconfig ${ifn} create
546 if [ $? -eq 0 ]; then
547 _list="${_list}${_prefix}${ifn}"
548 [ -z "$_prefix" ] && _prefix=' '
551 if [ -n "${_list}" ]; then
552 echo "Created clone interfaces: ${_list}"
554 debug "Created clone interfaces: ${_list}"
558 # Destroy cloned interfaces.
562 local _prefix _list ifn
566 for ifn in ${cloned_interfaces}; do
567 ifconfig ${ifn} destroy
568 if [ $? -eq 0 ]; then
569 _list="${_list}${_prefix}${ifn}"
570 [ -z "$_prefix" ] && _prefix=' '
573 if [ -n "${_list}" ]; then
574 echo "Destroyed clone interfaces: ${_list}"
576 debug "Destroyed clone interfaces: ${_list}"
580 # Create IPv6<-->IPv4 tunnels
585 case ${gif_interfaces} in
591 for _if in ${gif_interfaces}; do
592 eval _peers=\$gifconfig_${_if}
598 ifconfig $_if create >/dev/null 2>&1
599 ifconfig $_if tunnel ${_peers}
607 # Rename all requested interfaces.
611 local _ifn_list _if _ifname
613 _ifn_list=$(ifconfig -l)
614 [ -z "$_ifn_list" ] && return 0
616 for _if in ${_ifn_list} ; do
617 _ifname=`get_if_var $_if ifconfig_IF_name`
618 if [ -n "$_ifname" ]; then
619 ifconfig $_if name $_ifname
625 # list_net_interfaces
626 # List all network interfaces.
627 # Note that the list will include cloned interfaces if applicable.
628 # Cloned interfaces must already exist to have a chance to appear
629 # in the list if ${network_interfaces} is set to `auto'.
631 list_net_interfaces()
633 local _tmplist _autolist _lo _if
635 case ${network_interfaces} in
637 _autolist=$(ifconfig -l)
639 for _if in ${_autolist} ; do
640 if [ "$_if" = "lo0" ]; then
643 _tmplist="${_tmplist} ${_if}"
646 _tmplist="${_lo} ${_tmplist}"
649 _tmplist="${network_interfaces} ${cloned_interfaces}"
658 if [ $1 -lt 10 ]; then
678 dig=`hexdigit $((${val} & 15))`
681 while [ ${val} -gt 0 ]; do
682 dig=`hexdigit $((${val} & 15))`
694 case `ifconfig $1 2>/dev/null` in
695 *media:?Ethernet*) media=Ethernet ;;
698 test "$media" = "Ethernet"
703 case `sysctl -n net.wlan.${1#wlan}.%parent 2>/dev/null` in
710 # IPv6-specific setup subroutines
713 # Setup the interfaces for IPv6
714 network6_interface_setup()
716 local interfaces rtsol_interfaces ipv6_ifconfig
717 local rtsol_available rtsol_interface
718 local prefix laddr hostid address
723 case ${ipv6_gateway_enable} in
731 for _if in $interfaces; do
733 prefix=`get_if_var $_if ipv6_prefix_IF`
734 if [ -n "${prefix}" ]; then
737 laddr=`network6_getladdr $_if`
738 hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'`
739 for j in ${prefix}; do
740 address=$j\:${hostid}
741 ifconfig $_if inet6 ${address} prefixlen 64 alias
743 case ${ipv6_gateway_enable} in
745 # subnet-router anycast address
747 ifconfig $_if inet6 $j:: prefixlen 64 \
753 ipv6_ifconfig=`ifconfig_getargs $_if ipv6`
754 ipv6_ifconfig="${ipv6_ifconfig#inet6 }"
755 if [ -n "${ipv6_ifconfig}" ]; then
758 ifconfig $_if inet6 ${ipv6_ifconfig} alias
761 if [ "${rtsol_available}" = "yes" -a \
762 "${rtsol_interface}" = "yes" ]; then
764 lo0|gif[0-9]*|stf[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*)
767 rtsol_interfaces="${rtsol_interfaces} ${_if}"
775 if [ "${rtsol_available}" = "yes" -a -n "${rtsol_interfaces}" ]; then
776 # Act as endhost - automatically configured.
777 # You can configure only single interface, as
778 # specification assumes that autoconfigured host has
779 # single interface only.
780 ${SYSCTL_W} net.inet6.ip6.accept_rtadv=1
781 set ${rtsol_interfaces}
783 echo "Auto configuring interface $1 ..."
787 for _if in $interfaces; do
792 # Setup IPv6 to IPv4 mapping
795 local stf_prefixlen stf_interface_ipv6_ifid
796 local hexfrag1 hexfrag2 ipv4_in_hexformat laddr
799 case ${stf_interface_ipv4addr} in
803 # assign IPv6 addr and interface route for 6to4 interface
804 stf_prefixlen=$((16+${stf_interface_ipv4plen:-0}))
807 set ${stf_interface_ipv4addr}
809 hexfrag1=`hexprint $(($1*256 + $2))`
810 hexfrag2=`hexprint $(($3*256 + $4))`
811 ipv4_in_hexformat="${hexfrag1}:${hexfrag2}"
812 case ${stf_interface_ipv6_ifid} in
813 [Aa][Uu][Tt][Oo] | '')
814 for _if in ${ipv6_network_interfaces}; do
815 laddr=`network6_getladdr $_if`
824 stf_interface_ipv6_ifid=`expr "${laddr}" : \
825 'fe80::\(.*\)%\(.*\)'`
826 case ${stf_interface_ipv6_ifid} in
828 stf_interface_ipv6_ifid=0:0:0:1
833 ifconfig stf0 create >/dev/null 2>&1
834 ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \
835 prefixlen ${stf_prefixlen}
836 # disallow packets to malicious 6to4 prefix
837 route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
838 route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
839 route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
840 route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
845 # Setup static routes
846 network6_static_routes_setup()
850 # Set up any static routes.
851 case ${ipv6_defaultrouter} in
855 ipv6_static_routes="default ${ipv6_static_routes}"
856 ipv6_route_default="default ${ipv6_defaultrouter}"
859 case ${ipv6_static_routes} in
863 for _rt in ${ipv6_static_routes}; do
864 eval ipv6_route_args=\$ipv6_route_${_rt}
865 route add -inet6 ${ipv6_route_args}
871 # Install the "default interface" to kernel, which will be used
872 # as the default route when there's no router.
873 network6_default_interface_setup()
877 # Choose IPv6 default interface if it is not clearly specified.
878 case ${ipv6_default_interface} in
880 for _if in ${ipv6_network_interfaces}; do
881 if [ "${_if}" = "lo0" ]; then
885 laddr=`network6_getladdr $_if exclude_tentative`
890 ipv6_default_interface=$_if
898 # Disallow unicast packets without outgoing scope identifiers,
899 # or route such packets to a "default" interface, if it is specified.
900 route add -inet6 fe80:: -prefixlen 10 ::1 -reject
901 case ${ipv6_default_interface} in
903 route add -inet6 ff02:: -prefixlen 16 ::1 -reject
906 laddr=`network6_getladdr ${ipv6_default_interface}`
907 route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \
910 # Disable installing the default interface with the
911 # case net.inet6.ip6.forwarding=0 and
912 # net.inet6.ip6.accept_rtadv=0, due to avoid conflict
913 # between the default router list and the manual
914 # configured default route.
915 case ${ipv6_gateway_enable} in
919 if [ `${SYSCTL_N} net.inet6.ip6.accept_rtadv` -eq 1 ]
921 ndp -I ${ipv6_default_interface}
931 local proto addr rest
933 ifconfig $1 2>/dev/null | while read proto addr rest; do