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