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