xref: /freebsd/libexec/rc/network.subr (revision 81ad6265)
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[[:space:]]*)	;;
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[[:space:]]*)	;;
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}[[:space:]]*)	;;
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}[[:space:]]*[0-9a-fA-F]-*)
1035				ifalias_af_common_handler $_if $_af $_action \
1036				`ifalias_expand_addr $_af $_action ${_tmpargs#${_af}[[:space:]]}`
1037			;;
1038			${_af}[[:space:]]*)
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}[[:space:]]pass[[:space:]]*)
1053			${IFCONFIG_CMD} $_if $_tmpargs $_action && _ret=0
1054		;;
1055		${_af}[[:space:]]*[0-9a-fA-F]-*)
1056			ifalias_af_common_handler $_if $_af $_action \
1057			`ifalias_expand_addr $_af $_action ${_tmpargs#${_af}[[:space:]]}`
1058		;;
1059		${_af}[[:space:]]*)
1060			${IFCONFIG_CMD} $_if $_tmpargs $_action && _ret=0
1061		;;
1062		esac
1063	fi
1064
1065	return $_ret
1066}
1067
1068# ifalias_af_common if af action
1069#	Helper function for ifalias().
1070#
1071ifalias_af_common()
1072{
1073	local _ret _if _af _action alias ifconfig_args _aliasn _c _tmpargs _iaf
1074	local _vif _punct=".-/+"
1075
1076	_ret=1
1077	_aliasn=
1078	_if=$1
1079	_af=$2
1080	_action=$3
1081
1082	# Normalize $_if before using it in a pattern to list_vars()
1083	ltr "$_if" "$_punct" "_" _vif
1084
1085	# ifconfig_IF_aliasN which starts with $_af
1086	for alias in `list_vars ifconfig_${_vif}_alias[0-9]\* |
1087		sort_lite -nk1.$((9+${#_vif}+7))`
1088	do
1089		eval ifconfig_args=\"\$$alias\"
1090		_iaf=
1091		case $ifconfig_args in
1092		inet[[:space:]]*)	_iaf=inet ;;
1093		inet6[[:space:]]*)	_iaf=inet6 ;;
1094		link[[:space:]]*)	_iaf=link ;;
1095		ether[[:space:]]*)	_iaf=ether ;;
1096		esac
1097
1098		case ${_af}:${_action}:${_iaf}:"${ifconfig_args}" in
1099		${_af}:*:${_af}:*)
1100			_aliasn="$_aliasn $ifconfig_args"
1101			;;
1102		${_af}:*:"":"")
1103			break
1104			;;
1105		inet:alias:"":*)
1106			_aliasn="$_aliasn inet $ifconfig_args"
1107			warn "\$${alias} needs leading" \
1108			    "\"inet\" keyword for an IPv4 address."
1109		esac
1110	done
1111
1112	# backward compatibility: ipv6_ifconfig_IF_aliasN.
1113	case $_af in
1114	inet6)
1115		for alias in `list_vars ipv6_ifconfig_${_vif}_alias[0-9]\* |
1116			sort_lite -nk1.$((14+${#_vif}+7))`
1117		do
1118			eval ifconfig_args=\"\$$alias\"
1119			case ${_action}:"${ifconfig_args}" in
1120			*:"")
1121				break
1122			;;
1123			alias:*)
1124				_aliasn="${_aliasn} inet6 ${ifconfig_args}"
1125				warn "\$${alias} is obsolete. " \
1126				    "Use ifconfig_${_vif}_aliasN instead."
1127			;;
1128			esac
1129		done
1130	esac
1131
1132	# backward compatibility: ipv4_addrs_IF.
1133	for _tmpargs in `get_if_var $_if ipv4_addrs_IF`; do
1134		_aliasn="$_aliasn inet $_tmpargs"
1135	done
1136
1137	# Handle ifconfig_IF_aliases, ifconfig_IF_aliasN, and the others.
1138	_tmpargs=
1139	for _c in `get_if_var $_if ifconfig_IF_aliases` $_aliasn; do
1140		case $_c in
1141		inet|inet6|link|ether)
1142			case $_tmpargs in
1143			${_af}[[:space:]]*)
1144				eval ifalias_af_common_handler $_if $_af $_action $_tmpargs && _ret=0
1145			;;
1146			esac
1147			_tmpargs=$_c
1148		;;
1149		*)
1150			_tmpargs="$_tmpargs $_c"
1151		esac
1152	done
1153	# Process the last component
1154	case $_tmpargs in
1155	${_af}[[:space:]]*)
1156		ifalias_af_common_handler $_if $_af $_action $_tmpargs && _ret=0
1157	;;
1158	esac
1159
1160	return $_ret
1161}
1162
1163# ipv6_prefix_hostid_addr_common if action
1164#	Add or remove IPv6 prefix + hostid addr on the interface $if
1165#
1166ipv6_prefix_hostid_addr_common()
1167{
1168	local _if _action prefix j
1169	_if=$1
1170	_action=$2
1171	prefix=`get_if_var ${_if} ipv6_prefix_IF`
1172
1173	if [ -n "${prefix}" ]; then
1174		for j in ${prefix}; do
1175			# The default prefixlen is 64.
1176			plen=${j#*/}
1177			case $j:$plen in
1178			$plen:$j)	plen=64 ;;
1179			*)		j=${j%/*} ;;
1180			esac
1181
1182			# Normalize the last part by removing ":"
1183			j=${j%::*}
1184			j=${j%:}
1185			${IFCONFIG_CMD} ${_if} inet6 $j:: \
1186				prefixlen $plen eui64 ${_action}
1187
1188			# if I am a router, add subnet router
1189			# anycast address (RFC 2373).
1190			if checkyesno ipv6_gateway_enable; then
1191				${IFCONFIG_CMD} ${_if} inet6 $j:: \
1192					prefixlen $plen ${_action} anycast
1193			fi
1194		done
1195	fi
1196}
1197
1198# ipv6_accept_rtadv_up if
1199#	Enable accepting Router Advertisement and send Router
1200#	Solicitation message
1201ipv6_accept_rtadv_up()
1202{
1203	if ipv6_autoconfif $1; then
1204		${IFCONFIG_CMD} $1 inet6 accept_rtadv up
1205		if [ -x /sbin/rtsol ]; then
1206			/sbin/rtsol ${rtsol_flags} $1
1207		fi
1208		return 0
1209	fi
1210	return 1
1211}
1212
1213# ipv6_accept_rtadv_down if
1214#	Disable accepting Router Advertisement
1215ipv6_accept_rtadv_down()
1216{
1217	if ipv6_autoconfif $1; then
1218		${IFCONFIG_CMD} $1 inet6 -accept_rtadv
1219	fi
1220}
1221
1222# ifscript_up if
1223#	Evaluate a startup script for the $if interface.
1224#	It returns 0 if a script was found and processed or
1225#	1 if no script was found.
1226#
1227ifscript_up()
1228{
1229	if [ -r /etc/start_if.$1 ]; then
1230		. /etc/start_if.$1
1231		return 0
1232	else
1233		return 1
1234	fi
1235}
1236
1237# ifscript_down if
1238#	Evaluate a shutdown script for the $if interface.
1239#	It returns 0 if a script was found and processed or
1240#	1 if no script was found.
1241#
1242ifscript_down()
1243{
1244	if [ -r /etc/stop_if.$1 ]; then
1245		. /etc/stop_if.$1
1246		return 0
1247	else
1248		return 1
1249	fi
1250}
1251
1252# wlan_up
1253#	Create IEEE802.11 interfaces.
1254#
1255wlan_up()
1256{
1257	local _list _iflist parent child_wlans child create_args debug_flags
1258	_list=
1259	_iflist=$*
1260
1261	# Parse wlans_$parent="$child ..."
1262	for parent in `set | sed -nE 's/wlans_([a-z]+[0-9]+)=.*/\1/p'`; do
1263		child_wlans=`get_if_var $parent wlans_IF`
1264		for child in ${child_wlans}; do
1265			create_args="wlandev $parent `get_if_var $child create_args_IF`"
1266			debug_flags="`get_if_var $child wlandebug_IF`"
1267			case $_iflist in
1268			""|$child|$child[[:space:]]*|*[[:space:]]$child[[:space:]]*|*[[:space:]]$child)	;;
1269			*)	continue ;;
1270			esac
1271			# Skip if ${child} already exists.
1272			if ${IFCONFIG_CMD} $child > /dev/null 2>&1; then
1273				continue
1274			fi
1275			if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
1276				${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1277			else
1278				${IFCONFIG_CMD} wlan create ${create_args} name $child && cfg=0
1279			fi
1280			if [ $? -eq 0 ]; then
1281				_list="$_list $child"
1282			fi
1283			if [ -n "${debug_flags}" ]; then
1284				wlandebug -i $child ${debug_flags}
1285			fi
1286		done
1287	done
1288	if [ -n "${_list# }" ]; then
1289		echo "Created wlan(4) interfaces: ${_list# }."
1290	fi
1291	debug "Created wlan(4)s: ${_list# }"
1292}
1293
1294# wlan_down
1295#	Destroy IEEE802.11 interfaces.
1296#
1297wlan_down()
1298{
1299	local _list _iflist parent child_wlans child
1300	_list=
1301	_iflist=$*
1302
1303	# Parse wlans_$parent="$child ..."
1304	for parent in `set | sed -nE 's/wlans_([a-z]+[0-9]+)=.*/\1/p'`; do
1305		child_wlans=`get_if_var $parent wlans_IF`
1306		for child in ${child_wlans}; do
1307			case $_iflist in
1308			""|$child|$child[[:space:]]*|*[[:space:]]$child[[:space:]]*|*[[:space:]]$child)	;;
1309			*)	continue ;;
1310			esac
1311			# Skip if ${child} doesn't exists.
1312			if ! ${IFCONFIG_CMD} $child > /dev/null 2>&1; then
1313				continue
1314			fi
1315			${IFCONFIG_CMD} -n ${child} destroy
1316			if [ $? -eq 0 ]; then
1317				_list="$_list $child"
1318			fi
1319		done
1320	done
1321	if [ -n "${_list# }" ]; then
1322		echo "Destroyed wlan(4) interfaces: ${_list# }."
1323	fi
1324	debug "Destroyed wlan(4)s: ${_list# }"
1325}
1326
1327# clone_up
1328#	Create cloneable interfaces.
1329#
1330clone_up()
1331{
1332	local _list ifn ifopt _iflist _inet6 _n tmpargs
1333	_list=
1334	_iflist=$*
1335
1336	# create_args_IF
1337	for ifn in ${cloned_interfaces}; do
1338		# Parse ifn:ifopt.
1339		OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1340		case $_iflist in
1341		""|$ifn|$ifn[[:space:]]*|*[[:space:]]$ifn[[:space:]]*|*[[:space:]]$ifn)	;;
1342		*)	continue ;;
1343		esac
1344		case $ifn in
1345		epair[0-9]*)
1346			# epair(4) uses epair[0-9] for creation and
1347			# epair[0-9][ab] for configuration.
1348			#
1349			# Skip if ${ifn}a or ${ifn}b already exist.
1350			if ${IFCONFIG_CMD} ${ifn}a > /dev/null 2>&1; then
1351				continue
1352			elif ${IFCONFIG_CMD} ${ifn}b > /dev/null 2>&1; then
1353				continue
1354			fi
1355			${IFCONFIG_CMD} ${ifn} create \
1356			    `get_if_var ${ifn} create_args_IF`
1357			if [ $? -eq 0 ]; then
1358				_list="$_list ${ifn}a ${ifn}b"
1359			fi
1360		;;
1361		*)
1362			# Skip if ${ifn} already exists.
1363			if ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1364				continue
1365			fi
1366			${IFCONFIG_CMD} ${ifn} create \
1367			    `get_if_var ${ifn} create_args_IF`
1368			if [ $? -eq 0 ]; then
1369				_list="$_list $ifn"
1370			fi
1371		esac
1372	done
1373	for ifn in ${gif_interfaces}; do
1374		# Parse ifn:ifopt.
1375		OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1376		case $_iflist in
1377		""|$ifn|$ifn[[:space:]]*|*[[:space:]]$ifn[[:space:]]*|*[[:space:]]$ifn)	;;
1378		*)	continue ;;
1379		esac
1380		# Skip if ifn already exists.
1381		if ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1382			continue
1383		fi
1384		case $ifn in
1385		gif[0-9]*)
1386			${IFCONFIG_CMD} $ifn create
1387		;;
1388		*)
1389			_n=$(${IFCONFIG_CMD} gif create)
1390			${IFCONFIG_CMD} $_n name $ifn
1391		;;
1392		esac
1393		if [ $? -eq 0 ]; then
1394			_list="$_list $ifn"
1395			tmpargs=$(get_if_var $ifn gifconfig_IF)
1396			_inet6=''
1397			case "$tmpargs" in
1398			'')
1399			;;
1400			inet6[[:space:]]*)
1401				tmpargs=${tmpargs#inet6}
1402				_inet6=inet6
1403				# FALLTHROUGH
1404			;&
1405			*)
1406				${IFCONFIG_CMD} $ifn $_inet6 tunnel $tmpargs
1407			;;
1408			esac
1409		fi
1410	done
1411	if [ -n "${_list# }" ]; then
1412		echo "Created clone interfaces: ${_list# }."
1413	fi
1414	debug "Cloned: ${_list# }"
1415}
1416
1417# clone_down
1418#	Destroy cloned interfaces. Destroyed interfaces are echoed to
1419#	standard output.
1420#
1421clone_down()
1422{
1423	local _list ifn _difn ifopt _iflist _sticky
1424	_list=
1425	_iflist=$*
1426
1427	: ${cloned_interfaces_sticky:=NO}
1428	if checkyesno cloned_interfaces_sticky; then
1429		_sticky=1
1430	else
1431		_sticky=0
1432	fi
1433	for ifn in ${cloned_interfaces} ${gif_interfaces}; do
1434		# Parse ifn:ifopt.
1435		OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1436		case $ifopt:$_sticky in
1437		sticky:*)	continue ;;	# :sticky => not destroy
1438		nosticky:*)	;;		# :nosticky => destroy
1439		*:1)		continue ;;	# global sticky knob == 1
1440		esac
1441		case $_iflist in
1442		""|$ifn|$ifn[[:space:]]*|*[[:space:]]$ifn[[:space:]]*|*[[:space:]]$ifn)	;;
1443		*)	continue ;;
1444		esac
1445		case $ifn in
1446		epair[0-9]*)
1447			# Note: epair(4) uses epair[0-9] for removal and
1448			# epair[0-9][ab] for configuration.
1449			#
1450			# Skip if both of ${ifn}a and ${ifn}b do not exist.
1451			if ${IFCONFIG_CMD} ${ifn}a > /dev/null 2>&1; then
1452				_difn=${ifn}a
1453			elif ${IFCONFIG_CMD} ${ifn}b > /dev/null 2>&1; then
1454				_difn=${ifn}b
1455			else
1456				continue
1457			fi
1458			${IFCONFIG_CMD} -n $_difn destroy
1459			if [ $? -eq 0 ]; then
1460				_list="$_list ${ifn}a ${ifn}b"
1461			fi
1462		;;
1463		*)
1464			# Skip if ifn does not exist.
1465			if ! ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1466				continue
1467			fi
1468			${IFCONFIG_CMD} -n ${ifn} destroy
1469			if [ $? -eq 0 ]; then
1470				_list="$_list $ifn"
1471			fi
1472		;;
1473		esac
1474	done
1475	if [ -n "${_list# }" ]; then
1476		echo "Destroyed clone interfaces: ${_list# }."
1477	fi
1478	debug "Destroyed clones: ${_list# }"
1479}
1480
1481# childif_create
1482#	Create and configure child interfaces.  Return 0 if child
1483#	interfaces are created.
1484#
1485childif_create()
1486{
1487	local cfg child child_vlans create_args debug_flags ifn i
1488	cfg=1
1489	ifn=$1
1490
1491	# Create vlan interfaces
1492	child_vlans=`get_if_var $ifn vlans_IF`
1493
1494	if [ -n "${child_vlans}" ]; then
1495		load_kld if_vlan
1496	fi
1497
1498	for child in ${child_vlans}; do
1499		if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1500			child="${ifn}.${child}"
1501			create_args=`get_if_var $child create_args_IF`
1502			${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1503		else
1504			create_args="vlandev $ifn `get_if_var $child create_args_IF`"
1505			if expr $child : 'vlan[0-9][0-9]*$' >/dev/null 2>&1; then
1506				${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1507			else
1508				i=`${IFCONFIG_CMD} vlan create ${create_args}`
1509				${IFCONFIG_CMD} $i name $child && cfg=0
1510			fi
1511		fi
1512		if autoif $child; then
1513			ifn_start $child
1514		fi
1515	done
1516
1517	return ${cfg}
1518}
1519
1520# childif_destroy
1521#	Destroy child interfaces.
1522#
1523childif_destroy()
1524{
1525	local cfg child child_vlans ifn
1526	cfg=1
1527
1528	child_vlans=`get_if_var $ifn vlans_IF`
1529	for child in ${child_vlans}; do
1530		if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1531			child="${ifn}.${child}"
1532		fi
1533		if ! ifexists $child; then
1534			continue
1535		fi
1536		${IFCONFIG_CMD} -n $child destroy && cfg=0
1537	done
1538
1539	return ${cfg}
1540}
1541
1542# ng_mkpeer
1543#	Create netgraph nodes.
1544#
1545ng_mkpeer()
1546{
1547	ngctl -f - 2> /dev/null <<EOF
1548mkpeer $*
1549msg dummy nodeinfo
1550EOF
1551}
1552
1553# ng_create_one
1554#	Create netgraph nodes.
1555#
1556ng_create_one()
1557{
1558	local t
1559
1560	ng_mkpeer $* | while read line; do
1561		t=`expr "${line}" : '.* name="\([a-z]*[0-9]*\)" .*'`
1562		if [ -n "${t}" ]; then
1563			echo ${t}
1564			return
1565		fi
1566	done
1567}
1568
1569# ifnet_rename [ifname]
1570#	Rename interfaces if ifconfig_IF_name is defined.
1571#
1572ifnet_rename()
1573{
1574	local _if _ifname
1575
1576	# ifconfig_IF_name
1577	for _if in ${*:-$(${IFCONFIG_CMD} -l)}; do
1578		_ifname=`get_if_var $_if ifconfig_IF_name`
1579		if [ ! -z "$_ifname" ]; then
1580			${IFCONFIG_CMD} $_if name $_ifname
1581		fi
1582	done
1583
1584	return 0
1585}
1586
1587# list_net_interfaces type
1588#	List all network interfaces. The type of interface returned
1589#	can be controlled by the type argument. The type
1590#	argument can be any of the following:
1591#		nodhcp	- all interfaces, excluding DHCP configured interfaces
1592#		dhcp	- list only DHCP configured interfaces
1593#		noautoconf	- all interfaces, excluding IPv6 Stateless
1594#				  Address Autoconf configured interfaces
1595#		autoconf	- list only IPv6 Stateless Address Autoconf
1596#				  configured interfaces
1597#	If no argument is specified all network interfaces are output.
1598#	Note that the list will include cloned interfaces if applicable.
1599#	Cloned interfaces must already exist to have a chance to appear
1600#	in the list if ${network_interfaces} is set to `auto'.
1601#
1602list_net_interfaces()
1603{
1604	local type _tmplist _list _autolist _lo _if
1605	type=$1
1606
1607	# Get a list of ALL the interfaces and make lo0 first if it's there.
1608	#
1609	_tmplist=
1610	case ${network_interfaces} in
1611	[Aa][Uu][Tt][Oo])
1612		_autolist="`${IFCONFIG_CMD} -l`"
1613		_lo=
1614		for _if in ${_autolist} ; do
1615			if autoif $_if; then
1616				if [ "$_if" = "lo0" ]; then
1617					_lo="lo0 "
1618				else
1619					_tmplist="${_tmplist} ${_if}"
1620				fi
1621			fi
1622		done
1623		_tmplist="${_lo}${_tmplist# }"
1624	;;
1625	*)
1626		for _if in ${network_interfaces} ${cloned_interfaces}; do
1627			# epair(4) uses epair[0-9] for creation and
1628			# epair[0-9][ab] for configuration.
1629			case $_if in
1630			epair[0-9]*)
1631				_tmplist="$_tmplist ${_if}a ${_if}b"
1632			;;
1633			*)
1634				_tmplist="$_tmplist $_if"
1635			;;
1636			esac
1637		done
1638		#
1639		# lo0 is effectively mandatory, so help prevent foot-shooting
1640		#
1641		case "$_tmplist" in
1642		lo0|'lo0 '*|*' lo0'|*' lo0 '*)
1643			# This is fine, do nothing
1644			_tmplist="${_tmplist# }"
1645		;;
1646		*)
1647			_tmplist="lo0 ${_tmplist# }"
1648		;;
1649		esac
1650	;;
1651	esac
1652
1653	_list=
1654	case "$type" in
1655	nodhcp)
1656		for _if in ${_tmplist} ; do
1657			if ! dhcpif $_if && \
1658			   [ -n "`_ifconfig_getargs $_if`" ]; then
1659				_list="${_list# } ${_if}"
1660			fi
1661		done
1662	;;
1663	dhcp)
1664		for _if in ${_tmplist} ; do
1665			if dhcpif $_if; then
1666				_list="${_list# } ${_if}"
1667			fi
1668		done
1669	;;
1670	noautoconf)
1671		for _if in ${_tmplist} ; do
1672			if ! ipv6_autoconfif $_if && \
1673			   [ -n "`_ifconfig_getargs $_if ipv6`" ]; then
1674				_list="${_list# } ${_if}"
1675			fi
1676		done
1677	;;
1678	autoconf)
1679		for _if in ${_tmplist} ; do
1680			if ipv6_autoconfif $_if; then
1681				_list="${_list# } ${_if}"
1682			fi
1683		done
1684	;;
1685	*)
1686		_list=${_tmplist}
1687	;;
1688	esac
1689
1690	echo $_list
1691
1692	return 0
1693}
1694
1695# get_default_if -address_family
1696#	Get the interface of the default route for the given address family.
1697#	The -address_family argument must be suitable passing to route(8).
1698#
1699get_default_if()
1700{
1701	local routeget oldifs defif line
1702	defif=
1703	oldifs="$IFS"
1704	IFS="
1705"
1706	for line in `route -n get $1 default 2>/dev/null`; do
1707		case $line in
1708		*interface:*)
1709			defif=${line##*: }
1710			;;
1711		esac
1712	done
1713	IFS=${oldifs}
1714
1715	echo $defif
1716}
1717
1718# hexdigit arg
1719#	Echo decimal number $arg (single digit) in hexadecimal format.
1720hexdigit()
1721{
1722	printf '%x\n' "$1"
1723}
1724
1725# hexprint arg
1726#	Echo decimal number $arg (multiple digits) in hexadecimal format.
1727hexprint()
1728{
1729	printf '%x\n' "$1"
1730}
1731
1732is_wired_interface()
1733{
1734	local media
1735
1736	case `${IFCONFIG_CMD} $1 2>/dev/null` in
1737	*media:?Ethernet*) media=Ethernet ;;
1738	esac
1739
1740	test "$media" = "Ethernet"
1741}
1742
1743# network6_getladdr if [flag]
1744#	Echo link-local address from $if if any.
1745#	If flag is defined, tentative ones will be excluded.
1746network6_getladdr()
1747{
1748	local _if _flag proto addr rest
1749	_if=$1
1750	_flag=$2
1751
1752	${IFCONFIG_CMD} $_if inet6 2>/dev/null | while read proto addr rest; do
1753		case "${proto}/${addr}/${_flag}/${rest}" in
1754		inet6/fe80::*//*)
1755			echo ${addr}
1756		;;
1757		inet6/fe80:://*tentative*)	# w/o flag
1758			sleep `${SYSCTL_N} net.inet6.ip6.dad_count`
1759			network6_getladdr $_if $_flags
1760		;;
1761		inet6/fe80::/*/*tentative*)	# w/ flag
1762			echo ${addr}
1763		;;
1764		*)
1765			continue
1766		;;
1767		esac
1768
1769		return
1770	done
1771}
1772