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