network.subr revision 226649
1#
2# Copyright (c) 2003 The FreeBSD Project. All rights reserved.
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions
6# are met:
7# 1. Redistributions of source code must retain the above copyright
8#    notice, this list of conditions and the following disclaimer.
9# 2. Redistributions in binary form must reproduce the above copyright
10#    notice, this list of conditions and the following disclaimer in the
11#    documentation and/or other materials provided with the distribution.
12#
13# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
14# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16# ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
17# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23# SUCH DAMAGE.
24#
25# $FreeBSD: head/etc/network.subr 226649 2011-10-23 05:56:59Z hrs $
26#
27
28#
29# Subroutines commonly used from network startup scripts.
30# Requires that rc.conf be loaded first.
31#
32
33# ifn_start ifn
34#	Bring up and configure an interface.  If some configuration is
35#	applied, print the interface configuration.
36#
37ifn_start()
38{
39	local ifn cfg
40	ifn="$1"
41	cfg=1
42
43	[ -z "$ifn" ] && err 1 "ifn_start called without an interface"
44
45	ifscript_up ${ifn} && cfg=0
46	ifconfig_up ${ifn} && cfg=0
47	afexists inet && ipv4_up ${ifn} && cfg=0
48	afexists inet6 && ipv6_up ${ifn} && cfg=0
49	afexists ipx && ipx_up ${ifn} && cfg=0
50	childif_create ${ifn} && cfg=0
51
52	return $cfg
53}
54
55# ifn_stop ifn
56#	Shutdown and de-configure an interface.  If action is taken,
57#	print the interface name.
58#
59ifn_stop()
60{
61	local ifn cfg
62	ifn="$1"
63	cfg=1
64
65	[ -z "$ifn" ] && err 1 "ifn_stop called without an interface"
66
67	afexists ipx && ipx_down ${ifn} && cfg=0
68	afexists inet6 && ipv6_down ${ifn} && cfg=0
69	afexists inet && ipv4_down ${ifn} && cfg=0
70	ifconfig_down ${ifn} && cfg=0
71	ifscript_down ${ifn} && cfg=0
72	childif_destroy ${ifn} && cfg=0
73
74	return $cfg
75}
76
77# ifconfig_up if
78#	Evaluate ifconfig(8) arguments for interface $if and
79#	run ifconfig(8) with those arguments. It returns 0 if
80#	arguments were found and executed or 1 if the interface
81#	had no arguments.  Pseudo arguments DHCP and WPA are handled
82#	here.
83#
84ifconfig_up()
85{
86	local _cfg _ipv6_opts ifconfig_args
87	_cfg=1
88
89	# Make sure lo0 always comes up.
90	if [ "$1" = "lo0" ]; then
91		_cfg=0
92	fi
93
94	# ifconfig_IF
95	ifconfig_args=`ifconfig_getargs $1`
96	if [ -n "${ifconfig_args}" ]; then
97		eval ifconfig $1 ${ifconfig_args}
98		_cfg=0
99	fi
100
101	# inet6 specific
102	if afexists inet6; then
103		if checkyesno ipv6_activate_all_interfaces; then
104			_ipv6_opts="-ifdisabled"
105		elif [ "$1" != "lo0" ]; then
106			_ipv6_opts="ifdisabled"
107		fi
108
109		# backward compatibility: $ipv6_enable
110		case $ipv6_enable in
111		[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
112			_ipv6_opts="${_ipv6_opts} accept_rtadv"
113			;;
114		esac
115
116		case $ipv6_cpe_wanif in
117		$1)
118			_ipv6_opts="${_ipv6_opts} -no_radr accept_rtadv"
119		;;
120		esac
121
122		if [ -n "${_ipv6_opts}" ]; then
123			ifconfig $1 inet6 ${_ipv6_opts}
124		fi
125
126		# ifconfig_IF_ipv6
127		ifconfig_args=`ifconfig_getargs $1 ipv6`
128		if [ -n "${ifconfig_args}" ]; then
129			# backward compatibility: inet6 keyword
130			case "${ifconfig_args}" in
131			:*|[0-9a-fA-F]*:*)
132				warn "\$ifconfig_$1_ipv6 needs " \
133				    "\"inet6\" keyword for an IPv6 address."
134				ifconfig_args="inet6 ${ifconfig_args}"
135			;;
136			esac
137			ifconfig $1 inet6 -ifdisabled
138			eval ifconfig $1 ${ifconfig_args}
139			_cfg=0
140		fi
141
142		# backward compatiblity: $ipv6_ifconfig_IF
143		ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF`
144		if [ -n "${ifconfig_args}" ]; then
145			warn "\$ipv6_ifconfig_$1 is obsolete." \
146			    "  Use ifconfig_$1_ipv6 instead."
147			ifconfig $1 inet6 -ifdisabled
148			eval ifconfig $1 inet6 ${ifconfig_args}
149			_cfg=0
150		fi
151	fi
152
153	if [ ${_cfg} -eq 0 ]; then
154		ifconfig $1 up
155	fi
156
157	if wpaif $1; then
158		/etc/rc.d/wpa_supplicant start $1
159		_cfg=0		# XXX: not sure this should count
160	fi
161
162	if dhcpif $1; then
163		if [ $_cfg -ne 0 ] ; then
164			ifconfig $1 up
165		fi
166		if syncdhcpif $1; then
167			/etc/rc.d/dhclient start $1
168		fi
169		_cfg=0
170	fi
171
172	return $_cfg
173}
174
175# ifconfig_down if
176#	returns 1 if wpa_supplicant or dhclient was stopped or
177#	the interface exists.
178#
179ifconfig_down()
180{
181	local _cfg
182	_cfg=1
183
184	if wpaif $1; then
185		/etc/rc.d/wpa_supplicant stop $1
186		_cfg=0
187	fi
188
189	if dhcpif $1; then
190		/etc/rc.d/dhclient stop $1
191		_cfg=0
192	fi
193
194	if ifexists $1; then
195		ifconfig $1 down
196		_cfg=0
197	fi
198
199	return $_cfg
200}
201
202# get_if_var if var [default]
203#	Return the value of the pseudo-hash corresponding to $if where
204#	$var is a string containg the sub-string "IF" which will be
205#	replaced with $if after the characters defined in _punct are
206#	replaced with '_'. If the variable is unset, replace it with
207#	$default if given.
208get_if_var()
209{
210	local _if _punct _punct_c _var _default prefix suffix
211
212	if [ $# -ne 2 -a $# -ne 3 ]; then
213		err 3 'USAGE: get_if_var name var [default]'
214	fi
215
216	_if=$1
217	_punct=". - / +"
218	for _punct_c in $_punct; do
219		_if=`ltr ${_if} ${_punct_c} '_'`
220	done
221	_var=$2
222	_default=$3
223
224	prefix=${_var%%IF*}
225	suffix=${_var##*IF}
226	eval echo \${${prefix}${_if}${suffix}-${_default}}
227}
228
229# _ifconfig_getargs if [af]
230#	Prints the arguments for the supplied interface to stdout.
231#	Returns 1 if empty.  In general, ifconfig_getargs should be used
232#	outside this file.
233_ifconfig_getargs()
234{
235	local _ifn _af
236	_ifn=$1
237	_af=${2+_$2}
238
239	if [ -z "$_ifn" ]; then
240		return 1
241	fi
242
243	get_if_var $_ifn ifconfig_IF$_af "$ifconfig_DEFAULT"
244}
245
246# ifconfig_getargs if [af]
247#	Takes the result from _ifconfig_getargs and removes pseudo
248#	args such as DHCP and WPA.
249ifconfig_getargs()
250{
251	local _tmpargs _arg _args
252	_tmpargs=`_ifconfig_getargs $1 $2`
253	if [ $? -eq 1 ]; then
254		return 1
255	fi
256	_args=
257
258	for _arg in $_tmpargs; do
259		case $_arg in
260		[Dd][Hh][Cc][Pp]) ;;
261		[Nn][Oo][Aa][Uu][Tt][Oo]) ;;
262		[Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]) ;;
263		[Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]) ;;
264		[Ww][Pp][Aa]) ;;
265		*)
266			_args="$_args $_arg"
267			;;
268		esac
269	done
270
271	echo $_args
272}
273
274# autoif
275#	Returns 0 if the interface should be automatically configured at
276#	boot time and 1 otherwise.
277autoif()
278{
279	local _tmpargs _arg
280	_tmpargs=`_ifconfig_getargs $1`
281
282	for _arg in $_tmpargs; do
283		case $_arg in
284		[Nn][Oo][Aa][Uu][Tt][Oo])
285			return 1
286			;;
287		esac
288	done
289
290	return 0
291}
292
293# dhcpif if
294#	Returns 0 if the interface is a DHCP interface and 1 otherwise.
295dhcpif()
296{
297	local _tmpargs _arg
298	_tmpargs=`_ifconfig_getargs $1`
299
300	if noafif $1; then
301		return 1
302	fi
303
304	for _arg in $_tmpargs; do
305		case $_arg in
306		[Dd][Hh][Cc][Pp])
307			return 0
308			;;
309		[Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
310			return 0
311			;;
312		[Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
313			return 0
314			;;
315		esac
316	done
317
318	return 1
319}
320
321# syncdhcpif
322#	Returns 0 if the interface should be configured synchronously and
323#	1 otherwise.
324syncdhcpif()
325{
326	local _tmpargs _arg
327	_tmpargs=`_ifconfig_getargs $1`
328
329	if noafif $1; then
330		return 1
331	fi
332
333	for _arg in $_tmpargs; do
334		case $_arg in
335		[Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
336			return 1
337			;;
338		[Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
339			return 0
340			;;
341		esac
342	done
343
344	checkyesno synchronous_dhclient
345}
346
347# wpaif if
348#	Returns 0 if the interface is a WPA interface and 1 otherwise.
349wpaif()
350{
351	local _tmpargs _arg
352	_tmpargs=`_ifconfig_getargs $1`
353
354	for _arg in $_tmpargs; do
355		case $_arg in
356		[Ww][Pp][Aa])
357			return 0
358			;;
359		esac
360	done
361
362	return 1
363}
364
365# afexists af
366#	Returns 0 if the address family is enabled in the kernel
367#	1 otherwise.
368afexists()
369{
370	local _af
371	_af=$1
372
373	case ${_af} in
374	inet|inet6)
375		check_kern_features ${_af}
376		;;
377	ipx)
378		${SYSCTL_N} net.ipx > /dev/null 2>&1
379		;;
380	atm)
381		if [ -x /sbin/atmconfig ]; then
382			/sbin/atmconfig diag list > /dev/null 2>&1
383		else
384			return 1
385		fi
386		;;
387	*)
388		err 1 "afexists(): Unsupported address family: $_af"
389		;;
390	esac
391}
392
393# noafif if
394#	Returns 0 if the interface has no af configuration and 1 otherwise.
395noafif()
396{
397	local _if
398	_if=$1
399
400	case $_if in
401	pflog[0-9]*|\
402	pfsync[0-9]*|\
403	an[0-9]*|\
404	ath[0-9]*|\
405	ipw[0-9]*|\
406	ipfw[0-9]*|\
407	iwi[0-9]*|\
408	iwn[0-9]*|\
409	ral[0-9]*|\
410	wi[0-9]*|\
411	wl[0-9]*|\
412	wpi[0-9]*)
413		return 0
414		;;
415	esac
416
417	return 1
418}
419
420# ipv6if if
421#	Returns 0 if the interface should be configured for IPv6 and
422#	1 otherwise.
423ipv6if()
424{
425	local _if _tmpargs i
426	_if=$1
427
428	if ! afexists inet6; then
429		return 1
430	fi
431
432	# lo0 is always IPv6-enabled
433	case $_if in
434	lo0)
435		return 0
436		;;
437	esac
438
439	case "${ipv6_network_interfaces}" in
440	$_if|"$_if "*|*" $_if"|*" $_if "*|[Aa][Uu][Tt][Oo])
441		# True if $ifconfig_IF_ipv6 is defined.
442		_tmpargs=`_ifconfig_getargs $_if ipv6`
443		if [ -n "${_tmpargs}" ]; then
444			return 0
445		fi
446
447		# backward compatibility: True if $ipv6_ifconfig_IF is defined.
448		_tmpargs=`get_if_var $_if ipv6_ifconfig_IF`
449		if [ -n "${_tmpargs}" ]; then
450			return 0
451		fi
452		;;
453	esac
454
455	return 1
456}
457
458# ipv6_autoconfif if
459#	Returns 0 if the interface should be configured for IPv6 with
460#	Stateless Address Configuration; 1 otherwise.
461ipv6_autoconfif()
462{
463	local _if _tmpargs _arg
464	_if=$1
465
466	case $_if in
467	lo0|\
468	stf[0-9]*|\
469	faith[0-9]*|\
470	lp[0-9]*|\
471	sl[0-9]*)
472		return 1
473		;;
474	esac
475	if noafif $_if; then
476		return 1
477	fi
478	if ! ipv6if $_if; then
479		return 1
480	fi
481	if checkyesno ipv6_gateway_enable; then
482		return 1
483	fi
484	_tmpargs=`get_if_var $_if ipv6_prefix_IF`
485	if [ -n "${_tmpargs}" ]; then
486		return 1
487	fi
488	# backward compatibility: $ipv6_enable
489	case $ipv6_enable in
490	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
491		return 0
492	;;
493	esac
494
495	_tmpargs=`_ifconfig_getargs $_if ipv6`
496	for _arg in $_tmpargs; do
497		case $_arg in
498		accept_rtadv)
499			return 0
500			;;
501		esac
502	done
503
504	# backward compatibility: $ipv6_ifconfig_IF
505	_tmpargs=`get_if_var $_if ipv6_ifconfig_IF`
506	for _arg in $_tmpargs; do
507		case $_arg in
508		accept_rtadv)
509			return 0
510			;;
511		esac
512	done
513
514	return 1
515}
516
517# ifexists if
518#	Returns 0 if the interface exists and 1 otherwise.
519ifexists()
520{
521	[ -z "$1" ] && return 1
522	ifconfig -n $1 > /dev/null 2>&1
523}
524
525# ipv4_up if
526#	add IPv4 addresses to the interface $if
527ipv4_up()
528{
529	local _if _ret
530	_if=$1
531	_ret=1
532
533	# Add 127.0.0.1/8 to lo0 unless otherwise specified.
534	if [ "${_if}" = "lo0" ]; then
535		ifconfig_args=`get_if_var ${_if} ifconfig_IF`
536		if [ -z "${ifconfig_args}" ]; then
537			ifconfig ${_if} inet 127.0.0.1/8 alias
538		fi
539	fi
540	ifalias_up ${_if} inet && _ret=0
541	ipv4_addrs_common ${_if} alias && _ret=0
542
543	return $_ret
544}
545
546# ipv6_up if
547#	add IPv6 addresses to the interface $if
548ipv6_up()
549{
550	local _if _ret
551	_if=$1
552	_ret=1
553
554	if ! ipv6if $_if; then
555		return 0
556	fi
557
558	ifalias_up ${_if} inet6 && _ret=0
559	ipv6_prefix_hostid_addr_up ${_if} && _ret=0
560	ipv6_accept_rtadv_up ${_if} && _ret=0
561
562	# wait for DAD
563	sleep `${SYSCTL_N} net.inet6.ip6.dad_count`
564	sleep 1
565
566	return $_ret
567}
568
569# ipv4_down if
570#	remove IPv4 addresses from the interface $if
571ipv4_down()
572{
573	local _if _ifs _ret inetList oldifs _inet
574	_if=$1
575	_ifs="^"
576	_ret=1
577
578	inetList="`ifconfig ${_if} | grep 'inet ' | tr "\n" "$_ifs"`"
579
580	oldifs="$IFS"
581	IFS="$_ifs"
582	for _inet in $inetList ; do
583		# get rid of extraneous line
584		[ -z "$_inet" ] && break
585
586		_inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'`
587
588		IFS="$oldifs"
589		ifconfig ${_if} ${_inet} delete
590		IFS="$_ifs"
591		_ret=0
592	done
593	IFS="$oldifs"
594
595	ifalias_down ${_if} inet && _ret=0
596	ipv4_addrs_common ${_if} -alias && _ret=0
597
598	return $_ret
599}
600
601# ipv6_down if
602#	remove IPv6 addresses from the interface $if
603ipv6_down()
604{
605	local _if _ifs _ret inetList oldifs _inet6
606	_if=$1
607	_ifs="^"
608	_ret=1
609
610	if ! ipv6if $_if; then
611		return 0
612	fi
613
614	ipv6_accept_rtadv_down ${_if} && _ret=0
615	ifalias_down ${_if} inet6 && _ret=0
616
617	inetList="`ifconfig ${_if} | grep 'inet6 ' | tr "\n" "$_ifs"`"
618
619	oldifs="$IFS"
620	IFS="$_ifs"
621	for _inet6 in $inetList ; do
622		# get rid of extraneous line
623		[ -z "$_inet6" ] && break
624
625		_inet6=`expr "$_inet6" : '.*\(inet6 \([0-9a-f:]*\)\).*'`
626
627		IFS="$oldifs"
628		ifconfig ${_if} ${_inet6} -alias
629		IFS="$_ifs"
630		_ret=0
631	done
632	IFS="$oldifs"
633
634	return $_ret
635}
636
637# ipv4_addrs_common if action
638#	Evaluate the ifconfig_if_ipv4 arguments for interface $if and
639#	use $action to add or remove IPv4 addresses from $if.
640ipv4_addrs_common()
641{
642	local _ret _if _action _cidr _cidr_addr
643	local _ipaddr _netmask _range _ipnet _iplow _iphigh _ipcount
644	_ret=1
645	_if=$1
646	_action=$2
647
648	# get ipv4-addresses
649	cidr_addr=`get_if_var $_if ipv4_addrs_IF`
650
651	for _cidr in ${cidr_addr}; do
652		_ipaddr=${_cidr%%/*}
653		_netmask="/"${_cidr##*/}
654		_range=${_ipaddr##*.}
655		_ipnet=${_ipaddr%.*}
656		_iplow=${_range%-*}
657		_iphigh=${_range#*-}
658
659		# clear netmask when removing aliases
660		if [ "${_action}" = "-alias" ]; then
661			_netmask=""
662		fi
663
664		_ipcount=${_iplow}
665		while [ "${_ipcount}" -le "${_iphigh}" ]; do
666			eval "ifconfig ${_if} ${_action} ${_ipnet}.${_ipcount}${_netmask}"
667			_ipcount=$((${_ipcount}+1))
668			_ret=0
669
670			# only the first ipaddr in a subnet need the real netmask
671			if [ "${_action}" != "-alias" ]; then
672				_netmask="/32"
673			fi
674		done
675	done
676
677	return $_ret
678}
679
680# ifalias_up if af
681#	Configure aliases for network interface $if.
682#	It returns 0 if at least one alias was configured or
683#	1 if there were none.
684#
685ifalias_up()
686{
687	local _ret
688	_ret=1
689
690	case "$2" in
691	inet)
692		_ret=`ifalias_ipv4_up "$1"`
693		;;
694	inet6)
695		_ret=`ifalias_ipv6_up "$1"`
696		;;
697	esac
698
699	return $_ret
700}
701
702# ifalias_ipv4_up if
703#	Helper function for ifalias_up().  Handles IPv4.
704#
705ifalias_ipv4_up()
706{
707	local _ret alias ifconfig_args
708	_ret=1
709
710	# ifconfig_IF_aliasN which starts with "inet"
711	alias=0
712	while : ; do
713		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
714		case "${ifconfig_args}" in
715		inet\ *)
716			ifconfig $1 ${ifconfig_args} alias && _ret=0
717			;;
718		"")
719			break
720			;;
721		esac
722		alias=$((${alias} + 1))
723	done
724
725	return $_ret
726}
727
728# ifalias_ipv6_up if
729#	Helper function for ifalias_up().  Handles IPv6.
730#
731ifalias_ipv6_up()
732{
733	local _ret alias ifconfig_args
734	_ret=1
735
736	# ifconfig_IF_aliasN which starts with "inet6"
737	alias=0
738	while : ; do
739		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
740		case "${ifconfig_args}" in
741		inet6\ *)
742			ifconfig $1 ${ifconfig_args} alias && _ret=0
743			;;
744		"")
745			break
746			;;
747		esac
748		alias=$((${alias} + 1))
749	done
750
751	# backward compatibility: ipv6_ifconfig_IF_aliasN.
752	alias=0
753	while : ; do
754		ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF_alias${alias}`
755		case "${ifconfig_args}" in
756		"")
757			break
758			;;
759		*)
760			ifconfig $1 inet6 ${ifconfig_args} alias && _ret=0
761			warn "\$ipv6_ifconfig_$1_alias${alias} is obsolete." \
762			    "  Use ifconfig_$1_aliasN instead."
763			;;
764		esac
765		alias=$((${alias} + 1))
766	done
767
768	return $_ret
769}
770
771# ifalias_down if af
772#	Remove aliases for network interface $if.
773#	It returns 0 if at least one alias was removed or
774#	1 if there were none.
775#
776ifalias_down()
777{
778	local _ret
779	_ret=1
780
781	case "$2" in
782	inet)
783		_ret=`ifalias_ipv4_down "$1"`
784		;;
785	inet6)
786		_ret=`ifalias_ipv6_down "$1"`
787		;;
788	esac
789
790	return $_ret
791}
792
793# ifalias_ipv4_down if
794#	Helper function for ifalias_down().  Handles IPv4.
795#
796ifalias_ipv4_down()
797{
798	local _ret alias ifconfig_args
799	_ret=1
800
801	# ifconfig_IF_aliasN which starts with "inet"
802	alias=0
803	while : ; do
804		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
805		case "${ifconfig_args}" in
806		inet\ *)
807			ifconfig $1 ${ifconfig_args} -alias && _ret=0
808			;;
809		"")
810			break
811			;;
812		esac
813		alias=$((${alias} + 1))
814	done
815
816	return $_ret
817}
818
819# ifalias_ipv6_down if
820#	Helper function for ifalias_down().  Handles IPv6.
821#
822ifalias_ipv6_down()
823{
824	local _ret alias ifconfig_args
825	_ret=1
826
827	# ifconfig_IF_aliasN which starts with "inet6"
828	alias=0
829	while : ; do
830		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
831		case "${ifconfig_args}" in
832		inet6\ *)
833			ifconfig $1 ${ifconfig_args} -alias && _ret=0
834			;;
835		"")
836			break
837			;;
838		esac
839		alias=$((${alias} + 1))
840	done
841
842	# backward compatibility: ipv6_ifconfig_IF_aliasN.
843	alias=0
844	while : ; do
845		ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF_alias${alias}`
846		case "${ifconfig_args}" in
847		"")
848			break
849			;;
850		*)
851			ifconfig $1 inet6 ${ifconfig_args} -alias && _ret=0
852			warn "\$ipv6_ifconfig_$1_alias${alias} is obsolete." \
853			    "  Use ifconfig_$1_aliasN instead."
854			;;
855		esac
856		alias=$((${alias} + 1))
857	done
858
859	return $_ret
860}
861
862# ipv6_prefix_hostid_addr_up if
863#	add IPv6 prefix + hostid addr to the interface $if
864ipv6_prefix_hostid_addr_up()
865{
866	local _if prefix laddr hostid j address
867	_if=$1
868	prefix=`get_if_var ${_if} ipv6_prefix_IF`
869
870	if [ -n "${prefix}" ]; then
871		laddr=`network6_getladdr ${_if}`
872		hostid=${laddr#fe80::}
873		hostid=${hostid%\%*}
874
875		for j in ${prefix}; do
876			address=$j\:${hostid}
877			ifconfig ${_if} inet6 ${address} prefixlen 64 alias
878
879			# if I am a router, add subnet router
880			# anycast address (RFC 2373).
881			if checkyesno ipv6_gateway_enable; then
882				ifconfig ${_if} inet6 $j:: prefixlen 64 \
883					alias anycast
884			fi
885		done
886	fi
887}
888
889# ipv6_accept_rtadv_up if
890#	Enable accepting Router Advertisement and send Router
891#	Solicitation message
892ipv6_accept_rtadv_up()
893{
894	if ipv6_autoconfif $1; then
895		ifconfig $1 inet6 accept_rtadv up
896		if ! checkyesno rtsold_enable; then
897			rtsol ${rtsol_flags} $1
898		fi
899	fi
900}
901
902# ipv6_accept_rtadv_down if
903#	Disable accepting Router Advertisement
904ipv6_accept_rtadv_down()
905{
906	if ipv6_autoconfif $1; then
907		ifconfig $1 inet6 -accept_rtadv
908	fi
909}
910
911# ifscript_up if
912#	Evaluate a startup script for the $if interface.
913#	It returns 0 if a script was found and processed or
914#	1 if no script was found.
915#
916ifscript_up()
917{
918	if [ -r /etc/start_if.$1 ]; then
919		. /etc/start_if.$1
920		return 0
921	else
922		return 1
923	fi
924}
925
926# ifscript_down if
927#	Evaluate a shutdown script for the $if interface.
928#	It returns 0 if a script was found and processed or
929#	1 if no script was found.
930#
931ifscript_down()
932{
933	if [ -r /etc/stop_if.$1 ]; then
934		. /etc/stop_if.$1
935		return 0
936	else
937		return 1
938	fi
939}
940
941# clone_up
942#	Create cloneable interfaces.
943#
944clone_up()
945{
946	local _prefix _list ifn
947	_prefix=
948	_list=
949
950	# create_args_IF
951	for ifn in ${cloned_interfaces}; do
952		ifconfig ${ifn} create `get_if_var ${ifn} create_args_IF`
953		if [ $? -eq 0 ]; then
954			_list="${_list}${_prefix}${ifn}"
955			[ -z "$_prefix" ] && _prefix=' '
956		fi
957	done
958	debug "Cloned: ${_list}"
959}
960
961# clone_down
962#	Destroy cloned interfaces. Destroyed interfaces are echoed to
963#	standard output.
964#
965clone_down()
966{
967	local _prefix _list ifn
968	_prefix=
969	_list=
970
971	for ifn in ${cloned_interfaces}; do
972		ifconfig -n ${ifn} destroy
973		if [ $? -eq 0 ]; then
974			_list="${_list}${_prefix}${ifn}"
975			[ -z "$_prefix" ] && _prefix=' '
976		fi
977	done
978	debug "Destroyed clones: ${_list}"
979}
980
981# childif_create
982#	Create and configure child interfaces.  Return 0 if child
983#	interfaces are created.
984#
985childif_create()
986{
987	local cfg child child_vlans child_wlans create_args debug_flags ifn i
988	cfg=1
989	ifn=$1
990
991	# Create wireless interfaces
992	child_wlans=`get_if_var $ifn wlans_IF`
993
994	for child in ${child_wlans}; do
995		create_args="wlandev $ifn `get_if_var $child create_args_IF`"
996		debug_flags="`get_if_var $child wlandebug_IF`"
997
998		if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
999			ifconfig $child create ${create_args} && cfg=0
1000			if [ -n "${debug_flags}" ]; then
1001				wlandebug -i $child ${debug_flags}
1002			fi
1003		else
1004			i=`ifconfig wlan create ${create_args}`
1005			if [ -n "${debug_flags}" ]; then
1006				wlandebug -i $i ${debug_flags}
1007			fi
1008			ifconfig $i name $child && cfg=0
1009		fi
1010		if autoif $child; then
1011			ifn_start $child
1012		fi
1013	done
1014
1015	# Create vlan interfaces
1016	child_vlans=`get_if_var $ifn vlans_IF`
1017
1018	if [ -n "${child_vlans}" ]; then
1019		load_kld if_vlan
1020	fi
1021
1022	for child in ${child_vlans}; do
1023		if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1024			child="${ifn}.${child}"
1025			create_args=`get_if_var $child create_args_IF`
1026			ifconfig $child create ${create_args} && cfg=0
1027		else
1028			create_args="vlandev $ifn `get_if_var $child create_args_IF`"
1029			if expr $child : 'vlan[0-9][0-9]*$' >/dev/null 2>&1; then
1030				ifconfig $child create ${create_args} && cfg=0
1031			else
1032				i=`ifconfig vlan create ${create_args}`
1033				ifconfig $i name $child && cfg=0
1034			fi
1035		fi
1036		if autoif $child; then
1037			ifn_start $child
1038		fi
1039	done
1040
1041	return ${cfg}
1042}
1043
1044# childif_destroy
1045#	Destroy child interfaces.
1046#
1047childif_destroy()
1048{
1049	local cfg child child_vlans child_wlans ifn
1050	cfg=1
1051
1052	child_wlans=`get_if_var $ifn wlans_IF`
1053	for child in ${child_wlans}; do
1054		if ! ifexists $child; then
1055			continue
1056		fi
1057		ifconfig -n $child destroy && cfg=0
1058	done
1059
1060	child_vlans=`get_if_var $ifn vlans_IF`
1061	for child in ${child_vlans}; do
1062		if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1063			child="${ifn}.${child}"
1064		fi
1065		if ! ifexists $child; then
1066			continue
1067		fi
1068		ifconfig -n $child destroy && cfg=0
1069	done
1070
1071	return ${cfg}
1072}
1073
1074# ng_mkpeer
1075#	Create netgraph nodes.
1076#
1077ng_mkpeer()
1078{
1079	ngctl -f - 2> /dev/null <<EOF
1080mkpeer $*
1081msg dummy nodeinfo
1082EOF
1083}
1084
1085# ng_create_one
1086#	Create netgraph nodes.
1087#
1088ng_create_one()
1089{
1090	local t
1091
1092	ng_mkpeer $* | while read line; do
1093		t=`expr "${line}" : '.* name="\([a-z]*[0-9]*\)" .*'`
1094		if [ -n "${t}" ]; then
1095			echo ${t}
1096			return
1097		fi
1098	done
1099}
1100
1101# gif_up
1102#	Create gif(4) tunnel interfaces.
1103gif_up()
1104{
1105	local i peers
1106
1107	for i in ${gif_interfaces}; do
1108		peers=`get_if_var $i gifconfig_IF`
1109		case ${peers} in
1110		'')
1111			continue
1112			;;
1113		*)
1114			if expr $i : 'gif[0-9][0-9]*$' >/dev/null 2>&1; then
1115				ifconfig $i create >/dev/null 2>&1
1116			else
1117				gif=`ifconfig gif create`
1118				ifconfig $gif name $i
1119			fi
1120			ifconfig $i tunnel ${peers}
1121			ifconfig $i up
1122			;;
1123		esac
1124	done
1125}
1126
1127# ng_fec_create ifn
1128#	Configure Fast EtherChannel for interface $ifn. Returns 0 if
1129#	FEC arguments were found and configured; returns !0 otherwise.
1130ng_fec_create()
1131{
1132	 local req_iface iface bogus
1133	 req_iface="$1"
1134
1135	 ngctl shutdown ${req_iface}: > /dev/null 2>&1
1136
1137	 bogus=""
1138	 while true; do
1139		 iface=`ng_create_one fec dummy fec`
1140		 if [ -z "${iface}" ]; then
1141			 exit 2
1142		 fi
1143		 if [ "${iface}" = "${req_iface}" ]; then
1144			 break
1145		 fi
1146		 bogus="${bogus} ${iface}"
1147	 done
1148
1149	 for iface in ${bogus}; do
1150		 ngctl shutdown ${iface}:
1151	 done
1152}
1153
1154# fec_up
1155#	Create Fast EtherChannel interfaces.
1156fec_up()
1157{
1158	local i j
1159
1160	for i in ${fec_interfaces}; do
1161		ng_fec_create $i
1162		for j in `get_if_var $i fecconfig_IF`; do
1163			case ${j} in
1164			'')
1165				continue
1166				;;
1167			*)
1168				ngctl msg ${i}: add_iface "\"${j}\""
1169				;;
1170			esac
1171		done
1172	done
1173}
1174
1175# ipx_up ifn
1176#	Configure any IPX addresses for interface $ifn. Returns 0 if
1177#	IPX arguments were found and configured; returns 1 otherwise.
1178#
1179ipx_up()
1180{
1181	local ifn
1182	ifn="$1"
1183
1184	# ifconfig_IF_ipx
1185	ifconfig_args=`_ifconfig_getargs $ifn ipx`
1186	if [ -n "${ifconfig_args}" ]; then
1187		ifconfig ${ifn} ${ifconfig_args}
1188		return 0
1189	fi
1190
1191	return 1
1192}
1193
1194# ipx_down ifn
1195#	Remove IPX addresses for interface $ifn. Returns 0 if IPX
1196#	addresses were found and unconfigured. It returns 1, otherwise.
1197#
1198ipx_down()
1199{
1200	local _if _ifs _ret ipxList oldifs _ipx
1201	_if=$1
1202	_ifs="^"
1203	_ret=1
1204	ipxList="`ifconfig ${_if} | grep 'ipx ' | tr "\n" "$_ifs"`"
1205	oldifs="$IFS"
1206
1207	IFS="$_ifs"
1208	for _ipx in $ipxList ; do
1209		# get rid of extraneous line
1210		[ -z "$_ipx" ] && break
1211
1212		_ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'`
1213
1214		IFS="$oldifs"
1215		ifconfig ${_if} ${_ipx} delete
1216		IFS="$_ifs"
1217		_ret=0
1218	done
1219	IFS="$oldifs"
1220
1221	return $_ret
1222}
1223
1224# ifnet_rename
1225#	Rename all requested interfaces.
1226#
1227ifnet_rename()
1228{
1229	local _if _ifname
1230
1231	# ifconfig_IF_name
1232	for _if in `ifconfig -l`; do
1233		_ifname=`get_if_var $_if ifconfig_IF_name`
1234		if [ ! -z "$_ifname" ]; then
1235			ifconfig $_if name $_ifname
1236		fi
1237	done
1238
1239	return 0
1240}
1241
1242# list_net_interfaces type
1243#	List all network interfaces. The type of interface returned
1244#	can be controlled by the type argument. The type
1245#	argument can be any of the following:
1246#		nodhcp	- all interfaces, excluding DHCP configured interfaces
1247#		dhcp	- list only DHCP configured interfaces
1248#		noautoconf	- all interfaces, excluding IPv6 Stateless
1249#				  Address Autoconf configured interfaces
1250#		autoconf	- list only IPv6 Stateless Address Autoconf
1251#				  configured interfaces
1252#	If no argument is specified all network interfaces are output.
1253#	Note that the list will include cloned interfaces if applicable.
1254#	Cloned interfaces must already exist to have a chance to appear
1255#	in the list if ${network_interfaces} is set to `auto'.
1256#
1257list_net_interfaces()
1258{
1259	local type _tmplist _list _autolist _lo _if
1260	type=$1
1261
1262	# Get a list of ALL the interfaces and make lo0 first if it's there.
1263	#
1264	_tmplist=
1265	case ${network_interfaces} in
1266	[Aa][Uu][Tt][Oo])
1267		_autolist="`ifconfig -l`"
1268		_lo=
1269		for _if in ${_autolist} ; do
1270			if autoif $_if; then
1271				if [ "$_if" = "lo0" ]; then
1272					_lo="lo0 "
1273				else
1274					_tmplist="${_tmplist} ${_if}"
1275				fi
1276			fi
1277		done
1278		_tmplist="${_lo}${_tmplist# }"
1279		;;
1280	*)
1281		_tmplist="${network_interfaces} ${cloned_interfaces}"
1282
1283		# lo0 is effectively mandatory, so help prevent foot-shooting
1284		#
1285		case "$_tmplist" in
1286		lo0|'lo0 '*|*' lo0'|*' lo0 '*) ;; # This is fine, do nothing
1287		*)	_tmplist="lo0 ${_tmplist}" ;;
1288		esac
1289		;;
1290	esac
1291
1292	_list=
1293	case "$type" in
1294	nodhcp)
1295		for _if in ${_tmplist} ; do
1296			if ! dhcpif $_if && \
1297			   [ -n "`_ifconfig_getargs $_if`" ]; then
1298				_list="${_list# } ${_if}"
1299			fi
1300		done
1301		;;
1302	dhcp)
1303		for _if in ${_tmplist} ; do
1304			if dhcpif $_if; then
1305				_list="${_list# } ${_if}"
1306			fi
1307		done
1308		;;
1309	noautoconf)
1310		for _if in ${_tmplist} ; do
1311			if ! ipv6_autoconfif $_if && \
1312			   [ -n "`_ifconfig_getargs $_if ipv6`" ]; then
1313				_list="${_list# } ${_if}"
1314			fi
1315		done
1316		;;
1317	autoconf)
1318		for _if in ${_tmplist} ; do
1319			if ipv6_autoconfif $_if; then
1320				_list="${_list# } ${_if}"
1321			fi
1322		done
1323		;;
1324	*)
1325		_list=${_tmplist}
1326		;;
1327	esac
1328
1329	echo $_list
1330
1331	return 0
1332}
1333
1334# get_default_if -address_family
1335#	Get the interface of the default route for the given address family.
1336#	The -address_family argument must be suitable passing to route(8).
1337#
1338get_default_if()
1339{
1340	local routeget oldifs defif line
1341	defif=
1342	oldifs="$IFS"
1343	IFS="
1344"
1345	for line in `route -n get $1 default 2>/dev/null`; do
1346		case $line in
1347		*interface:*)
1348			defif=${line##*: }
1349			;;
1350		esac
1351	done
1352	IFS=${oldifs}
1353
1354	echo $defif
1355}
1356
1357# hexdigit arg
1358#	Echo decimal number $arg (single digit) in hexadecimal format.
1359hexdigit()
1360{
1361	printf '%x\n' "$1"
1362}
1363
1364# hexprint arg
1365#	Echo decimal number $arg (multiple digits) in hexadecimal format.
1366hexprint()
1367{
1368	printf '%x\n' "$1"
1369}
1370
1371is_wired_interface()
1372{
1373	local media
1374
1375	case `ifconfig $1 2>/dev/null` in
1376	*media:?Ethernet*) media=Ethernet ;;
1377	esac
1378
1379	test "$media" = "Ethernet"
1380}
1381
1382# network6_getladdr if [flag]
1383#	Echo link-local address from $if if any.
1384#	If flag is defined, tentative ones will be excluded.
1385network6_getladdr()
1386{
1387	local proto addr rest
1388	ifconfig $1 2>/dev/null | while read proto addr rest; do
1389		case ${proto} in
1390		inet6)
1391			case ${addr} in
1392			fe80::*)
1393				if [ -z "$2" ]; then
1394					echo ${addr}
1395					return
1396				fi
1397				case ${rest} in
1398				*tentative*)
1399					continue
1400					;;
1401				*)
1402					echo ${addr}
1403					return
1404				esac
1405			esac
1406		esac
1407	done
1408}
1409