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