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