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