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