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