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