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