network.subr revision 161386
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 161386 2006-08-17 03:03:38Z brooks $
26#
27
28#
29# Subroutines commonly used from network startup scripts.
30# Requires that rc.conf be loaded first.
31#
32
33# ifconfig_up if
34#	Evaluate ifconfig(8) arguments for interface $if and
35#	run ifconfig(8) with those arguments. It returns 0 if
36#	arguments were found and executed or 1 if the interface
37#	had no arguments.  Pseudo arguments DHCP and WPA are handled
38#	here.
39#
40ifconfig_up()
41{
42	_cfg=1
43
44	ifconfig_args=`ifconfig_getargs $1`
45	if [ -n "${ifconfig_args}" ]; then
46		ifconfig $1 up
47		ifconfig $1 ${ifconfig_args}
48		_cfg=0
49	fi
50
51	if wpaif $1; then
52		if [ $_cfg -ne 0 ] ; then
53			ifconfig $1 up
54		fi
55		/etc/rc.d/wpa_supplicant start $1
56		_cfg=0		# XXX: not sure this should count
57	fi
58
59	if dhcpif $1; then
60		if [ $_cfg -ne 0 ] ; then
61			ifconfig $1 up
62		fi
63		if syncdhcpif $1; then
64			/etc/rc.d/dhclient start $1
65		fi
66		_cfg=0
67	fi
68
69	return $_cfg
70}
71
72# ifconfig_down if
73#	returns 1 if wpa_supplicant or dhclient was stopped or
74#	the interface exists.
75#
76ifconfig_down()
77{
78	[ -z "$1" ] && return 1
79	_cfg=1
80
81	if wpaif $1; then
82		/etc/rc.d/wpa_supplicant stop $1
83		_cfg=0
84	fi
85
86	if dhcpif $1; then
87		/etc/rc.d/dhclient stop $1
88		_cfg=0
89	fi
90
91	if ifexists $1; then
92		ifconfig $1 down
93		_cfg=0
94	fi
95
96	return $_cfg
97}
98
99# get_if_var if var [default]
100#       Return the value of the pseudo-hash corresponding to $if where
101#       $var is a string containg the sub-string "IF" which will be
102#       replaced with $if after the characters defined in _punct are
103#       replaced with '_'. If the variable is unset, replace it with
104#       $default if given.
105get_if_var()
106{
107	if [ $# -ne 2 -a $# -ne 3 ]; then
108		err 3 'USAGE: get_if_var name var [default]'
109	fi
110
111	_if=$1
112	_punct=". - / +"
113	for _punct_c in $_punct; do
114		_if=`ltr ${_if} ${_punct_c} '_'`
115	done
116	_var=$2
117	_default=$3
118
119	prefix=${_var%%IF*}
120	suffix=${_var##*IF}
121	eval echo \${${prefix}${_if}${suffix}-${_default}}
122}
123
124# _ifconfig_getargs if
125#	Echos the arguments for the supplied interface to stdout.
126#	returns 1 if empty.  In general, ifconfig_getargs should be used
127#	outside this file.
128_ifconfig_getargs()
129{
130	_ifn=$1
131	if [ -z "$_ifn" ]; then
132		return 1
133	fi
134
135	get_if_var $_ifn ifconfig_IF "$ifconfig_DEFAULT"
136}
137
138# ifconfig_getargs if
139#	Takes the result from _ifconfig_getargs and removes pseudo
140#	args such as DHCP and WPA.
141ifconfig_getargs()
142{
143	_tmpargs=`_ifconfig_getargs $1`
144	if [ $? -eq 1 ]; then
145		return 1
146	fi
147	_args=
148
149	for _arg in $_tmpargs; do
150		case $_arg in
151		[Dd][Hh][Cc][Pp]) ;;
152		[Nn][Oo][Aa][Uu][Tt][Oo]) ;;
153		[Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]) ;;
154		[Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]) ;;
155		[Ww][Pp][Aa]) ;;
156		*)
157			_args="$_args $_arg"
158			;;
159		esac
160	done
161
162	echo $_args
163}
164
165# autoif
166#	Returns 0 if the interface should be automaticly configured at
167#	boot time and 1 otherwise.
168autoif()
169{
170	_tmpargs=`_ifconfig_getargs $1`
171	for _arg in $_tmpargs; do
172		case $_arg in
173		[Nn][Oo][Aa][Uu][Tt][Oo])
174			return 1
175			;;
176		esac
177	done
178	return 0
179}
180
181# dhcpif if
182#	Returns 0 if the interface is a DHCP interface and 1 otherwise.
183dhcpif()
184{
185	_tmpargs=`_ifconfig_getargs $1`
186	for _arg in $_tmpargs; do
187		case $_arg in
188		[Dd][Hh][Cc][Pp])
189			return 0
190			;;
191		[Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
192			return 0
193			;;
194		[Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
195			return 0
196			;;
197		esac
198	done
199	return 1
200}
201
202# syncdhcpif
203#	Returns 0 if the interface should be configured synchronously and
204#	1 otherwise.
205syncdhcpif()
206{
207	_tmpargs=`_ifconfig_getargs $1`
208	for _arg in $_tmpargs; do
209		case $_arg in
210		[Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
211			return 1
212			;;
213		[Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
214			return 0
215			;;
216		esac
217	done
218	if checkyesno synchronous_dhclient; then
219		return 0
220	else
221		return 1
222	fi
223}
224
225# wpaif if
226#	Returns 0 if the interface is a WPA interface and 1 otherwise.
227wpaif()
228{
229	_tmpargs=`_ifconfig_getargs $1`
230	for _arg in $_tmpargs; do
231		case $_arg in
232		[Ww][Pp][Aa])
233			return 0
234			;;
235		esac
236	done
237	return 1
238}
239
240# ifexists if
241#	Returns 0 if the interface exists and 1 otherwise.
242ifexists()
243{
244	ifconfig $1 > /dev/null 2>&1
245}
246
247# ipv4_up if
248#  add IPv4 addresses to the interface $if 
249ipv4_up()
250{
251	_if=$1
252	ifalias_up ${_if}
253	ipv4_addrs_common ${_if} alias
254}
255
256# ipv4_down if
257#  remove IPv4 addresses from the interface $if
258ipv4_down()
259{
260	_if=$1
261	_ifs="^"
262	_ret=1
263
264	ifexists ${_if} || return 1
265
266	inetList="`ifconfig ${_if} | grep 'inet ' | tr "\n" "$_ifs"`"
267
268	oldifs="$IFS"
269	IFS="$_ifs"
270	for _inet in $inetList ; do
271		# get rid of extraneous line
272		[ -z "$_inet" ] && break
273
274		_inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'`
275
276		IFS="$oldifs"
277		ifconfig ${_if} ${_inet} delete
278		IFS="$_ifs"
279		_ret=0
280	done
281	IFS="$oldifs"
282
283	ifalias_down ${_if} && _ret=0
284	ipv4_addrs_common ${_if} -alias && _ret=0
285
286	return $_ret
287}
288
289# ipv4_addrs_common if action
290#   Evaluate the ifconfig_if_ipv4 arguments for interface $if
291#   and use $action to add or remove IPv4 addresses from $if.
292ipv4_addrs_common()
293{  
294	_ret=1
295	_if=$1
296	_action=$2
297    
298	# get ipv4-addresses
299	cidr_addr=`get_if_var $_if ipv4_addrs_IF`
300    
301	for _cidr in ${cidr_addr}; do
302		_ipaddr=${_cidr%%/*}
303		_netmask="/"${_cidr##*/}
304		_range=${_ipaddr##*.}
305		_ipnet=${_ipaddr%.*}
306		_iplow=${_range%-*}
307		_iphigh=${_range#*-}
308
309		# clear netmask when removing aliases
310		if [ "${_action}" = "-alias" ]; then
311			_netmask=""
312		fi
313        
314		_ipcount=${_iplow}
315		while [ "${_ipcount}" -le "${_iphigh}" ]; do
316			eval "ifconfig ${_if} ${_action} ${_ipnet}.${_ipcount}${_netmask}"
317			_ipcount=$((${_ipcount}+1))
318			_ret=0
319
320			# only the first ipaddr in a subnet need the real netmask
321			if [ "${_action}" != "-alias" ]; then
322				_netmask="/32"
323			fi
324		done
325	done
326	return $_ret
327}
328
329# ifalias_up if
330#	Configure aliases for network interface $if.
331#	It returns 0 if at least one alias was configured or
332#	1 if there were none.
333#
334ifalias_up()
335{
336	_ret=1
337	alias=0
338	while : ; do
339		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
340		if [ -n "${ifconfig_args}" ]; then
341			ifconfig $1 ${ifconfig_args} alias
342			alias=$((${alias} + 1))
343			_ret=0
344		else
345			break
346		fi
347	done
348	return $_ret
349}
350
351#ifalias_down if
352#	Remove aliases for network interface $if.
353#	It returns 0 if at least one alias was removed or
354#	1 if there were none.
355#
356ifalias_down()
357{
358	_ret=1
359	alias=0
360	while : ; do
361		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
362		if [ -n "${ifconfig_args}" ]; then
363			ifconfig $1 ${ifconfig_args} -alias
364			alias=$((${alias} + 1))
365			_ret=0
366		else
367			break
368		fi
369	done
370	return $_ret
371}
372
373# ifscript_up if
374#	Evaluate a startup script for the $if interface.
375#	It returns 0 if a script was found and processed or
376#	1 if no script was found.
377#
378ifscript_up()
379{
380	if [ -r /etc/start_if.$1 ]; then
381		. /etc/start_if.$1
382		return 0
383	fi
384	return 1
385}
386
387# ifscript_down if
388#	Evaluate a shutdown script for the $if interface.
389#	It returns 0 if a script was found and processed or
390#	1 if no script was found.
391#
392ifscript_down()
393{
394	if [ -r /etc/stop_if.$1 ]; then
395		. /etc/stop_if.$1
396		return 0
397	fi
398	return 1
399}
400
401# Create cloneable interfaces.
402#
403clone_up()
404{
405	_prefix=
406	_list=
407	for ifn in ${cloned_interfaces}; do
408		ifconfig ${ifn} create
409		if [ $? -eq 0 ]; then
410			_list="${_list}${_prefix}${ifn}"
411			[ -z "$_prefix" ] && _prefix=' '
412		fi
413	done
414	debug "Cloned: ${_list}"
415}
416
417# Destroy cloned interfaces. Destroyed interfaces are echoed
418# to standard output.
419#
420clone_down()
421{
422	_prefix=
423	_list=
424	for ifn in ${cloned_interfaces}; do
425		ifconfig ${ifn} destroy
426		if [ $? -eq 0 ]; then
427			_list="${_list}${_prefix}${ifn}"
428			[ -z "$_prefix" ] && _prefix=' '
429		fi
430	done
431	debug "Destroyed clones: ${_list}"
432}
433
434gif_up() {
435	case ${gif_interfaces} in
436	[Nn][Oo] | '')
437		;;
438	*)
439		for i in ${gif_interfaces}; do
440			peers=`get_if_var $i gifconfig_IF`
441			case ${peers} in
442			'')
443				continue
444				;;
445			*)
446				ifconfig $i create >/dev/null 2>&1
447				ifconfig $i tunnel ${peers}
448				ifconfig $i up
449				;;
450			esac
451		done
452		;;
453	esac
454}
455
456#
457# ipx_up ifn
458# Configure any IPX addresses for interface $ifn. Returns 0 if IPX
459# arguments were found and configured; returns 1 otherwise.
460#
461ipx_up()
462{
463	ifn="$1"
464	ifconfig_args=`get_if_var $ifn ifconfig_IF_ipx`
465	if [ -n "${ifconfig_args}" ]; then
466		ifconfig ${ifn} ${ifconfig_args}
467		return 0
468	fi
469	return 1
470}
471
472# ipx_down ifn
473#	Remove IPX addresses for interface $ifn. Returns 0 if IPX
474#	addresses were found and unconfigured. It returns 1, otherwise.
475#
476ipx_down()
477{
478	[ -z "$1" ] && return 1
479	_ifs="^"
480	_ret=1
481
482	ifexists $1 || return 1
483
484	ipxList="`ifconfig $1 | grep 'ipx ' | tr "\n" "$_ifs"`"
485
486	oldifs="$IFS"
487	IFS="$_ifs"
488	for _ipx in $ipxList ; do
489		# get rid of extraneous line
490		[ -z "$_ipx" ] && break
491
492		_ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'`
493
494		IFS="$oldifs"
495		ifconfig $1 ${_ipx} delete
496		IFS="$_ifs"
497		_ret=0
498	done
499	IFS="$oldifs"
500
501	return $_ret
502}
503
504# ifnet_rename
505#	Rename all requested interfaces.
506#
507ifnet_rename()
508{
509
510	_ifn_list="`ifconfig -l`"
511	[ -z "$_ifn_list" ] && return 0
512	for _if in ${_ifn_list} ; do
513		_ifname=`get_if_var $_if ifconfig_IF_name`
514		if [ ! -z "$_ifname" ]; then
515			ifconfig $_if name $_ifname
516		fi
517	done
518	return 0
519}
520
521#
522# list_net_interfaces type
523#	List all network interfaces. The type of interface returned
524#	can be controlled by the type argument. The type
525#	argument can be any of the following:
526#		nodhcp - all interfaces, excluding DHCP configured interfaces
527#		dhcp   - list only DHCP configured interfaces
528#	If no argument is specified all network interfaces are output.
529#	Note that the list will include cloned interfaces if applicable.
530#	Cloned interfaces must already exist to have a chance to appear
531#	in the list if ${network_interfaces} is set to `auto'.
532#
533list_net_interfaces()
534{
535	type=$1
536
537	# Get a list of ALL the interfaces and make lo0 first if it's there.
538	#
539	case ${network_interfaces} in
540	[Aa][Uu][Tt][Oo])
541		_prefix=''
542		_autolist="`ifconfig -l`"
543		_lo=
544		for _if in ${_autolist} ; do
545			if autoif $_if; then
546				if [ "$_if" = "lo0" ]; then
547					_lo="lo0 "
548				else
549					_tmplist="${_tmplist}${_prefix}${_if}"
550					[ -z "$_prefix" ] && _prefix=' '
551				fi
552			fi
553		done
554		_tmplist="${_lo}${_tmplist}"
555		;;
556	*)
557		_tmplist="${network_interfaces} ${cloned_interfaces}"
558		;;
559	esac
560
561	if [ -z "$type" ]; then
562		echo $_tmplist
563		return 0
564	fi
565
566	# Separate out dhcp and non-dhcp interfaces
567	#
568	_aprefix=
569	_bprefix=
570	for _if in ${_tmplist} ; do
571		if dhcpif $_if; then
572			_dhcplist="${_dhcplist}${_aprefix}${_if}"
573			[ -z "$_aprefix" ] && _aprefix=' '
574		elif [ -n "`_ifconfig_getargs $_if`" ]; then
575			_nodhcplist="${_nodhcplist}${_bprefix}${_if}"
576			[ -z "$_bprefix" ] && _bprefix=' '
577		fi
578	done
579
580	case "$type" in
581	nodhcp)
582		echo $_nodhcplist
583		;;
584	dhcp)
585		echo $_dhcplist
586		;;
587	esac
588	return 0
589}
590
591hexdigit()
592{
593	if [ $1 -lt 10 ]; then
594		echo $1
595	else
596		case $1 in
597		10)	echo a ;;
598		11)	echo b ;;
599		12)	echo c ;;
600		13)	echo d ;;
601		14)	echo e ;;
602		15)	echo f ;;
603		esac
604	fi
605}
606
607hexprint()
608{
609	val=$1
610	str=''
611
612	dig=`hexdigit $((${val} & 15))`
613	str=${dig}${str}
614	val=$((${val} >> 4))
615	while [ ${val} -gt 0 ]; do
616		dig=`hexdigit $((${val} & 15))`
617		str=${dig}${str}
618		val=$((${val} >> 4))
619	done
620
621	echo ${str}
622}
623
624# Setup the interfaces for IPv6
625network6_interface_setup()
626{
627	interfaces=$*
628	rtsol_interfaces=''
629	case ${ipv6_gateway_enable} in
630	[Yy][Ee][Ss])
631		rtsol_available=no
632		;;
633	*)
634		rtsol_available=yes
635		;;
636	esac
637	for i in $interfaces; do
638		rtsol_interface=yes
639		prefix=`get_if_var $i ipv6_prefix_IF`
640		if [ -n "${prefix}" ]; then
641			rtsol_available=no
642			rtsol_interface=no
643			laddr=`network6_getladdr $i`
644			hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'`
645			for j in ${prefix}; do
646				address=$j\:${hostid}
647				ifconfig $i inet6 ${address} prefixlen 64 alias
648
649				case ${ipv6_gateway_enable} in
650				[Yy][Ee][Ss])
651					# subnet-router anycast address
652					# (rfc2373)
653					ifconfig $i inet6 $j:: prefixlen 64 \
654						alias anycast
655					;;
656				esac
657			done
658		fi
659		ipv6_ifconfig=`get_if_var $i ipv6_ifconfig_IF`
660		if [ -n "${ipv6_ifconfig}" ]; then
661			rtsol_available=no
662			rtsol_interface=no
663			ifconfig $i inet6 ${ipv6_ifconfig} alias
664		fi
665
666		if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ]
667		then
668			case ${i} in
669			lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*)
670				;;
671			*)
672				rtsol_interfaces="${rtsol_interfaces} ${i}"
673				;;
674			esac
675		else
676			ifconfig $i inet6
677		fi
678	done
679
680	if [ ${rtsol_available} = yes -a -n "${rtsol_interfaces}" ]; then
681		# Act as endhost - automatically configured.
682		# You can configure only single interface, as
683		# specification assumes that autoconfigured host has
684		# single interface only.
685		sysctl net.inet6.ip6.accept_rtadv=1
686		set ${rtsol_interfaces}
687		ifconfig $1 up
688		rtsol ${rtsol_flags} $1
689	fi
690
691	for i in $interfaces; do
692		alias=0
693		while : ; do
694			ipv6_ifconfig=`get_if_var $i ipv6_ifconfig_IF_alias${alias}`
695			if [ -z "${ipv6_ifconfig}" ]; then
696				break;
697			fi
698			ifconfig $i inet6 ${ipv6_ifconfig} alias
699			alias=$((${alias} + 1))
700		done
701	done
702}
703
704# Setup IPv6 to IPv4 mapping
705network6_stf_setup()
706{
707	case ${stf_interface_ipv4addr} in
708	[Nn][Oo] | '')
709		;;
710	*)
711		# assign IPv6 addr and interface route for 6to4 interface
712		stf_prefixlen=$((16+${stf_interface_ipv4plen:-0}))
713		OIFS="$IFS"
714		IFS=".$IFS"
715		set ${stf_interface_ipv4addr}
716		IFS="$OIFS"
717		hexfrag1=`hexprint $(($1*256 + $2))`
718		hexfrag2=`hexprint $(($3*256 + $4))`
719		ipv4_in_hexformat="${hexfrag1}:${hexfrag2}"
720		case ${stf_interface_ipv6_ifid} in
721		[Aa][Uu][Tt][Oo] | '')
722			for i in ${ipv6_network_interfaces}; do
723				laddr=`network6_getladdr ${i}`
724				case ${laddr} in
725				'')
726					;;
727				*)
728					break
729					;;
730				esac
731			done
732			stf_interface_ipv6_ifid=`expr "${laddr}" : \
733						      'fe80::\(.*\)%\(.*\)'`
734			case ${stf_interface_ipv6_ifid} in
735			'')
736				stf_interface_ipv6_ifid=0:0:0:1
737				;;
738			esac
739			;;
740		esac
741		ifconfig stf0 create >/dev/null 2>&1
742		ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \
743			prefixlen ${stf_prefixlen}
744		# disallow packets to malicious 6to4 prefix
745		route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
746		route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
747		route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
748		route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
749		;;
750	esac
751}
752
753# Setup static routes
754network6_static_routes_setup()
755{
756	# Set up any static routes.
757	case ${ipv6_defaultrouter} in
758	[Nn][Oo] | '')
759		;;
760	*)
761		ipv6_static_routes="default ${ipv6_static_routes}"
762		ipv6_route_default="default ${ipv6_defaultrouter}"
763		;;
764	esac
765	case ${ipv6_static_routes} in
766	[Nn][Oo] | '')
767		;;
768	*)
769		for i in ${ipv6_static_routes}; do
770			ipv6_route_args=`get_if_var $i ipv6_route_IF`
771			route add -inet6 ${ipv6_route_args}
772		done
773		;;
774	esac
775}
776
777# Setup faith
778network6_faith_setup()
779{
780	case ${ipv6_faith_prefix} in
781	[Nn][Oo] | '')
782		;;
783	*)
784		sysctl net.inet6.ip6.keepfaith=1
785		ifconfig faith0 create >/dev/null 2>&1
786		ifconfig faith0 up
787		for prefix in ${ipv6_faith_prefix}; do
788			prefixlen=`expr "${prefix}" : ".*/\(.*\)"`
789			case ${prefixlen} in
790			'')
791				prefixlen=96
792				;;
793			*)
794				prefix=`expr "${prefix}" : \
795					     "\(.*\)/${prefixlen}"`
796				;;
797			esac
798			route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1
799			route change -inet6 ${prefix} -prefixlen ${prefixlen} \
800				-ifp faith0
801		done
802		;;
803	esac
804}
805
806# Install the "default interface" to kernel, which will be used
807# as the default route when there's no router.
808network6_default_interface_setup()
809{
810	# Choose IPv6 default interface if it is not clearly specified.
811	case ${ipv6_default_interface} in
812	'')
813		for i in ${ipv6_network_interfaces}; do
814			case $i in
815			lo0|faith[0-9]*)
816				continue
817				;;
818			esac
819			laddr=`network6_getladdr $i exclude_tentative`
820			case ${laddr} in
821			'')
822				;;
823			*)
824				ipv6_default_interface=$i
825				break
826				;;
827			esac
828		done
829		;;
830	esac
831
832	# Disallow unicast packets without outgoing scope identifiers,
833	# or route such packets to a "default" interface, if it is specified.
834	route add -inet6 fe80:: -prefixlen 10 ::1 -reject
835	case ${ipv6_default_interface} in
836	[Nn][Oo] | '')
837		route add -inet6 ff02:: -prefixlen 16 ::1 -reject
838		;;
839	*)
840		laddr=`network6_getladdr ${ipv6_default_interface}`
841		route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \
842			-cloning
843
844		# Disable installing the default interface with the
845		# case net.inet6.ip6.forwarding=0 and
846		# net.inet6.ip6.accept_rtadv=0, due to avoid conflict
847		# between the default router list and the manual
848		# configured default route.
849		case ${ipv6_gateway_enable} in
850		[Yy][Ee][Ss])
851			;;
852		*)
853			if [ `sysctl -n net.inet6.ip6.accept_rtadv` -eq 1 ]
854			then
855				ndp -I ${ipv6_default_interface}
856			fi
857			;;
858		esac
859		;;
860	esac
861}
862
863network6_getladdr()
864{
865	ifconfig $1 2>/dev/null | while read proto addr rest; do
866		case ${proto} in
867		inet6)
868			case ${addr} in
869			fe80::*)
870				if [ -z "$2" ]; then
871					echo ${addr}
872					return
873				fi
874				case ${rest} in
875				*tentative*)
876					continue
877					;;
878				*)
879					echo ${addr}
880					return
881				esac
882			esac
883		esac
884	done
885}
886