network.subr revision 325799
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: stable/10/etc/network.subr 325799 2017-11-14 09:31:56Z eugen $
26#
27IFCONFIG_CMD="/sbin/ifconfig"
28: ${netif_ipexpand_max:=2048}
29
30#
31# Subroutines commonly used from network startup scripts.
32# Requires that rc.conf be loaded first.
33#
34
35# ifn_start ifn
36#	Bring up and configure an interface.  If some configuration is
37#	applied, print the interface configuration.
38#
39ifn_start()
40{
41	local ifn cfg
42	ifn="$1"
43	cfg=1
44
45	[ -z "$ifn" ] && err 1 "ifn_start called without an interface"
46
47	ifscript_up ${ifn} && cfg=0
48	ifconfig_up ${ifn} && cfg=0
49	if ! noafif $ifn; then
50		afexists inet && ipv4_up ${ifn} && cfg=0
51		afexists inet6 && ipv6_up ${ifn} && cfg=0
52		afexists ipx && ipx_up ${ifn} && cfg=0
53	fi
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	if ! noafif $ifn; then
72		afexists ipx && ipx_down ${ifn} && cfg=0
73		afexists inet6 && ipv6_down ${ifn} && cfg=0
74		afexists inet && ipv4_down ${ifn} && cfg=0
75	fi
76	ifconfig_down ${ifn} && cfg=0
77	ifscript_down ${ifn} && cfg=0
78	childif_destroy ${ifn} && cfg=0
79
80	return $cfg
81}
82
83# ifn_vnetup ifn
84#	Move ifn to the specified vnet jail.
85#
86ifn_vnetup()
87{
88
89	ifn_vnet0 $1 vnet
90}
91
92# ifn_vnetdown ifn
93#	Reclaim ifn from the specified vnet jail.
94#
95ifn_vnetdown()
96{
97
98	ifn_vnet0 $1 -vnet
99}
100
101# ifn_vnet0 ifn action
102#	Helper function for ifn_vnetup and ifn_vnetdown.
103#
104ifn_vnet0()
105{
106	local _ifn _cfg _action _vnet
107	_ifn="$1"
108	_action="$2"
109	_cfg=1
110
111	if _vnet=$(vnetif $_ifn); then
112		${IFCONFIG_CMD} $_ifn $_action $_vnet && _cfg=0
113	fi
114
115	return $_cfg
116}
117
118# ifconfig_up if
119#	Evaluate ifconfig(8) arguments for interface $if and
120#	run ifconfig(8) with those arguments. It returns 0 if
121#	arguments were found and executed or 1 if the interface
122#	had no arguments.  Pseudo arguments DHCP and WPA are handled
123#	here.
124#
125ifconfig_up()
126{
127	local _cfg _ifconfig_descr _ipv6_opts ifconfig_args 
128	_cfg=1
129
130	# Make sure lo0 always comes up.
131	if [ "$1" = "lo0" ]; then
132		_cfg=0
133	fi
134
135	# inet6 specific
136	if ! noafif $1 && afexists inet6; then
137		if checkyesno ipv6_activate_all_interfaces; then
138			_ipv6_opts="-ifdisabled"
139		elif [ "$1" != "lo0" ]; then
140			_ipv6_opts="ifdisabled"
141		fi
142
143		# backward compatibility: $ipv6_enable
144		case $ipv6_enable in
145		[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
146			case $1 in
147			bridge[0-9]*)
148				# No accept_rtadv by default on if_bridge(4)
149				# to avoid a conflict with the member
150				# interfaces.
151			;;
152			*)
153				if ! checkyesno ipv6_gateway_enable; then
154					_ipv6_opts="${_ipv6_opts} accept_rtadv"
155				fi
156			;;
157			esac
158		;;
159		esac
160
161		case $ipv6_cpe_wanif in
162		$1)
163			_ipv6_opts="${_ipv6_opts} -no_radr accept_rtadv"
164		;;
165		esac
166
167		if [ -n "${_ipv6_opts}" ]; then
168			${IFCONFIG_CMD} $1 inet6 ${_ipv6_opts}
169		fi
170	fi
171
172	# ifconfig_IF
173	ifconfig_args=`ifconfig_getargs $1`
174	if [ -n "${ifconfig_args}" ]; then
175		eval ${IFCONFIG_CMD} $1 ${ifconfig_args}
176		_cfg=0
177	fi
178
179	# inet6 specific
180	if ! noafif $1 && afexists inet6; then
181		# ifconfig_IF_ipv6
182		ifconfig_args=`ifconfig_getargs $1 ipv6`
183		if [ -n "${ifconfig_args}" ]; then
184			# backward compatibility: inet6 keyword
185			case "${ifconfig_args}" in
186			:*|[0-9a-fA-F]*:*)
187				warn "\$ifconfig_$1_ipv6 needs leading" \
188				    "\"inet6\" keyword for an IPv6 address."
189				ifconfig_args="inet6 ${ifconfig_args}"
190			;;
191			esac
192			${IFCONFIG_CMD} $1 inet6 -ifdisabled
193			eval ${IFCONFIG_CMD} $1 ${ifconfig_args}
194			_cfg=0
195		fi
196
197		# $ipv6_prefix_IF will be handled in
198		# ipv6_prefix_hostid_addr_common().
199		ifconfig_args=`get_if_var $1 ipv6_prefix_IF`
200		if [ -n "${ifconfig_args}" ]; then
201			${IFCONFIG_CMD} $1 inet6 -ifdisabled
202			_cfg=0
203		fi
204
205		# backward compatibility: $ipv6_ifconfig_IF
206		ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF`
207		if [ -n "${ifconfig_args}" ]; then
208			warn "\$ipv6_ifconfig_$1 is obsolete." \
209			    "  Use ifconfig_$1_ipv6 instead."
210			${IFCONFIG_CMD} $1 inet6 -ifdisabled
211			eval ${IFCONFIG_CMD} $1 inet6 ${ifconfig_args}
212			_cfg=0
213		fi
214	fi
215
216	ifalias $1 link alias
217	ifalias $1 ether alias
218
219	_ifconfig_descr=`get_if_var $1 ifconfig_IF_descr`
220	if [ -n "${_ifconfig_descr}" ]; then
221		${IFCONFIG_CMD} $1 description "${_ifconfig_descr}"
222	fi
223
224	if wpaif $1; then
225		/etc/rc.d/wpa_supplicant start $1
226		_cfg=0		# XXX: not sure this should count
227	elif hostapif $1; then
228		/etc/rc.d/hostapd start $1
229		_cfg=0
230	fi
231
232	if dhcpif $1; then
233		if [ $_cfg -ne 0 ] ; then
234			${IFCONFIG_CMD} $1 up
235		fi
236		if syncdhcpif $1; then
237			/etc/rc.d/dhclient start $1
238		fi
239		_cfg=0
240	fi
241
242	return $_cfg
243}
244
245# ifconfig_down if
246#	returns 1 if wpa_supplicant or dhclient was stopped or
247#	the interface exists.
248#
249ifconfig_down()
250{
251	local _cfg
252	_cfg=1
253
254	if wpaif $1; then
255		/etc/rc.d/wpa_supplicant stop $1
256		_cfg=0
257	elif hostapif $1; then
258		/etc/rc.d/hostapd stop $1
259		_cfg=0
260	fi
261
262	if dhcpif $1; then
263		/etc/rc.d/dhclient stop $1
264		_cfg=0
265	fi
266
267	if ifexists $1; then
268		${IFCONFIG_CMD} $1 down
269		_cfg=0
270	fi
271
272	return $_cfg
273}
274
275# get_if_var if var [default]
276#	Return the value of the pseudo-hash corresponding to $if where
277#	$var is a string containg the sub-string "IF" which will be
278#	replaced with $if after the characters defined in _punct are
279#	replaced with '_'. If the variable is unset, replace it with
280#	$default if given.
281get_if_var()
282{
283	local _if _punct _punct_c _var _default prefix suffix
284
285	if [ $# -ne 2 -a $# -ne 3 ]; then
286		err 3 'USAGE: get_if_var name var [default]'
287	fi
288
289	_if=$1
290	_punct=".-/+"
291	ltr ${_if} "${_punct}" '_' _if
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 $_inet6 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 + $netif_ipexpand_max)) ]; 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.  Increase \$netif_ipexpand_max in rc.conf."
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 + $netif_ipexpand_max)) ]
984					then
985						warn "Range specification is too large $(printf '(%s:%x%s-%s:%x%s)' "$_ipleft" "$_iplow" "$_ipright" "$_ipleft" "$_iphigh" "$_ipright"). $(printf '%s:%x%s-%s:%x%s' "$_ipleft" "$_iplow" "$_ipright" "$_ipleft" "$_ipcount" "$_ipright") was processed.  Increase \$netif_ipexpand_max in rc.conf."
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}\ *[0-9a-fA-F]-*)
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}\ *[0-9a-fA-F]-*)
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	local _vif _punct=".-/+"
1085
1086	_ret=1
1087	_aliasn=
1088	_if=$1
1089	_af=$2
1090	_action=$3
1091
1092	# Normalize $_if before using it in a pattern to list_vars()
1093	ltr "$_if" "$_punct" "_" _vif
1094
1095	# ifconfig_IF_aliasN which starts with $_af
1096	for alias in `list_vars ifconfig_${_vif}_alias[0-9]\* |
1097		sort_lite -nk1.$((9+${#_vif}+7))`
1098	do
1099		eval ifconfig_args=\"\$$alias\"
1100		_iaf=
1101		case $ifconfig_args in
1102		inet\ *)	_iaf=inet ;;
1103		inet6\ *)	_iaf=inet6 ;;
1104		ipx\ *)		_iaf=ipx ;;
1105		link\ *)	_iaf=link ;;
1106		ether\ *)	_iaf=ether ;;
1107		esac
1108
1109		case ${_af}:${_action}:${_iaf}:"${ifconfig_args}" in
1110		${_af}:*:${_af}:*)
1111			_aliasn="$_aliasn $ifconfig_args"
1112			;;
1113		${_af}:*:"":"")
1114			break
1115			;;
1116		inet:alias:"":*)
1117			_aliasn="$_aliasn inet $ifconfig_args"
1118			warn "\$${alias} needs leading" \
1119			    "\"inet\" keyword for an IPv4 address."
1120		esac
1121	done
1122
1123	# backward compatibility: ipv6_ifconfig_IF_aliasN.
1124	case $_af in
1125	inet6)
1126		for alias in `list_vars ipv6_ifconfig_${_vif}_alias[0-9]\* |
1127			sort_lite -nk1.$((14+${#_vif}+7))`
1128		do
1129			eval ifconfig_args=\"\$$alias\"
1130			case ${_action}:"${ifconfig_args}" in
1131			*:"")
1132				break
1133			;;
1134			alias:*)
1135				_aliasn="${_aliasn} inet6 ${ifconfig_args}"
1136				warn "\$${alias} is obsolete. " \
1137				    "Use ifconfig_${_vif}_aliasN instead."
1138			;;
1139			esac
1140		done
1141	esac
1142
1143	# backward compatibility: ipv4_addrs_IF.
1144	for _tmpargs in `get_if_var $_if ipv4_addrs_IF`; do
1145		_aliasn="$_aliasn inet $_tmpargs"
1146	done
1147
1148	# Handle ifconfig_IF_aliases, ifconfig_IF_aliasN, and the others.
1149	_tmpargs=
1150	for _c in `get_if_var $_if ifconfig_IF_aliases` $_aliasn; do
1151		case $_c in
1152		inet|inet6|ipx|link|ether)
1153			case $_tmpargs in
1154			${_af}\ *)
1155				eval ifalias_af_common_handler $_if $_af $_action $_tmpargs && _ret=0
1156			;;
1157			esac
1158			_tmpargs=$_c
1159		;;
1160		*)
1161			_tmpargs="$_tmpargs $_c"
1162		esac
1163	done
1164	# Process the last component
1165	case $_tmpargs in
1166	${_af}\ *)
1167		ifalias_af_common_handler $_if $_af $_action $_tmpargs && _ret=0
1168	;;
1169	esac
1170
1171	return $_ret
1172}
1173
1174# ipv6_prefix_hostid_addr_common if action
1175#	Add or remove IPv6 prefix + hostid addr on the interface $if
1176#
1177ipv6_prefix_hostid_addr_common()
1178{
1179	local _if _action prefix j
1180	_if=$1
1181	_action=$2
1182	prefix=`get_if_var ${_if} ipv6_prefix_IF`
1183
1184	if [ -n "${prefix}" ]; then
1185		for j in ${prefix}; do
1186			# The default prefixlen is 64.
1187			plen=${j#*/}
1188			case $j:$plen in
1189			$plen:$j)	plen=64 ;;
1190			*)		j=${j%/*} ;;
1191			esac
1192
1193			# Normalize the last part by removing ":"
1194			j=${j%::*}
1195			j=${j%:}
1196			${IFCONFIG_CMD} ${_if} inet6 $j:: \
1197				prefixlen $plen eui64 ${_action}
1198
1199			# if I am a router, add subnet router
1200			# anycast address (RFC 2373).
1201			if checkyesno ipv6_gateway_enable; then
1202				${IFCONFIG_CMD} ${_if} inet6 $j:: \
1203					prefixlen $plen ${_action} anycast
1204			fi
1205		done
1206	fi
1207}
1208
1209# ipv6_accept_rtadv_up if
1210#	Enable accepting Router Advertisement and send Router
1211#	Solicitation message
1212ipv6_accept_rtadv_up()
1213{
1214	if ipv6_autoconfif $1; then
1215		${IFCONFIG_CMD} $1 inet6 accept_rtadv up
1216		if ! checkyesno rtsold_enable; then
1217			rtsol ${rtsol_flags} $1
1218		fi
1219	fi
1220}
1221
1222# ipv6_accept_rtadv_down if
1223#	Disable accepting Router Advertisement
1224ipv6_accept_rtadv_down()
1225{
1226	if ipv6_autoconfif $1; then
1227		${IFCONFIG_CMD} $1 inet6 -accept_rtadv
1228	fi
1229}
1230
1231# ifscript_up if
1232#	Evaluate a startup script for the $if interface.
1233#	It returns 0 if a script was found and processed or
1234#	1 if no script was found.
1235#
1236ifscript_up()
1237{
1238	if [ -r /etc/start_if.$1 ]; then
1239		. /etc/start_if.$1
1240		return 0
1241	else
1242		return 1
1243	fi
1244}
1245
1246# ifscript_down if
1247#	Evaluate a shutdown script for the $if interface.
1248#	It returns 0 if a script was found and processed or
1249#	1 if no script was found.
1250#
1251ifscript_down()
1252{
1253	if [ -r /etc/stop_if.$1 ]; then
1254		. /etc/stop_if.$1
1255		return 0
1256	else
1257		return 1
1258	fi
1259}
1260
1261# clone_up
1262#	Create cloneable interfaces.
1263#
1264clone_up()
1265{
1266	local _list ifn ifopt _iflist _n tmpargs
1267	_list=
1268	_iflist=$*
1269
1270	# create_args_IF
1271	for ifn in ${cloned_interfaces}; do
1272		# Parse ifn:ifopt.
1273		OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1274		case $_iflist in
1275		""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn)	;;
1276		*)	continue ;;
1277		esac
1278		case $ifn in
1279		epair[0-9]*)
1280			# epair(4) uses epair[0-9] for creation and
1281			# epair[0-9][ab] for configuration.
1282			#
1283			# Skip if ${ifn}a or ${ifn}b already exist.
1284			if ${IFCONFIG_CMD} ${ifn}a > /dev/null 2>&1; then
1285				continue
1286			elif ${IFCONFIG_CMD} ${ifn}b > /dev/null 2>&1; then
1287				continue
1288			fi
1289			${IFCONFIG_CMD} ${ifn} create \
1290			    `get_if_var ${ifn} create_args_IF`
1291			if [ $? -eq 0 ]; then
1292				_list="$_list ${ifn}a ${ifn}b"
1293			fi
1294		;;
1295		*)
1296			# Skip if ${ifn} already exists.
1297			if ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1298				continue
1299			fi
1300			${IFCONFIG_CMD} ${ifn} create \
1301			    `get_if_var ${ifn} create_args_IF`
1302			if [ $? -eq 0 ]; then
1303				_list="$_list $ifn"
1304			fi
1305		esac
1306	done
1307	if [ -n "$gif_interfaces" ]; then
1308		warn "\$gif_interfaces is obsolete.  Use \$cloned_interfaces instead."
1309	fi
1310	for ifn in ${gif_interfaces}; do
1311		# Parse ifn:ifopt.
1312		OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1313		case $_iflist in
1314		""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn)	;;
1315		*)	continue ;;
1316		esac
1317		# Skip if ifn already exists.
1318		if ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1319			continue
1320		fi
1321		case $ifn in
1322		gif[0-9]*)
1323			${IFCONFIG_CMD} $ifn create
1324		;;
1325		*)
1326			_n=$(${IFCONFIG_CMD} gif create)
1327			${IFCONFIG_CMD} $_n name $ifn
1328		;;
1329		esac
1330		if [ $? -eq 0 ]; then
1331			_list="$_list $ifn"
1332		fi
1333		tmpargs=$(get_if_var $ifn gifconfig_IF)
1334		eval ifconfig_${ifn}=\"tunnel \$tmpargs\"
1335	done
1336	if [ -n "${_list# }" ]; then
1337		echo "Created clone interfaces: ${_list# }."
1338	fi
1339	debug "Cloned: ${_list# }"
1340}
1341
1342# clone_down
1343#	Destroy cloned interfaces. Destroyed interfaces are echoed to
1344#	standard output.
1345#
1346clone_down()
1347{
1348	local _list ifn _difn ifopt _iflist _sticky
1349	_list=
1350	_iflist=$*
1351
1352	: ${cloned_interfaces_sticky:=NO}
1353	if checkyesno cloned_interfaces_sticky; then
1354		_sticky=1
1355	else
1356		_sticky=0
1357	fi
1358	for ifn in ${cloned_interfaces} ${gif_interfaces}; do
1359		# Parse ifn:ifopt.
1360		OIFS=$IFS; IFS=:; set -- $ifn; ifn=$1; ifopt=$2; IFS=$OIFS
1361		case $ifopt:$_sticky in
1362		sticky:*)	continue ;;	# :sticky => not destroy
1363		nosticky:*)	;;		# :nosticky => destroy
1364		*:1)		continue ;;	# global sticky knob == 1
1365		esac
1366		case $_iflist in
1367		""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn)	;;
1368		*)	continue ;;
1369		esac
1370		case $ifn in
1371		epair[0-9]*)
1372			# Note: epair(4) uses epair[0-9] for removal and
1373			# epair[0-9][ab] for configuration.
1374			#
1375			# Skip if both of ${ifn}a and ${ifn}b do not exist.
1376			if ${IFCONFIG_CMD} ${ifn}a > /dev/null 2>&1; then
1377				_difn=${ifn}a
1378			elif ${IFCONFIG_CMD} ${ifn}b > /dev/null 2>&1; then
1379				_difn=${ifn}b
1380			else
1381				continue
1382			fi
1383			${IFCONFIG_CMD} -n $_difn destroy
1384			if [ $? -eq 0 ]; then
1385				_list="$_list ${ifn}a ${ifn}b"
1386			fi
1387		;;
1388		*)
1389			# Skip if ifn does not exist.
1390			if ! ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
1391				continue
1392			fi
1393			${IFCONFIG_CMD} -n ${ifn} destroy
1394			if [ $? -eq 0 ]; then
1395				_list="$_list $ifn"
1396			fi
1397		;;
1398		esac
1399	done
1400	if [ -n "${_list# }" ]; then
1401		echo "Destroyed clone interfaces: ${_list# }."
1402	fi
1403	debug "Destroyed clones: ${_list# }"
1404}
1405
1406# childif_create
1407#	Create and configure child interfaces.  Return 0 if child
1408#	interfaces are created.
1409#
1410childif_create()
1411{
1412	local cfg child child_vlans child_wlans create_args debug_flags ifn i
1413	cfg=1
1414	ifn=$1
1415
1416	# Create wireless interfaces
1417	child_wlans=`get_if_var $ifn wlans_IF`
1418
1419	for child in ${child_wlans}; do
1420		create_args="wlandev $ifn `get_if_var $child create_args_IF`"
1421		debug_flags="`get_if_var $child wlandebug_IF`"
1422
1423		if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
1424			${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1425			if [ -n "${debug_flags}" ]; then
1426				wlandebug -i $child ${debug_flags}
1427			fi
1428		else
1429			i=`${IFCONFIG_CMD} wlan create ${create_args}`
1430			if [ -n "${debug_flags}" ]; then
1431				wlandebug -i $i ${debug_flags}
1432			fi
1433			${IFCONFIG_CMD} $i name $child && cfg=0
1434		fi
1435		if autoif $child; then
1436			ifn_start $child
1437		fi
1438	done
1439
1440	# Create vlan interfaces
1441	child_vlans=`get_if_var $ifn vlans_IF`
1442
1443	if [ -n "${child_vlans}" ]; then
1444		load_kld if_vlan
1445	fi
1446
1447	for child in ${child_vlans}; do
1448		if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1449			child="${ifn}.${child}"
1450			create_args=`get_if_var $child create_args_IF`
1451			${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1452		else
1453			create_args="vlandev $ifn `get_if_var $child create_args_IF`"
1454			if expr $child : 'vlan[0-9][0-9]*$' >/dev/null 2>&1; then
1455				${IFCONFIG_CMD} $child create ${create_args} && cfg=0
1456			else
1457				i=`${IFCONFIG_CMD} vlan create ${create_args}`
1458				${IFCONFIG_CMD} $i name $child && cfg=0
1459			fi
1460		fi
1461		if autoif $child; then
1462			ifn_start $child
1463		fi
1464	done
1465
1466	return ${cfg}
1467}
1468
1469# childif_destroy
1470#	Destroy child interfaces.
1471#
1472childif_destroy()
1473{
1474	local cfg child child_vlans child_wlans ifn
1475	cfg=1
1476
1477	child_wlans=`get_if_var $ifn wlans_IF`
1478	for child in ${child_wlans}; do
1479		if ! ifexists $child; then
1480			continue
1481		fi
1482		${IFCONFIG_CMD} -n $child destroy && cfg=0
1483	done
1484
1485	child_vlans=`get_if_var $ifn vlans_IF`
1486	for child in ${child_vlans}; do
1487		if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1488			child="${ifn}.${child}"
1489		fi
1490		if ! ifexists $child; then
1491			continue
1492		fi
1493		${IFCONFIG_CMD} -n $child destroy && cfg=0
1494	done
1495
1496	return ${cfg}
1497}
1498
1499# ng_mkpeer
1500#	Create netgraph nodes.
1501#
1502ng_mkpeer()
1503{
1504	ngctl -f - 2> /dev/null <<EOF
1505mkpeer $*
1506msg dummy nodeinfo
1507EOF
1508}
1509
1510# ng_create_one
1511#	Create netgraph nodes.
1512#
1513ng_create_one()
1514{
1515	local t
1516
1517	ng_mkpeer $* | while read line; do
1518		t=`expr "${line}" : '.* name="\([a-z]*[0-9]*\)" .*'`
1519		if [ -n "${t}" ]; then
1520			echo ${t}
1521			return
1522		fi
1523	done
1524}
1525
1526# ng_fec_create ifn
1527#	Configure Fast EtherChannel for interface $ifn. Returns 0 if
1528#	FEC arguments were found and configured; returns !0 otherwise.
1529ng_fec_create()
1530{
1531	 local req_iface iface bogus
1532	 req_iface="$1"
1533
1534	 ngctl shutdown ${req_iface}: > /dev/null 2>&1
1535
1536	 bogus=""
1537	 while true; do
1538		 iface=`ng_create_one fec dummy fec`
1539		 if [ -z "${iface}" ]; then
1540			 exit 2
1541		 fi
1542		 if [ "${iface}" = "${req_iface}" ]; then
1543			 break
1544		 fi
1545		 bogus="${bogus} ${iface}"
1546	 done
1547
1548	 for iface in ${bogus}; do
1549		 ngctl shutdown ${iface}:
1550	 done
1551}
1552
1553# fec_up
1554#	Create Fast EtherChannel interfaces.
1555fec_up()
1556{
1557	local i j
1558
1559	for i in ${fec_interfaces}; do
1560		ng_fec_create $i
1561		for j in `get_if_var $i fecconfig_IF`; do
1562			case ${j} in
1563			'')
1564				continue
1565				;;
1566			*)
1567				ngctl msg ${i}: add_iface "\"${j}\""
1568				;;
1569			esac
1570		done
1571	done
1572}
1573
1574# ipx_up ifn
1575#	Configure any IPX addresses for interface $ifn. Returns 0 if
1576#	IPX arguments were found and configured; returns 1 otherwise.
1577#
1578ipx_up()
1579{
1580	local ifn
1581	ifn="$1"
1582
1583	# ifconfig_IF_ipx
1584	ifconfig_args=`_ifconfig_getargs $ifn ipx`
1585	if [ -n "${ifconfig_args}" ]; then
1586		${IFCONFIG_CMD} ${ifn} ${ifconfig_args}
1587		return 0
1588	fi
1589
1590	return 1
1591}
1592
1593# ipx_down ifn
1594#	Remove IPX addresses for interface $ifn. Returns 0 if IPX
1595#	addresses were found and unconfigured. It returns 1, otherwise.
1596#
1597ipx_down()
1598{
1599	local _if _ifs _ret ipxList oldifs _ipx
1600	_if=$1
1601	_ifs="^"
1602	_ret=1
1603	ipxList="`${IFCONFIG_CMD} ${_if} | grep 'ipx ' | tr "\n" "$_ifs"`"
1604	oldifs="$IFS"
1605
1606	IFS="$_ifs"
1607	for _ipx in $ipxList ; do
1608		# get rid of extraneous line
1609		[ -z "$_ipx" ] && break
1610
1611		_ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'`
1612
1613		IFS="$oldifs"
1614		${IFCONFIG_CMD} ${_if} ${_ipx} delete
1615		IFS="$_ifs"
1616		_ret=0
1617	done
1618	IFS="$oldifs"
1619
1620	return $_ret
1621}
1622
1623# ifnet_rename [ifname]
1624#	Rename interfaces if ifconfig_IF_name is defined.
1625#
1626ifnet_rename()
1627{
1628	local _if _ifname
1629
1630	# ifconfig_IF_name
1631	for _if in ${*:-$(${IFCONFIG_CMD} -l)}; do
1632		_ifname=`get_if_var $_if ifconfig_IF_name`
1633		if [ ! -z "$_ifname" ]; then
1634			${IFCONFIG_CMD} $_if name $_ifname
1635		fi
1636	done
1637
1638	return 0
1639}
1640
1641# list_net_interfaces type
1642#	List all network interfaces. The type of interface returned
1643#	can be controlled by the type argument. The type
1644#	argument can be any of the following:
1645#		nodhcp	- all interfaces, excluding DHCP configured interfaces
1646#		dhcp	- list only DHCP configured interfaces
1647#		noautoconf	- all interfaces, excluding IPv6 Stateless
1648#				  Address Autoconf configured interfaces
1649#		autoconf	- list only IPv6 Stateless Address Autoconf
1650#				  configured interfaces
1651#	If no argument is specified all network interfaces are output.
1652#	Note that the list will include cloned interfaces if applicable.
1653#	Cloned interfaces must already exist to have a chance to appear
1654#	in the list if ${network_interfaces} is set to `auto'.
1655#
1656list_net_interfaces()
1657{
1658	local type _tmplist _list _autolist _lo _if
1659	type=$1
1660
1661	# Get a list of ALL the interfaces and make lo0 first if it's there.
1662	#
1663	_tmplist=
1664	case ${network_interfaces} in
1665	[Aa][Uu][Tt][Oo])
1666		_autolist="`${IFCONFIG_CMD} -l`"
1667		_lo=
1668		for _if in ${_autolist} ; do
1669			if autoif $_if; then
1670				if [ "$_if" = "lo0" ]; then
1671					_lo="lo0 "
1672				else
1673					_tmplist="${_tmplist} ${_if}"
1674				fi
1675			fi
1676		done
1677		_tmplist="${_lo}${_tmplist# }"
1678	;;
1679	*)
1680		for _if in ${network_interfaces} ${cloned_interfaces}; do
1681			# epair(4) uses epair[0-9] for creation and
1682			# epair[0-9][ab] for configuration.
1683			case $_if in
1684			epair[0-9]*)
1685				_tmplist="$_tmplist ${_if}a ${_if}b"
1686			;;
1687			*)
1688				_tmplist="$_tmplist $_if"
1689			;;
1690			esac
1691		done
1692		#
1693		# lo0 is effectively mandatory, so help prevent foot-shooting
1694		#
1695		case "$_tmplist" in
1696		lo0|'lo0 '*|*' lo0'|*' lo0 '*)
1697			# This is fine, do nothing
1698			_tmplist="${_tmplist# }"
1699		;;
1700		*)
1701			_tmplist="lo0 ${_tmplist# }"
1702		;;
1703		esac
1704	;;
1705	esac
1706
1707	_list=
1708	case "$type" in
1709	nodhcp)
1710		for _if in ${_tmplist} ; do
1711			if ! dhcpif $_if && \
1712			   [ -n "`_ifconfig_getargs $_if`" ]; then
1713				_list="${_list# } ${_if}"
1714			fi
1715		done
1716	;;
1717	dhcp)
1718		for _if in ${_tmplist} ; do
1719			if dhcpif $_if; then
1720				_list="${_list# } ${_if}"
1721			fi
1722		done
1723	;;
1724	noautoconf)
1725		for _if in ${_tmplist} ; do
1726			if ! ipv6_autoconfif $_if && \
1727			   [ -n "`_ifconfig_getargs $_if ipv6`" ]; then
1728				_list="${_list# } ${_if}"
1729			fi
1730		done
1731	;;
1732	autoconf)
1733		for _if in ${_tmplist} ; do
1734			if ipv6_autoconfif $_if; then
1735				_list="${_list# } ${_if}"
1736			fi
1737		done
1738	;;
1739	*)
1740		_list=${_tmplist}
1741	;;
1742	esac
1743
1744	echo $_list
1745
1746	return 0
1747}
1748
1749# get_default_if -address_family
1750#	Get the interface of the default route for the given address family.
1751#	The -address_family argument must be suitable passing to route(8).
1752#
1753get_default_if()
1754{
1755	local routeget oldifs defif line
1756	defif=
1757	oldifs="$IFS"
1758	IFS="
1759"
1760	for line in `route -n get $1 default 2>/dev/null`; do
1761		case $line in
1762		*interface:*)
1763			defif=${line##*: }
1764			;;
1765		esac
1766	done
1767	IFS=${oldifs}
1768
1769	echo $defif
1770}
1771
1772# hexdigit arg
1773#	Echo decimal number $arg (single digit) in hexadecimal format.
1774hexdigit()
1775{
1776	printf '%x\n' "$1"
1777}
1778
1779# hexprint arg
1780#	Echo decimal number $arg (multiple digits) in hexadecimal format.
1781hexprint()
1782{
1783	printf '%x\n' "$1"
1784}
1785
1786is_wired_interface()
1787{
1788	local media
1789
1790	case `${IFCONFIG_CMD} $1 2>/dev/null` in
1791	*media:?Ethernet*) media=Ethernet ;;
1792	esac
1793
1794	test "$media" = "Ethernet"
1795}
1796
1797# network6_getladdr if [flag]
1798#	Echo link-local address from $if if any.
1799#	If flag is defined, tentative ones will be excluded.
1800network6_getladdr()
1801{
1802	local _if _flag proto addr rest
1803	_if=$1
1804	_flag=$2
1805
1806	${IFCONFIG_CMD} $_if 2>/dev/null | while read proto addr rest; do
1807		case "${proto}/${addr}/${_flag}/${rest}" in
1808		inet6/fe80::*//*)
1809			echo ${addr}
1810		;;
1811		inet6/fe80:://*tentative*)	# w/o flag
1812			sleep `${SYSCTL_N} net.inet6.ip6.dad_count`
1813			network6_getladdr $_if $_flags
1814		;;
1815		inet6/fe80::/*/*tentative*)	# w/ flag
1816			echo ${addr}
1817		;;
1818		*)
1819			continue
1820		;;
1821		esac
1822
1823		return
1824	done
1825}
1826