xref: /freebsd/libexec/rc/network.subr (revision d68cc5a8390f5316400181b77a195f734567abd3)
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		fi
138
139		# backward compatibility: $ipv6_enable
140		case $ipv6_enable in
141		[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
142			case $1 in
143			bridge[0-9]*)
144				# No accept_rtadv by default on if_bridge(4)
145				# to avoid a conflict with the member
146				# interfaces.
147			;;
148			*)
149				if ! checkyesno ipv6_gateway_enable; then
150					_ipv6_opts="${_ipv6_opts} accept_rtadv"
151				fi
152			;;
153			esac
154		;;
155		esac
156
157		case $ipv6_cpe_wanif in
158		$1)
159			_ipv6_opts="${_ipv6_opts} -no_radr accept_rtadv"
160		;;
161		esac
162
163		if [ -n "${_ipv6_opts}" ]; then
164			${IFCONFIG_CMD} $1 inet6 ${_ipv6_opts}
165		fi
166	fi
167
168	# ifconfig_IF
169	ifconfig_args=`ifconfig_getargs $1`
170	if [ -n "${ifconfig_args}" ]; then
171		eval ${IFCONFIG_CMD} $1 ${ifconfig_args}
172		_cfg=0
173	fi
174
175	# inet6 specific
176	if ! noafif $1 && afexists inet6; then
177		# ifconfig_IF_ipv6
178		ifconfig_args=`ifconfig_getargs $1 ipv6`
179		if [ -n "${ifconfig_args}" ]; then
180			# backward compatibility: inet6 keyword
181			case "${ifconfig_args}" in
182			:*|[0-9a-fA-F]*:*)
183				warn "\$ifconfig_$1_ipv6 needs leading" \
184				    "\"inet6\" keyword for an IPv6 address."
185				ifconfig_args="inet6 ${ifconfig_args}"
186			;;
187			esac
188			${IFCONFIG_CMD} $1 inet6 -ifdisabled
189			eval ${IFCONFIG_CMD} $1 ${ifconfig_args}
190			_cfg=0
191		fi
192
193		# $ipv6_prefix_IF will be handled in
194		# ipv6_prefix_hostid_addr_common().
195		ifconfig_args=`get_if_var $1 ipv6_prefix_IF`
196		if [ -n "${ifconfig_args}" ]; then
197			${IFCONFIG_CMD} $1 inet6 -ifdisabled
198			_cfg=0
199		fi
200
201		# backward compatibility: $ipv6_ifconfig_IF
202		ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF`
203		if [ -n "${ifconfig_args}" ]; then
204			warn "\$ipv6_ifconfig_$1 is obsolete." \
205			    "  Use ifconfig_$1_ipv6 instead."
206			${IFCONFIG_CMD} $1 inet6 -ifdisabled
207			eval ${IFCONFIG_CMD} $1 inet6 ${ifconfig_args}
208			_cfg=0
209		fi
210	fi
211
212	ifalias $1 link alias
213	ifalias $1 ether alias
214
215	_ifconfig_descr=`get_if_var $1 ifconfig_IF_descr`
216	if [ -n "${_ifconfig_descr}" ]; then
217		${IFCONFIG_CMD} $1 description "${_ifconfig_descr}"
218	fi
219
220	if wpaif $1; then
221		/etc/rc.d/wpa_supplicant start $1
222		_cfg=0		# XXX: not sure this should count
223	elif hostapif $1; then
224		/etc/rc.d/hostapd start $1
225		_cfg=0
226	elif [ ${_cfg} -eq 0 ]; then
227		${IFCONFIG_CMD} $1 up
228	fi
229
230	if ! noafif $1 && afexists inet6; then
231		ipv6_accept_rtadv_up $1 && _cfg=0
232	fi
233
234	if dhcpif $1; then
235		if [ $_cfg -ne 0 ] ; then
236			${IFCONFIG_CMD} $1 up
237		fi
238		if syncdhcpif $1; then
239			/etc/rc.d/dhclient start $1
240		fi
241		_cfg=0
242	fi
243
244	return $_cfg
245}
246
247# ifconfig_down if
248#	returns 1 if wpa_supplicant or dhclient was stopped or
249#	the interface exists.
250#
251ifconfig_down()
252{
253	local _cfg
254	_cfg=1
255
256	if wpaif $1; then
257		/etc/rc.d/wpa_supplicant stop $1
258		_cfg=0
259	elif hostapif $1; then
260		/etc/rc.d/hostapd stop $1
261		_cfg=0
262	elif 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
692	return $_ret
693}
694
695# ipv4_down if
696#	remove IPv4 addresses from the interface $if
697ipv4_down()
698{
699	local _if _ifs _ret inetList oldifs _inet
700	_if=$1
701	_ifs="^"
702	_ret=1
703
704	ifalias ${_if} inet -alias && _ret=0
705
706	inetList="`${IFCONFIG_CMD} ${_if} | grep 'inet ' | tr "\n\t" "$_ifs"`"
707
708	oldifs="$IFS"
709	IFS="$_ifs"
710	for _inet in $inetList ; do
711		# get rid of extraneous line
712		case $_inet in
713		inet\ *)	;;
714		*)		continue ;;
715		esac
716
717		_inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'`
718
719		IFS="$oldifs"
720		${IFCONFIG_CMD} ${_if} ${_inet} delete
721		IFS="$_ifs"
722		_ret=0
723	done
724	IFS="$oldifs"
725
726	return $_ret
727}
728
729# ipv6_down if
730#	remove IPv6 addresses from the interface $if
731ipv6_down()
732{
733	local _if _ifs _ret inetList oldifs _inet6
734	_if=$1
735	_ifs="^"
736	_ret=1
737
738	if ! ipv6if $_if; then
739		return 0
740	fi
741
742	ipv6_accept_rtadv_down ${_if} && _ret=0
743	ipv6_prefix_hostid_addr_common ${_if} -alias && _ret=0
744	ifalias ${_if} inet6 -alias && _ret=0
745
746	inetList="`${IFCONFIG_CMD} ${_if} | grep 'inet6 ' | tr "\n\t" "$_ifs"`"
747
748	oldifs="$IFS"
749	IFS="$_ifs"
750	for _inet6 in $inetList ; do
751		# get rid of extraneous line
752		case $_inet6 in
753		inet6\ *)	;;
754		*)		continue ;;
755		esac
756
757		_inet6=`expr "$_inet6" : '.*\(inet6 \([0-9a-f:]*\)\).*'`
758
759		IFS="$oldifs"
760		${IFCONFIG_CMD} ${_if} ${_inet6} -alias
761		IFS="$_ifs"
762		_ret=0
763	done
764	IFS="$oldifs"
765
766	return $_ret
767}
768
769# ifalias if af action
770#	Configure or remove aliases for network interface $if.
771#	It returns 0 if at least one alias was configured or
772#	removed, or 1 if there were none.
773#
774ifalias()
775{
776	local _ret
777	_ret=1
778
779	afexists $2 || return $_ret
780
781	case "$2" in
782	inet|inet6|link|ether)
783		ifalias_af_common $1 $2 $3 && _ret=0
784		;;
785	esac
786
787	return $_ret
788}
789
790# ifalias_expand_addr af action addr
791#	Expand address range ("N-M") specification in addr.
792#	"addr" must not include an address-family keyword.
793#	The results will include an address-family keyword.
794#
795ifalias_expand_addr()
796{
797	local _af _action
798
799	_af=$1
800	_action=$2
801	shift 2
802
803	afexists $_af || return
804	ifalias_expand_addr_$_af $_action $*
805}
806
807# ifalias_expand_addr_inet action addr
808#	Helper function for ifalias_expand_addr().  Handles IPv4.
809#
810ifalias_expand_addr_inet()
811{
812	local _action _arg _cidr _cidr_addr _exargs
813	local _ipaddr _plen _range _iphead _iptail _iplow _iphigh _ipcount
814	local _retstr _c
815	_action=$1
816	_arg=$2
817	shift 2
818	_exargs=$*
819	_retstr=
820
821	case $_action:$_arg:$_exargs in
822	*:*--*)		return ;;	# invalid
823	tmp:*[0-9]-[0-9]*:*)		# to be expanded
824		_action="alias"
825	;;
826	*:*[0-9]-[0-9]*:*)		# to be expanded
827	;;
828	tmp:*:*netmask*)		# already expanded w/ netmask option
829		echo ${_arg%/[0-9]*} $_exargs && return
830	;;
831	tmp:*:*)			# already expanded w/o netmask option
832		echo $_arg $_exargs && return
833	;;
834	*:*:*netmask*)			# already expanded w/ netmask option
835		echo inet ${_arg%/[0-9]*} $_exargs && return
836	;;
837	*:*:*)				# already expanded w/o netmask option
838		echo inet $_arg $_exargs && return
839	;;
840	esac
841
842	for _cidr in $_arg; do
843		_ipaddr=${_cidr%%/*}
844		_plen=${_cidr##*/}
845		# When subnet prefix length is not specified, use /32.
846		case $_plen in
847		$_ipaddr)	_plen=32 ;;	# "/" character not found
848		esac
849
850		OIFS=$IFS
851		IFS=. set -- $_ipaddr
852		_range=
853		_iphead=
854		_iptail=
855		for _c in $@; do
856			case $_range:$_c in
857			:[0-9]*-[0-9]*)
858				_range=$_c
859			;;
860			:*)
861				_iphead="${_iphead}${_iphead:+.}${_c}"
862			;;
863			*:*)
864				_iptail="${_iptail}${_iptail:+.}${_c}"
865			;;
866			esac
867		done
868		IFS=$OIFS
869		_iplow=${_range%-*}
870		_iphigh=${_range#*-}
871
872		# clear netmask when removing aliases
873		if [ "$_action" = "-alias" ]; then
874			_plen=""
875		fi
876
877		_ipcount=$_iplow
878		while [ "$_ipcount" -le "$_iphigh" ]; do
879			_retstr="${_retstr} ${_iphead}${_iphead:+.}${_ipcount}${_iptail:+.}${_iptail}${_plen:+/}${_plen}"
880			if [ $_ipcount -gt $(($_iplow + $netif_ipexpand_max)) ]; then
881				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."
882				break
883			else
884				_ipcount=$(($_ipcount + 1))
885			fi
886			# Forcibly set /32 for remaining aliases.
887			_plen=32
888		done
889	done
890
891	for _c in $_retstr; do
892		ifalias_expand_addr_inet $_action $_c $_exargs
893	done
894}
895
896# ifalias_expand_addr_inet6 action addr
897#	Helper function for ifalias_expand_addr().  Handles IPv6.
898#
899ifalias_expand_addr_inet6()
900{
901	local _action _arg _cidr _cidr_addr _exargs
902	local _ipaddr _plen _ipleft _ipright _iplow _iphigh _ipcount
903	local _ipv4part
904	local _retstr _c
905	_action=$1
906	_arg=$2
907	shift 2
908	_exargs=$*
909	_retstr=
910
911	case $_action:$_arg:$_exargs in
912	*:*--*:*)	return ;;	# invalid
913	tmp:*[0-9a-zA-Z]-[0-9a-zA-Z]*:*)# to be expanded
914		_action="alias"
915	;;
916	*:*[0-9a-zA-Z]-[0-9a-zA-Z]*:*)	# to be expanded
917	;;
918	tmp:*:*prefixlen*)	# already expanded w/ prefixlen option
919		echo ${_arg%/[0-9]*} $_exargs && return
920	;;
921	tmp:*:*)		# already expanded w/o prefixlen option
922		echo $_arg $_exargs && return
923	;;
924	*:*:*prefixlen*)	# already expanded w/ prefixlen option
925		echo inet6 ${_arg%/[0-9]*} $_exargs && return
926	;;
927	*:*:*)			# already expanded w/o prefixlen option
928		echo inet6 $_arg $_exargs && return
929	;;
930	esac
931
932	for _cidr in $_arg; do
933		_ipaddr="${_cidr%%/*}"
934		_plen="${_cidr##*/}"
935
936		case $_action:$_ipaddr:$_cidr in
937		-alias:*:*)		unset _plen ;;
938		*:$_cidr:$_ipaddr)	unset _plen ;;
939		esac
940
941		if [ "${_ipaddr%:*.*.*.*}" = "$_ipaddr" ]; then
942			# Handle !v4mapped && !v4compat addresses.
943
944			# The default prefix length is 64.
945			case $_ipaddr:$_cidr in
946			$_cidr:$_ipaddr)	_plen="64" ;;
947			esac
948			_ipleft=${_ipaddr%-*}
949			_ipright=${_ipaddr#*-}
950			_iplow=${_ipleft##*:}
951			_iphigh=${_ipright%%:*}
952			_ipleft=${_ipleft%:*}
953			_ipright=${_ipright#*:}
954
955			if [ "$_iphigh" = "$_ipright" ]; then
956				unset _ipright
957			else
958				_ipright=:$_ipright
959			fi
960
961			if [ -n "$_iplow" -a -n "$_iphigh" ]; then
962				_iplow=$((0x$_iplow))
963				_iphigh=$((0x$_iphigh))
964				_ipcount=$_iplow
965				while [ $_ipcount -le $_iphigh ]; do
966					_r=`printf "%s:%04x%s%s" \
967					    $_ipleft $_ipcount $_ipright \
968					    ${_plen:+/}$_plen`
969					_retstr="$_retstr $_r"
970					if [ $_ipcount -gt $(($_iplow + $netif_ipexpand_max)) ]
971					then
972						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."
973						break
974					else
975						_ipcount=$(($_ipcount + 1))
976					fi
977				done
978			else
979				_retstr="${_ipaddr}${_plen:+/}${_plen}"
980			fi
981
982			for _c in $_retstr; do
983				ifalias_expand_addr_inet6 $_action $_c $_exargs
984			done
985		else
986			# v4mapped/v4compat should handle as an IPv4 alias
987			_ipv4part=${_ipaddr##*:}
988
989			# Adjust prefix length if any.  If not, set the
990			# default prefix length as 32.
991			case $_ipaddr:$_cidr in
992			$_cidr:$_ipaddr)	_plen=32 ;;
993			*)			_plen=$(($_plen - 96)) ;;
994			esac
995
996			_retstr=`ifalias_expand_addr_inet \
997			    tmp ${_ipv4part}${_plen:+/}${_plen}`
998			for _c in $_retstr; do
999				ifalias_expand_addr_inet $_action $_c $_exargs
1000			done
1001		fi
1002	done
1003}
1004
1005# ifalias_af_common_handler if af action args
1006#	Helper function for ifalias_af_common().
1007#
1008ifalias_af_common_handler()
1009{
1010	local _ret _if _af _action _args _c _tmpargs
1011
1012	_ret=1
1013	_if=$1
1014	_af=$2
1015	_action=$3
1016	shift 3
1017	_args=$*
1018
1019	case $_args in
1020	${_af}\ *)	;;
1021	*)	return	;;
1022	esac
1023
1024	# link(ether) does not support address removal.
1025	case $_af:$_action in
1026	link:-alias|ether:-alias)	return ;;
1027	esac
1028
1029	_tmpargs=
1030	for _c in $_args; do
1031		case $_c in
1032		${_af})
1033			case $_tmpargs in
1034			${_af}\ *[0-9a-fA-F]-*)
1035				ifalias_af_common_handler $_if $_af $_action \
1036				`ifalias_expand_addr $_af $_action ${_tmpargs#${_af}\ }`
1037			;;
1038			${_af}\ *)
1039				${IFCONFIG_CMD} $_if $_tmpargs $_action && _ret=0
1040			;;
1041			esac
1042			_tmpargs=$_af
1043		;;
1044		*)
1045			_tmpargs="$_tmpargs $_c"
1046		;;
1047		esac
1048	done
1049	# Process the last component if any.
1050	if [ -n "$_tmpargs}" ]; then
1051		case $_tmpargs in
1052		${_af}\ *[0-9a-fA-F]-*)
1053			ifalias_af_common_handler $_if $_af $_action \
1054			`ifalias_expand_addr $_af $_action ${_tmpargs#${_af}\ }`
1055		;;
1056		${_af}\ *)
1057			${IFCONFIG_CMD} $_if $_tmpargs $_action && _ret=0
1058		;;
1059		esac
1060	fi
1061
1062	return $_ret
1063}
1064
1065# ifalias_af_common if af action
1066#	Helper function for ifalias().
1067#
1068ifalias_af_common()
1069{
1070	local _ret _if _af _action alias ifconfig_args _aliasn _c _tmpargs _iaf
1071	local _vif _punct=".-/+"
1072
1073	_ret=1
1074	_aliasn=
1075	_if=$1
1076	_af=$2
1077	_action=$3
1078
1079	# Normalize $_if before using it in a pattern to list_vars()
1080	ltr "$_if" "$_punct" "_" _vif
1081
1082	# ifconfig_IF_aliasN which starts with $_af
1083	for alias in `list_vars ifconfig_${_vif}_alias[0-9]\* |
1084		sort_lite -nk1.$((9+${#_vif}+7))`
1085	do
1086		eval ifconfig_args=\"\$$alias\"
1087		_iaf=
1088		case $ifconfig_args in
1089		inet\ *)	_iaf=inet ;;
1090		inet6\ *)	_iaf=inet6 ;;
1091		link\ *)	_iaf=link ;;
1092		ether\ *)	_iaf=ether ;;
1093		esac
1094
1095		case ${_af}:${_action}:${_iaf}:"${ifconfig_args}" in
1096		${_af}:*:${_af}:*)
1097			_aliasn="$_aliasn $ifconfig_args"
1098			;;
1099		${_af}:*:"":"")
1100			break
1101			;;
1102		inet:alias:"":*)
1103			_aliasn="$_aliasn inet $ifconfig_args"
1104			warn "\$${alias} needs leading" \
1105			    "\"inet\" keyword for an IPv4 address."
1106		esac
1107	done
1108
1109	# backward compatibility: ipv6_ifconfig_IF_aliasN.
1110	case $_af in
1111	inet6)
1112		for alias in `list_vars ipv6_ifconfig_${_vif}_alias[0-9]\* |
1113			sort_lite -nk1.$((14+${#_vif}+7))`
1114		do
1115			eval ifconfig_args=\"\$$alias\"
1116			case ${_action}:"${ifconfig_args}" in
1117			*:"")
1118				break
1119			;;
1120			alias:*)
1121				_aliasn="${_aliasn} inet6 ${ifconfig_args}"
1122				warn "\$${alias} is obsolete. " \
1123				    "Use ifconfig_${_vif}_aliasN instead."
1124			;;
1125			esac
1126		done
1127	esac
1128
1129	# backward compatibility: ipv4_addrs_IF.
1130	for _tmpargs in `get_if_var $_if ipv4_addrs_IF`; do
1131		_aliasn="$_aliasn inet $_tmpargs"
1132	done
1133
1134	# Handle ifconfig_IF_aliases, ifconfig_IF_aliasN, and the others.
1135	_tmpargs=
1136	for _c in `get_if_var $_if ifconfig_IF_aliases` $_aliasn; do
1137		case $_c in
1138		inet|inet6|link|ether)
1139			case $_tmpargs in
1140			${_af}\ *)
1141				eval ifalias_af_common_handler $_if $_af $_action $_tmpargs && _ret=0
1142			;;
1143			esac
1144			_tmpargs=$_c
1145		;;
1146		*)
1147			_tmpargs="$_tmpargs $_c"
1148		esac
1149	done
1150	# Process the last component
1151	case $_tmpargs in
1152	${_af}\ *)
1153		ifalias_af_common_handler $_if $_af $_action $_tmpargs && _ret=0
1154	;;
1155	esac
1156
1157	return $_ret
1158}
1159
1160# ipv6_prefix_hostid_addr_common if action
1161#	Add or remove IPv6 prefix + hostid addr on the interface $if
1162#
1163ipv6_prefix_hostid_addr_common()
1164{
1165	local _if _action prefix j
1166	_if=$1
1167	_action=$2
1168	prefix=`get_if_var ${_if} ipv6_prefix_IF`
1169
1170	if [ -n "${prefix}" ]; then
1171		for j in ${prefix}; do
1172			# The default prefixlen is 64.
1173			plen=${j#*/}
1174			case $j:$plen in
1175			$plen:$j)	plen=64 ;;
1176			*)		j=${j%/*} ;;
1177			esac
1178
1179			# Normalize the last part by removing ":"
1180			j=${j%::*}
1181			j=${j%:}
1182			${IFCONFIG_CMD} ${_if} inet6 $j:: \
1183				prefixlen $plen eui64 ${_action}
1184
1185			# if I am a router, add subnet router
1186			# anycast address (RFC 2373).
1187			if checkyesno ipv6_gateway_enable; then
1188				${IFCONFIG_CMD} ${_if} inet6 $j:: \
1189					prefixlen $plen ${_action} anycast
1190			fi
1191		done
1192	fi
1193}
1194
1195# ipv6_accept_rtadv_up if
1196#	Enable accepting Router Advertisement and send Router
1197#	Solicitation message
1198ipv6_accept_rtadv_up()
1199{
1200	if ipv6_autoconfif $1; then
1201		${IFCONFIG_CMD} $1 inet6 accept_rtadv up
1202		if [ -x /sbin/rtsol ]; then
1203			/sbin/rtsol ${rtsol_flags} $1
1204		fi
1205		return 0
1206	fi
1207	return 1
1208}
1209
1210# ipv6_accept_rtadv_down if
1211#	Disable accepting Router Advertisement
1212ipv6_accept_rtadv_down()
1213{
1214	if ipv6_autoconfif $1; then
1215		${IFCONFIG_CMD} $1 inet6 -accept_rtadv
1216	fi
1217}
1218
1219# ifscript_up if
1220#	Evaluate a startup script for the $if interface.
1221#	It returns 0 if a script was found and processed or
1222#	1 if no script was found.
1223#
1224ifscript_up()
1225{
1226	if [ -r /etc/start_if.$1 ]; then
1227		. /etc/start_if.$1
1228		return 0
1229	else
1230		return 1
1231	fi
1232}
1233
1234# ifscript_down if
1235#	Evaluate a shutdown script for the $if interface.
1236#	It returns 0 if a script was found and processed or
1237#	1 if no script was found.
1238#
1239ifscript_down()
1240{
1241	if [ -r /etc/stop_if.$1 ]; then
1242		. /etc/stop_if.$1
1243		return 0
1244	else
1245		return 1
1246	fi
1247}
1248
1249# wlan_up
1250#	Create IEEE802.11 interfaces.
1251#
1252wlan_up()
1253{
1254	local _list _iflist parent child_wlans child create_args debug_flags
1255	_list=
1256	_iflist=$*
1257
1258	# Parse wlans_$parent="$child ..."
1259	for parent in `set | sed -nE 's/wlans_([a-z]+[0-9]+)=.*/\1/p'`; do
1260		child_wlans=`get_if_var $parent wlans_IF`
1261		for child in ${child_wlans}; do
1262			create_args="wlandev $parent `get_if_var $child create_args_IF`"
1263			debug_flags="`get_if_var $child wlandebug_IF`"
1264			case $_iflist in
1265			""|$child|$child\ *|*\ $child\ *|*\ $child)	;;
1266			*)	continue ;;
1267			esac
1268			# Skip if ${child} already exists.
1269			if ${IFCONFIG_CMD} $child > /dev/null 2>&1; then
1270				continue
1271			fi
1272			if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
1273				${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1274			else
1275				${IFCONFIG_CMD} wlan create ${create_args} name $child && cfg=0
1276			fi
1277			if [ $? -eq 0 ]; then
1278				_list="$_list $child"
1279			fi
1280			if [ -n "${debug_flags}" ]; then
1281				wlandebug -i $child ${debug_flags}
1282			fi
1283		done
1284	done
1285	if [ -n "${_list# }" ]; then
1286		echo "Created wlan(4) interfaces: ${_list# }."
1287	fi
1288	debug "Created wlan(4)s: ${_list# }"
1289}
1290
1291# wlan_down
1292#	Destroy IEEE802.11 interfaces.
1293#
1294wlan_down()
1295{
1296	local _list _iflist parent child_wlans child
1297	_list=
1298	_iflist=$*
1299
1300	# Parse wlans_$parent="$child ..."
1301	for parent in `set | sed -nE 's/wlans_([a-z]+[0-9]+)=.*/\1/p'`; do
1302		child_wlans=`get_if_var $parent wlans_IF`
1303		for child in ${child_wlans}; do
1304			case $_iflist in
1305			""|$child|$child\ *|*\ $child\ *|*\ $child)	;;
1306			*)	continue ;;
1307			esac
1308			# Skip if ${child} doesn't exists.
1309			if ! ${IFCONFIG_CMD} $child > /dev/null 2>&1; then
1310				continue
1311			fi
1312			${IFCONFIG_CMD} -n ${child} destroy
1313			if [ $? -eq 0 ]; then
1314				_list="$_list $child"
1315			fi
1316		done
1317	done
1318	if [ -n "${_list# }" ]; then
1319		echo "Destroyed wlan(4) interfaces: ${_list# }."
1320	fi
1321	debug "Destroyed wlan(4)s: ${_list# }"
1322}
1323
1324# clone_up
1325#	Create cloneable interfaces.
1326#
1327clone_up()
1328{
1329	local _list ifn ifopt _iflist _inet6 _n tmpargs
1330	_list=
1331	_iflist=$*
1332
1333	# create_args_IF
1334	for ifn in ${cloned_interfaces}; do
1335		# Parse ifn:ifopt.
1336		OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1337		case $_iflist in
1338		""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn)	;;
1339		*)	continue ;;
1340		esac
1341		case $ifn in
1342		epair[0-9]*)
1343			# epair(4) uses epair[0-9] for creation and
1344			# epair[0-9][ab] for configuration.
1345			#
1346			# Skip if ${ifn}a or ${ifn}b already exist.
1347			if ${IFCONFIG_CMD} ${ifn}a > /dev/null 2>&1; then
1348				continue
1349			elif ${IFCONFIG_CMD} ${ifn}b > /dev/null 2>&1; then
1350				continue
1351			fi
1352			${IFCONFIG_CMD} ${ifn} create \
1353			    `get_if_var ${ifn} create_args_IF`
1354			if [ $? -eq 0 ]; then
1355				_list="$_list ${ifn}a ${ifn}b"
1356			fi
1357		;;
1358		*)
1359			# Skip if ${ifn} already exists.
1360			if ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1361				continue
1362			fi
1363			${IFCONFIG_CMD} ${ifn} create \
1364			    `get_if_var ${ifn} create_args_IF`
1365			if [ $? -eq 0 ]; then
1366				_list="$_list $ifn"
1367			fi
1368		esac
1369	done
1370	for ifn in ${gif_interfaces}; do
1371		# Parse ifn:ifopt.
1372		OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1373		case $_iflist in
1374		""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn)	;;
1375		*)	continue ;;
1376		esac
1377		# Skip if ifn already exists.
1378		if ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1379			continue
1380		fi
1381		case $ifn in
1382		gif[0-9]*)
1383			${IFCONFIG_CMD} $ifn create
1384		;;
1385		*)
1386			_n=$(${IFCONFIG_CMD} gif create)
1387			${IFCONFIG_CMD} $_n name $ifn
1388		;;
1389		esac
1390		if [ $? -eq 0 ]; then
1391			_list="$_list $ifn"
1392			tmpargs=$(get_if_var $ifn gifconfig_IF)
1393			_inet6=''
1394			case "$tmpargs" in
1395			'')
1396			;;
1397			inet6[[:space:]]*)
1398				tmpargs=${tmpargs#inet6}
1399				_inet6=inet6
1400				# FALLTHROUGH
1401			;&
1402			*)
1403				${IFCONFIG_CMD} $ifn $_inet6 tunnel $tmpargs
1404			;;
1405			esac
1406		fi
1407	done
1408	if [ -n "${_list# }" ]; then
1409		echo "Created clone interfaces: ${_list# }."
1410	fi
1411	debug "Cloned: ${_list# }"
1412}
1413
1414# clone_down
1415#	Destroy cloned interfaces. Destroyed interfaces are echoed to
1416#	standard output.
1417#
1418clone_down()
1419{
1420	local _list ifn _difn ifopt _iflist _sticky
1421	_list=
1422	_iflist=$*
1423
1424	: ${cloned_interfaces_sticky:=NO}
1425	if checkyesno cloned_interfaces_sticky; then
1426		_sticky=1
1427	else
1428		_sticky=0
1429	fi
1430	for ifn in ${cloned_interfaces} ${gif_interfaces}; do
1431		# Parse ifn:ifopt.
1432		OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1433		case $ifopt:$_sticky in
1434		sticky:*)	continue ;;	# :sticky => not destroy
1435		nosticky:*)	;;		# :nosticky => destroy
1436		*:1)		continue ;;	# global sticky knob == 1
1437		esac
1438		case $_iflist in
1439		""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn)	;;
1440		*)	continue ;;
1441		esac
1442		case $ifn in
1443		epair[0-9]*)
1444			# Note: epair(4) uses epair[0-9] for removal and
1445			# epair[0-9][ab] for configuration.
1446			#
1447			# Skip if both of ${ifn}a and ${ifn}b do not exist.
1448			if ${IFCONFIG_CMD} ${ifn}a > /dev/null 2>&1; then
1449				_difn=${ifn}a
1450			elif ${IFCONFIG_CMD} ${ifn}b > /dev/null 2>&1; then
1451				_difn=${ifn}b
1452			else
1453				continue
1454			fi
1455			${IFCONFIG_CMD} -n $_difn destroy
1456			if [ $? -eq 0 ]; then
1457				_list="$_list ${ifn}a ${ifn}b"
1458			fi
1459		;;
1460		*)
1461			# Skip if ifn does not exist.
1462			if ! ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1463				continue
1464			fi
1465			${IFCONFIG_CMD} -n ${ifn} destroy
1466			if [ $? -eq 0 ]; then
1467				_list="$_list $ifn"
1468			fi
1469		;;
1470		esac
1471	done
1472	if [ -n "${_list# }" ]; then
1473		echo "Destroyed clone interfaces: ${_list# }."
1474	fi
1475	debug "Destroyed clones: ${_list# }"
1476}
1477
1478# childif_create
1479#	Create and configure child interfaces.  Return 0 if child
1480#	interfaces are created.
1481#
1482childif_create()
1483{
1484	local cfg child child_vlans create_args debug_flags ifn i
1485	cfg=1
1486	ifn=$1
1487
1488	# Create vlan interfaces
1489	child_vlans=`get_if_var $ifn vlans_IF`
1490
1491	if [ -n "${child_vlans}" ]; then
1492		load_kld if_vlan
1493	fi
1494
1495	for child in ${child_vlans}; do
1496		if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1497			child="${ifn}.${child}"
1498			create_args=`get_if_var $child create_args_IF`
1499			${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1500		else
1501			create_args="vlandev $ifn `get_if_var $child create_args_IF`"
1502			if expr $child : 'vlan[0-9][0-9]*$' >/dev/null 2>&1; then
1503				${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1504			else
1505				i=`${IFCONFIG_CMD} vlan create ${create_args}`
1506				${IFCONFIG_CMD} $i name $child && cfg=0
1507			fi
1508		fi
1509		if autoif $child; then
1510			ifn_start $child
1511		fi
1512	done
1513
1514	return ${cfg}
1515}
1516
1517# childif_destroy
1518#	Destroy child interfaces.
1519#
1520childif_destroy()
1521{
1522	local cfg child child_vlans ifn
1523	cfg=1
1524
1525	child_vlans=`get_if_var $ifn vlans_IF`
1526	for child in ${child_vlans}; do
1527		if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1528			child="${ifn}.${child}"
1529		fi
1530		if ! ifexists $child; then
1531			continue
1532		fi
1533		${IFCONFIG_CMD} -n $child destroy && cfg=0
1534	done
1535
1536	return ${cfg}
1537}
1538
1539# ng_mkpeer
1540#	Create netgraph nodes.
1541#
1542ng_mkpeer()
1543{
1544	ngctl -f - 2> /dev/null <<EOF
1545mkpeer $*
1546msg dummy nodeinfo
1547EOF
1548}
1549
1550# ng_create_one
1551#	Create netgraph nodes.
1552#
1553ng_create_one()
1554{
1555	local t
1556
1557	ng_mkpeer $* | while read line; do
1558		t=`expr "${line}" : '.* name="\([a-z]*[0-9]*\)" .*'`
1559		if [ -n "${t}" ]; then
1560			echo ${t}
1561			return
1562		fi
1563	done
1564}
1565
1566# ifnet_rename [ifname]
1567#	Rename interfaces if ifconfig_IF_name is defined.
1568#
1569ifnet_rename()
1570{
1571	local _if _ifname
1572
1573	# ifconfig_IF_name
1574	for _if in ${*:-$(${IFCONFIG_CMD} -l)}; do
1575		_ifname=`get_if_var $_if ifconfig_IF_name`
1576		if [ ! -z "$_ifname" ]; then
1577			${IFCONFIG_CMD} $_if name $_ifname
1578		fi
1579	done
1580
1581	return 0
1582}
1583
1584# list_net_interfaces type
1585#	List all network interfaces. The type of interface returned
1586#	can be controlled by the type argument. The type
1587#	argument can be any of the following:
1588#		nodhcp	- all interfaces, excluding DHCP configured interfaces
1589#		dhcp	- list only DHCP configured interfaces
1590#		noautoconf	- all interfaces, excluding IPv6 Stateless
1591#				  Address Autoconf configured interfaces
1592#		autoconf	- list only IPv6 Stateless Address Autoconf
1593#				  configured interfaces
1594#	If no argument is specified all network interfaces are output.
1595#	Note that the list will include cloned interfaces if applicable.
1596#	Cloned interfaces must already exist to have a chance to appear
1597#	in the list if ${network_interfaces} is set to `auto'.
1598#
1599list_net_interfaces()
1600{
1601	local type _tmplist _list _autolist _lo _if
1602	type=$1
1603
1604	# Get a list of ALL the interfaces and make lo0 first if it's there.
1605	#
1606	_tmplist=
1607	case ${network_interfaces} in
1608	[Aa][Uu][Tt][Oo])
1609		_autolist="`${IFCONFIG_CMD} -l`"
1610		_lo=
1611		for _if in ${_autolist} ; do
1612			if autoif $_if; then
1613				if [ "$_if" = "lo0" ]; then
1614					_lo="lo0 "
1615				else
1616					_tmplist="${_tmplist} ${_if}"
1617				fi
1618			fi
1619		done
1620		_tmplist="${_lo}${_tmplist# }"
1621	;;
1622	*)
1623		for _if in ${network_interfaces} ${cloned_interfaces}; do
1624			# epair(4) uses epair[0-9] for creation and
1625			# epair[0-9][ab] for configuration.
1626			case $_if in
1627			epair[0-9]*)
1628				_tmplist="$_tmplist ${_if}a ${_if}b"
1629			;;
1630			*)
1631				_tmplist="$_tmplist $_if"
1632			;;
1633			esac
1634		done
1635		#
1636		# lo0 is effectively mandatory, so help prevent foot-shooting
1637		#
1638		case "$_tmplist" in
1639		lo0|'lo0 '*|*' lo0'|*' lo0 '*)
1640			# This is fine, do nothing
1641			_tmplist="${_tmplist# }"
1642		;;
1643		*)
1644			_tmplist="lo0 ${_tmplist# }"
1645		;;
1646		esac
1647	;;
1648	esac
1649
1650	_list=
1651	case "$type" in
1652	nodhcp)
1653		for _if in ${_tmplist} ; do
1654			if ! dhcpif $_if && \
1655			   [ -n "`_ifconfig_getargs $_if`" ]; then
1656				_list="${_list# } ${_if}"
1657			fi
1658		done
1659	;;
1660	dhcp)
1661		for _if in ${_tmplist} ; do
1662			if dhcpif $_if; then
1663				_list="${_list# } ${_if}"
1664			fi
1665		done
1666	;;
1667	noautoconf)
1668		for _if in ${_tmplist} ; do
1669			if ! ipv6_autoconfif $_if && \
1670			   [ -n "`_ifconfig_getargs $_if ipv6`" ]; then
1671				_list="${_list# } ${_if}"
1672			fi
1673		done
1674	;;
1675	autoconf)
1676		for _if in ${_tmplist} ; do
1677			if ipv6_autoconfif $_if; then
1678				_list="${_list# } ${_if}"
1679			fi
1680		done
1681	;;
1682	*)
1683		_list=${_tmplist}
1684	;;
1685	esac
1686
1687	echo $_list
1688
1689	return 0
1690}
1691
1692# get_default_if -address_family
1693#	Get the interface of the default route for the given address family.
1694#	The -address_family argument must be suitable passing to route(8).
1695#
1696get_default_if()
1697{
1698	local routeget oldifs defif line
1699	defif=
1700	oldifs="$IFS"
1701	IFS="
1702"
1703	for line in `route -n get $1 default 2>/dev/null`; do
1704		case $line in
1705		*interface:*)
1706			defif=${line##*: }
1707			;;
1708		esac
1709	done
1710	IFS=${oldifs}
1711
1712	echo $defif
1713}
1714
1715# hexdigit arg
1716#	Echo decimal number $arg (single digit) in hexadecimal format.
1717hexdigit()
1718{
1719	printf '%x\n' "$1"
1720}
1721
1722# hexprint arg
1723#	Echo decimal number $arg (multiple digits) in hexadecimal format.
1724hexprint()
1725{
1726	printf '%x\n' "$1"
1727}
1728
1729is_wired_interface()
1730{
1731	local media
1732
1733	case `${IFCONFIG_CMD} $1 2>/dev/null` in
1734	*media:?Ethernet*) media=Ethernet ;;
1735	esac
1736
1737	test "$media" = "Ethernet"
1738}
1739
1740# network6_getladdr if [flag]
1741#	Echo link-local address from $if if any.
1742#	If flag is defined, tentative ones will be excluded.
1743network6_getladdr()
1744{
1745	local _if _flag proto addr rest
1746	_if=$1
1747	_flag=$2
1748
1749	${IFCONFIG_CMD} $_if inet6 2>/dev/null | while read proto addr rest; do
1750		case "${proto}/${addr}/${_flag}/${rest}" in
1751		inet6/fe80::*//*)
1752			echo ${addr}
1753		;;
1754		inet6/fe80:://*tentative*)	# w/o flag
1755			sleep `${SYSCTL_N} net.inet6.ip6.dad_count`
1756			network6_getladdr $_if $_flags
1757		;;
1758		inet6/fe80::/*/*tentative*)	# w/ flag
1759			echo ${addr}
1760		;;
1761		*)
1762			continue
1763		;;
1764		esac
1765
1766		return
1767	done
1768}
1769