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