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