xref: /freebsd/libexec/rc/network.subr (revision 85732ac8)
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$
26#
27IFCONFIG_CMD="/sbin/ifconfig"
28: ${netif_ipexpand_max:=2048}
29
30#
31# Subroutines commonly used from network startup scripts.
32# Requires that rc.conf be loaded first.
33#
34
35# ifn_start ifn
36#	Bring up and configure an interface.  If some configuration is
37#	applied, print the interface configuration.
38#
39ifn_start()
40{
41	local ifn cfg
42	ifn="$1"
43	cfg=1
44
45	[ -z "$ifn" ] && err 1 "ifn_start called without an interface"
46
47	ifscript_up ${ifn} && cfg=0
48	ifconfig_up ${ifn} && cfg=0
49	if ! noafif $ifn; then
50		afexists inet && ipv4_up ${ifn} && cfg=0
51		afexists inet6 && ipv6_up ${ifn} && cfg=0
52	fi
53	childif_create ${ifn} && cfg=0
54
55	return $cfg
56}
57
58# ifn_stop ifn
59#	Shutdown and de-configure an interface.  If action is taken,
60#	print the interface name.
61#
62ifn_stop()
63{
64	local ifn cfg
65	ifn="$1"
66	cfg=1
67
68	[ -z "$ifn" ] && err 1 "ifn_stop called without an interface"
69
70	if ! noafif $ifn; then
71		afexists inet6 && ipv6_down ${ifn} && cfg=0
72		afexists inet && ipv4_down ${ifn} && cfg=0
73	fi
74	ifconfig_down ${ifn} && cfg=0
75	ifscript_down ${ifn} && cfg=0
76	childif_destroy ${ifn} && cfg=0
77
78	return $cfg
79}
80
81# ifn_vnetup ifn
82#	Move ifn to the specified vnet jail.
83#
84ifn_vnetup()
85{
86
87	ifn_vnet0 $1 vnet
88}
89
90# ifn_vnetdown ifn
91#	Reclaim ifn from the specified vnet jail.
92#
93ifn_vnetdown()
94{
95
96	ifn_vnet0 $1 -vnet
97}
98
99# ifn_vnet0 ifn action
100#	Helper function for ifn_vnetup and ifn_vnetdown.
101#
102ifn_vnet0()
103{
104	local _ifn _cfg _action _vnet
105	_ifn="$1"
106	_action="$2"
107	_cfg=1
108
109	if _vnet=$(vnetif $_ifn); then
110		${IFCONFIG_CMD} $_ifn $_action $_vnet && _cfg=0
111	fi
112
113	return $_cfg
114}
115
116# ifconfig_up if
117#	Evaluate ifconfig(8) arguments for interface $if and
118#	run ifconfig(8) with those arguments. It returns 0 if
119#	arguments were found and executed or 1 if the interface
120#	had no arguments.  Pseudo arguments DHCP and WPA are handled
121#	here.
122#
123ifconfig_up()
124{
125	local _cfg _ifconfig_descr _ipv6_opts ifconfig_args
126	_cfg=1
127
128	# Make sure lo0 always comes up.
129	if [ "$1" = "lo0" ]; then
130		_cfg=0
131	fi
132
133	# inet6 specific
134	if ! noafif $1 && afexists inet6; then
135		if checkyesno ipv6_activate_all_interfaces; then
136			_ipv6_opts="-ifdisabled"
137		elif [ "$1" != "lo0" ]; then
138			_ipv6_opts="ifdisabled"
139		fi
140
141		# backward compatibility: $ipv6_enable
142		case $ipv6_enable in
143		[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
144			case $1 in
145			bridge[0-9]*)
146				# No accept_rtadv by default on if_bridge(4)
147				# to avoid a conflict with the member
148				# interfaces.
149			;;
150			*)
151				if ! checkyesno ipv6_gateway_enable; then
152					_ipv6_opts="${_ipv6_opts} accept_rtadv"
153				fi
154			;;
155			esac
156		;;
157		esac
158
159		case $ipv6_cpe_wanif in
160		$1)
161			_ipv6_opts="${_ipv6_opts} -no_radr accept_rtadv"
162		;;
163		esac
164
165		if [ -n "${_ipv6_opts}" ]; then
166			${IFCONFIG_CMD} $1 inet6 ${_ipv6_opts}
167		fi
168	fi
169
170	# ifconfig_IF
171	ifconfig_args=`ifconfig_getargs $1`
172	if [ -n "${ifconfig_args}" ]; then
173		eval ${IFCONFIG_CMD} $1 ${ifconfig_args}
174		_cfg=0
175	fi
176
177	# inet6 specific
178	if ! noafif $1 && afexists inet6; then
179		# ifconfig_IF_ipv6
180		ifconfig_args=`ifconfig_getargs $1 ipv6`
181		if [ -n "${ifconfig_args}" ]; then
182			# backward compatibility: inet6 keyword
183			case "${ifconfig_args}" in
184			:*|[0-9a-fA-F]*:*)
185				warn "\$ifconfig_$1_ipv6 needs leading" \
186				    "\"inet6\" keyword for an IPv6 address."
187				ifconfig_args="inet6 ${ifconfig_args}"
188			;;
189			esac
190			${IFCONFIG_CMD} $1 inet6 -ifdisabled
191			eval ${IFCONFIG_CMD} $1 ${ifconfig_args}
192			_cfg=0
193		fi
194
195		# $ipv6_prefix_IF will be handled in
196		# ipv6_prefix_hostid_addr_common().
197		ifconfig_args=`get_if_var $1 ipv6_prefix_IF`
198		if [ -n "${ifconfig_args}" ]; then
199			${IFCONFIG_CMD} $1 inet6 -ifdisabled
200			_cfg=0
201		fi
202
203		# backward compatibility: $ipv6_ifconfig_IF
204		ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF`
205		if [ -n "${ifconfig_args}" ]; then
206			warn "\$ipv6_ifconfig_$1 is obsolete." \
207			    "  Use ifconfig_$1_ipv6 instead."
208			${IFCONFIG_CMD} $1 inet6 -ifdisabled
209			eval ${IFCONFIG_CMD} $1 inet6 ${ifconfig_args}
210			_cfg=0
211		fi
212	fi
213
214	ifalias $1 link alias
215	ifalias $1 ether alias
216
217	_ifconfig_descr=`get_if_var $1 ifconfig_IF_descr`
218	if [ -n "${_ifconfig_descr}" ]; then
219		${IFCONFIG_CMD} $1 description "${_ifconfig_descr}"
220	fi
221
222	if wpaif $1; then
223		/etc/rc.d/wpa_supplicant start $1
224		_cfg=0		# XXX: not sure this should count
225	elif hostapif $1; then
226		/etc/rc.d/hostapd start $1
227		_cfg=0
228	elif [ ${_cfg} -eq 0 ]; then
229		${IFCONFIG_CMD} $1 up
230	fi
231
232	if dhcpif $1; then
233		if [ $_cfg -ne 0 ] ; then
234			${IFCONFIG_CMD} $1 up
235		fi
236		if syncdhcpif $1; then
237			/etc/rc.d/dhclient start $1
238		fi
239		_cfg=0
240	fi
241
242	return $_cfg
243}
244
245# ifconfig_down if
246#	returns 1 if wpa_supplicant or dhclient was stopped or
247#	the interface exists.
248#
249ifconfig_down()
250{
251	local _cfg
252	_cfg=1
253
254	if wpaif $1; then
255		/etc/rc.d/wpa_supplicant stop $1
256		_cfg=0
257	elif hostapif $1; then
258		/etc/rc.d/hostapd stop $1
259		_cfg=0
260	fi
261
262	if dhcpif $1; then
263		/etc/rc.d/dhclient stop $1
264		_cfg=0
265	fi
266
267	if ifexists $1; then
268		${IFCONFIG_CMD} $1 down
269		_cfg=0
270	fi
271
272	return $_cfg
273}
274
275# get_if_var if var [default]
276#	Return the value of the pseudo-hash corresponding to $if where
277#	$var is a string containg the sub-string "IF" which will be
278#	replaced with $if after the characters defined in _punct are
279#	replaced with '_'. If the variable is unset, replace it with
280#	$default if given.
281get_if_var()
282{
283	local _if _punct _punct_c _var _default prefix suffix
284
285	if [ $# -ne 2 -a $# -ne 3 ]; then
286		err 3 'USAGE: get_if_var name var [default]'
287	fi
288
289	_if=$1
290	_punct=".-/+"
291	ltr ${_if} "${_punct}" '_' _if
292	_var=$2
293	_default=$3
294
295	prefix=${_var%%IF*}
296	suffix=${_var##*IF}
297	eval echo \${${prefix}${_if}${suffix}-${_default}}
298}
299
300# _ifconfig_getargs if [af]
301#	Prints the arguments for the supplied interface to stdout.
302#	Returns 1 if empty.  In general, ifconfig_getargs should be used
303#	outside this file.
304_ifconfig_getargs()
305{
306	local _ifn _af
307	_ifn=$1
308	_af=${2+_$2}
309
310	if [ -z "$_ifn" ]; then
311		return 1
312	fi
313
314	get_if_var $_ifn ifconfig_IF$_af "$ifconfig_DEFAULT"
315}
316
317# ifconfig_getargs if [af]
318#	Takes the result from _ifconfig_getargs and removes pseudo
319#	args such as DHCP and WPA.
320ifconfig_getargs()
321{
322	local _tmpargs _arg _args _vnet
323	_tmpargs=`_ifconfig_getargs $1 $2`
324	if [ $? -eq 1 ]; then
325		return 1
326	fi
327	_args=
328	_vnet=0
329
330	for _arg in $_tmpargs; do
331		case $_arg:$_vnet in
332		[Dd][Hh][Cc][Pp]:0) ;;
333		[Nn][Oo][Aa][Uu][Tt][Oo]:0) ;;
334		[Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]:0) ;;
335		[Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]:0) ;;
336		[Ww][Pp][Aa]:0) ;;
337		[Hh][Oo][Ss][Tt][Aa][Pp]:0) ;;
338		vnet:0)	_vnet=1 ;;
339		*:1)	_vnet=0 ;;
340		*:0)
341			_args="$_args $_arg"
342		;;
343		esac
344	done
345
346	echo $_args
347}
348
349# autoif
350#	Returns 0 if the interface should be automatically configured at
351#	boot time and 1 otherwise.
352autoif()
353{
354	local _tmpargs _arg
355	_tmpargs=`_ifconfig_getargs $1`
356
357	for _arg in $_tmpargs; do
358		case $_arg in
359		[Nn][Oo][Aa][Uu][Tt][Oo])
360			return 1
361			;;
362		esac
363	done
364
365	return 0
366}
367
368# dhcpif if
369#	Returns 0 if the interface is a DHCP interface and 1 otherwise.
370dhcpif()
371{
372	local _tmpargs _arg
373	_tmpargs=`_ifconfig_getargs $1`
374
375	case $1 in
376	lo[0-9]*|\
377	stf[0-9]*|\
378	lp[0-9]*|\
379	sl[0-9]*)
380		return 1
381		;;
382	esac
383	if noafif $1; then
384		return 1
385	fi
386
387	for _arg in $_tmpargs; do
388		case $_arg in
389		[Dd][Hh][Cc][Pp])
390			return 0
391			;;
392		[Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
393			return 0
394			;;
395		[Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
396			return 0
397			;;
398		esac
399	done
400
401	return 1
402}
403
404# syncdhcpif
405#	Returns 0 if the interface should be configured synchronously and
406#	1 otherwise.
407syncdhcpif()
408{
409	local _tmpargs _arg
410	_tmpargs=`_ifconfig_getargs $1`
411
412	if noafif $1; then
413		return 1
414	fi
415
416	for _arg in $_tmpargs; do
417		case $_arg in
418		[Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
419			return 1
420			;;
421		[Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
422			return 0
423			;;
424		esac
425	done
426
427	checkyesno synchronous_dhclient
428}
429
430# wpaif if
431#	Returns 0 if the interface is a WPA interface and 1 otherwise.
432wpaif()
433{
434	local _tmpargs _arg
435	_tmpargs=`_ifconfig_getargs $1`
436
437	for _arg in $_tmpargs; do
438		case $_arg in
439		[Ww][Pp][Aa])
440			return 0
441			;;
442		esac
443	done
444
445	return 1
446}
447
448# hostapif if
449#	Returns 0 if the interface is a HOSTAP interface and 1 otherwise.
450hostapif()
451{
452	local _tmpargs _arg
453	_tmpargs=`_ifconfig_getargs $1`
454
455	for _arg in $_tmpargs; do
456		case $_arg in
457		[Hh][Oo][Ss][Tt][Aa][Pp])
458			return 0
459			;;
460		esac
461	done
462
463	return 1
464}
465
466# vnetif if
467#	Returns 0 and echo jail if "vnet" keyword is specified on the
468#	interface, and 1 otherwise.
469vnetif()
470{
471	local _tmpargs _arg _vnet
472	_tmpargs=`_ifconfig_getargs $1`
473
474	_vnet=0
475	for _arg in $_tmpargs; do
476		case $_arg:$_vnet in
477		vnet:0)	_vnet=1 ;;
478		*:1)	echo $_arg; return 0 ;;
479		esac
480	done
481
482	return 1
483}
484
485# afexists af
486#	Returns 0 if the address family is enabled in the kernel
487#	1 otherwise.
488afexists()
489{
490	local _af
491	_af=$1
492
493	case ${_af} in
494	inet|inet6)
495		check_kern_features ${_af}
496		;;
497	link|ether)
498		return 0
499		;;
500	*)
501		err 1 "afexists(): Unsupported address family: $_af"
502		;;
503	esac
504}
505
506# noafif if
507#	Returns 0 if the interface has no af configuration and 1 otherwise.
508noafif()
509{
510	local _if
511	_if=$1
512
513	case $_if in
514	pflog[0-9]*|\
515	pfsync[0-9]*|\
516	usbus[0-9]*|\
517	an[0-9]*|\
518	ath[0-9]*|\
519	ipw[0-9]*|\
520	ipfw[0-9]*|\
521	iwi[0-9]*|\
522	iwn[0-9]*|\
523	ral[0-9]*|\
524	wi[0-9]*|\
525	wl[0-9]*|\
526	wpi[0-9]*)
527		return 0
528		;;
529	esac
530
531	return 1
532}
533
534# ipv6if if
535#	Returns 0 if the interface should be configured for IPv6 and
536#	1 otherwise.
537ipv6if()
538{
539	local _if _tmpargs i
540	_if=$1
541
542	if ! afexists inet6; then
543		return 1
544	fi
545
546	# lo0 is always IPv6-enabled
547	case $_if in
548	lo0)
549		return 0
550		;;
551	esac
552
553	case "${ipv6_network_interfaces}" in
554	$_if|"$_if "*|*" $_if"|*" $_if "*|[Aa][Uu][Tt][Oo])
555		# True if $ifconfig_IF_ipv6 is defined.
556		_tmpargs=`_ifconfig_getargs $_if ipv6`
557		if [ -n "${_tmpargs}" ]; then
558			return 0
559		fi
560
561		# True if $ipv6_prefix_IF is defined.
562		_tmpargs=`get_if_var $_if ipv6_prefix_IF`
563		if [ -n "${_tmpargs}" ]; then
564			return 0
565		fi
566
567		# backward compatibility: True if $ipv6_ifconfig_IF is defined.
568		_tmpargs=`get_if_var $_if ipv6_ifconfig_IF`
569		if [ -n "${_tmpargs}" ]; then
570			return 0
571		fi
572		;;
573	esac
574
575	return 1
576}
577
578# ipv6_autoconfif if
579#	Returns 0 if the interface should be configured for IPv6 with
580#	Stateless Address Configuration; 1 otherwise.
581ipv6_autoconfif()
582{
583	local _if _tmpargs _arg
584	_if=$1
585
586	case $_if in
587	lo[0-9]*|\
588	stf[0-9]*|\
589	lp[0-9]*|\
590	sl[0-9]*)
591		return 1
592		;;
593	esac
594	if noafif $_if; then
595		return 1
596	fi
597	if ! ipv6if $_if; then
598		return 1
599	fi
600	if checkyesno ipv6_gateway_enable; then
601		return 1
602	fi
603	_tmpargs=`get_if_var $_if ipv6_prefix_IF`
604	if [ -n "${_tmpargs}" ]; then
605		return 1
606	fi
607	# backward compatibility: $ipv6_enable
608	case $ipv6_enable in
609	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
610		if checkyesno ipv6_gateway_enable; then
611			return 1
612		fi
613		case $1 in
614		bridge[0-9]*)
615			# No accept_rtadv by default on if_bridge(4)
616			# to avoid a conflict with the member
617			# interfaces.
618			return 1
619		;;
620		*)
621			return 0
622		;;
623		esac
624	;;
625	esac
626
627	_tmpargs=`_ifconfig_getargs $_if ipv6`
628	for _arg in $_tmpargs; do
629		case $_arg in
630		accept_rtadv)
631			return 0
632			;;
633		esac
634	done
635
636	# backward compatibility: $ipv6_ifconfig_IF
637	_tmpargs=`get_if_var $_if ipv6_ifconfig_IF`
638	for _arg in $_tmpargs; do
639		case $_arg in
640		accept_rtadv)
641			return 0
642			;;
643		esac
644	done
645
646	return 1
647}
648
649# ifexists if
650#	Returns 0 if the interface exists and 1 otherwise.
651ifexists()
652{
653	[ -z "$1" ] && return 1
654	${IFCONFIG_CMD} -n $1 > /dev/null 2>&1
655}
656
657# ipv4_up if
658#	add IPv4 addresses to the interface $if
659ipv4_up()
660{
661	local _if _ret
662	_if=$1
663	_ret=1
664
665	# Add 127.0.0.1/8 to lo0 unless otherwise specified.
666	if [ "${_if}" = "lo0" ]; then
667		ifconfig_args=`get_if_var ${_if} ifconfig_IF`
668		if [ -z "${ifconfig_args}" ]; then
669			${IFCONFIG_CMD} ${_if} inet 127.0.0.1/8 alias
670		fi
671	fi
672	ifalias ${_if} inet alias && _ret=0
673
674	return $_ret
675}
676
677# ipv6_up if
678#	add IPv6 addresses to the interface $if
679ipv6_up()
680{
681	local _if _ret
682	_if=$1
683	_ret=1
684
685	if ! ipv6if $_if; then
686		return 0
687	fi
688
689	ifalias ${_if} inet6 alias && _ret=0
690	ipv6_prefix_hostid_addr_common ${_if} alias && _ret=0
691	ipv6_accept_rtadv_up ${_if} && _ret=0
692
693	return $_ret
694}
695
696# ipv4_down if
697#	remove IPv4 addresses from the interface $if
698ipv4_down()
699{
700	local _if _ifs _ret inetList oldifs _inet
701	_if=$1
702	_ifs="^"
703	_ret=1
704
705	ifalias ${_if} inet -alias && _ret=0
706
707	inetList="`${IFCONFIG_CMD} ${_if} | grep 'inet ' | tr "\n\t" "$_ifs"`"
708
709	oldifs="$IFS"
710	IFS="$_ifs"
711	for _inet in $inetList ; do
712		# get rid of extraneous line
713		case $_inet in
714		inet\ *)	;;
715		*)		continue ;;
716		esac
717
718		_inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'`
719
720		IFS="$oldifs"
721		${IFCONFIG_CMD} ${_if} ${_inet} delete
722		IFS="$_ifs"
723		_ret=0
724	done
725	IFS="$oldifs"
726
727	return $_ret
728}
729
730# ipv6_down if
731#	remove IPv6 addresses from the interface $if
732ipv6_down()
733{
734	local _if _ifs _ret inetList oldifs _inet6
735	_if=$1
736	_ifs="^"
737	_ret=1
738
739	if ! ipv6if $_if; then
740		return 0
741	fi
742
743	ipv6_accept_rtadv_down ${_if} && _ret=0
744	ipv6_prefix_hostid_addr_common ${_if} -alias && _ret=0
745	ifalias ${_if} inet6 -alias && _ret=0
746
747	inetList="`${IFCONFIG_CMD} ${_if} | grep 'inet6 ' | tr "\n\t" "$_ifs"`"
748
749	oldifs="$IFS"
750	IFS="$_ifs"
751	for _inet6 in $inetList ; do
752		# get rid of extraneous line
753		case $_inet6 in
754		inet6\ *)	;;
755		*)		continue ;;
756		esac
757
758		_inet6=`expr "$_inet6" : '.*\(inet6 \([0-9a-f:]*\)\).*'`
759
760		IFS="$oldifs"
761		${IFCONFIG_CMD} ${_if} ${_inet6} -alias
762		IFS="$_ifs"
763		_ret=0
764	done
765	IFS="$oldifs"
766
767	return $_ret
768}
769
770# ifalias if af action
771#	Configure or remove aliases for network interface $if.
772#	It returns 0 if at least one alias was configured or
773#	removed, or 1 if there were none.
774#
775ifalias()
776{
777	local _ret
778	_ret=1
779
780	afexists $2 || return $_ret
781
782	case "$2" in
783	inet|inet6|link|ether)
784		ifalias_af_common $1 $2 $3 && _ret=0
785		;;
786	esac
787
788	return $_ret
789}
790
791# ifalias_expand_addr af action addr
792#	Expand address range ("N-M") specification in addr.
793#	"addr" must not include an address-family keyword.
794#	The results will include an address-family keyword.
795#
796ifalias_expand_addr()
797{
798	local _af _action
799
800	_af=$1
801	_action=$2
802	shift 2
803
804	afexists $_af || return
805	ifalias_expand_addr_$_af $_action $*
806}
807
808# ifalias_expand_addr_inet action addr
809#	Helper function for ifalias_expand_addr().  Handles IPv4.
810#
811ifalias_expand_addr_inet()
812{
813	local _action _arg _cidr _cidr_addr _exargs
814	local _ipaddr _plen _range _iphead _iptail _iplow _iphigh _ipcount
815	local _retstr _c
816	_action=$1
817	_arg=$2
818	shift 2
819	_exargs=$*
820	_retstr=
821
822	case $_action:$_arg:$_exargs in
823	*:*--*)		return ;;	# invalid
824	tmp:*[0-9]-[0-9]*:*)		# to be expanded
825		_action="alias"
826	;;
827	*:*[0-9]-[0-9]*:*)		# to be expanded
828	;;
829	tmp:*:*netmask*)		# already expanded w/ netmask option
830		echo ${_arg%/[0-9]*} $_exargs && return
831	;;
832	tmp:*:*)			# already expanded w/o netmask option
833		echo $_arg $_exargs && return
834	;;
835	*:*:*netmask*)			# already expanded w/ netmask option
836		echo inet ${_arg%/[0-9]*} $_exargs && return
837	;;
838	*:*:*)				# already expanded w/o netmask option
839		echo inet $_arg $_exargs && return
840	;;
841	esac
842
843	for _cidr in $_arg; do
844		_ipaddr=${_cidr%%/*}
845		_plen=${_cidr##*/}
846		# When subnet prefix length is not specified, use /32.
847		case $_plen in
848		$_ipaddr)	_plen=32 ;;	# "/" character not found
849		esac
850
851		OIFS=$IFS
852		IFS=. set -- $_ipaddr
853		_range=
854		_iphead=
855		_iptail=
856		for _c in $@; do
857			case $_range:$_c in
858			:[0-9]*-[0-9]*)
859				_range=$_c
860			;;
861			:*)
862				_iphead="${_iphead}${_iphead:+.}${_c}"
863			;;
864			*:*)
865				_iptail="${_iptail}${_iptail:+.}${_c}"
866			;;
867			esac
868		done
869		IFS=$OIFS
870		_iplow=${_range%-*}
871		_iphigh=${_range#*-}
872
873		# clear netmask when removing aliases
874		if [ "$_action" = "-alias" ]; then
875			_plen=""
876		fi
877
878		_ipcount=$_iplow
879		while [ "$_ipcount" -le "$_iphigh" ]; do
880			_retstr="${_retstr} ${_iphead}${_iphead:+.}${_ipcount}${_iptail:+.}${_iptail}${_plen:+/}${_plen}"
881			if [ $_ipcount -gt $(($_iplow + $netif_ipexpand_max)) ]; then
882				warn "Range specification is too large (${_iphead}${_iphead:+.}${_iplow}${_iptail:+.}${_iptail}-${_iphead}${_iphead:+.}${_iphigh}${_iptail:+.}${_iptail}).  ${_iphead}${_iphead:+.}${_iplow}${_iptail:+.}${_iptail}-${_iphead}${_iphead:+.}${_ipcount}${_iptail:+.}${_iptail} was processed.  Increase \$netif_ipexpand_max in rc.conf."
883				break
884			else
885				_ipcount=$(($_ipcount + 1))
886			fi
887			# Forcibly set /32 for remaining aliases.
888			_plen=32
889		done
890	done
891
892	for _c in $_retstr; do
893		ifalias_expand_addr_inet $_action $_c $_exargs
894	done
895}
896
897# ifalias_expand_addr_inet6 action addr
898#	Helper function for ifalias_expand_addr().  Handles IPv6.
899#
900ifalias_expand_addr_inet6()
901{
902	local _action _arg _cidr _cidr_addr _exargs
903	local _ipaddr _plen _ipleft _ipright _iplow _iphigh _ipcount
904	local _ipv4part
905	local _retstr _c
906	_action=$1
907	_arg=$2
908	shift 2
909	_exargs=$*
910	_retstr=
911
912	case $_action:$_arg:$_exargs in
913	*:*--*:*)	return ;;	# invalid
914	tmp:*[0-9a-zA-Z]-[0-9a-zA-Z]*:*)# to be expanded
915		_action="alias"
916	;;
917	*:*[0-9a-zA-Z]-[0-9a-zA-Z]*:*)	# to be expanded
918	;;
919	tmp:*:*prefixlen*)	# already expanded w/ prefixlen option
920		echo ${_arg%/[0-9]*} $_exargs && return
921	;;
922	tmp:*:*)		# already expanded w/o prefixlen option
923		echo $_arg $_exargs && return
924	;;
925	*:*:*prefixlen*)	# already expanded w/ prefixlen option
926		echo inet6 ${_arg%/[0-9]*} $_exargs && return
927	;;
928	*:*:*)			# already expanded w/o prefixlen option
929		echo inet6 $_arg $_exargs && return
930	;;
931	esac
932
933	for _cidr in $_arg; do
934		_ipaddr="${_cidr%%/*}"
935		_plen="${_cidr##*/}"
936
937		case $_action:$_ipaddr:$_cidr in
938		-alias:*:*)		unset _plen ;;
939		*:$_cidr:$_ipaddr)	unset _plen ;;
940		esac
941
942		if [ "${_ipaddr%:*.*.*.*}" = "$_ipaddr" ]; then
943			# Handle !v4mapped && !v4compat addresses.
944
945			# The default prefix length is 64.
946			case $_ipaddr:$_cidr in
947			$_cidr:$_ipaddr)	_plen="64" ;;
948			esac
949			_ipleft=${_ipaddr%-*}
950			_ipright=${_ipaddr#*-}
951			_iplow=${_ipleft##*:}
952			_iphigh=${_ipright%%:*}
953			_ipleft=${_ipleft%:*}
954			_ipright=${_ipright#*:}
955
956			if [ "$_iphigh" = "$_ipright" ]; then
957				unset _ipright
958			else
959				_ipright=:$_ipright
960			fi
961
962			if [ -n "$_iplow" -a -n "$_iphigh" ]; then
963				_iplow=$((0x$_iplow))
964				_iphigh=$((0x$_iphigh))
965				_ipcount=$_iplow
966				while [ $_ipcount -le $_iphigh ]; do
967					_r=`printf "%s:%04x%s%s" \
968					    $_ipleft $_ipcount $_ipright \
969					    ${_plen:+/}$_plen`
970					_retstr="$_retstr $_r"
971					if [ $_ipcount -gt $(($_iplow + $netif_ipexpand_max)) ]
972					then
973						warn "Range specification is too large $(printf '(%s:%x%s-%s:%x%s)' "$_ipleft" "$_iplow" "$_ipright" "$_ipleft" "$_iphigh" "$_ipright"). $(printf '%s:%x%s-%s:%x%s' "$_ipleft" "$_iplow" "$_ipright" "$_ipleft" "$_ipcount" "$_ipright") was processed.  Increase \$netif_ipexpand_max in rc.conf."
974						break
975					else
976						_ipcount=$(($_ipcount + 1))
977					fi
978				done
979			else
980				_retstr="${_ipaddr}${_plen:+/}${_plen}"
981			fi
982
983			for _c in $_retstr; do
984				ifalias_expand_addr_inet6 $_action $_c $_exargs
985			done
986		else
987			# v4mapped/v4compat should handle as an IPv4 alias
988			_ipv4part=${_ipaddr##*:}
989
990			# Adjust prefix length if any.  If not, set the
991			# default prefix length as 32.
992			case $_ipaddr:$_cidr in
993			$_cidr:$_ipaddr)	_plen=32 ;;
994			*)			_plen=$(($_plen - 96)) ;;
995			esac
996
997			_retstr=`ifalias_expand_addr_inet \
998			    tmp ${_ipv4part}${_plen:+/}${_plen}`
999			for _c in $_retstr; do
1000				ifalias_expand_addr_inet $_action $_c $_exargs
1001			done
1002		fi
1003	done
1004}
1005
1006# ifalias_af_common_handler if af action args
1007#	Helper function for ifalias_af_common().
1008#
1009ifalias_af_common_handler()
1010{
1011	local _ret _if _af _action _args _c _tmpargs
1012
1013	_ret=1
1014	_if=$1
1015	_af=$2
1016	_action=$3
1017	shift 3
1018	_args=$*
1019
1020	case $_args in
1021	${_af}\ *)	;;
1022	*)	return	;;
1023	esac
1024
1025	# link(ether) does not support address removal.
1026	case $_af:$_action in
1027	link:-alias|ether:-alias)	return ;;
1028	esac
1029
1030	_tmpargs=
1031	for _c in $_args; do
1032		case $_c in
1033		${_af})
1034			case $_tmpargs in
1035			${_af}\ *[0-9a-fA-F]-*)
1036				ifalias_af_common_handler $_if $_af $_action \
1037				`ifalias_expand_addr $_af $_action ${_tmpargs#${_af}\ }`
1038			;;
1039			${_af}\ *)
1040				${IFCONFIG_CMD} $_if $_tmpargs $_action && _ret=0
1041			;;
1042			esac
1043			_tmpargs=$_af
1044		;;
1045		*)
1046			_tmpargs="$_tmpargs $_c"
1047		;;
1048		esac
1049	done
1050	# Process the last component if any.
1051	if [ -n "$_tmpargs}" ]; then
1052		case $_tmpargs in
1053		${_af}\ *[0-9a-fA-F]-*)
1054			ifalias_af_common_handler $_if $_af $_action \
1055			`ifalias_expand_addr $_af $_action ${_tmpargs#${_af}\ }`
1056		;;
1057		${_af}\ *)
1058			${IFCONFIG_CMD} $_if $_tmpargs $_action && _ret=0
1059		;;
1060		esac
1061	fi
1062
1063	return $_ret
1064}
1065
1066# ifalias_af_common if af action
1067#	Helper function for ifalias().
1068#
1069ifalias_af_common()
1070{
1071	local _ret _if _af _action alias ifconfig_args _aliasn _c _tmpargs _iaf
1072	local _vif _punct=".-/+"
1073
1074	_ret=1
1075	_aliasn=
1076	_if=$1
1077	_af=$2
1078	_action=$3
1079
1080	# Normalize $_if before using it in a pattern to list_vars()
1081	ltr "$_if" "$_punct" "_" _vif
1082
1083	# ifconfig_IF_aliasN which starts with $_af
1084	for alias in `list_vars ifconfig_${_vif}_alias[0-9]\* |
1085		sort_lite -nk1.$((9+${#_vif}+7))`
1086	do
1087		eval ifconfig_args=\"\$$alias\"
1088		_iaf=
1089		case $ifconfig_args in
1090		inet\ *)	_iaf=inet ;;
1091		inet6\ *)	_iaf=inet6 ;;
1092		link\ *)	_iaf=link ;;
1093		ether\ *)	_iaf=ether ;;
1094		esac
1095
1096		case ${_af}:${_action}:${_iaf}:"${ifconfig_args}" in
1097		${_af}:*:${_af}:*)
1098			_aliasn="$_aliasn $ifconfig_args"
1099			;;
1100		${_af}:*:"":"")
1101			break
1102			;;
1103		inet:alias:"":*)
1104			_aliasn="$_aliasn inet $ifconfig_args"
1105			warn "\$${alias} needs leading" \
1106			    "\"inet\" keyword for an IPv4 address."
1107		esac
1108	done
1109
1110	# backward compatibility: ipv6_ifconfig_IF_aliasN.
1111	case $_af in
1112	inet6)
1113		for alias in `list_vars ipv6_ifconfig_${_vif}_alias[0-9]\* |
1114			sort_lite -nk1.$((14+${#_vif}+7))`
1115		do
1116			eval ifconfig_args=\"\$$alias\"
1117			case ${_action}:"${ifconfig_args}" in
1118			*:"")
1119				break
1120			;;
1121			alias:*)
1122				_aliasn="${_aliasn} inet6 ${ifconfig_args}"
1123				warn "\$${alias} is obsolete. " \
1124				    "Use ifconfig_${_vif}_aliasN instead."
1125			;;
1126			esac
1127		done
1128	esac
1129
1130	# backward compatibility: ipv4_addrs_IF.
1131	for _tmpargs in `get_if_var $_if ipv4_addrs_IF`; do
1132		_aliasn="$_aliasn inet $_tmpargs"
1133	done
1134
1135	# Handle ifconfig_IF_aliases, ifconfig_IF_aliasN, and the others.
1136	_tmpargs=
1137	for _c in `get_if_var $_if ifconfig_IF_aliases` $_aliasn; do
1138		case $_c in
1139		inet|inet6|link|ether)
1140			case $_tmpargs in
1141			${_af}\ *)
1142				eval ifalias_af_common_handler $_if $_af $_action $_tmpargs && _ret=0
1143			;;
1144			esac
1145			_tmpargs=$_c
1146		;;
1147		*)
1148			_tmpargs="$_tmpargs $_c"
1149		esac
1150	done
1151	# Process the last component
1152	case $_tmpargs in
1153	${_af}\ *)
1154		ifalias_af_common_handler $_if $_af $_action $_tmpargs && _ret=0
1155	;;
1156	esac
1157
1158	return $_ret
1159}
1160
1161# ipv6_prefix_hostid_addr_common if action
1162#	Add or remove IPv6 prefix + hostid addr on the interface $if
1163#
1164ipv6_prefix_hostid_addr_common()
1165{
1166	local _if _action prefix j
1167	_if=$1
1168	_action=$2
1169	prefix=`get_if_var ${_if} ipv6_prefix_IF`
1170
1171	if [ -n "${prefix}" ]; then
1172		for j in ${prefix}; do
1173			# The default prefixlen is 64.
1174			plen=${j#*/}
1175			case $j:$plen in
1176			$plen:$j)	plen=64 ;;
1177			*)		j=${j%/*} ;;
1178			esac
1179
1180			# Normalize the last part by removing ":"
1181			j=${j%::*}
1182			j=${j%:}
1183			${IFCONFIG_CMD} ${_if} inet6 $j:: \
1184				prefixlen $plen eui64 ${_action}
1185
1186			# if I am a router, add subnet router
1187			# anycast address (RFC 2373).
1188			if checkyesno ipv6_gateway_enable; then
1189				${IFCONFIG_CMD} ${_if} inet6 $j:: \
1190					prefixlen $plen ${_action} anycast
1191			fi
1192		done
1193	fi
1194}
1195
1196# ipv6_accept_rtadv_up if
1197#	Enable accepting Router Advertisement and send Router
1198#	Solicitation message
1199ipv6_accept_rtadv_up()
1200{
1201	if ipv6_autoconfif $1; then
1202		${IFCONFIG_CMD} $1 inet6 accept_rtadv up
1203		if ! checkyesno rtsold_enable; then
1204			rtsol ${rtsol_flags} $1
1205		fi
1206	fi
1207}
1208
1209# ipv6_accept_rtadv_down if
1210#	Disable accepting Router Advertisement
1211ipv6_accept_rtadv_down()
1212{
1213	if ipv6_autoconfif $1; then
1214		${IFCONFIG_CMD} $1 inet6 -accept_rtadv
1215	fi
1216}
1217
1218# ifscript_up if
1219#	Evaluate a startup script for the $if interface.
1220#	It returns 0 if a script was found and processed or
1221#	1 if no script was found.
1222#
1223ifscript_up()
1224{
1225	if [ -r /etc/start_if.$1 ]; then
1226		. /etc/start_if.$1
1227		return 0
1228	else
1229		return 1
1230	fi
1231}
1232
1233# ifscript_down if
1234#	Evaluate a shutdown script for the $if interface.
1235#	It returns 0 if a script was found and processed or
1236#	1 if no script was found.
1237#
1238ifscript_down()
1239{
1240	if [ -r /etc/stop_if.$1 ]; then
1241		. /etc/stop_if.$1
1242		return 0
1243	else
1244		return 1
1245	fi
1246}
1247
1248# wlan_up
1249#	Create IEEE802.11 interfaces.
1250#
1251wlan_up()
1252{
1253	local _list _iflist parent child_wlans child create_args debug_flags
1254	_list=
1255	_iflist=$*
1256
1257	# Parse wlans_$parent="$child ..."
1258	for parent in `set | sed -nE 's/wlans_([a-z]+[0-9]+)=.*/\1/p'`; do
1259		child_wlans=`get_if_var $parent wlans_IF`
1260		for child in ${child_wlans}; do
1261			create_args="wlandev $parent `get_if_var $child create_args_IF`"
1262			debug_flags="`get_if_var $child wlandebug_IF`"
1263			case $_iflist in
1264			""|$child|$child\ *|*\ $child\ *|*\ $child)	;;
1265			*)	continue ;;
1266			esac
1267			# Skip if ${child} already exists.
1268			if ${IFCONFIG_CMD} $child > /dev/null 2>&1; then
1269				continue
1270			fi
1271			if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
1272				${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1273			else
1274				${IFCONFIG_CMD} wlan create ${create_args} name $child && cfg=0
1275			fi
1276			if [ $? -eq 0 ]; then
1277				_list="$_list $child"
1278			fi
1279			if [ -n "${debug_flags}" ]; then
1280				wlandebug -i $child ${debug_flags}
1281			fi
1282		done
1283	done
1284	if [ -n "${_list# }" ]; then
1285		echo "Created wlan(4) interfaces: ${_list# }."
1286	fi
1287	debug "Created wlan(4)s: ${_list# }"
1288}
1289
1290# wlan_down
1291#	Destroy IEEE802.11 interfaces.
1292#
1293wlan_down()
1294{
1295	local _list _iflist parent child_wlans child
1296	_list=
1297	_iflist=$*
1298
1299	# Parse wlans_$parent="$child ..."
1300	for parent in `set | sed -nE 's/wlans_([a-z]+[0-9]+)=.*/\1/p'`; do
1301		child_wlans=`get_if_var $parent wlans_IF`
1302		for child in ${child_wlans}; do
1303			case $_iflist in
1304			""|$child|$child\ *|*\ $child\ *|*\ $child)	;;
1305			*)	continue ;;
1306			esac
1307			# Skip if ${child} doesn't exists.
1308			if ! ${IFCONFIG_CMD} $child > /dev/null 2>&1; then
1309				continue
1310			fi
1311			${IFCONFIG_CMD} -n ${child} destroy
1312			if [ $? -eq 0 ]; then
1313				_list="$_list $child"
1314			fi
1315		done
1316	done
1317	if [ -n "${_list# }" ]; then
1318		echo "Destroyed wlan(4) interfaces: ${_list# }."
1319	fi
1320	debug "Destroyed wlan(4)s: ${_list# }"
1321}
1322
1323# clone_up
1324#	Create cloneable interfaces.
1325#
1326clone_up()
1327{
1328	local _list ifn ifopt _iflist _n tmpargs
1329	_list=
1330	_iflist=$*
1331
1332	# create_args_IF
1333	for ifn in ${cloned_interfaces}; do
1334		# Parse ifn:ifopt.
1335		OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1336		case $_iflist in
1337		""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn)	;;
1338		*)	continue ;;
1339		esac
1340		case $ifn in
1341		epair[0-9]*)
1342			# epair(4) uses epair[0-9] for creation and
1343			# epair[0-9][ab] for configuration.
1344			#
1345			# Skip if ${ifn}a or ${ifn}b already exist.
1346			if ${IFCONFIG_CMD} ${ifn}a > /dev/null 2>&1; then
1347				continue
1348			elif ${IFCONFIG_CMD} ${ifn}b > /dev/null 2>&1; then
1349				continue
1350			fi
1351			${IFCONFIG_CMD} ${ifn} create \
1352			    `get_if_var ${ifn} create_args_IF`
1353			if [ $? -eq 0 ]; then
1354				_list="$_list ${ifn}a ${ifn}b"
1355			fi
1356		;;
1357		*)
1358			# Skip if ${ifn} already exists.
1359			if ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1360				continue
1361			fi
1362			${IFCONFIG_CMD} ${ifn} create \
1363			    `get_if_var ${ifn} create_args_IF`
1364			if [ $? -eq 0 ]; then
1365				_list="$_list $ifn"
1366			fi
1367		esac
1368	done
1369	if [ -n "$gif_interfaces" ]; then
1370		warn "\$gif_interfaces is obsolete.  Use \$cloned_interfaces instead."
1371	fi
1372	for ifn in ${gif_interfaces}; do
1373		# Parse ifn:ifopt.
1374		OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1375		case $_iflist in
1376		""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn)	;;
1377		*)	continue ;;
1378		esac
1379		# Skip if ifn already exists.
1380		if ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1381			continue
1382		fi
1383		case $ifn in
1384		gif[0-9]*)
1385			${IFCONFIG_CMD} $ifn create
1386		;;
1387		*)
1388			_n=$(${IFCONFIG_CMD} gif create)
1389			${IFCONFIG_CMD} $_n name $ifn
1390		;;
1391		esac
1392		if [ $? -eq 0 ]; then
1393			_list="$_list $ifn"
1394		fi
1395		tmpargs=$(get_if_var $ifn gifconfig_IF)
1396		eval ifconfig_${ifn}=\"\$ifconfig_${ifn} tunnel \$tmpargs\"
1397	done
1398	if [ -n "${_list# }" ]; then
1399		echo "Created clone interfaces: ${_list# }."
1400	fi
1401	debug "Cloned: ${_list# }"
1402}
1403
1404# clone_down
1405#	Destroy cloned interfaces. Destroyed interfaces are echoed to
1406#	standard output.
1407#
1408clone_down()
1409{
1410	local _list ifn _difn ifopt _iflist _sticky
1411	_list=
1412	_iflist=$*
1413
1414	: ${cloned_interfaces_sticky:=NO}
1415	if checkyesno cloned_interfaces_sticky; then
1416		_sticky=1
1417	else
1418		_sticky=0
1419	fi
1420	for ifn in ${cloned_interfaces} ${gif_interfaces}; do
1421		# Parse ifn:ifopt.
1422		OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1423		case $ifopt:$_sticky in
1424		sticky:*)	continue ;;	# :sticky => not destroy
1425		nosticky:*)	;;		# :nosticky => destroy
1426		*:1)		continue ;;	# global sticky knob == 1
1427		esac
1428		case $_iflist in
1429		""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn)	;;
1430		*)	continue ;;
1431		esac
1432		case $ifn in
1433		epair[0-9]*)
1434			# Note: epair(4) uses epair[0-9] for removal and
1435			# epair[0-9][ab] for configuration.
1436			#
1437			# Skip if both of ${ifn}a and ${ifn}b do not exist.
1438			if ${IFCONFIG_CMD} ${ifn}a > /dev/null 2>&1; then
1439				_difn=${ifn}a
1440			elif ${IFCONFIG_CMD} ${ifn}b > /dev/null 2>&1; then
1441				_difn=${ifn}b
1442			else
1443				continue
1444			fi
1445			${IFCONFIG_CMD} -n $_difn destroy
1446			if [ $? -eq 0 ]; then
1447				_list="$_list ${ifn}a ${ifn}b"
1448			fi
1449		;;
1450		*)
1451			# Skip if ifn does not exist.
1452			if ! ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1453				continue
1454			fi
1455			${IFCONFIG_CMD} -n ${ifn} destroy
1456			if [ $? -eq 0 ]; then
1457				_list="$_list $ifn"
1458			fi
1459		;;
1460		esac
1461	done
1462	if [ -n "${_list# }" ]; then
1463		echo "Destroyed clone interfaces: ${_list# }."
1464	fi
1465	debug "Destroyed clones: ${_list# }"
1466}
1467
1468# childif_create
1469#	Create and configure child interfaces.  Return 0 if child
1470#	interfaces are created.
1471#
1472childif_create()
1473{
1474	local cfg child child_vlans create_args debug_flags ifn i
1475	cfg=1
1476	ifn=$1
1477
1478	# Create vlan interfaces
1479	child_vlans=`get_if_var $ifn vlans_IF`
1480
1481	if [ -n "${child_vlans}" ]; then
1482		load_kld if_vlan
1483	fi
1484
1485	for child in ${child_vlans}; do
1486		if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1487			child="${ifn}.${child}"
1488			create_args=`get_if_var $child create_args_IF`
1489			${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1490		else
1491			create_args="vlandev $ifn `get_if_var $child create_args_IF`"
1492			if expr $child : 'vlan[0-9][0-9]*$' >/dev/null 2>&1; then
1493				${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1494			else
1495				i=`${IFCONFIG_CMD} vlan create ${create_args}`
1496				${IFCONFIG_CMD} $i name $child && cfg=0
1497			fi
1498		fi
1499		if autoif $child; then
1500			ifn_start $child
1501		fi
1502	done
1503
1504	return ${cfg}
1505}
1506
1507# childif_destroy
1508#	Destroy child interfaces.
1509#
1510childif_destroy()
1511{
1512	local cfg child child_vlans ifn
1513	cfg=1
1514
1515	child_vlans=`get_if_var $ifn vlans_IF`
1516	for child in ${child_vlans}; do
1517		if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1518			child="${ifn}.${child}"
1519		fi
1520		if ! ifexists $child; then
1521			continue
1522		fi
1523		${IFCONFIG_CMD} -n $child destroy && cfg=0
1524	done
1525
1526	return ${cfg}
1527}
1528
1529# ng_mkpeer
1530#	Create netgraph nodes.
1531#
1532ng_mkpeer()
1533{
1534	ngctl -f - 2> /dev/null <<EOF
1535mkpeer $*
1536msg dummy nodeinfo
1537EOF
1538}
1539
1540# ng_create_one
1541#	Create netgraph nodes.
1542#
1543ng_create_one()
1544{
1545	local t
1546
1547	ng_mkpeer $* | while read line; do
1548		t=`expr "${line}" : '.* name="\([a-z]*[0-9]*\)" .*'`
1549		if [ -n "${t}" ]; then
1550			echo ${t}
1551			return
1552		fi
1553	done
1554}
1555
1556# ifnet_rename [ifname]
1557#	Rename interfaces if ifconfig_IF_name is defined.
1558#
1559ifnet_rename()
1560{
1561	local _if _ifname
1562
1563	# ifconfig_IF_name
1564	for _if in ${*:-$(${IFCONFIG_CMD} -l)}; do
1565		_ifname=`get_if_var $_if ifconfig_IF_name`
1566		if [ ! -z "$_ifname" ]; then
1567			${IFCONFIG_CMD} $_if name $_ifname
1568		fi
1569	done
1570
1571	return 0
1572}
1573
1574# list_net_interfaces type
1575#	List all network interfaces. The type of interface returned
1576#	can be controlled by the type argument. The type
1577#	argument can be any of the following:
1578#		nodhcp	- all interfaces, excluding DHCP configured interfaces
1579#		dhcp	- list only DHCP configured interfaces
1580#		noautoconf	- all interfaces, excluding IPv6 Stateless
1581#				  Address Autoconf configured interfaces
1582#		autoconf	- list only IPv6 Stateless Address Autoconf
1583#				  configured interfaces
1584#	If no argument is specified all network interfaces are output.
1585#	Note that the list will include cloned interfaces if applicable.
1586#	Cloned interfaces must already exist to have a chance to appear
1587#	in the list if ${network_interfaces} is set to `auto'.
1588#
1589list_net_interfaces()
1590{
1591	local type _tmplist _list _autolist _lo _if
1592	type=$1
1593
1594	# Get a list of ALL the interfaces and make lo0 first if it's there.
1595	#
1596	_tmplist=
1597	case ${network_interfaces} in
1598	[Aa][Uu][Tt][Oo])
1599		_autolist="`${IFCONFIG_CMD} -l`"
1600		_lo=
1601		for _if in ${_autolist} ; do
1602			if autoif $_if; then
1603				if [ "$_if" = "lo0" ]; then
1604					_lo="lo0 "
1605				else
1606					_tmplist="${_tmplist} ${_if}"
1607				fi
1608			fi
1609		done
1610		_tmplist="${_lo}${_tmplist# }"
1611	;;
1612	*)
1613		for _if in ${network_interfaces} ${cloned_interfaces}; do
1614			# epair(4) uses epair[0-9] for creation and
1615			# epair[0-9][ab] for configuration.
1616			case $_if in
1617			epair[0-9]*)
1618				_tmplist="$_tmplist ${_if}a ${_if}b"
1619			;;
1620			*)
1621				_tmplist="$_tmplist $_if"
1622			;;
1623			esac
1624		done
1625		#
1626		# lo0 is effectively mandatory, so help prevent foot-shooting
1627		#
1628		case "$_tmplist" in
1629		lo0|'lo0 '*|*' lo0'|*' lo0 '*)
1630			# This is fine, do nothing
1631			_tmplist="${_tmplist# }"
1632		;;
1633		*)
1634			_tmplist="lo0 ${_tmplist# }"
1635		;;
1636		esac
1637	;;
1638	esac
1639
1640	_list=
1641	case "$type" in
1642	nodhcp)
1643		for _if in ${_tmplist} ; do
1644			if ! dhcpif $_if && \
1645			   [ -n "`_ifconfig_getargs $_if`" ]; then
1646				_list="${_list# } ${_if}"
1647			fi
1648		done
1649	;;
1650	dhcp)
1651		for _if in ${_tmplist} ; do
1652			if dhcpif $_if; then
1653				_list="${_list# } ${_if}"
1654			fi
1655		done
1656	;;
1657	noautoconf)
1658		for _if in ${_tmplist} ; do
1659			if ! ipv6_autoconfif $_if && \
1660			   [ -n "`_ifconfig_getargs $_if ipv6`" ]; then
1661				_list="${_list# } ${_if}"
1662			fi
1663		done
1664	;;
1665	autoconf)
1666		for _if in ${_tmplist} ; do
1667			if ipv6_autoconfif $_if; then
1668				_list="${_list# } ${_if}"
1669			fi
1670		done
1671	;;
1672	*)
1673		_list=${_tmplist}
1674	;;
1675	esac
1676
1677	echo $_list
1678
1679	return 0
1680}
1681
1682# get_default_if -address_family
1683#	Get the interface of the default route for the given address family.
1684#	The -address_family argument must be suitable passing to route(8).
1685#
1686get_default_if()
1687{
1688	local routeget oldifs defif line
1689	defif=
1690	oldifs="$IFS"
1691	IFS="
1692"
1693	for line in `route -n get $1 default 2>/dev/null`; do
1694		case $line in
1695		*interface:*)
1696			defif=${line##*: }
1697			;;
1698		esac
1699	done
1700	IFS=${oldifs}
1701
1702	echo $defif
1703}
1704
1705# hexdigit arg
1706#	Echo decimal number $arg (single digit) in hexadecimal format.
1707hexdigit()
1708{
1709	printf '%x\n' "$1"
1710}
1711
1712# hexprint arg
1713#	Echo decimal number $arg (multiple digits) in hexadecimal format.
1714hexprint()
1715{
1716	printf '%x\n' "$1"
1717}
1718
1719is_wired_interface()
1720{
1721	local media
1722
1723	case `${IFCONFIG_CMD} $1 2>/dev/null` in
1724	*media:?Ethernet*) media=Ethernet ;;
1725	esac
1726
1727	test "$media" = "Ethernet"
1728}
1729
1730# network6_getladdr if [flag]
1731#	Echo link-local address from $if if any.
1732#	If flag is defined, tentative ones will be excluded.
1733network6_getladdr()
1734{
1735	local _if _flag proto addr rest
1736	_if=$1
1737	_flag=$2
1738
1739	${IFCONFIG_CMD} $_if 2>/dev/null | while read proto addr rest; do
1740		case "${proto}/${addr}/${_flag}/${rest}" in
1741		inet6/fe80::*//*)
1742			echo ${addr}
1743		;;
1744		inet6/fe80:://*tentative*)	# w/o flag
1745			sleep `${SYSCTL_N} net.inet6.ip6.dad_count`
1746			network6_getladdr $_if $_flags
1747		;;
1748		inet6/fe80::/*/*tentative*)	# w/ flag
1749			echo ${addr}
1750		;;
1751		*)
1752			continue
1753		;;
1754		esac
1755
1756		return
1757	done
1758}
1759