network.subr revision 166583
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 166583 2007-02-09 12:11:27Z flz $
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
458# Create netgraph nodes.
459#
460ng_mkpeer() {
461	ngctl -f - 2> /dev/null <<EOF
462mkpeer $*
463msg dummy nodeinfo
464EOF
465}
466
467ng_create_one() {
468	ng_mkpeer $* | while read line; do
469		t=`expr "${line}" : '.* name="\([a-z]*[0-9]*\)" .*'`
470		if [ -n "${t}" ]; then
471			echo ${t}
472			return
473		fi
474	done
475}
476
477gif_up() {
478	# The following must be removed once RELENG_7 is branched.
479	case ${gif_interfaces} in
480	[Nn][Oo])
481		warn "gif_interfaces=\"NO\" is deprecated, use gif_interfaces=\"\" instead."
482		gif_interfaces=""
483		;;
484	esac
485
486	for i in ${gif_interfaces}; do
487		peers=`get_if_var $i gifconfig_IF`
488		case ${peers} in
489		'')
490			continue
491			;;
492		*)
493			ifconfig $i create >/dev/null 2>&1
494			ifconfig $i tunnel ${peers}
495			ifconfig $i up
496			;;
497		esac
498	done
499}
500
501# ng_fec_create ifn
502# Configure Fast EtherChannel for interface $ifn. Returns 0 if FEC
503# arguments were found and configured; returns !0 otherwise.
504ng_fec_create() {
505	 local req_iface iface bogus
506	 req_iface="$1"
507
508	 ngctl shutdown ${req_iface}: > /dev/null 2>&1
509
510	 bogus=""
511	 while true; do
512		 iface=`ng_create_one fec dummy fec`
513		 if [ -z "${iface}" ]; then
514			 exit 2
515		 fi
516		 if [ "${iface}" = "${req_iface}" ]; then
517			 break
518		 fi
519		 bogus="${bogus} ${iface}"
520	 done
521
522	 for iface in ${bogus}; do
523		 ngctl shutdown ${iface}:
524	 done
525}
526
527fec_up() {
528	for i in ${fec_interfaces}; do
529		ng_fec_create $i
530		for j in `get_if_var $i fecconfig_IF`; do
531			case ${j} in
532			'')
533				continue
534				;;
535			*)
536				ngctl msg ${i}: add_iface "\"${j}\""
537				;;
538			esac
539		done
540	done
541}
542
543#
544# ipx_up ifn
545# Configure any IPX addresses for interface $ifn. Returns 0 if IPX
546# arguments were found and configured; returns 1 otherwise.
547#
548ipx_up()
549{
550	ifn="$1"
551	ifconfig_args=`get_if_var $ifn ifconfig_IF_ipx`
552	if [ -n "${ifconfig_args}" ]; then
553		ifconfig ${ifn} ${ifconfig_args}
554		return 0
555	fi
556	return 1
557}
558
559# ipx_down ifn
560#	Remove IPX addresses for interface $ifn. Returns 0 if IPX
561#	addresses were found and unconfigured. It returns 1, otherwise.
562#
563ipx_down()
564{
565	[ -z "$1" ] && return 1
566	_ifs="^"
567	_ret=1
568
569	ifexists $1 || return 1
570
571	ipxList="`ifconfig $1 | grep 'ipx ' | tr "\n" "$_ifs"`"
572
573	oldifs="$IFS"
574	IFS="$_ifs"
575	for _ipx in $ipxList ; do
576		# get rid of extraneous line
577		[ -z "$_ipx" ] && break
578
579		_ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'`
580
581		IFS="$oldifs"
582		ifconfig $1 ${_ipx} delete
583		IFS="$_ifs"
584		_ret=0
585	done
586	IFS="$oldifs"
587
588	return $_ret
589}
590
591# ifnet_rename
592#	Rename all requested interfaces.
593#
594ifnet_rename()
595{
596
597	_ifn_list="`ifconfig -l`"
598	[ -z "$_ifn_list" ] && return 0
599	for _if in ${_ifn_list} ; do
600		_ifname=`get_if_var $_if ifconfig_IF_name`
601		if [ ! -z "$_ifname" ]; then
602			ifconfig $_if name $_ifname
603		fi
604	done
605	return 0
606}
607
608#
609# list_net_interfaces type
610#	List all network interfaces. The type of interface returned
611#	can be controlled by the type argument. The type
612#	argument can be any of the following:
613#		nodhcp - all interfaces, excluding DHCP configured interfaces
614#		dhcp   - list only DHCP configured interfaces
615#	If no argument is specified all network interfaces are output.
616#	Note that the list will include cloned interfaces if applicable.
617#	Cloned interfaces must already exist to have a chance to appear
618#	in the list if ${network_interfaces} is set to `auto'.
619#
620list_net_interfaces()
621{
622	type=$1
623
624	# Get a list of ALL the interfaces and make lo0 first if it's there.
625	#
626	case ${network_interfaces} in
627	[Aa][Uu][Tt][Oo])
628		_prefix=''
629		_autolist="`ifconfig -l`"
630		_lo=
631		for _if in ${_autolist} ; do
632			if autoif $_if; then
633				if [ "$_if" = "lo0" ]; then
634					_lo="lo0 "
635				else
636					_tmplist="${_tmplist}${_prefix}${_if}"
637					[ -z "$_prefix" ] && _prefix=' '
638				fi
639			fi
640		done
641		_tmplist="${_lo}${_tmplist}"
642		;;
643	*)
644		_tmplist="${network_interfaces} ${cloned_interfaces}"
645		;;
646	esac
647
648	if [ -z "$type" ]; then
649		echo $_tmplist
650		return 0
651	fi
652
653	# Separate out dhcp and non-dhcp interfaces
654	#
655	_aprefix=
656	_bprefix=
657	for _if in ${_tmplist} ; do
658		if dhcpif $_if; then
659			_dhcplist="${_dhcplist}${_aprefix}${_if}"
660			[ -z "$_aprefix" ] && _aprefix=' '
661		elif [ -n "`_ifconfig_getargs $_if`" ]; then
662			_nodhcplist="${_nodhcplist}${_bprefix}${_if}"
663			[ -z "$_bprefix" ] && _bprefix=' '
664		fi
665	done
666
667	case "$type" in
668	nodhcp)
669		echo $_nodhcplist
670		;;
671	dhcp)
672		echo $_dhcplist
673		;;
674	esac
675	return 0
676}
677
678hexdigit()
679{
680	if [ $1 -lt 10 ]; then
681		echo $1
682	else
683		case $1 in
684		10)	echo a ;;
685		11)	echo b ;;
686		12)	echo c ;;
687		13)	echo d ;;
688		14)	echo e ;;
689		15)	echo f ;;
690		esac
691	fi
692}
693
694hexprint()
695{
696	val=$1
697	str=''
698
699	dig=`hexdigit $((${val} & 15))`
700	str=${dig}${str}
701	val=$((${val} >> 4))
702	while [ ${val} -gt 0 ]; do
703		dig=`hexdigit $((${val} & 15))`
704		str=${dig}${str}
705		val=$((${val} >> 4))
706	done
707
708	echo ${str}
709}
710
711# Setup the interfaces for IPv6
712network6_interface_setup()
713{
714	interfaces=$*
715	rtsol_interfaces=''
716	case ${ipv6_gateway_enable} in
717	[Yy][Ee][Ss])
718		rtsol_available=no
719		;;
720	*)
721		rtsol_available=yes
722		;;
723	esac
724	for i in $interfaces; do
725		rtsol_interface=yes
726		prefix=`get_if_var $i ipv6_prefix_IF`
727		if [ -n "${prefix}" ]; then
728			rtsol_available=no
729			rtsol_interface=no
730			laddr=`network6_getladdr $i`
731			hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'`
732			for j in ${prefix}; do
733				address=$j\:${hostid}
734				ifconfig $i inet6 ${address} prefixlen 64 alias
735
736				case ${ipv6_gateway_enable} in
737				[Yy][Ee][Ss])
738					# subnet-router anycast address
739					# (rfc2373)
740					ifconfig $i inet6 $j:: prefixlen 64 \
741						alias anycast
742					;;
743				esac
744			done
745		fi
746		ipv6_ifconfig=`get_if_var $i ipv6_ifconfig_IF`
747		if [ -n "${ipv6_ifconfig}" ]; then
748			rtsol_available=no
749			rtsol_interface=no
750			ifconfig $i inet6 ${ipv6_ifconfig} alias
751		fi
752
753		if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ]
754		then
755			case ${i} in
756			lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*|pflog[0-9]*|pfsync[0-9]*)
757				;;
758			*)
759				rtsol_interfaces="${rtsol_interfaces} ${i}"
760				;;
761			esac
762		else
763			ifconfig $i inet6
764		fi
765	done
766
767	if [ ${rtsol_available} = yes -a -n "${rtsol_interfaces}" ]; then
768		# Act as endhost - automatically configured.
769		# You can configure only single interface, as
770		# specification assumes that autoconfigured host has
771		# single interface only.
772		sysctl net.inet6.ip6.accept_rtadv=1
773		set ${rtsol_interfaces}
774		ifconfig $1 up
775		rtsol ${rtsol_flags} $1
776	fi
777
778	for i in $interfaces; do
779		alias=0
780		while : ; do
781			ipv6_ifconfig=`get_if_var $i ipv6_ifconfig_IF_alias${alias}`
782			if [ -z "${ipv6_ifconfig}" ]; then
783				break;
784			fi
785			ifconfig $i inet6 ${ipv6_ifconfig} alias
786			alias=$((${alias} + 1))
787		done
788	done
789}
790
791# Setup IPv6 to IPv4 mapping
792network6_stf_setup()
793{
794	case ${stf_interface_ipv4addr} in
795	[Nn][Oo] | '')
796		;;
797	*)
798		# assign IPv6 addr and interface route for 6to4 interface
799		stf_prefixlen=$((16+${stf_interface_ipv4plen:-0}))
800		OIFS="$IFS"
801		IFS=".$IFS"
802		set ${stf_interface_ipv4addr}
803		IFS="$OIFS"
804		hexfrag1=`hexprint $(($1*256 + $2))`
805		hexfrag2=`hexprint $(($3*256 + $4))`
806		ipv4_in_hexformat="${hexfrag1}:${hexfrag2}"
807		case ${stf_interface_ipv6_ifid} in
808		[Aa][Uu][Tt][Oo] | '')
809			for i in ${ipv6_network_interfaces}; do
810				laddr=`network6_getladdr ${i}`
811				case ${laddr} in
812				'')
813					;;
814				*)
815					break
816					;;
817				esac
818			done
819			stf_interface_ipv6_ifid=`expr "${laddr}" : \
820						      'fe80::\(.*\)%\(.*\)'`
821			case ${stf_interface_ipv6_ifid} in
822			'')
823				stf_interface_ipv6_ifid=0:0:0:1
824				;;
825			esac
826			;;
827		esac
828		ifconfig stf0 create >/dev/null 2>&1
829		ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \
830			prefixlen ${stf_prefixlen}
831		# disallow packets to malicious 6to4 prefix
832		route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
833		route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
834		route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
835		route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
836		;;
837	esac
838}
839
840# Setup static routes
841network6_static_routes_setup()
842{
843	# Set up any static routes.
844	case ${ipv6_defaultrouter} in
845	[Nn][Oo] | '')
846		;;
847	*)
848		ipv6_static_routes="default ${ipv6_static_routes}"
849		ipv6_route_default="default ${ipv6_defaultrouter}"
850		;;
851	esac
852	case ${ipv6_static_routes} in
853	[Nn][Oo] | '')
854		;;
855	*)
856		for i in ${ipv6_static_routes}; do
857			ipv6_route_args=`get_if_var $i ipv6_route_IF`
858			route add -inet6 ${ipv6_route_args}
859		done
860		;;
861	esac
862}
863
864# Setup faith
865network6_faith_setup()
866{
867	case ${ipv6_faith_prefix} in
868	[Nn][Oo] | '')
869		;;
870	*)
871		sysctl net.inet6.ip6.keepfaith=1
872		ifconfig faith0 create >/dev/null 2>&1
873		ifconfig faith0 up
874		for prefix in ${ipv6_faith_prefix}; do
875			prefixlen=`expr "${prefix}" : ".*/\(.*\)"`
876			case ${prefixlen} in
877			'')
878				prefixlen=96
879				;;
880			*)
881				prefix=`expr "${prefix}" : \
882					     "\(.*\)/${prefixlen}"`
883				;;
884			esac
885			route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1
886			route change -inet6 ${prefix} -prefixlen ${prefixlen} \
887				-ifp faith0
888		done
889		;;
890	esac
891}
892
893# Install the "default interface" to kernel, which will be used
894# as the default route when there's no router.
895network6_default_interface_setup()
896{
897	# Choose IPv6 default interface if it is not clearly specified.
898	case ${ipv6_default_interface} in
899	'')
900		for i in ${ipv6_network_interfaces}; do
901			case $i in
902			lo0|faith[0-9]*)
903				continue
904				;;
905			esac
906			laddr=`network6_getladdr $i exclude_tentative`
907			case ${laddr} in
908			'')
909				;;
910			*)
911				ipv6_default_interface=$i
912				break
913				;;
914			esac
915		done
916		;;
917	esac
918
919	# Disallow unicast packets without outgoing scope identifiers,
920	# or route such packets to a "default" interface, if it is specified.
921	route add -inet6 fe80:: -prefixlen 10 ::1 -reject
922	case ${ipv6_default_interface} in
923	[Nn][Oo] | '')
924		route add -inet6 ff02:: -prefixlen 16 ::1 -reject
925		;;
926	*)
927		laddr=`network6_getladdr ${ipv6_default_interface}`
928		route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \
929			-cloning
930
931		# Disable installing the default interface with the
932		# case net.inet6.ip6.forwarding=0 and
933		# net.inet6.ip6.accept_rtadv=0, due to avoid conflict
934		# between the default router list and the manual
935		# configured default route.
936		case ${ipv6_gateway_enable} in
937		[Yy][Ee][Ss])
938			;;
939		*)
940			if [ `sysctl -n net.inet6.ip6.accept_rtadv` -eq 1 ]
941			then
942				ndp -I ${ipv6_default_interface}
943			fi
944			;;
945		esac
946		;;
947	esac
948}
949
950network6_getladdr()
951{
952	ifconfig $1 2>/dev/null | while read proto addr rest; do
953		case ${proto} in
954		inet6)
955			case ${addr} in
956			fe80::*)
957				if [ -z "$2" ]; then
958					echo ${addr}
959					return
960				fi
961				case ${rest} in
962				*tentative*)
963					continue
964					;;
965				*)
966					echo ${addr}
967					return
968				esac
969			esac
970		esac
971	done
972}
973