network.subr revision 226652
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 226652 2011-10-23 07:37:36Z 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_common ${_if} alias && _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	ipv6_prefix_hostid_addr_common ${_if} -alias && _ret=0
616	ifalias_down ${_if} inet6 && _ret=0
617
618	inetList="`ifconfig ${_if} | grep 'inet6 ' | tr "\n" "$_ifs"`"
619
620	oldifs="$IFS"
621	IFS="$_ifs"
622	for _inet6 in $inetList ; do
623		# get rid of extraneous line
624		[ -z "$_inet6" ] && break
625
626		_inet6=`expr "$_inet6" : '.*\(inet6 \([0-9a-f:]*\)\).*'`
627
628		IFS="$oldifs"
629		ifconfig ${_if} ${_inet6} -alias
630		IFS="$_ifs"
631		_ret=0
632	done
633	IFS="$oldifs"
634
635	return $_ret
636}
637
638# ipv4_addrs_common if action
639#	Evaluate the ifconfig_if_ipv4 arguments for interface $if and
640#	use $action to add or remove IPv4 addresses from $if.
641ipv4_addrs_common()
642{
643	local _ret _if _action _cidr _cidr_addr
644	local _ipaddr _netmask _range _ipnet _iplow _iphigh _ipcount
645	_ret=1
646	_if=$1
647	_action=$2
648
649	# get ipv4-addresses
650	cidr_addr=`get_if_var $_if ipv4_addrs_IF`
651
652	for _cidr in ${cidr_addr}; do
653		_ipaddr=${_cidr%%/*}
654		_netmask="/"${_cidr##*/}
655		_range=${_ipaddr##*.}
656		_ipnet=${_ipaddr%.*}
657		_iplow=${_range%-*}
658		_iphigh=${_range#*-}
659
660		# clear netmask when removing aliases
661		if [ "${_action}" = "-alias" ]; then
662			_netmask=""
663		fi
664
665		_ipcount=${_iplow}
666		while [ "${_ipcount}" -le "${_iphigh}" ]; do
667			eval "ifconfig ${_if} ${_action} ${_ipnet}.${_ipcount}${_netmask}"
668			_ipcount=$((${_ipcount}+1))
669			_ret=0
670
671			# only the first ipaddr in a subnet need the real netmask
672			if [ "${_action}" != "-alias" ]; then
673				_netmask="/32"
674			fi
675		done
676	done
677
678	return $_ret
679}
680
681# ifalias_up if af
682#	Configure aliases for network interface $if.
683#	It returns 0 if at least one alias was configured or
684#	1 if there were none.
685#
686ifalias_up()
687{
688	local _ret
689	_ret=1
690
691	case "$2" in
692	inet)
693		_ret=`ifalias_ipv4_up "$1"`
694		;;
695	inet6)
696		_ret=`ifalias_ipv6_up "$1"`
697		;;
698	esac
699
700	return $_ret
701}
702
703# ifalias_ipv4_up if
704#	Helper function for ifalias_up().  Handles IPv4.
705#
706ifalias_ipv4_up()
707{
708	local _ret alias ifconfig_args
709	_ret=1
710
711	# ifconfig_IF_aliasN which starts with "inet"
712	alias=0
713	while : ; do
714		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
715		case "${ifconfig_args}" in
716		inet\ *)
717			ifconfig $1 ${ifconfig_args} alias && _ret=0
718			;;
719		"")
720			break
721			;;
722		esac
723		alias=$((${alias} + 1))
724	done
725
726	return $_ret
727}
728
729# ifalias_ipv6_up if
730#	Helper function for ifalias_up().  Handles IPv6.
731#
732ifalias_ipv6_up()
733{
734	local _ret alias ifconfig_args
735	_ret=1
736
737	# ifconfig_IF_aliasN which starts with "inet6"
738	alias=0
739	while : ; do
740		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
741		case "${ifconfig_args}" in
742		inet6\ *)
743			ifconfig $1 ${ifconfig_args} alias && _ret=0
744			;;
745		"")
746			break
747			;;
748		esac
749		alias=$((${alias} + 1))
750	done
751
752	# backward compatibility: ipv6_ifconfig_IF_aliasN.
753	alias=0
754	while : ; do
755		ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF_alias${alias}`
756		case "${ifconfig_args}" in
757		"")
758			break
759			;;
760		*)
761			ifconfig $1 inet6 ${ifconfig_args} alias && _ret=0
762			warn "\$ipv6_ifconfig_$1_alias${alias} is obsolete." \
763			    "  Use ifconfig_$1_aliasN instead."
764			;;
765		esac
766		alias=$((${alias} + 1))
767	done
768
769	return $_ret
770}
771
772# ifalias_down if af
773#	Remove aliases for network interface $if.
774#	It returns 0 if at least one alias was removed or
775#	1 if there were none.
776#
777ifalias_down()
778{
779	local _ret
780	_ret=1
781
782	case "$2" in
783	inet)
784		_ret=`ifalias_ipv4_down "$1"`
785		;;
786	inet6)
787		_ret=`ifalias_ipv6_down "$1"`
788		;;
789	esac
790
791	return $_ret
792}
793
794# ifalias_ipv4_down if
795#	Helper function for ifalias_down().  Handles IPv4.
796#
797ifalias_ipv4_down()
798{
799	local _ret alias ifconfig_args
800	_ret=1
801
802	# ifconfig_IF_aliasN which starts with "inet"
803	alias=0
804	while : ; do
805		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
806		case "${ifconfig_args}" in
807		inet\ *)
808			ifconfig $1 ${ifconfig_args} -alias && _ret=0
809			;;
810		"")
811			break
812			;;
813		esac
814		alias=$((${alias} + 1))
815	done
816
817	return $_ret
818}
819
820# ifalias_ipv6_down if
821#	Helper function for ifalias_down().  Handles IPv6.
822#
823ifalias_ipv6_down()
824{
825	local _ret alias ifconfig_args
826	_ret=1
827
828	# ifconfig_IF_aliasN which starts with "inet6"
829	alias=0
830	while : ; do
831		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
832		case "${ifconfig_args}" in
833		inet6\ *)
834			ifconfig $1 ${ifconfig_args} -alias && _ret=0
835			;;
836		"")
837			break
838			;;
839		esac
840		alias=$((${alias} + 1))
841	done
842
843	# backward compatibility: ipv6_ifconfig_IF_aliasN.
844	alias=0
845	while : ; do
846		ifconfig_args=`get_if_var $1 ipv6_ifconfig_IF_alias${alias}`
847		case "${ifconfig_args}" in
848		"")
849			break
850			;;
851		*)
852			ifconfig $1 inet6 ${ifconfig_args} -alias && _ret=0
853			warn "\$ipv6_ifconfig_$1_alias${alias} is obsolete." \
854			    "  Use ifconfig_$1_aliasN instead."
855			;;
856		esac
857		alias=$((${alias} + 1))
858	done
859
860	return $_ret
861}
862
863# ipv6_prefix_hostid_addr_common if action
864#	Add or remove IPv6 prefix + hostid addr on the interface $if
865#
866ipv6_prefix_hostid_addr_common()
867{
868	local _if _action prefix laddr hostid j address
869	_if=$1
870	_action=$2
871	prefix=`get_if_var ${_if} ipv6_prefix_IF`
872
873	if [ -n "${prefix}" ]; then
874		laddr=`network6_getladdr ${_if}`
875		hostid=${laddr#fe80::}
876		hostid=${hostid%\%*}
877
878		for j in ${prefix}; do
879			address=$j\:${hostid}
880			ifconfig ${_if} inet6 ${address} prefixlen 64 ${_action}
881
882			# if I am a router, add subnet router
883			# anycast address (RFC 2373).
884			if checkyesno ipv6_gateway_enable; then
885				ifconfig ${_if} inet6 $j:: prefixlen 64 \
886					${_action} anycast
887			fi
888		done
889	fi
890}
891
892# ipv6_accept_rtadv_up if
893#	Enable accepting Router Advertisement and send Router
894#	Solicitation message
895ipv6_accept_rtadv_up()
896{
897	if ipv6_autoconfif $1; then
898		ifconfig $1 inet6 accept_rtadv up
899		if ! checkyesno rtsold_enable; then
900			rtsol ${rtsol_flags} $1
901		fi
902	fi
903}
904
905# ipv6_accept_rtadv_down if
906#	Disable accepting Router Advertisement
907ipv6_accept_rtadv_down()
908{
909	if ipv6_autoconfif $1; then
910		ifconfig $1 inet6 -accept_rtadv
911	fi
912}
913
914# ifscript_up if
915#	Evaluate a startup script for the $if interface.
916#	It returns 0 if a script was found and processed or
917#	1 if no script was found.
918#
919ifscript_up()
920{
921	if [ -r /etc/start_if.$1 ]; then
922		. /etc/start_if.$1
923		return 0
924	else
925		return 1
926	fi
927}
928
929# ifscript_down if
930#	Evaluate a shutdown script for the $if interface.
931#	It returns 0 if a script was found and processed or
932#	1 if no script was found.
933#
934ifscript_down()
935{
936	if [ -r /etc/stop_if.$1 ]; then
937		. /etc/stop_if.$1
938		return 0
939	else
940		return 1
941	fi
942}
943
944# clone_up
945#	Create cloneable interfaces.
946#
947clone_up()
948{
949	local _prefix _list ifn
950	_prefix=
951	_list=
952
953	# create_args_IF
954	for ifn in ${cloned_interfaces}; do
955		ifconfig ${ifn} create `get_if_var ${ifn} create_args_IF`
956		if [ $? -eq 0 ]; then
957			_list="${_list}${_prefix}${ifn}"
958			[ -z "$_prefix" ] && _prefix=' '
959		fi
960	done
961	debug "Cloned: ${_list}"
962}
963
964# clone_down
965#	Destroy cloned interfaces. Destroyed interfaces are echoed to
966#	standard output.
967#
968clone_down()
969{
970	local _prefix _list ifn
971	_prefix=
972	_list=
973
974	for ifn in ${cloned_interfaces}; do
975		ifconfig -n ${ifn} destroy
976		if [ $? -eq 0 ]; then
977			_list="${_list}${_prefix}${ifn}"
978			[ -z "$_prefix" ] && _prefix=' '
979		fi
980	done
981	debug "Destroyed clones: ${_list}"
982}
983
984# childif_create
985#	Create and configure child interfaces.  Return 0 if child
986#	interfaces are created.
987#
988childif_create()
989{
990	local cfg child child_vlans child_wlans create_args debug_flags ifn i
991	cfg=1
992	ifn=$1
993
994	# Create wireless interfaces
995	child_wlans=`get_if_var $ifn wlans_IF`
996
997	for child in ${child_wlans}; do
998		create_args="wlandev $ifn `get_if_var $child create_args_IF`"
999		debug_flags="`get_if_var $child wlandebug_IF`"
1000
1001		if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
1002			ifconfig $child create ${create_args} && cfg=0
1003			if [ -n "${debug_flags}" ]; then
1004				wlandebug -i $child ${debug_flags}
1005			fi
1006		else
1007			i=`ifconfig wlan create ${create_args}`
1008			if [ -n "${debug_flags}" ]; then
1009				wlandebug -i $i ${debug_flags}
1010			fi
1011			ifconfig $i name $child && cfg=0
1012		fi
1013		if autoif $child; then
1014			ifn_start $child
1015		fi
1016	done
1017
1018	# Create vlan interfaces
1019	child_vlans=`get_if_var $ifn vlans_IF`
1020
1021	if [ -n "${child_vlans}" ]; then
1022		load_kld if_vlan
1023	fi
1024
1025	for child in ${child_vlans}; do
1026		if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1027			child="${ifn}.${child}"
1028			create_args=`get_if_var $child create_args_IF`
1029			ifconfig $child create ${create_args} && cfg=0
1030		else
1031			create_args="vlandev $ifn `get_if_var $child create_args_IF`"
1032			if expr $child : 'vlan[0-9][0-9]*$' >/dev/null 2>&1; then
1033				ifconfig $child create ${create_args} && cfg=0
1034			else
1035				i=`ifconfig vlan create ${create_args}`
1036				ifconfig $i name $child && cfg=0
1037			fi
1038		fi
1039		if autoif $child; then
1040			ifn_start $child
1041		fi
1042	done
1043
1044	return ${cfg}
1045}
1046
1047# childif_destroy
1048#	Destroy child interfaces.
1049#
1050childif_destroy()
1051{
1052	local cfg child child_vlans child_wlans ifn
1053	cfg=1
1054
1055	child_wlans=`get_if_var $ifn wlans_IF`
1056	for child in ${child_wlans}; do
1057		if ! ifexists $child; then
1058			continue
1059		fi
1060		ifconfig -n $child destroy && cfg=0
1061	done
1062
1063	child_vlans=`get_if_var $ifn vlans_IF`
1064	for child in ${child_vlans}; do
1065		if expr $child : '[1-9][0-9]*$' >/dev/null 2>&1; then
1066			child="${ifn}.${child}"
1067		fi
1068		if ! ifexists $child; then
1069			continue
1070		fi
1071		ifconfig -n $child destroy && cfg=0
1072	done
1073
1074	return ${cfg}
1075}
1076
1077# ng_mkpeer
1078#	Create netgraph nodes.
1079#
1080ng_mkpeer()
1081{
1082	ngctl -f - 2> /dev/null <<EOF
1083mkpeer $*
1084msg dummy nodeinfo
1085EOF
1086}
1087
1088# ng_create_one
1089#	Create netgraph nodes.
1090#
1091ng_create_one()
1092{
1093	local t
1094
1095	ng_mkpeer $* | while read line; do
1096		t=`expr "${line}" : '.* name="\([a-z]*[0-9]*\)" .*'`
1097		if [ -n "${t}" ]; then
1098			echo ${t}
1099			return
1100		fi
1101	done
1102}
1103
1104# gif_up
1105#	Create gif(4) tunnel interfaces.
1106gif_up()
1107{
1108	local i peers
1109
1110	for i in ${gif_interfaces}; do
1111		peers=`get_if_var $i gifconfig_IF`
1112		case ${peers} in
1113		'')
1114			continue
1115			;;
1116		*)
1117			if expr $i : 'gif[0-9][0-9]*$' >/dev/null 2>&1; then
1118				ifconfig $i create >/dev/null 2>&1
1119			else
1120				gif=`ifconfig gif create`
1121				ifconfig $gif name $i
1122			fi
1123			ifconfig $i tunnel ${peers}
1124			ifconfig $i up
1125			;;
1126		esac
1127	done
1128}
1129
1130# ng_fec_create ifn
1131#	Configure Fast EtherChannel for interface $ifn. Returns 0 if
1132#	FEC arguments were found and configured; returns !0 otherwise.
1133ng_fec_create()
1134{
1135	 local req_iface iface bogus
1136	 req_iface="$1"
1137
1138	 ngctl shutdown ${req_iface}: > /dev/null 2>&1
1139
1140	 bogus=""
1141	 while true; do
1142		 iface=`ng_create_one fec dummy fec`
1143		 if [ -z "${iface}" ]; then
1144			 exit 2
1145		 fi
1146		 if [ "${iface}" = "${req_iface}" ]; then
1147			 break
1148		 fi
1149		 bogus="${bogus} ${iface}"
1150	 done
1151
1152	 for iface in ${bogus}; do
1153		 ngctl shutdown ${iface}:
1154	 done
1155}
1156
1157# fec_up
1158#	Create Fast EtherChannel interfaces.
1159fec_up()
1160{
1161	local i j
1162
1163	for i in ${fec_interfaces}; do
1164		ng_fec_create $i
1165		for j in `get_if_var $i fecconfig_IF`; do
1166			case ${j} in
1167			'')
1168				continue
1169				;;
1170			*)
1171				ngctl msg ${i}: add_iface "\"${j}\""
1172				;;
1173			esac
1174		done
1175	done
1176}
1177
1178# ipx_up ifn
1179#	Configure any IPX addresses for interface $ifn. Returns 0 if
1180#	IPX arguments were found and configured; returns 1 otherwise.
1181#
1182ipx_up()
1183{
1184	local ifn
1185	ifn="$1"
1186
1187	# ifconfig_IF_ipx
1188	ifconfig_args=`_ifconfig_getargs $ifn ipx`
1189	if [ -n "${ifconfig_args}" ]; then
1190		ifconfig ${ifn} ${ifconfig_args}
1191		return 0
1192	fi
1193
1194	return 1
1195}
1196
1197# ipx_down ifn
1198#	Remove IPX addresses for interface $ifn. Returns 0 if IPX
1199#	addresses were found and unconfigured. It returns 1, otherwise.
1200#
1201ipx_down()
1202{
1203	local _if _ifs _ret ipxList oldifs _ipx
1204	_if=$1
1205	_ifs="^"
1206	_ret=1
1207	ipxList="`ifconfig ${_if} | grep 'ipx ' | tr "\n" "$_ifs"`"
1208	oldifs="$IFS"
1209
1210	IFS="$_ifs"
1211	for _ipx in $ipxList ; do
1212		# get rid of extraneous line
1213		[ -z "$_ipx" ] && break
1214
1215		_ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'`
1216
1217		IFS="$oldifs"
1218		ifconfig ${_if} ${_ipx} delete
1219		IFS="$_ifs"
1220		_ret=0
1221	done
1222	IFS="$oldifs"
1223
1224	return $_ret
1225}
1226
1227# ifnet_rename
1228#	Rename all requested interfaces.
1229#
1230ifnet_rename()
1231{
1232	local _if _ifname
1233
1234	# ifconfig_IF_name
1235	for _if in `ifconfig -l`; do
1236		_ifname=`get_if_var $_if ifconfig_IF_name`
1237		if [ ! -z "$_ifname" ]; then
1238			ifconfig $_if name $_ifname
1239		fi
1240	done
1241
1242	return 0
1243}
1244
1245# list_net_interfaces type
1246#	List all network interfaces. The type of interface returned
1247#	can be controlled by the type argument. The type
1248#	argument can be any of the following:
1249#		nodhcp	- all interfaces, excluding DHCP configured interfaces
1250#		dhcp	- list only DHCP configured interfaces
1251#		noautoconf	- all interfaces, excluding IPv6 Stateless
1252#				  Address Autoconf configured interfaces
1253#		autoconf	- list only IPv6 Stateless Address Autoconf
1254#				  configured interfaces
1255#	If no argument is specified all network interfaces are output.
1256#	Note that the list will include cloned interfaces if applicable.
1257#	Cloned interfaces must already exist to have a chance to appear
1258#	in the list if ${network_interfaces} is set to `auto'.
1259#
1260list_net_interfaces()
1261{
1262	local type _tmplist _list _autolist _lo _if
1263	type=$1
1264
1265	# Get a list of ALL the interfaces and make lo0 first if it's there.
1266	#
1267	_tmplist=
1268	case ${network_interfaces} in
1269	[Aa][Uu][Tt][Oo])
1270		_autolist="`ifconfig -l`"
1271		_lo=
1272		for _if in ${_autolist} ; do
1273			if autoif $_if; then
1274				if [ "$_if" = "lo0" ]; then
1275					_lo="lo0 "
1276				else
1277					_tmplist="${_tmplist} ${_if}"
1278				fi
1279			fi
1280		done
1281		_tmplist="${_lo}${_tmplist# }"
1282		;;
1283	*)
1284		_tmplist="${network_interfaces} ${cloned_interfaces}"
1285
1286		# lo0 is effectively mandatory, so help prevent foot-shooting
1287		#
1288		case "$_tmplist" in
1289		lo0|'lo0 '*|*' lo0'|*' lo0 '*) ;; # This is fine, do nothing
1290		*)	_tmplist="lo0 ${_tmplist}" ;;
1291		esac
1292		;;
1293	esac
1294
1295	_list=
1296	case "$type" in
1297	nodhcp)
1298		for _if in ${_tmplist} ; do
1299			if ! dhcpif $_if && \
1300			   [ -n "`_ifconfig_getargs $_if`" ]; then
1301				_list="${_list# } ${_if}"
1302			fi
1303		done
1304		;;
1305	dhcp)
1306		for _if in ${_tmplist} ; do
1307			if dhcpif $_if; then
1308				_list="${_list# } ${_if}"
1309			fi
1310		done
1311		;;
1312	noautoconf)
1313		for _if in ${_tmplist} ; do
1314			if ! ipv6_autoconfif $_if && \
1315			   [ -n "`_ifconfig_getargs $_if ipv6`" ]; then
1316				_list="${_list# } ${_if}"
1317			fi
1318		done
1319		;;
1320	autoconf)
1321		for _if in ${_tmplist} ; do
1322			if ipv6_autoconfif $_if; then
1323				_list="${_list# } ${_if}"
1324			fi
1325		done
1326		;;
1327	*)
1328		_list=${_tmplist}
1329		;;
1330	esac
1331
1332	echo $_list
1333
1334	return 0
1335}
1336
1337# get_default_if -address_family
1338#	Get the interface of the default route for the given address family.
1339#	The -address_family argument must be suitable passing to route(8).
1340#
1341get_default_if()
1342{
1343	local routeget oldifs defif line
1344	defif=
1345	oldifs="$IFS"
1346	IFS="
1347"
1348	for line in `route -n get $1 default 2>/dev/null`; do
1349		case $line in
1350		*interface:*)
1351			defif=${line##*: }
1352			;;
1353		esac
1354	done
1355	IFS=${oldifs}
1356
1357	echo $defif
1358}
1359
1360# hexdigit arg
1361#	Echo decimal number $arg (single digit) in hexadecimal format.
1362hexdigit()
1363{
1364	printf '%x\n' "$1"
1365}
1366
1367# hexprint arg
1368#	Echo decimal number $arg (multiple digits) in hexadecimal format.
1369hexprint()
1370{
1371	printf '%x\n' "$1"
1372}
1373
1374is_wired_interface()
1375{
1376	local media
1377
1378	case `ifconfig $1 2>/dev/null` in
1379	*media:?Ethernet*) media=Ethernet ;;
1380	esac
1381
1382	test "$media" = "Ethernet"
1383}
1384
1385# network6_getladdr if [flag]
1386#	Echo link-local address from $if if any.
1387#	If flag is defined, tentative ones will be excluded.
1388network6_getladdr()
1389{
1390	local proto addr rest
1391	ifconfig $1 2>/dev/null | while read proto addr rest; do
1392		case ${proto} in
1393		inet6)
1394			case ${addr} in
1395			fe80::*)
1396				if [ -z "$2" ]; then
1397					echo ${addr}
1398					return
1399				fi
1400				case ${rest} in
1401				*tentative*)
1402					continue
1403					;;
1404				*)
1405					echo ${addr}
1406					return
1407				esac
1408			esac
1409		esac
1410	done
1411}
1412