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