network.subr revision 162490
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 162490 2006-09-21 01:44:52Z 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# ipv6if if
241#	Returns 0 if the interface should be configured for IPv6 and
242#	1 otherwise.
243ipv6if()
244{
245	if ! checkyesno ipv6_enable; then
246		return 1
247	fi
248	case "${ipv6_network_interfaces}" in
249	[Aa][Uu][Tt][Oo])
250		return 0
251		;;
252	''|[Nn][Oo][Nn][Ee])
253		return 1
254		;;
255	esac
256	for v6if in ${ipv6_network_interfaces}; do
257		if [ "${v6if}" = "${1}" ]; then
258			return 0
259		fi
260	done
261	return 1
262}
263
264# ifexists if
265#	Returns 0 if the interface exists and 1 otherwise.
266ifexists()
267{
268	ifconfig $1 > /dev/null 2>&1
269}
270
271# ipv4_up if
272#  add IPv4 addresses to the interface $if 
273ipv4_up()
274{
275	_if=$1
276	ifalias_up ${_if}
277	ipv4_addrs_common ${_if} alias
278}
279
280# ipv4_down if
281#  remove IPv4 addresses from the interface $if
282ipv4_down()
283{
284	_if=$1
285	_ifs="^"
286	_ret=1
287
288	ifexists ${_if} || return 1
289
290	inetList="`ifconfig ${_if} | grep 'inet ' | tr "\n" "$_ifs"`"
291
292	oldifs="$IFS"
293	IFS="$_ifs"
294	for _inet in $inetList ; do
295		# get rid of extraneous line
296		[ -z "$_inet" ] && break
297
298		_inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'`
299
300		IFS="$oldifs"
301		ifconfig ${_if} ${_inet} delete
302		IFS="$_ifs"
303		_ret=0
304	done
305	IFS="$oldifs"
306
307	ifalias_down ${_if} && _ret=0
308	ipv4_addrs_common ${_if} -alias && _ret=0
309
310	return $_ret
311}
312
313# ipv4_addrs_common if action
314#   Evaluate the ifconfig_if_ipv4 arguments for interface $if
315#   and use $action to add or remove IPv4 addresses from $if.
316ipv4_addrs_common()
317{  
318	_ret=1
319	_if=$1
320	_action=$2
321    
322	# get ipv4-addresses
323	cidr_addr=`get_if_var $_if ipv4_addrs_IF`
324    
325	for _cidr in ${cidr_addr}; do
326		_ipaddr=${_cidr%%/*}
327		_netmask="/"${_cidr##*/}
328		_range=${_ipaddr##*.}
329		_ipnet=${_ipaddr%.*}
330		_iplow=${_range%-*}
331		_iphigh=${_range#*-}
332
333		# clear netmask when removing aliases
334		if [ "${_action}" = "-alias" ]; then
335			_netmask=""
336		fi
337        
338		_ipcount=${_iplow}
339		while [ "${_ipcount}" -le "${_iphigh}" ]; do
340			eval "ifconfig ${_if} ${_action} ${_ipnet}.${_ipcount}${_netmask}"
341			_ipcount=$((${_ipcount}+1))
342			_ret=0
343
344			# only the first ipaddr in a subnet need the real netmask
345			if [ "${_action}" != "-alias" ]; then
346				_netmask="/32"
347			fi
348		done
349	done
350	return $_ret
351}
352
353# ifalias_up if
354#	Configure aliases for network interface $if.
355#	It returns 0 if at least one alias was configured or
356#	1 if there were none.
357#
358ifalias_up()
359{
360	_ret=1
361	alias=0
362	while : ; do
363		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
364		if [ -n "${ifconfig_args}" ]; then
365			ifconfig $1 ${ifconfig_args} alias
366			alias=$((${alias} + 1))
367			_ret=0
368		else
369			break
370		fi
371	done
372	return $_ret
373}
374
375#ifalias_down if
376#	Remove aliases for network interface $if.
377#	It returns 0 if at least one alias was removed or
378#	1 if there were none.
379#
380ifalias_down()
381{
382	_ret=1
383	alias=0
384	while : ; do
385		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
386		if [ -n "${ifconfig_args}" ]; then
387			ifconfig $1 ${ifconfig_args} -alias
388			alias=$((${alias} + 1))
389			_ret=0
390		else
391			break
392		fi
393	done
394	return $_ret
395}
396
397# ifscript_up if
398#	Evaluate a startup script for the $if interface.
399#	It returns 0 if a script was found and processed or
400#	1 if no script was found.
401#
402ifscript_up()
403{
404	if [ -r /etc/start_if.$1 ]; then
405		. /etc/start_if.$1
406		return 0
407	fi
408	return 1
409}
410
411# ifscript_down if
412#	Evaluate a shutdown script for the $if interface.
413#	It returns 0 if a script was found and processed or
414#	1 if no script was found.
415#
416ifscript_down()
417{
418	if [ -r /etc/stop_if.$1 ]; then
419		. /etc/stop_if.$1
420		return 0
421	fi
422	return 1
423}
424
425# Create cloneable interfaces.
426#
427clone_up()
428{
429	_prefix=
430	_list=
431	for ifn in ${cloned_interfaces}; do
432		ifconfig ${ifn} create
433		if [ $? -eq 0 ]; then
434			_list="${_list}${_prefix}${ifn}"
435			[ -z "$_prefix" ] && _prefix=' '
436		fi
437	done
438	debug "Cloned: ${_list}"
439}
440
441# Destroy cloned interfaces. Destroyed interfaces are echoed
442# to standard output.
443#
444clone_down()
445{
446	_prefix=
447	_list=
448	for ifn in ${cloned_interfaces}; do
449		ifconfig ${ifn} destroy
450		if [ $? -eq 0 ]; then
451			_list="${_list}${_prefix}${ifn}"
452			[ -z "$_prefix" ] && _prefix=' '
453		fi
454	done
455	debug "Destroyed clones: ${_list}"
456}
457
458gif_up() {
459	case ${gif_interfaces} in
460	[Nn][Oo] | '')
461		;;
462	*)
463		for i in ${gif_interfaces}; do
464			peers=`get_if_var $i gifconfig_IF`
465			case ${peers} in
466			'')
467				continue
468				;;
469			*)
470				ifconfig $i create >/dev/null 2>&1
471				ifconfig $i tunnel ${peers}
472				ifconfig $i up
473				;;
474			esac
475		done
476		;;
477	esac
478}
479
480#
481# ipx_up ifn
482# Configure any IPX addresses for interface $ifn. Returns 0 if IPX
483# arguments were found and configured; returns 1 otherwise.
484#
485ipx_up()
486{
487	ifn="$1"
488	ifconfig_args=`get_if_var $ifn ifconfig_IF_ipx`
489	if [ -n "${ifconfig_args}" ]; then
490		ifconfig ${ifn} ${ifconfig_args}
491		return 0
492	fi
493	return 1
494}
495
496# ipx_down ifn
497#	Remove IPX addresses for interface $ifn. Returns 0 if IPX
498#	addresses were found and unconfigured. It returns 1, otherwise.
499#
500ipx_down()
501{
502	[ -z "$1" ] && return 1
503	_ifs="^"
504	_ret=1
505
506	ifexists $1 || return 1
507
508	ipxList="`ifconfig $1 | grep 'ipx ' | tr "\n" "$_ifs"`"
509
510	oldifs="$IFS"
511	IFS="$_ifs"
512	for _ipx in $ipxList ; do
513		# get rid of extraneous line
514		[ -z "$_ipx" ] && break
515
516		_ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'`
517
518		IFS="$oldifs"
519		ifconfig $1 ${_ipx} delete
520		IFS="$_ifs"
521		_ret=0
522	done
523	IFS="$oldifs"
524
525	return $_ret
526}
527
528# ifnet_rename
529#	Rename all requested interfaces.
530#
531ifnet_rename()
532{
533
534	_ifn_list="`ifconfig -l`"
535	[ -z "$_ifn_list" ] && return 0
536	for _if in ${_ifn_list} ; do
537		_ifname=`get_if_var $_if ifconfig_IF_name`
538		if [ ! -z "$_ifname" ]; then
539			ifconfig $_if name $_ifname
540		fi
541	done
542	return 0
543}
544
545#
546# list_net_interfaces type
547#	List all network interfaces. The type of interface returned
548#	can be controlled by the type argument. The type
549#	argument can be any of the following:
550#		nodhcp - all interfaces, excluding DHCP configured interfaces
551#		dhcp   - list only DHCP configured interfaces
552#	If no argument is specified all network interfaces are output.
553#	Note that the list will include cloned interfaces if applicable.
554#	Cloned interfaces must already exist to have a chance to appear
555#	in the list if ${network_interfaces} is set to `auto'.
556#
557list_net_interfaces()
558{
559	type=$1
560
561	# Get a list of ALL the interfaces and make lo0 first if it's there.
562	#
563	case ${network_interfaces} in
564	[Aa][Uu][Tt][Oo])
565		_prefix=''
566		_autolist="`ifconfig -l`"
567		_lo=
568		for _if in ${_autolist} ; do
569			if autoif $_if; then
570				if [ "$_if" = "lo0" ]; then
571					_lo="lo0 "
572				else
573					_tmplist="${_tmplist}${_prefix}${_if}"
574					[ -z "$_prefix" ] && _prefix=' '
575				fi
576			fi
577		done
578		_tmplist="${_lo}${_tmplist}"
579		;;
580	*)
581		_tmplist="${network_interfaces} ${cloned_interfaces}"
582		;;
583	esac
584
585	if [ -z "$type" ]; then
586		echo $_tmplist
587		return 0
588	fi
589
590	# Separate out dhcp and non-dhcp interfaces
591	#
592	_aprefix=
593	_bprefix=
594	for _if in ${_tmplist} ; do
595		if dhcpif $_if; then
596			_dhcplist="${_dhcplist}${_aprefix}${_if}"
597			[ -z "$_aprefix" ] && _aprefix=' '
598		elif [ -n "`_ifconfig_getargs $_if`" ]; then
599			_nodhcplist="${_nodhcplist}${_bprefix}${_if}"
600			[ -z "$_bprefix" ] && _bprefix=' '
601		fi
602	done
603
604	case "$type" in
605	nodhcp)
606		echo $_nodhcplist
607		;;
608	dhcp)
609		echo $_dhcplist
610		;;
611	esac
612	return 0
613}
614
615hexdigit()
616{
617	if [ $1 -lt 10 ]; then
618		echo $1
619	else
620		case $1 in
621		10)	echo a ;;
622		11)	echo b ;;
623		12)	echo c ;;
624		13)	echo d ;;
625		14)	echo e ;;
626		15)	echo f ;;
627		esac
628	fi
629}
630
631hexprint()
632{
633	val=$1
634	str=''
635
636	dig=`hexdigit $((${val} & 15))`
637	str=${dig}${str}
638	val=$((${val} >> 4))
639	while [ ${val} -gt 0 ]; do
640		dig=`hexdigit $((${val} & 15))`
641		str=${dig}${str}
642		val=$((${val} >> 4))
643	done
644
645	echo ${str}
646}
647
648# Setup the interfaces for IPv6
649network6_interface_setup()
650{
651	interfaces=$*
652	rtsol_interfaces=''
653	case ${ipv6_gateway_enable} in
654	[Yy][Ee][Ss])
655		rtsol_available=no
656		;;
657	*)
658		rtsol_available=yes
659		;;
660	esac
661	for i in $interfaces; do
662		rtsol_interface=yes
663		prefix=`get_if_var $i ipv6_prefix_IF`
664		if [ -n "${prefix}" ]; then
665			rtsol_available=no
666			rtsol_interface=no
667			laddr=`network6_getladdr $i`
668			hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'`
669			for j in ${prefix}; do
670				address=$j\:${hostid}
671				ifconfig $i inet6 ${address} prefixlen 64 alias
672
673				case ${ipv6_gateway_enable} in
674				[Yy][Ee][Ss])
675					# subnet-router anycast address
676					# (rfc2373)
677					ifconfig $i inet6 $j:: prefixlen 64 \
678						alias anycast
679					;;
680				esac
681			done
682		fi
683		ipv6_ifconfig=`get_if_var $i ipv6_ifconfig_IF`
684		if [ -n "${ipv6_ifconfig}" ]; then
685			rtsol_available=no
686			rtsol_interface=no
687			ifconfig $i inet6 ${ipv6_ifconfig} alias
688		fi
689
690		if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ]
691		then
692			case ${i} in
693			lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*)
694				;;
695			*)
696				rtsol_interfaces="${rtsol_interfaces} ${i}"
697				;;
698			esac
699		else
700			ifconfig $i inet6
701		fi
702	done
703
704	if [ ${rtsol_available} = yes -a -n "${rtsol_interfaces}" ]; then
705		# Act as endhost - automatically configured.
706		# You can configure only single interface, as
707		# specification assumes that autoconfigured host has
708		# single interface only.
709		sysctl net.inet6.ip6.accept_rtadv=1
710		set ${rtsol_interfaces}
711		ifconfig $1 up
712		rtsol ${rtsol_flags} $1
713	fi
714
715	for i in $interfaces; do
716		alias=0
717		while : ; do
718			ipv6_ifconfig=`get_if_var $i ipv6_ifconfig_IF_alias${alias}`
719			if [ -z "${ipv6_ifconfig}" ]; then
720				break;
721			fi
722			ifconfig $i inet6 ${ipv6_ifconfig} alias
723			alias=$((${alias} + 1))
724		done
725	done
726}
727
728# Setup IPv6 to IPv4 mapping
729network6_stf_setup()
730{
731	case ${stf_interface_ipv4addr} in
732	[Nn][Oo] | '')
733		;;
734	*)
735		# assign IPv6 addr and interface route for 6to4 interface
736		stf_prefixlen=$((16+${stf_interface_ipv4plen:-0}))
737		OIFS="$IFS"
738		IFS=".$IFS"
739		set ${stf_interface_ipv4addr}
740		IFS="$OIFS"
741		hexfrag1=`hexprint $(($1*256 + $2))`
742		hexfrag2=`hexprint $(($3*256 + $4))`
743		ipv4_in_hexformat="${hexfrag1}:${hexfrag2}"
744		case ${stf_interface_ipv6_ifid} in
745		[Aa][Uu][Tt][Oo] | '')
746			for i in ${ipv6_network_interfaces}; do
747				laddr=`network6_getladdr ${i}`
748				case ${laddr} in
749				'')
750					;;
751				*)
752					break
753					;;
754				esac
755			done
756			stf_interface_ipv6_ifid=`expr "${laddr}" : \
757						      'fe80::\(.*\)%\(.*\)'`
758			case ${stf_interface_ipv6_ifid} in
759			'')
760				stf_interface_ipv6_ifid=0:0:0:1
761				;;
762			esac
763			;;
764		esac
765		ifconfig stf0 create >/dev/null 2>&1
766		ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \
767			prefixlen ${stf_prefixlen}
768		# disallow packets to malicious 6to4 prefix
769		route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
770		route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
771		route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
772		route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
773		;;
774	esac
775}
776
777# Setup static routes
778network6_static_routes_setup()
779{
780	# Set up any static routes.
781	case ${ipv6_defaultrouter} in
782	[Nn][Oo] | '')
783		;;
784	*)
785		ipv6_static_routes="default ${ipv6_static_routes}"
786		ipv6_route_default="default ${ipv6_defaultrouter}"
787		;;
788	esac
789	case ${ipv6_static_routes} in
790	[Nn][Oo] | '')
791		;;
792	*)
793		for i in ${ipv6_static_routes}; do
794			ipv6_route_args=`get_if_var $i ipv6_route_IF`
795			route add -inet6 ${ipv6_route_args}
796		done
797		;;
798	esac
799}
800
801# Setup faith
802network6_faith_setup()
803{
804	case ${ipv6_faith_prefix} in
805	[Nn][Oo] | '')
806		;;
807	*)
808		sysctl net.inet6.ip6.keepfaith=1
809		ifconfig faith0 create >/dev/null 2>&1
810		ifconfig faith0 up
811		for prefix in ${ipv6_faith_prefix}; do
812			prefixlen=`expr "${prefix}" : ".*/\(.*\)"`
813			case ${prefixlen} in
814			'')
815				prefixlen=96
816				;;
817			*)
818				prefix=`expr "${prefix}" : \
819					     "\(.*\)/${prefixlen}"`
820				;;
821			esac
822			route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1
823			route change -inet6 ${prefix} -prefixlen ${prefixlen} \
824				-ifp faith0
825		done
826		;;
827	esac
828}
829
830# Install the "default interface" to kernel, which will be used
831# as the default route when there's no router.
832network6_default_interface_setup()
833{
834	# Choose IPv6 default interface if it is not clearly specified.
835	case ${ipv6_default_interface} in
836	'')
837		for i in ${ipv6_network_interfaces}; do
838			case $i in
839			lo0|faith[0-9]*)
840				continue
841				;;
842			esac
843			laddr=`network6_getladdr $i exclude_tentative`
844			case ${laddr} in
845			'')
846				;;
847			*)
848				ipv6_default_interface=$i
849				break
850				;;
851			esac
852		done
853		;;
854	esac
855
856	# Disallow unicast packets without outgoing scope identifiers,
857	# or route such packets to a "default" interface, if it is specified.
858	route add -inet6 fe80:: -prefixlen 10 ::1 -reject
859	case ${ipv6_default_interface} in
860	[Nn][Oo] | '')
861		route add -inet6 ff02:: -prefixlen 16 ::1 -reject
862		;;
863	*)
864		laddr=`network6_getladdr ${ipv6_default_interface}`
865		route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \
866			-cloning
867
868		# Disable installing the default interface with the
869		# case net.inet6.ip6.forwarding=0 and
870		# net.inet6.ip6.accept_rtadv=0, due to avoid conflict
871		# between the default router list and the manual
872		# configured default route.
873		case ${ipv6_gateway_enable} in
874		[Yy][Ee][Ss])
875			;;
876		*)
877			if [ `sysctl -n net.inet6.ip6.accept_rtadv` -eq 1 ]
878			then
879				ndp -I ${ipv6_default_interface}
880			fi
881			;;
882		esac
883		;;
884	esac
885}
886
887network6_getladdr()
888{
889	ifconfig $1 2>/dev/null | while read proto addr rest; do
890		case ${proto} in
891		inet6)
892			case ${addr} in
893			fe80::*)
894				if [ -z "$2" ]; then
895					echo ${addr}
896					return
897				fi
898				case ${rest} in
899				*tentative*)
900					continue
901					;;
902				*)
903					echo ${addr}
904					return
905				esac
906			esac
907		esac
908	done
909}
910