xref: /dragonfly/etc/network.subr (revision 75a74ed8)
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_up
418#	Create IEEE 802.11 interfaces.
419#
420wlan_up()
421{
422	local _prefix _list parent child child_wlans create_args debug_flags
423	_prefix=
424	_list=
425
426	for parent in `${SYSCTL_N} -q net.wlan.devices`; do
427		# Parse wlans_$parent="$child ..."
428		child_wlans=`get_if_var $parent wlans_IF`
429		for child in ${child_wlans}; do
430			if ifexists $child; then
431				continue
432			fi
433
434			create_args="wlandev $parent `get_if_var $child create_args_IF`"
435			debug_flags="`get_if_var $child wlandebug_IF`"
436			if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
437				ifconfig $child create ${create_args}
438			else
439				ifconfig wlan create ${create_args} name $child
440			fi
441			if [ $? -eq 0 ]; then
442				_list="${_list}${_prefix}${child}"
443				[ -z "$_prefix" ] && _prefix=' '
444			fi
445			if [ -n "${debug_flags}" ]; then
446				wlandebug -i $child ${debug_flags}
447			fi
448		done
449	done
450
451	if [ -n "${_list}" ]; then
452		echo "Created wlan interfaces: ${_list}"
453	fi
454	debug "Created wlan interfaces: ${_list}"
455}
456
457# wlan_down
458#	Destroy IEEE 802.11 interfaces.
459#
460wlan_down()
461{
462	local _prefix _list parent child child_wlans
463	_prefix=
464	_list=
465
466	for parent in `${SYSCTL_N} -q net.wlan.devices`; do
467		child_wlans=`get_if_var $parent wlans_IF`
468		for child in ${child_wlans}; do
469			if ! ifexists $child; then
470				continue
471			fi
472
473			ifconfig -n $child destroy
474			if [ $? -eq 0 ]; then
475				_list="${_list}${_prefix}${child}"
476				[ -z "$_prefix" ] && _prefix=' '
477			fi
478		done
479	done
480
481	if [ -n "${_list}" ]; then
482		echo "Destroyed wlan interfaces: ${_list}"
483	fi
484	debug "Destroyed wlan interfaces: ${_list}"
485}
486
487# clone_up
488#	Create cloneable interfaces.
489#
490clone_up()
491{
492	local _prefix _list ifn
493	_prefix=
494	_list=
495
496	for ifn in ${cloned_interfaces}; do
497		ifconfig ${ifn} create
498		if [ $? -eq 0 ]; then
499			_list="${_list}${_prefix}${ifn}"
500			[ -z "$_prefix" ] && _prefix=' '
501		fi
502	done
503	if [ -n "${_list}" ]; then
504		echo "Created clone interfaces: ${_list}"
505	fi
506	debug "Created clone interfaces: ${_list}"
507}
508
509# clone_down
510#	Destroy cloned interfaces.
511#
512clone_down()
513{
514	local _prefix _list ifn
515	_prefix=
516	_list=
517
518	for ifn in ${cloned_interfaces}; do
519		ifconfig ${ifn} destroy
520		if [ $? -eq 0 ]; then
521			_list="${_list}${_prefix}${ifn}"
522			[ -z "$_prefix" ] && _prefix=' '
523		fi
524	done
525	if [ -n "${_list}" ]; then
526		echo "Destroyed clone interfaces: ${_list}"
527	fi
528	debug "Destroyed clone interfaces: ${_list}"
529}
530
531# gif_up
532#	Create IPv6<-->IPv4 tunnels
533#
534gif_up() {
535	local _if _peers
536
537	case ${gif_interfaces} in
538	[Nn][Oo] | '')
539		return
540		;;
541	esac
542
543	for _if in ${gif_interfaces}; do
544		eval _peers=\$gifconfig_${_if}
545		case ${_peers} in
546		'')
547			continue
548			;;
549		*)
550			ifconfig $_if create >/dev/null 2>&1
551			ifconfig $_if tunnel ${_peers}
552			ifconfig $_if up
553			;;
554		esac
555	done
556}
557
558# ifnet_rename
559#	Rename all requested interfaces.
560#
561ifnet_rename()
562{
563	local _ifn_list _if _ifname
564
565	_ifn_list=$(ifconfig -l)
566	[ -z "$_ifn_list" ] && return 0
567
568	for _if in ${_ifn_list} ; do
569		_ifname=`get_if_var $_if ifconfig_IF_name`
570		if [ -n "$_ifname" ]; then
571			ifconfig $_if name $_ifname
572		fi
573	done
574	return 0
575}
576
577# list_net_interfaces
578#	List all network interfaces.
579#	Note that the list will include cloned interfaces if applicable.
580#	Cloned interfaces must already exist to have a chance to appear
581#	in the list if ${network_interfaces} is set to `auto'.
582#
583list_net_interfaces()
584{
585	local _tmplist _autolist _lo _if
586
587	case ${network_interfaces} in
588	[Aa][Uu][Tt][Oo])
589		_autolist=$(ifconfig -l)
590		_lo=
591		for _if in ${_autolist} ; do
592			if [ "$_if" = "lo0" ]; then
593				_lo="lo0"
594			else
595				_tmplist="${_tmplist} ${_if}"
596			fi
597		done
598		_tmplist="${_lo} ${_tmplist}"
599		;;
600	*)
601		_tmplist="${network_interfaces} ${cloned_interfaces}"
602		;;
603	esac
604
605	echo $_tmplist
606}
607
608hexdigit()
609{
610	if [ $1 -lt 10 ]; then
611		echo $1
612	else
613		case $1 in
614		10)	echo a ;;
615		11)	echo b ;;
616		12)	echo c ;;
617		13)	echo d ;;
618		14)	echo e ;;
619		15)	echo f ;;
620		esac
621	fi
622}
623
624hexprint()
625{
626	local val str dig
627	val=$1
628	str=''
629
630	dig=`hexdigit $((${val} & 15))`
631	str=${dig}${str}
632	val=$((${val} >> 4))
633	while [ ${val} -gt 0 ]; do
634		dig=`hexdigit $((${val} & 15))`
635		str=${dig}${str}
636		val=$((${val} >> 4))
637	done
638
639	echo ${str}
640}
641
642
643#
644# IPv6-specific setup subroutines
645#
646
647# Setup the interfaces for IPv6
648network6_interface_setup()
649{
650	local interfaces rtsol_interfaces ipv6_ifconfig
651	local rtsol_available rtsol_interface
652	local prefix laddr hostid address
653	local _if j
654
655	interfaces=$*
656	rtsol_interfaces=''
657	case ${ipv6_gateway_enable} in
658	[Yy][Ee][Ss])
659		rtsol_available=no
660		;;
661	*)
662		rtsol_available=yes
663		;;
664	esac
665	for _if in $interfaces; do
666		rtsol_interface=yes
667		prefix=`get_if_var $_if ipv6_prefix_IF`
668		if [ -n "${prefix}" ]; then
669			rtsol_available=no
670			rtsol_interface=no
671			laddr=`network6_getladdr $_if`
672			hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'`
673			for j in ${prefix}; do
674				address=$j\:${hostid}
675				ifconfig $_if inet6 ${address} prefixlen 64 alias
676
677				case ${ipv6_gateway_enable} in
678				[Yy][Ee][Ss])
679					# subnet-router anycast address
680					# (rfc2373)
681					ifconfig $_if inet6 $j:: prefixlen 64 \
682						alias anycast
683					;;
684				esac
685			done
686		fi
687		ipv6_ifconfig=`ifconfig_getargs $_if ipv6`
688		ipv6_ifconfig="${ipv6_ifconfig#inet6 }"
689		if [ -n "${ipv6_ifconfig}" ]; then
690			rtsol_available=no
691			rtsol_interface=no
692			ifconfig $_if inet6 ${ipv6_ifconfig} alias
693		fi
694
695		if [ "${rtsol_available}" = "yes" -a \
696		     "${rtsol_interface}" = "yes" ]; then
697			case ${i} in
698			lo0|gif[0-9]*|stf[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*)
699				;;
700			*)
701				rtsol_interfaces="${rtsol_interfaces} ${_if}"
702				;;
703			esac
704		else
705			ifconfig $_if inet6
706		fi
707	done
708
709	if [ "${rtsol_available}" = "yes" -a -n "${rtsol_interfaces}" ]; then
710		# Act as endhost - automatically configured.
711		# You can configure only single interface, as
712		# specification assumes that autoconfigured host has
713		# single interface only.
714		${SYSCTL_W} net.inet6.ip6.accept_rtadv=1
715		set ${rtsol_interfaces}
716		ifconfig $1 up
717		echo "Auto configuring interface $1 ..."
718		rtsol $1
719	fi
720
721	for _if in $interfaces; do
722		ifalias_up $_if ipv6
723	done
724}
725
726# Setup IPv6 to IPv4 mapping
727network6_stf_setup()
728{
729	local stf_prefixlen stf_interface_ipv6_ifid
730	local hexfrag1 hexfrag2 ipv4_in_hexformat laddr
731	local _if OIFS
732
733	case ${stf_interface_ipv4addr} in
734	[Nn][Oo] | '')
735		;;
736	*)
737		# assign IPv6 addr and interface route for 6to4 interface
738		stf_prefixlen=$((16+${stf_interface_ipv4plen:-0}))
739		OIFS="$IFS"
740		IFS=".$IFS"
741		set ${stf_interface_ipv4addr}
742		IFS="$OIFS"
743		hexfrag1=`hexprint $(($1*256 + $2))`
744		hexfrag2=`hexprint $(($3*256 + $4))`
745		ipv4_in_hexformat="${hexfrag1}:${hexfrag2}"
746		case ${stf_interface_ipv6_ifid} in
747		[Aa][Uu][Tt][Oo] | '')
748			for _if in ${ipv6_network_interfaces}; do
749				laddr=`network6_getladdr $_if`
750				case ${laddr} in
751				'')
752					;;
753				*)
754					break
755					;;
756				esac
757			done
758			stf_interface_ipv6_ifid=`expr "${laddr}" : \
759						      'fe80::\(.*\)%\(.*\)'`
760			case ${stf_interface_ipv6_ifid} in
761			'')
762				stf_interface_ipv6_ifid=0:0:0:1
763				;;
764			esac
765			;;
766		esac
767		ifconfig stf0 create >/dev/null 2>&1
768		ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \
769			prefixlen ${stf_prefixlen}
770		# disallow packets to malicious 6to4 prefix
771		route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
772		route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
773		route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
774		route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
775		;;
776	esac
777}
778
779# Setup static routes
780network6_static_routes_setup()
781{
782	local _rt
783
784	# Set up any static routes.
785	case ${ipv6_defaultrouter} in
786	[Nn][Oo] | '')
787		;;
788	*)
789		ipv6_static_routes="default ${ipv6_static_routes}"
790		ipv6_route_default="default ${ipv6_defaultrouter}"
791		;;
792	esac
793	case ${ipv6_static_routes} in
794	[Nn][Oo] | '')
795		;;
796	*)
797		for _rt in ${ipv6_static_routes}; do
798			eval ipv6_route_args=\$ipv6_route_${_rt}
799			route add -inet6 ${ipv6_route_args}
800		done
801		;;
802	esac
803}
804
805# Install the "default interface" to kernel, which will be used
806# as the default route when there's no router.
807network6_default_interface_setup()
808{
809	local _if laddr
810
811	# Choose IPv6 default interface if it is not clearly specified.
812	case ${ipv6_default_interface} in
813	'')
814		for _if in ${ipv6_network_interfaces}; do
815			if [ "${_if}" = "lo0" ]; then
816				continue
817			fi
818
819			laddr=`network6_getladdr $_if exclude_tentative`
820			case ${laddr} in
821			'')
822				;;
823			*)
824				ipv6_default_interface=$_if
825				break
826				;;
827			esac
828		done
829		;;
830	esac
831
832	# Disallow unicast packets without outgoing scope identifiers,
833	# or route such packets to a "default" interface, if it is specified.
834	route add -inet6 fe80:: -prefixlen 10 ::1 -reject
835	case ${ipv6_default_interface} in
836	[Nn][Oo] | '')
837		route add -inet6 ff02:: -prefixlen 16 ::1 -reject
838		;;
839	*)
840		laddr=`network6_getladdr ${ipv6_default_interface}`
841		route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \
842			-cloning
843
844		# Disable installing the default interface with the
845		# case net.inet6.ip6.forwarding=0 and
846		# net.inet6.ip6.accept_rtadv=0, due to avoid conflict
847		# between the default router list and the manual
848		# configured default route.
849		case ${ipv6_gateway_enable} in
850		[Yy][Ee][Ss])
851			;;
852		*)
853			if [ `${SYSCTL_N} net.inet6.ip6.accept_rtadv` -eq 1 ]
854			then
855				ndp -I ${ipv6_default_interface}
856			fi
857			;;
858		esac
859		;;
860	esac
861}
862
863network6_getladdr()
864{
865	local proto addr rest
866
867	ifconfig $1 2>/dev/null | while read proto addr rest; do
868		case ${proto} in
869		inet6)
870			case ${addr} in
871			fe80::*)
872				if [ -z "$2" ]; then
873					echo ${addr}
874					return
875				fi
876				case ${rest} in
877				*tentative*)
878					continue
879					;;
880				*)
881					echo ${addr}
882					return
883				esac
884			esac
885		esac
886	done
887}
888