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