freebsd-skq/etc/network.subr
Doug Barton 8aa4c57946 Improve the handling of IPv6 configuration in rc.d. The ipv6_enable
and ipv6_ifconfig_<interface> options have already been deprecated,
these changes do not alter that.

With these changes any value set for ipv6_enable will emit a
warning. In order to avoid a POLA violation for the deprecation
of the option ipv6_enable=NO will still disable configuration
for all interfaces other than lo0. ipv6_enable=YES will not have
any effect, but will emit an additional warning. Support and
warnings for this option will be removed in FreeBSD 10.x.

Consistent with the current code, in order for IPv6 to be configured
on an interface (other than lo0) an ifconfig_<interface>_ipv6
option will have to be added to /etc/rc.conf[.local].

1. Clean up and minor optimizations for the following functions:
ifconfig_up (the ipv6 elements)
ipv6if
ipv6_autoconfif
get_if_var
_ifconfig_getargs
The cleanups generally were to move the "easy" tests earlier in the
functions, and consolidate duplicate code.

2. Stop overloading ipv6_prefer with the ability to disable IPv6
configuration.

3. Remove noafif() which was only ever called from ipv6_autoconfif.
Instead, simplify and integrate the tests into that function, and
convert the test to use is_wired_interface() instead of listing
wireless interfaces explicitly.

4. Integrate backwards compatibility for ipv6_ifconfig_<interface>
into _ifconfig_getargs. This dramatically simplifies the code in
all of the callers, and avoids a lot of other code duplication.

5. In rc.d/netoptions, add code for an ipv6_privacy option to use
RFC 4193 style pseudo-random addresses (this is what windows does
by default, FYI).

6. Add support for the [NO]RTADV options in ifconfig_getargs() and
ipv6_autoconfif(). In the latter, include support for the explicit
addition of [-]accept_rtadv in ifconfig_<interface>_ipv6 as is done
in the current code.

7. In rc.d/netif add a warning if $ipv6_enable is set, and remove
the set_rcvar_obsolete for it. Also remove the latter from
rc.d/ip6addrctl.

8. In /etc/defaults/rc.conf:

Add an example for RTADV configuration.

Set ipv6_network_interfaces to AUTO.

Switch ipv6_prefer to YES. If ipv6_enable is not set this will have
no effect.

Add a default for ipv6_privacy (NO).

9. Document all of this in rc.conf.5.
2010-04-09 01:35:09 +00:00

1385 lines
26 KiB
Plaintext

#
# Copyright (c) 2003 The FreeBSD Project. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD$
#
#
# Subroutines commonly used from network startup scripts.
# Requires that rc.conf be loaded first.
#
# ifn_start ifn
# Bring up and configure an interface. If some configuration is
# applied print the interface configuration.
#
ifn_start()
{
local ifn cfg
ifn="$1"
cfg=1
[ -z "$ifn" ] && err 1 "ifn_start called without an interface"
ifscript_up ${ifn} && cfg=0
ifconfig_up ${ifn} && cfg=0
ipv4_up ${ifn} && cfg=0
ipv6_up ${ifn} && cfg=0
ipx_up ${ifn} && cfg=0
childif_create ${ifn} && cfg=0
return $cfg
}
# ifn_stop ifn
# Shutdown and de-configure an interface. If action is taken
# print the interface name.
#
ifn_stop()
{
local ifn cfg
ifn="$1"
cfg=1
[ -z "$ifn" ] && err 1 "ifn_stop called without an interface"
ipx_down ${ifn} && cfg=0
ipv6_down ${ifn} && cfg=0
ipv4_down ${ifn} && cfg=0
ifconfig_down ${ifn} && cfg=0
ifscript_down ${ifn} && cfg=0
childif_destroy ${ifn} && cfg=0
return $cfg
}
# ifconfig_up if
# Evaluate ifconfig(8) arguments for interface $if and
# run ifconfig(8) with those arguments. It returns 0 if
# arguments were found and executed or 1 if the interface
# had no arguments. Pseudo arguments DHCP and WPA are handled
# here.
#
ifconfig_up()
{
local _cfg _ipv6_opts ifconfig_args
_cfg=1
# ifconfig_IF
ifconfig_args=`ifconfig_getargs $1`
if [ -n "${ifconfig_args}" ]; then
ifconfig $1 ${ifconfig_args}
_cfg=0
fi
# inet6 specific
if afexists inet6; then
if ipv6if $1; then
# Implicitly handles ipv6_gateway_enable
_ipv6_opts='-ifdisabled -accept_rtadv'
if ipv6_autoconfif $1; then
_ipv6_opts='-ifdisabled accept_rtadv'
fi
ifconfig $1 inet6 $_ipv6_opts
# ifconfig_IF_ipv6
ifconfig_args=`ifconfig_getargs $1 ipv6`
if [ -n "$ifconfig_args" ]; then
ifconfig $1 $ifconfig_args
_cfg=0
fi
else
# Remove in FreeBSD 10.x
# Explicit test is necessary here to avoid nonexistence error
case "$ipv6_enable" in
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
warn "Interface $1 will NOT be configured for IPv6"
;;
esac
ifconfig $1 inet6 ifdisabled
fi
fi
if [ ${_cfg} -eq 0 ]; then
ifconfig $1 up
fi
if wpaif $1; then
/etc/rc.d/wpa_supplicant start $1
_cfg=0 # XXX: not sure this should count
fi
if dhcpif $1; then
if [ $_cfg -ne 0 ] ; then
ifconfig $1 up
fi
if syncdhcpif $1; then
/etc/rc.d/dhclient start $1
fi
_cfg=0
fi
return $_cfg
}
# ifconfig_down if
# returns 1 if wpa_supplicant or dhclient was stopped or
# the interface exists.
#
ifconfig_down()
{
local _cfg
_cfg=1
if wpaif $1; then
/etc/rc.d/wpa_supplicant stop $1
_cfg=0
fi
if dhcpif $1; then
/etc/rc.d/dhclient stop $1
_cfg=0
fi
if ifexists $1; then
ifconfig $1 down
_cfg=0
fi
return $_cfg
}
# get_if_var if var [default]
# Return the value of the pseudo-hash corresponding to $if where
# $var is a string containg the sub-string "IF" which will be
# replaced with $if after the characters defined in _punct are
# replaced with '_'. If the variable is unset, replace it with
# $default if given.
get_if_var()
{
local _if _punct _punct_c _var _default prefix suffix
if [ $# -ne 2 -a $# -ne 3 ]; then
err 3 'USAGE: get_if_var name var [default]'
fi
_if=$1
_punct=". - / +"
for _punct_c in $_punct; do
_if=`ltr ${_if} ${_punct_c} '_'`
done
_var=$2
_default=$3
prefix=${_var%%IF*}
suffix=${_var##*IF}
eval echo \${${prefix}${_if}${suffix}-${_default}}
}
# _ifconfig_getargs if [af]
# Echos the arguments for the supplied interface to stdout.
# returns 1 if empty. In general, ifconfig_getargs should be used
# outside this file.
_ifconfig_getargs()
{
local _ifn _af value
_ifn=$1
_af=${2+_$2}
if [ -z "$_ifn" ]; then
return 1
fi
value=`get_if_var $_ifn ifconfig_IF$_af "$ifconfig_DEFAULT"`
# Remove in FreeBSD 10.x
if [ "$_af" = _ipv6 -a -z "$value" ]; then
value=`get_if_var $_ifn ipv6_ifconfig_IF "$ifconfig_DEFAULT"`
if [ -n "$value" ]; then
warn "\$ipv6_ifconfig_$1 is obsolete." \
" Use ifconfig_$1_ipv6 instead."
fi
fi
echo $value
}
# ifconfig_getargs if [af]
# Takes the result from _ifconfig_getargs and removes pseudo
# args such as DHCP and WPA.
ifconfig_getargs()
{
local _tmpargs _arg _args
_tmpargs=`_ifconfig_getargs $1 $2`
if [ $? -eq 1 ]; then
return 1
fi
_args=
for _arg in $_tmpargs; do
case $_arg in
[Dd][Hh][Cc][Pp]) ;;
[Nn][Oo][Aa][Uu][Tt][Oo]) ;;
[Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]) ;;
[Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]) ;;
[Ww][Pp][Aa]) ;;
[Rr][Tt][Aa][Dd][Vv]) ;;
[Nn][Oo][Rr][Tt][Aa][Dd][Vv]) ;;
*)
_args="$_args $_arg"
;;
esac
done
echo $_args
}
# autoif
# Returns 0 if the interface should be automaticly configured at
# boot time and 1 otherwise.
autoif()
{
local _tmpargs _arg
_tmpargs=`_ifconfig_getargs $1`
for _arg in $_tmpargs; do
case $_arg in
[Nn][Oo][Aa][Uu][Tt][Oo])
return 1
;;
esac
done
return 0
}
# dhcpif if
# Returns 0 if the interface is a DHCP interface and 1 otherwise.
dhcpif()
{
local _tmpargs _arg
_tmpargs=`_ifconfig_getargs $1`
for _arg in $_tmpargs; do
case $_arg in
[Dd][Hh][Cc][Pp])
return 0
;;
[Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
return 0
;;
[Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
return 0
;;
esac
done
return 1
}
# syncdhcpif
# Returns 0 if the interface should be configured synchronously and
# 1 otherwise.
syncdhcpif()
{
local _tmpargs _arg
_tmpargs=`_ifconfig_getargs $1`
for _arg in $_tmpargs; do
case $_arg in
[Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
return 1
;;
[Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
return 0
;;
esac
done
checkyesno synchronous_dhclient
}
# wpaif if
# Returns 0 if the interface is a WPA interface and 1 otherwise.
wpaif()
{
local _tmpargs _arg
_tmpargs=`_ifconfig_getargs $1`
for _arg in $_tmpargs; do
case $_arg in
[Ww][Pp][Aa])
return 0
;;
esac
done
return 1
}
# afexists af
# Returns 0 if the address family is enabled in the kernel
# 1 otherwise.
afexists()
{
local _af
_af=$1
case ${_af} in
inet)
${SYSCTL_N} net.inet > /dev/null 2>&1
;;
inet6)
${SYSCTL_N} net.inet6 > /dev/null 2>&1
;;
ipx)
${SYSCTL_N} net.ipx > /dev/null 2>&1
;;
atm)
if [ -x /sbin/atmconfig ]; then
/sbin/atmconfig diag list > /dev/null 2>&1
else
return 1
fi
;;
*)
err 1 "afexists(): Unsupported address family: $_af"
;;
esac
}
# ipv6if if
# Returns 0 if the interface should be configured for IPv6 and
# 1 otherwise.
ipv6if()
{
if ! afexists inet6; then
return 1
fi
# lo0 is always IPv6-enabled
case $1 in
lo0)
return 0
;;
esac
local _if _tmpargs i
_if=$1
case "$ipv6_network_interfaces" in
''|[Nn][Oo][Nn][Ee])
return 1
;;
$_if|"$_if "*|*" $_if"|*" $_if "*|[Aa][Uu][Tt][Oo])
# True if $ifconfig_IF_ipv6 is defined.
_tmpargs=`_ifconfig_getargs $_if ipv6`
;;
esac
if [ -n "$_tmpargs" ]; then
# Remove in FreeBSD 10.x
# Explicit test is necessary here to avoid nonexistence error
case "$ipv6_enable" in
[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
;;
*) return 0
;;
esac
fi
return 1
}
# ipv6_autoconfif if
# Returns 0 if the interface should be configured for IPv6 with
# Stateless Address Configuration, 1 otherwise.
ipv6_autoconfif()
{
case $1 in
lo0|\
stf[0-9]*|\
faith[0-9]*|\
lp[0-9]*|\
sl[0-9]*|\
pflog[0-9]*|\
pfsync[0-9]*)
return 1
;;
esac
local _if _tmpargs _arg
_if=$1
if ! ipv6if $_if; then
return 1
fi
if checkyesno ipv6_gateway_enable; then
return 1
fi
_tmpargs=`get_if_var $_if ipv6_prefix_IF`
if [ -n "${_tmpargs}" ]; then
return 1
fi
if ! is_wired_interface $_if; then
case $_if in
wlan[0-9]*) ;; # Allow test to continue
*) return 1
;;
esac
fi
_tmpargs=`_ifconfig_getargs $_if ipv6`
case "$_tmpargs" in
*inet6\ *|*[Nn][Oo][Rr][Tt][Aa][Dd][Vv]*|*-accept_rtadv*)
return 1
;;
*[Rr][Tt][Aa][Dd][Vv]*|*accept_rtadv*)
return 0
;;
esac
return 1
}
# ifexists if
# Returns 0 if the interface exists and 1 otherwise.
ifexists()
{
[ -z "$1" ] && return 1
ifconfig -n $1 > /dev/null 2>&1
}
# ipv4_up if
# add IPv4 addresses to the interface $if
ipv4_up()
{
local _if _ret
_if=$1
_ret=1
ifalias_up ${_if} inet && _ret=0
ipv4_addrs_common ${_if} alias && _ret=0
return $_ret
}
# ipv6_up if
# add IPv6 addresses to the interface $if
ipv6_up()
{
local _if _ret
_if=$1
_ret=1
if ! ipv6if $_if; then
return 0
fi
ifalias_up ${_if} inet6 && _ret=0
ipv6_prefix_hostid_addr_up ${_if} && _ret=0
ipv6_accept_rtadv_up ${_if} && _ret=0
# wait for DAD
sleep `${SYSCTL_N} net.inet6.ip6.dad_count`
sleep 1
return $_ret
}
# ipv4_down if
# remove IPv4 addresses from the interface $if
ipv4_down()
{
local _if _ifs _ret inetList oldifs _inet
_if=$1
_ifs="^"
_ret=1
inetList="`ifconfig ${_if} | grep 'inet ' | tr "\n" "$_ifs"`"
oldifs="$IFS"
IFS="$_ifs"
for _inet in $inetList ; do
# get rid of extraneous line
[ -z "$_inet" ] && break
_inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'`
IFS="$oldifs"
ifconfig ${_if} ${_inet} delete
IFS="$_ifs"
_ret=0
done
IFS="$oldifs"
ifalias_down ${_if} inet && _ret=0
ipv4_addrs_common ${_if} -alias && _ret=0
return $_ret
}
# ipv6_down if
# remove IPv6 addresses from the interface $if
ipv6_down()
{
local _if _ifs _ret inetList oldifs _inet6
_if=$1
_ifs="^"
_ret=1
if ! ipv6if $_if; then
return 0
fi
ipv6_accept_rtadv_down ${_if} && _ret=0
ifalias_down ${_if} inet6 && _ret=0
inetList="`ifconfig ${_if} | grep 'inet6 ' | tr "\n" "$_ifs"`"
oldifs="$IFS"
IFS="$_ifs"
for _inet6 in $inetList ; do
# get rid of extraneous line
[ -z "$_inet6" ] && break
_inet6=`expr "$_inet6" : '.*\(inet6 \([0-9a-f:]*\)\).*'`
IFS="$oldifs"
ifconfig ${_if} ${_inet6} -alias
IFS="$_ifs"
_ret=0
done
IFS="$oldifs"
return $_ret
}
# ipv4_addrs_common if action
# Evaluate the ifconfig_if_ipv4 arguments for interface $if and
# use $action to add or remove IPv4 addresses from $if.
ipv4_addrs_common()
{
local _ret _if _action _cidr _cidr_addr
local _ipaddr _netmask _range _ipnet _iplow _iphigh _ipcount
_ret=1
_if=$1
_action=$2
# get ipv4-addresses
cidr_addr=`get_if_var $_if ipv4_addrs_IF`
for _cidr in ${cidr_addr}; do
_ipaddr=${_cidr%%/*}
_netmask="/"${_cidr##*/}
_range=${_ipaddr##*.}
_ipnet=${_ipaddr%.*}
_iplow=${_range%-*}
_iphigh=${_range#*-}
# clear netmask when removing aliases
if [ "${_action}" = "-alias" ]; then
_netmask=""
fi
_ipcount=${_iplow}
while [ "${_ipcount}" -le "${_iphigh}" ]; do
eval "ifconfig ${_if} ${_action} ${_ipnet}.${_ipcount}${_netmask}"
_ipcount=$((${_ipcount}+1))
_ret=0
# only the first ipaddr in a subnet need the real netmask
if [ "${_action}" != "-alias" ]; then
_netmask="/32"
fi
done
done
return $_ret
}
# ifalias_up if af
# Configure aliases for network interface $if.
# It returns 0 if at least one alias was configured or
# 1 if there were none.
#
ifalias_up()
{
local _ret
_ret=1
case "$2" in
inet)
_ret=`ifalias_ipv4_up "$1"`
;;
inet6)
_ret=`ifalias_ipv6_up "$1"`
;;
esac
return $_ret
}
# ifalias_ipv4_up if
# Helper function for ifalias_up(). Handles IPv4.
#
ifalias_ipv4_up()
{
local _ret alias ifconfig_args
_ret=1
# ifconfig_IF_aliasN which starts with "inet"
alias=0
while : ; do
ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
case "${ifconfig_args}" in
inet\ *)
ifconfig $1 ${ifconfig_args} alias && _ret=0
;;
"")
break
;;
esac
alias=$((${alias} + 1))
done
return $_ret
}
# ifalias_ipv6_up if
# Helper function for ifalias_up(). Handles IPv6.
#
ifalias_ipv6_up()
{
local _ret alias ifconfig_args
_ret=1
# ifconfig_IF_aliasN which starts with "inet6"
alias=0
while : ; do
ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
case "${ifconfig_args}" in
inet6\ *)
ifconfig $1 ${ifconfig_args} alias && _ret=0
;;
"")
break
;;
esac
alias=$((${alias} + 1))
done
# backward compatibility: ipv6_ifconfig_IF_aliasN.
alias=0
while : ; do
ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF_alias${alias}`
case "${ifconfig_args}" in
"")
break
;;
*)
ifconfig $1 inet6 ${ifconfig_args} alias && _ret=0
warn "\$ipv6_ifconfig_$1_alias${alias} is obsolete." \
" Use ifconfig_$1_aliasN instead."
;;
esac
alias=$((${alias} + 1))
done
return $_ret
}
# ifalias_down if af
# Remove aliases for network interface $if.
# It returns 0 if at least one alias was removed or
# 1 if there were none.
#
ifalias_down()
{
local _ret
_ret=1
case "$2" in
inet)
_ret=`ifalias_ipv4_down "$1"`
;;
inet6)
_ret=`ifalias_ipv6_down "$1"`
;;
esac
return $_ret
}
# ifalias_ipv4_down if
# Helper function for ifalias_down(). Handles IPv4.
#
ifalias_ipv4_down()
{
local _ret alias ifconfig_args
_ret=1
# ifconfig_IF_aliasN which starts with "inet"
alias=0
while : ; do
ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
case "${ifconfig_args}" in
inet\ *)
ifconfig $1 ${ifconfig_args} -alias && _ret=0
;;
"")
break
;;
esac
alias=$((${alias} + 1))
done
return $_ret
}
# ifalias_ipv6_down if
# Helper function for ifalias_down(). Handles IPv6.
#
ifalias_ipv6_down()
{
local _ret alias ifconfig_args
_ret=1
# ifconfig_IF_aliasN which starts with "inet6"
alias=0
while : ; do
ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
case "${ifconfig_args}" in
inet6\ *)
ifconfig $1 ${ifconfig_args} -alias && _ret=0
;;
"")
break
;;
esac
alias=$((${alias} + 1))
done
# backward compatibility: ipv6_ifconfig_IF_aliasN.
alias=0
while : ; do
ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF_alias${alias}`
case "${ifconfig_args}" in
"")
break
;;
*)
ifconfig $1 inet6 ${ifconfig_args} -alias && _ret=0
warn "\$ipv6_ifconfig_$1_alias${alias} is obsolete." \
" Use ifconfig_$1_aliasN instead."
;;
esac
alias=$((${alias} + 1))
done
return $_ret
}
# ipv6_prefix_hostid_addr_up if
# add IPv6 prefix + hostid addr to the interface $if
ipv6_prefix_hostid_addr_up()
{
local _if prefix laddr hostid j address
_if=$1
prefix=`get_if_var ${_if} ipv6_prefix_IF`
if [ -n "${prefix}" ]; then
laddr=`network6_getladdr ${_if}`
hostid=${laddr#fe80::}
hostid=${hostid%\%*}
for j in ${prefix}; do
address=$j\:${hostid}
ifconfig ${_if} inet6 ${address} prefixlen 64 alias
# if I am a router, add subnet router
# anycast address (RFC 2373).
if checkyesno ipv6_gateway_enable; then
ifconfig ${_if} inet6 $j:: prefixlen 64 \
alias anycast
fi
done
fi
}
# ipv6_accept_rtadv_up if
# Enable accepting Router Advertisement and send Router
# Solicitation message
ipv6_accept_rtadv_up()
{
if ipv6_autoconfif $1; then
ifconfig $1 inet6 accept_rtadv up
if ! checkyesno rtsold_enable; then
rtsol ${rtsol_flags} $1
fi
fi
}
# ipv6_accept_rtadv_down if
# Disable accepting Router Advertisement
ipv6_accept_rtadv_down()
{
if ipv6_autoconfif $1; then
ifconfig $1 inet6 -accept_rtadv
fi
}
# ifscript_up if
# Evaluate a startup script for the $if interface.
# It returns 0 if a script was found and processed or
# 1 if no script was found.
#
ifscript_up()
{
if [ -r /etc/start_if.$1 ]; then
. /etc/start_if.$1
return 0
else
return 1
fi
}
# ifscript_down if
# Evaluate a shutdown script for the $if interface.
# It returns 0 if a script was found and processed or
# 1 if no script was found.
#
ifscript_down()
{
if [ -r /etc/stop_if.$1 ]; then
. /etc/stop_if.$1
return 0
else
return 1
fi
}
# clone_up
# Create cloneable interfaces.
#
clone_up()
{
local _prefix _list ifn
_prefix=
_list=
# create_args_IF
for ifn in ${cloned_interfaces}; do
ifconfig ${ifn} create `get_if_var ${ifn} create_args_IF`
if [ $? -eq 0 ]; then
_list="${_list}${_prefix}${ifn}"
[ -z "$_prefix" ] && _prefix=' '
fi
done
debug "Cloned: ${_list}"
}
# clone_down
# Destroy cloned interfaces. Destroyed interfaces are echoed to
# standard output.
#
clone_down()
{
local _prefix _list ifn
_prefix=
_list=
for ifn in ${cloned_interfaces}; do
ifconfig ${ifn} destroy
if [ $? -eq 0 ]; then
_list="${_list}${_prefix}${ifn}"
[ -z "$_prefix" ] && _prefix=' '
fi
done
debug "Destroyed clones: ${_list}"
}
# childif_create
# Create and configure child interfaces. Return 0 if child
# interfaces are created.
#
childif_create()
{
local cfg child child_vlans child_wlans create_args debug_flags ifn i
cfg=1
ifn=$1
# Create wireless interfaces
child_wlans=`get_if_var $ifn wlans_IF`
for child in ${child_wlans}; do
create_args="wlandev $ifn `get_if_var $child create_args_IF`"
debug_flags="`get_if_var $child wlandebug_IF`"
if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
ifconfig $child create ${create_args} && cfg=0
if [ -n "${debug_flags}" ]; then
wlandebug -i $child ${debug_flags}
fi
else
i=`ifconfig wlan create ${create_args}`
if [ -n "${debug_flags}" ]; then
wlandebug -i $i ${debug_flags}
fi
ifconfig $i name $child && cfg=0
fi
if autoif $child; then
ifn_start $child
fi
done
# Create vlan interfaces
child_vlans=`get_if_var $ifn vlans_IF`
if [ -n "${child_vlans}" ]; then
load_kld if_vlan
fi
for child in ${child_vlans}; do
if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
child="${ifn}.${child}"
create_args=`get_if_var $child create_args_IF`
ifconfig $child create ${create_args} && cfg=0
else
create_args="vlandev $ifn `get_if_var $child create_args_IF`"
if expr $child : 'vlan[0-9][0-9]*$' >/dev/null 2>&1; then
ifconfig $child create ${create_args} && cfg=0
else
i=`ifconfig vlan create ${create_args}`
ifconfig $i name $child && cfg=0
fi
fi
if autoif $child; then
ifn_start $child
fi
done
return ${cfg}
}
# childif_destroy
# Destroy child interfaces.
#
childif_destroy()
{
local cfg child child_vlans child_wlans ifn
cfg=1
child_wlans=`get_if_var $ifn wlans_IF`
for child in ${child_wlans}; do
if ! ifexists $child; then
continue
fi
if autoif $child; then
ifn_stop $child
fi
ifconfig $child destroy && cfg=0
done
child_vlans=`get_if_var $ifn vlans_IF`
for child in ${child_vlans}; do
if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
child="${ifn}.${child}"
fi
if ! ifexists $child; then
continue
fi
if autoif $child; then
ifn_stop $child
fi
ifconfig $child destroy && cfg=0
done
return ${cfg}
}
# ng_mkpeer
# Create netgraph nodes.
#
ng_mkpeer()
{
ngctl -f - 2> /dev/null <<EOF
mkpeer $*
msg dummy nodeinfo
EOF
}
# ng_create_one
# Create netgraph nodes.
#
ng_create_one()
{
local t
ng_mkpeer $* | while read line; do
t=`expr "${line}" : '.* name="\([a-z]*[0-9]*\)" .*'`
if [ -n "${t}" ]; then
echo ${t}
return
fi
done
}
# gif_up
# Create gif(4) tunnel interfaces.
gif_up()
{
local i peers
for i in ${gif_interfaces}; do
peers=`get_if_var $i gifconfig_IF`
case ${peers} in
'')
continue
;;
*)
if expr $i : 'gif[0-9][0-9]*$' >/dev/null 2>&1; then
ifconfig $i create >/dev/null 2>&1
else
gif=`ifconfig gif create`
ifconfig $gif name $i
fi
ifconfig $i tunnel ${peers}
ifconfig $i up
;;
esac
done
}
# ng_fec_create ifn
# Configure Fast EtherChannel for interface $ifn. Returns 0 if
# FEC arguments were found and configured; returns !0 otherwise.
ng_fec_create()
{
local req_iface iface bogus
req_iface="$1"
ngctl shutdown ${req_iface}: > /dev/null 2>&1
bogus=""
while true; do
iface=`ng_create_one fec dummy fec`
if [ -z "${iface}" ]; then
exit 2
fi
if [ "${iface}" = "${req_iface}" ]; then
break
fi
bogus="${bogus} ${iface}"
done
for iface in ${bogus}; do
ngctl shutdown ${iface}:
done
}
# fec_up
# Create Fast EtherChannel interfaces.
fec_up()
{
local i j
for i in ${fec_interfaces}; do
ng_fec_create $i
for j in `get_if_var $i fecconfig_IF`; do
case ${j} in
'')
continue
;;
*)
ngctl msg ${i}: add_iface "\"${j}\""
;;
esac
done
done
}
# ipx_up ifn
# Configure any IPX addresses for interface $ifn. Returns 0 if
# IPX arguments were found and configured; returns 1 otherwise.
#
ipx_up()
{
local ifn
ifn="$1"
# ifconfig_IF_ipx
ifconfig_args=`_ifconfig_getargs $ifn ipx`
if [ -n "${ifconfig_args}" ]; then
ifconfig ${ifn} ${ifconfig_args}
return 0
fi
return 1
}
# ipx_down ifn
# Remove IPX addresses for interface $ifn. Returns 0 if IPX
# addresses were found and unconfigured. It returns 1, otherwise.
#
ipx_down()
{
local _if _ifs _ret ipxList oldifs _ipx
_if=$1
_ifs="^"
_ret=1
ipxList="`ifconfig ${_if} | grep 'ipx ' | tr "\n" "$_ifs"`"
oldifs="$IFS"
IFS="$_ifs"
for _ipx in $ipxList ; do
# get rid of extraneous line
[ -z "$_ipx" ] && break
_ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'`
IFS="$oldifs"
ifconfig ${_if} ${_ipx} delete
IFS="$_ifs"
_ret=0
done
IFS="$oldifs"
return $_ret
}
# ifnet_rename
# Rename all requested interfaces.
#
ifnet_rename()
{
local _if _ifname
# ifconfig_IF_name
for _if in `ifconfig -l`; do
_ifname=`get_if_var $_if ifconfig_IF_name`
if [ ! -z "$_ifname" ]; then
ifconfig $_if name $_ifname
fi
done
return 0
}
# list_net_interfaces type
# List all network interfaces. The type of interface returned
# can be controlled by the type argument. The type
# argument can be any of the following:
# nodhcp - all interfaces, excluding DHCP configured interfaces
# dhcp - list only DHCP configured interfaces
# noautoconf - all interfaces, excluding IPv6 Stateless
# Address Autoconf configured interfaces
# autoconf - list only IPv6 Stateless Address Autoconf
# configured interfaces
# If no argument is specified all network interfaces are output.
# Note that the list will include cloned interfaces if applicable.
# Cloned interfaces must already exist to have a chance to appear
# in the list if ${network_interfaces} is set to `auto'.
#
list_net_interfaces()
{
local type _tmplist _list _autolist _lo _if
type=$1
# Get a list of ALL the interfaces and make lo0 first if it's there.
#
_tmplist=
case ${network_interfaces} in
[Aa][Uu][Tt][Oo])
_autolist="`ifconfig -l`"
_lo=
for _if in ${_autolist} ; do
if autoif $_if; then
if [ "$_if" = "lo0" ]; then
_lo="lo0 "
else
_tmplist="${_tmplist} ${_if}"
fi
fi
done
_tmplist="${_lo}${_tmplist# }"
;;
*)
_tmplist="${network_interfaces} ${cloned_interfaces}"
# lo0 is effectively mandatory, so help prevent foot-shooting
#
case "$_tmplist" in
lo0|'lo0 '*|*' lo0'|*' lo0 '*) ;; # This is fine, do nothing
*) _tmplist="lo0 ${_tmplist}" ;;
esac
;;
esac
_list=
case "$type" in
nodhcp)
for _if in ${_tmplist} ; do
if ! dhcpif $_if && \
[ -n "`_ifconfig_getargs $_if`" ]; then
_list="${_list# } ${_if}"
fi
done
;;
dhcp)
for _if in ${_tmplist} ; do
if dhcpif $_if; then
_list="${_list# } ${_if}"
fi
done
;;
noautoconf)
for _if in ${_tmplist} ; do
if ! ipv6_autoconfif $_if && \
[ -n "`_ifconfig_getargs $_if ipv6`" ]; then
_list="${_list# } ${_if}"
fi
done
;;
autoconf)
for _if in ${_tmplist} ; do
if ipv6_autoconfif $_if; then
_list="${_list# } ${_if}"
fi
done
;;
*)
_list=${_tmplist}
;;
esac
echo $_list
return 0
}
# get_default_if -address_family
# Get the interface of the default route for the given address family.
# The -address_family argument must be suitable passing to route(8).
#
get_default_if()
{
local routeget oldifs defif line
defif=
oldifs="$IFS"
IFS="
"
for line in `route -n get $1 default 2>/dev/null`; do
case $line in
*interface:*)
defif=${line##*: }
;;
esac
done
IFS=${oldifs}
echo $defif
}
# hexdigit arg
# Echo decimal number $arg (single digit) in hexadecimal format.
hexdigit()
{
if [ $1 -lt 10 ]; then
echo $1
else
case $1 in
10) echo a ;;
11) echo b ;;
12) echo c ;;
13) echo d ;;
14) echo e ;;
15) echo f ;;
esac
fi
}
# hexprint arg
# Echo decimal number $arg (multiple digits) in hexadecimal format.
hexprint()
{
local val str dig
val=$1
str=''
dig=`hexdigit $((${val} & 15))`
str=${dig}${str}
val=$((${val} >> 4))
while [ ${val} -gt 0 ]; do
dig=`hexdigit $((${val} & 15))`
str=${dig}${str}
val=$((${val} >> 4))
done
echo ${str}
}
is_wired_interface()
{
local media
case `ifconfig $1 2>/dev/null` in
*media:?Ethernet*) media=Ethernet ;;
esac
test "$media" = "Ethernet"
}
# network6_getladdr if [flag]
# Echo link-local address from $if if any.
# If flag is defined, tentative ones will be excluded.
network6_getladdr()
{
local proto addr rest
ifconfig $1 2>/dev/null | while read proto addr rest; do
case ${proto} in
inet6)
case ${addr} in
fe80::*)
if [ -z "$2" ]; then
echo ${addr}
return
fi
case ${rest} in
*tentative*)
continue
;;
*)
echo ${addr}
return
esac
esac
esac
done
}