network.subr revision 137070
125184Sjkh#
2113674Smtm# Copyright (c) 2003 The FreeBSD Project. All rights reserved.
3113674Smtm#
4113674Smtm# Redistribution and use in source and binary forms, with or without
5113674Smtm# modification, are permitted provided that the following conditions
6113674Smtm# are met:
7113674Smtm# 1. Redistributions of source code must retain the above copyright
8113674Smtm#    notice, this list of conditions and the following disclaimer.
9113674Smtm# 2. Redistributions in binary form must reproduce the above copyright
10113674Smtm#    notice, this list of conditions and the following disclaimer in the
11113674Smtm#    documentation and/or other materials provided with the distribution.
12113674Smtm#
13113674Smtm# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
14113674Smtm# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15113674Smtm# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16113674Smtm# ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
17113674Smtm# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18113674Smtm# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19113674Smtm# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20113674Smtm# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21113674Smtm# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22113674Smtm# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23113674Smtm# SUCH DAMAGE.
24113674Smtm#
2550472Speter# $FreeBSD: head/etc/network.subr 137070 2004-10-30 13:44:06Z pjd $
2666830Sobrien#
2725184Sjkh
28113674Smtm#
29113674Smtm# Subroutines commonly used from network startup scripts.
30113674Smtm# Requires that rc.conf be loaded first.
31113674Smtm#
3225184Sjkh
33113674Smtm# ifconfig_up if
34113674Smtm#	Evaluate ifconfig(8) arguments for interface $if and
35113674Smtm#	run ifconfig(8) with those arguments. It returns 0 if
36113674Smtm#	arguments were found and executed or 1 if the interface
37113674Smtm#	had no arguments.
38113674Smtm#
39113674Smtmifconfig_up()
40113674Smtm{
41113674Smtm	eval ifconfig_args=\$ifconfig_$1
42113674Smtm	if [ -n "${ifconfig_args}" ]; then
43113674Smtm		ifconfig $1 ${ifconfig_args}
44113674Smtm		return 0
45113674Smtm	fi
46113674Smtm	return 1
47113674Smtm}
4825184Sjkh
49116029Smtm# ifconfig_down if
50116029Smtm#	Remove all inet entries from the $if interface. It returns
51116029Smtm#	0 if inet entries were found and removed. It returns 1 if
52116100Smtm#	no entries were found or they could not be removed.
53116029Smtm#
54116029Smtmifconfig_down()
55116029Smtm{
56116029Smtm	[ -z "$1" ] && return 1
57116029Smtm	_ifs="^"
58116029Smtm	_ret=1
59116029Smtm
60116029Smtm	inetList="`ifconfig $1 | grep 'inet ' | tr "\n" "$_ifs"`"
61116029Smtm
62116029Smtm	oldifs="$IFS"
63116029Smtm	IFS="$_ifs"
64116029Smtm	for _inet in $inetList ; do
65116029Smtm		# get rid of extraneous line
66116029Smtm		[ -z "$_inet" ] && break
67116029Smtm
68116029Smtm		_inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'`
69116029Smtm
70116032Smtm		IFS="$oldifs"
71116032Smtm		ifconfig $1 ${_inet} delete
72116032Smtm		IFS="$_ifs"
73116029Smtm		_ret=0
74116029Smtm	done
75116029Smtm	IFS="$oldifs"
76116029Smtm
77116029Smtm	return $_ret
78116029Smtm}
79116029Smtm
80113674Smtm# ifalias_up if
81113674Smtm#	Configure aliases for network interface $if.
82113674Smtm#	It returns 0 if at least one alias was configured or
83113674Smtm#	1 if there were none.
84113674Smtm#
85113674Smtmifalias_up()
86113674Smtm{
87113674Smtm	_ret=1
88113674Smtm	alias=0
89113674Smtm	while : ; do
90113674Smtm		eval ifconfig_args=\$ifconfig_$1_alias${alias}
91113674Smtm		if [ -n "${ifconfig_args}" ]; then
92113674Smtm			ifconfig $1 ${ifconfig_args} alias
93113674Smtm			alias=$((${alias} + 1))
94113674Smtm			_ret=0
95113674Smtm		else
96113674Smtm			break
97113674Smtm		fi
98113674Smtm	done
99113674Smtm	return $_ret
100113674Smtm}
101100280Sgordon
102116029Smtm#ifalias_down if
103116029Smtm#	Remove aliases for network interface $if.
104116029Smtm#	It returns 0 if at least one alias was removed or
105116029Smtm#	1 if there were none.
106116029Smtm#
107116029Smtmifalias_down()
108116029Smtm{
109116029Smtm	_ret=1
110116029Smtm	alias=0
111116029Smtm	while : ; do
112116029Smtm		eval ifconfig_args=\$ifconfig_$1_alias${alias}
113116029Smtm		if [ -n "${ifconfig_args}" ]; then
114116029Smtm			ifconfig $1 ${ifconfig_args} -alias
115116029Smtm			alias=$((${alias} + 1))
116116029Smtm			_ret=0
117116029Smtm		else
118116029Smtm			break
119116029Smtm		fi
120116029Smtm	done
121116029Smtm	return $_ret
122116029Smtm}
123116029Smtm
124113674Smtm# ifscript_up if
125113674Smtm#	Evaluate a startup script for the $if interface.
126113674Smtm#	It returns 0 if a script was found and processed or
127113674Smtm#	1 if no script was found.
128113674Smtm#
129113674Smtmifscript_up()
130100280Sgordon{
131113674Smtm	if [ -r /etc/start_if.$1 ]; then
132113674Smtm		. /etc/start_if.$1
133113674Smtm		return 0
134113674Smtm	fi
135113674Smtm	return 1
136100280Sgordon}
137100280Sgordon
138116029Smtm# ifscript_down if
139116029Smtm#	Evaluate a shutdown script for the $if interface.
140116029Smtm#	It returns 0 if a script was found and processed or
141116029Smtm#	1 if no script was found.
142116029Smtm#
143116029Smtmifscript_down()
144116029Smtm{
145116029Smtm	if [ -r /etc/stop_if.$1 ]; then
146116029Smtm		. /etc/stop_if.$1
147116029Smtm		return 0
148116029Smtm	fi
149116029Smtm	return 1
150116029Smtm}
151116029Smtm
152113674Smtm# Create cloneable interfaces.
153113674Smtm#
154113674Smtmclone_up()
155100280Sgordon{
156113674Smtm	_prefix=
157113674Smtm	_list=
158113674Smtm	for ifn in ${cloned_interfaces}; do
159113674Smtm		ifconfig ${ifn} create
160116774Skuriyama		if [ $? -eq 0 ]; then
161113674Smtm			_list="${_list}${_prefix}${ifn}"
162113674Smtm			[ -z "$_prefix" ] && _prefix=' '
163113674Smtm		fi
164113674Smtm	done
165113674Smtm	debug "Cloned: ${_list}"
166113674Smtm}
167100280Sgordon
168113674Smtm# Destroy cloned interfaces. Destroyed interfaces are echoed
169113674Smtm# to standard output.
170113674Smtm#
171113674Smtmclone_down()
172113674Smtm{
173113674Smtm	_prefix=
174113674Smtm	_list=
175113674Smtm	for ifn in ${cloned_interfaces}; do
176113674Smtm		ifconfig ${ifn} destroy
177116774Skuriyama		if [ $? -eq 0 ]; then
178113674Smtm			_list="${_list}${_prefix}${ifn}"
179113674Smtm			[ -z "$_prefix" ] && _prefix=' '
180113674Smtm		fi
181113674Smtm	done
182113674Smtm	debug "Destroyed clones: ${_list}"
183100280Sgordon}
184100280Sgordon
185113674Smtmgif_up() {
186100282Sdougb	case ${gif_interfaces} in
187100282Sdougb	[Nn][Oo] | '')
188100282Sdougb		;;
189100282Sdougb	*)
190100282Sdougb		for i in ${gif_interfaces}; do
191100282Sdougb			eval peers=\$gifconfig_$i
192100282Sdougb			case ${peers} in
193100282Sdougb			'')
194100282Sdougb				continue
195100282Sdougb				;;
196100282Sdougb			*)
197100282Sdougb				ifconfig $i create >/dev/null 2>&1
198100282Sdougb				ifconfig $i tunnel ${peers}
199103710Sume				ifconfig $i up
200100282Sdougb				;;
201100282Sdougb			esac
202100282Sdougb		done
203100282Sdougb		;;
204100282Sdougb	esac
205100282Sdougb}
206100282Sdougb
207113674Smtm#
208113674Smtm# ipx_up ifn
209113674Smtm# Configure any IPX addresses for interface $ifn. Returns 0 if IPX
210113674Smtm# arguments were found and configured; returns 1 otherwise.
211113674Smtm#
212113674Smtmipx_up()
213100280Sgordon{
214113674Smtm	ifn="$1"
215113674Smtm	eval ifconfig_args=\$ifconfig_${ifn}_ipx
216113674Smtm	if [ -n "${ifconfig_args}" ]; then
217113674Smtm		ifconfig ${ifn} ${ifconfig_args}
218113674Smtm		return 0
21985831Sdes	fi
220113674Smtm	return 1
221113674Smtm}
22285831Sdes
223116029Smtm# ipx_down ifn
224116029Smtm#	Remove IPX addresses for interface $ifn. Returns 0 if IPX
225116029Smtm#	addresses were found and unconfigured. It returns 1, otherwise.
226113674Smtm#
227116029Smtmipx_down()
228116029Smtm{
229116100Smtm	[ -z "$1" ] && return 1
230116100Smtm	_ifs="^"
231116100Smtm	_ret=1
232116100Smtm
233116100Smtm	ipxList="`ifconfig $1 | grep 'ipx ' | tr "\n" "$_ifs"`"
234116100Smtm
235116100Smtm	oldifs="$IFS"
236116100Smtm	IFS="$_ifs"
237116100Smtm	for _ipx in $ipxList ; do
238116100Smtm		# get rid of extraneous line
239116100Smtm		[ -z "$_ipx" ] && break
240116100Smtm
241116100Smtm		_ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'`
242116100Smtm
243116100Smtm		IFS="$oldifs"
244116100Smtm		ifconfig $1 ${_ipx} delete
245116100Smtm		IFS="$_ifs"
246116100Smtm		_ret=0
247116100Smtm	done
248116100Smtm	IFS="$oldifs"
249116100Smtm
250116100Smtm	return $_ret
251116029Smtm}
252116029Smtm
253137070Spjd# ifnet_rename
254137070Spjd#	Rename all requested interfaces.
255116029Smtm#
256137070Spjdifnet_rename()
257137070Spjd{
258137070Spjd
259137070Spjd	_ifn_list="`list_net_interfaces all`"
260137070Spjd	[ -z "$_ifn_list" ] && return 0
261137070Spjd	for _if in ${_ifn_list} ; do
262137070Spjd		eval _ifname=\$ifconfig_${_if}_name
263137070Spjd		if [ ! -z "$_ifname" ]; then
264137070Spjd			ifconfig $_if name $_ifname
265137070Spjd		fi
266137070Spjd	done
267137070Spjd	return 0
268137070Spjd}
269137070Spjd
270137070Spjd#
271113674Smtm# list_net_interfaces type
272113674Smtm#	List all network interfaces. The type of interface returned
273113674Smtm#	can be controlled by the type argument. The type
274113674Smtm#	argument can be any of the following:
275113674Smtm#		nodhcp - all interfaces, excluding DHCP configured interfaces
276113674Smtm#		dhcp   - list only DHCP configured interfaces
277137070Spjd#		all    - all interfaces
278113674Smtm#	If no argument is specified all network interfaces are output.
279134429Syar#	Note that the list will include cloned interfaces if applicable.
280134429Syar#	Cloned interfaces must already exist to have a chance to appear
281134429Syar#	in the list if ${network_interfaces} is set to `auto'.
282113674Smtm#
283113674Smtmlist_net_interfaces()
284113674Smtm{
285113674Smtm	type=$1
28665532Snectar
287113674Smtm	# Get a list of ALL the interfaces
28851231Ssheldonh	#
28951231Ssheldonh	case ${network_interfaces} in
29051231Ssheldonh	[Aa][Uu][Tt][Oo])
291113674Smtm		_tmplist="`ifconfig -l`"
29251231Ssheldonh		;;
29383677Sbrooks	*)
294134429Syar		_tmplist="${network_interfaces} ${cloned_interfaces}"
29583677Sbrooks		;;
29651231Ssheldonh	esac
29749122Sbrian
298113674Smtm	if [ -z "$type" ]; then
299113674Smtm		echo $_tmplist
300113674Smtm		return 0
301113674Smtm	fi
30249122Sbrian
303113674Smtm	# Separate out dhcp and non-dhcp intefraces
304113674Smtm	#
305113674Smtm	_aprefix=
306134376Syar	_bprefix=
307113674Smtm	for _if in ${_tmplist} ; do
308113674Smtm		eval _ifarg="\$ifconfig_${_if}"
309113674Smtm		case "$_ifarg" in
31051231Ssheldonh		[Dd][Hh][Cc][Pp])
311113674Smtm			_dhcplist="${_dhcplist}${_aprefix}${_if}"
312113674Smtm			[ -z "$_aprefix" ] && _aprefix=' '
31351231Ssheldonh			;;
314113674Smtm		''|*)
315113674Smtm			_nodhcplist="${_nodhcplist}${_bprefix}${_if}"
316113674Smtm			[ -z "$_bprefix" ] && _bprefix=' '
31751231Ssheldonh			;;
31851231Ssheldonh		esac
31954458Sobrien	done
32051231Ssheldonh
321118797Smbr	case ${pccard_ifconfig} in
322118797Smbr	[Dd][Hh][Cc][Pp])
323118797Smbr		for _if in ${removable_interfaces} ; do
324118797Smbr			_test_if=`ifconfig ${_if} 2>&1`
325118797Smbr			case "$_test_if" in
326118797Smbr			"ifconfig: interface $_if does not exist")
327118797Smbr				;;
328118797Smbr			*)
329118797Smbr				_dhcplist="${_dhcplist}${_aprefix}${_if}"
330118797Smbr				[ -z "$_aprefix" ] && _aprefix=' '
331118797Smbr				;;
332118797Smbr			esac
333118797Smbr		done
334118797Smbr		;;
335118797Smbr	*)
336118797Smbr		;;
337118797Smbr	esac
338118797Smbr
339113674Smtm	case "$type" in
340113674Smtm	nodhcp)
341113674Smtm		echo $_nodhcplist
342113674Smtm		;;
343113674Smtm	dhcp)
344113674Smtm		echo $_dhcplist
345113674Smtm		;;
346137070Spjd	all)
347137070Spjd		echo $_nodhcplist $_dhcplist
348137070Spjd		;;
349113674Smtm	esac
350130151Sschweikh	return 0
35125184Sjkh}
352114942Sume
353114942Sumehexdigit()
354114942Sume{
355114942Sume	if [ $1 -lt 10 ]; then
356114942Sume		echo $1
357114942Sume	else
358114942Sume		case $1 in
359114942Sume		10)	echo a ;;
360114942Sume		11)	echo b ;;
361114942Sume		12)	echo c ;;
362114942Sume		13)	echo d ;;
363114942Sume		14)	echo e ;;
364114942Sume		15)	echo f ;;
365114942Sume		esac
366114942Sume	fi
367114942Sume}
368114942Sume
369114942Sumehexprint()
370114942Sume{
371114942Sume	val=$1
372114942Sume	str=''
373114942Sume
374114942Sume	dig=`hexdigit $((${val} & 15))`
375114942Sume	str=${dig}${str}
376114942Sume	val=$((${val} >> 4))
377114942Sume	while [ ${val} -gt 0 ]; do
378114942Sume		dig=`hexdigit $((${val} & 15))`
379114942Sume		str=${dig}${str}
380114942Sume		val=$((${val} >> 4))
381114942Sume	done
382114942Sume
383114942Sume	echo ${str}
384114942Sume}
385114942Sume
386114942Sume# Setup the interfaces for IPv6
387114942Sumenetwork6_interface_setup()
388114942Sume{
389114942Sume	interfaces=$*
390114942Sume	rtsol_interfaces=''
391114942Sume	case ${ipv6_gateway_enable} in
392114942Sume	[Yy][Ee][Ss])
393114942Sume		rtsol_available=no
394114942Sume		;;
395114942Sume	*)
396114942Sume		rtsol_available=yes
397114942Sume		;;
398114942Sume	esac
399114942Sume	for i in $interfaces; do
400114942Sume		rtsol_interface=yes
401114942Sume		eval prefix=\$ipv6_prefix_$i
402114942Sume		if [ -n "${prefix}" ]; then
403114942Sume			rtsol_available=no
404114942Sume			rtsol_interface=no
405114942Sume			laddr=`network6_getladdr $i`
406114942Sume			hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'`
407114942Sume			for j in ${prefix}; do
408114942Sume				address=$j\:${hostid}
409114942Sume				ifconfig $i inet6 ${address} prefixlen 64 alias
410114942Sume
411114942Sume				case ${ipv6_gateway_enable} in
412114942Sume				[Yy][Ee][Ss])
413114942Sume					# subnet-router anycast address
414114942Sume					# (rfc2373)
415114942Sume					ifconfig $i inet6 $j:: prefixlen 64 \
416114942Sume						alias anycast
417114942Sume					;;
418114942Sume				esac
419114942Sume			done
420114942Sume		fi
421114942Sume		eval ipv6_ifconfig=\$ipv6_ifconfig_$i
422114942Sume		if [ -n "${ipv6_ifconfig}" ]; then
423114942Sume			rtsol_available=no
424114942Sume			rtsol_interface=no
425114942Sume			ifconfig $i inet6 ${ipv6_ifconfig} alias
426114942Sume		fi
427114942Sume
428114942Sume		if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ]
429114942Sume		then
430114942Sume			case ${i} in
431114942Sume			lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*)
432114942Sume				;;
433114942Sume			*)
434114942Sume				rtsol_interfaces="${rtsol_interfaces} ${i}"
435114942Sume				;;
436114942Sume			esac
437114942Sume		else
438114942Sume			ifconfig $i inet6
439114942Sume		fi
440114942Sume	done
441114942Sume
442114942Sume	if [ ${rtsol_available} = yes -a -n "${rtsol_interfaces}" ]; then
443114942Sume		# Act as endhost - automatically configured.
444114942Sume		# You can configure only single interface, as
445114942Sume		# specification assumes that autoconfigured host has
446114942Sume		# single interface only.
447114942Sume		sysctl net.inet6.ip6.accept_rtadv=1
448114942Sume		set ${rtsol_interfaces}
449114942Sume		ifconfig $1 up
450118666Sume		rtsol ${rtsol_flags} $1
451114942Sume	fi
452114942Sume
453114942Sume	for i in $interfaces; do
454114942Sume		alias=0
455114942Sume		while : ; do
456114942Sume			eval ipv6_ifconfig=\$ipv6_ifconfig_${i}_alias${alias}
457114942Sume			if [ -z "${ipv6_ifconfig}" ]; then
458114942Sume				break;
459114942Sume			fi
460114942Sume			ifconfig $i inet6 ${ipv6_ifconfig} alias
461114942Sume			alias=$((${alias} + 1))
462114942Sume		done
463114942Sume	done
464114942Sume}
465114942Sume
466114942Sume# Setup IPv6 to IPv4 mapping
467114942Sumenetwork6_stf_setup()
468114942Sume{
469114942Sume	case ${stf_interface_ipv4addr} in
470114942Sume	[Nn][Oo] | '')
471114942Sume		;;
472114942Sume	*)
473114942Sume		# assign IPv6 addr and interface route for 6to4 interface
474114942Sume		stf_prefixlen=$((16+${stf_interface_ipv4plen:-0}))
475114942Sume		OIFS="$IFS"
476114942Sume		IFS=".$IFS"
477114942Sume		set ${stf_interface_ipv4addr}
478114942Sume		IFS="$OIFS"
479114942Sume		hexfrag1=`hexprint $(($1*256 + $2))`
480114942Sume		hexfrag2=`hexprint $(($3*256 + $4))`
481114942Sume		ipv4_in_hexformat="${hexfrag1}:${hexfrag2}"
482114942Sume		case ${stf_interface_ipv6_ifid} in
483114942Sume		[Aa][Uu][Tt][Oo] | '')
484114942Sume			for i in ${ipv6_network_interfaces}; do
485114942Sume				laddr=`network6_getladdr ${i}`
486114942Sume				case ${laddr} in
487114942Sume				'')
488114942Sume					;;
489114942Sume				*)
490114942Sume					break
491114942Sume					;;
492114942Sume				esac
493114942Sume			done
494114942Sume			stf_interface_ipv6_ifid=`expr "${laddr}" : \
495114942Sume						      'fe80::\(.*\)%\(.*\)'`
496114942Sume			case ${stf_interface_ipv6_ifid} in
497114942Sume			'')
498114942Sume				stf_interface_ipv6_ifid=0:0:0:1
499114942Sume				;;
500114942Sume			esac
501114942Sume			;;
502114942Sume		esac
503114942Sume		ifconfig stf0 create >/dev/null 2>&1
504114942Sume		ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \
505114942Sume			prefixlen ${stf_prefixlen}
506114942Sume		# disallow packets to malicious 6to4 prefix
507114942Sume		route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
508114942Sume		route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
509114942Sume		route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
510114942Sume		route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
511114942Sume		;;
512114942Sume	esac
513114942Sume}
514114942Sume
515114942Sume# Setup static routes
516114942Sumenetwork6_static_routes_setup()
517114942Sume{
518114942Sume	# Set up any static routes.
519114942Sume	case ${ipv6_defaultrouter} in
520114942Sume	[Nn][Oo] | '')
521114942Sume		;;
522114942Sume	*)
523114942Sume		ipv6_static_routes="default ${ipv6_static_routes}"
524114942Sume		ipv6_route_default="default ${ipv6_defaultrouter}"
525114942Sume		;;
526114942Sume	esac
527114942Sume	case ${ipv6_static_routes} in
528114942Sume	[Nn][Oo] | '')
529114942Sume		;;
530114942Sume	*)
531114942Sume		for i in ${ipv6_static_routes}; do
532114942Sume			eval ipv6_route_args=\$ipv6_route_${i}
533114942Sume			route add -inet6 ${ipv6_route_args}
534114942Sume		done
535114942Sume		;;
536114942Sume	esac
537114942Sume}
538114942Sume
539114942Sume# Setup faith
540114942Sumenetwork6_faith_setup()
541114942Sume{
542114942Sume	case ${ipv6_faith_prefix} in
543114942Sume	[Nn][Oo] | '')
544114942Sume		;;
545114942Sume	*)
546114942Sume		sysctl net.inet6.ip6.keepfaith=1
547114942Sume		ifconfig faith0 create >/dev/null 2>&1
548114942Sume		ifconfig faith0 up
549114942Sume		for prefix in ${ipv6_faith_prefix}; do
550114942Sume			prefixlen=`expr "${prefix}" : ".*/\(.*\)"`
551114942Sume			case ${prefixlen} in
552114942Sume			'')
553114942Sume				prefixlen=96
554114942Sume				;;
555114942Sume			*)
556114942Sume				prefix=`expr "${prefix}" : \
557114942Sume					     "\(.*\)/${prefixlen}"`
558114942Sume				;;
559114942Sume			esac
560114942Sume			route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1
561114942Sume			route change -inet6 ${prefix} -prefixlen ${prefixlen} \
562114942Sume				-ifp faith0
563114942Sume		done
564114942Sume		;;
565114942Sume	esac
566114942Sume}
567114942Sume
568114942Sume# Install the "default interface" to kernel, which will be used
569114942Sume# as the default route when there's no router.
570114942Sumenetwork6_default_interface_setup()
571114942Sume{
572114942Sume	# Choose IPv6 default interface if it is not clearly specified.
573114942Sume	case ${ipv6_default_interface} in
574114942Sume	'')
575114942Sume		for i in ${ipv6_network_interfaces}; do
576114942Sume			case $i in
577114942Sume			lo0|faith[0-9]*)
578114942Sume				continue
579114942Sume				;;
580114942Sume			esac
581114942Sume			laddr=`network6_getladdr $i exclude_tentative`
582114942Sume			case ${laddr} in
583114942Sume			'')
584114942Sume				;;
585114942Sume			*)
586114942Sume				ipv6_default_interface=$i
587114942Sume				break
588114942Sume				;;
589114942Sume			esac
590114942Sume		done
591114942Sume		;;
592114942Sume	esac
593114942Sume
594114942Sume	# Disallow unicast packets without outgoing scope identifiers,
595114942Sume	# or route such packets to a "default" interface, if it is specified.
596114942Sume	route add -inet6 fe80:: -prefixlen 10 ::1 -reject
597114942Sume	case ${ipv6_default_interface} in
598114942Sume	[Nn][Oo] | '')
599114942Sume		route add -inet6 ff02:: -prefixlen 16 ::1 -reject
600114942Sume		;;
601114942Sume	*)
602114942Sume		laddr=`network6_getladdr ${ipv6_default_interface}`
603114942Sume		route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \
604114942Sume			-cloning
605114942Sume
606114942Sume		# Disable installing the default interface with the
607114942Sume		# case net.inet6.ip6.forwarding=0 and
608114942Sume		# net.inet6.ip6.accept_rtadv=0, due to avoid conflict
609114942Sume		# between the default router list and the manual
610114942Sume		# configured default route.
611114942Sume		case ${ipv6_gateway_enable} in
612114942Sume		[Yy][Ee][Ss])
613114942Sume			;;
614114942Sume		*)
615114942Sume			if [ `sysctl -n net.inet6.ip6.accept_rtadv` -eq 1 ]
616114942Sume			then
617114942Sume				ndp -I ${ipv6_default_interface}
618114942Sume			fi
619114942Sume			;;
620114942Sume		esac
621114942Sume		;;
622114942Sume	esac
623114942Sume}
624114942Sume
625114942Sumenetwork6_getladdr()
626114942Sume{
627114942Sume	ifconfig $1 2>/dev/null | while read proto addr rest; do
628114942Sume		case ${proto} in
629114942Sume		inet6)
630114942Sume			case ${addr} in
631114942Sume			fe80::*)
632114942Sume				if [ -z "$2" ]; then
633114942Sume					echo ${addr}
634114942Sume					return
635114942Sume				fi
636114942Sume				case ${rest} in
637114942Sume				*tentative*)
638114942Sume					continue
639114942Sume					;;
640114942Sume				*)
641114942Sume					echo ${addr}
642114942Sume					return
643114942Sume				esac
644114942Sume			esac
645114942Sume		esac
646114942Sume	done
647114942Sume}
648