network.subr revision 179003
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 179003 2008-05-15 01:06:10Z brooks $
26#
27
28#
29# Subroutines commonly used from network startup scripts.
30# Requires that rc.conf be loaded first.
31#
32
33# ifn_start ifn
34# Bring up and configure an interface.  If some configuration is applied
35# print the interface configuration.
36#
37ifn_start()
38{
39	local ifn cfg
40	ifn="$1"
41	cfg=1
42
43	[ -z "$ifn" ] && err 1 "ifn_start called without an interface"
44
45	ifscript_up ${ifn} && cfg=0
46	ifconfig_up ${ifn} && cfg=0
47	ipv4_up ${ifn} && cfg=0
48	ipx_up ${ifn} && cfg=0
49	childif_create ${ifn}
50
51	if [ "$cfg" -eq 0 ]; then
52		ifconfig ${ifn}
53	fi
54
55	return $cfg
56}
57
58# ifn_start ifn
59# Shutdown and de-configure an interface.  If action is taken print the
60# interface name.
61#
62ifn_stop()
63{
64	local ifn cfg
65	ifn="$1"
66	cfg=1
67
68	[ -z "$ifn" ] && return 1
69
70	ipx_down ${ifn} && cfg=0
71	ipv4_down ${ifn} && cfg=0
72	ifconfig_down ${ifn} && cfg=0
73	ifscript_down ${ifn} && cfg=0
74	childif_destroy ${ifn}
75
76	if [ "$cfg" -eq 0 ]; then
77		echo -n " ${ifn}"
78	fi
79
80	return $cfg
81}
82
83# ifconfig_up if
84#	Evaluate ifconfig(8) arguments for interface $if and
85#	run ifconfig(8) with those arguments. It returns 0 if
86#	arguments were found and executed or 1 if the interface
87#	had no arguments.  Pseudo arguments DHCP and WPA are handled
88#	here.
89#
90ifconfig_up()
91{
92	_cfg=1
93
94	ifconfig_args=`ifconfig_getargs $1`
95	if [ -n "${ifconfig_args}" ]; then
96		ifconfig $1 ${ifconfig_args}
97		ifconfig $1 up
98		_cfg=0
99	fi
100
101	if wpaif $1; then
102		/etc/rc.d/wpa_supplicant start $1
103		_cfg=0		# XXX: not sure this should count
104	fi
105
106	if dhcpif $1; then
107		if [ $_cfg -ne 0 ] ; then
108			ifconfig $1 up
109		fi
110		if syncdhcpif $1; then
111			/etc/rc.d/dhclient start $1
112		fi
113		_cfg=0
114	fi
115
116	return $_cfg
117}
118
119# ifconfig_down if
120#	returns 1 if wpa_supplicant or dhclient was stopped or
121#	the interface exists.
122#
123ifconfig_down()
124{
125	[ -z "$1" ] && return 1
126	_cfg=1
127
128	if wpaif $1; then
129		/etc/rc.d/wpa_supplicant stop $1
130		_cfg=0
131	fi
132
133	if dhcpif $1; then
134		/etc/rc.d/dhclient stop $1
135		_cfg=0
136	fi
137
138	if ifexists $1; then
139		ifconfig $1 down
140		_cfg=0
141	fi
142
143	return $_cfg
144}
145
146# get_if_var if var [default]
147#       Return the value of the pseudo-hash corresponding to $if where
148#       $var is a string containg the sub-string "IF" which will be
149#       replaced with $if after the characters defined in _punct are
150#       replaced with '_'. If the variable is unset, replace it with
151#       $default if given.
152get_if_var()
153{
154	if [ $# -ne 2 -a $# -ne 3 ]; then
155		err 3 'USAGE: get_if_var name var [default]'
156	fi
157
158	_if=$1
159	_punct=". - / +"
160	for _punct_c in $_punct; do
161		_if=`ltr ${_if} ${_punct_c} '_'`
162	done
163	_var=$2
164	_default=$3
165
166	prefix=${_var%%IF*}
167	suffix=${_var##*IF}
168	eval echo \${${prefix}${_if}${suffix}-${_default}}
169}
170
171# _ifconfig_getargs if
172#	Echos the arguments for the supplied interface to stdout.
173#	returns 1 if empty.  In general, ifconfig_getargs should be used
174#	outside this file.
175_ifconfig_getargs()
176{
177	_ifn=$1
178	if [ -z "$_ifn" ]; then
179		return 1
180	fi
181
182	get_if_var $_ifn ifconfig_IF "$ifconfig_DEFAULT"
183}
184
185# ifconfig_getargs if
186#	Takes the result from _ifconfig_getargs and removes pseudo
187#	args such as DHCP and WPA.
188ifconfig_getargs()
189{
190	_tmpargs=`_ifconfig_getargs $1`
191	if [ $? -eq 1 ]; then
192		return 1
193	fi
194	_args=
195
196	for _arg in $_tmpargs; do
197		case $_arg in
198		[Dd][Hh][Cc][Pp]) ;;
199		[Nn][Oo][Aa][Uu][Tt][Oo]) ;;
200		[Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]) ;;
201		[Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp]) ;;
202		[Ww][Pp][Aa]) ;;
203		*)
204			_args="$_args $_arg"
205			;;
206		esac
207	done
208
209	echo $_args
210}
211
212# autoif
213#	Returns 0 if the interface should be automaticly configured at
214#	boot time and 1 otherwise.
215autoif()
216{
217	_tmpargs=`_ifconfig_getargs $1`
218	for _arg in $_tmpargs; do
219		case $_arg in
220		[Nn][Oo][Aa][Uu][Tt][Oo])
221			return 1
222			;;
223		esac
224	done
225	return 0
226}
227
228# dhcpif if
229#	Returns 0 if the interface is a DHCP interface and 1 otherwise.
230dhcpif()
231{
232	_tmpargs=`_ifconfig_getargs $1`
233	for _arg in $_tmpargs; do
234		case $_arg in
235		[Dd][Hh][Cc][Pp])
236			return 0
237			;;
238		[Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
239			return 0
240			;;
241		[Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
242			return 0
243			;;
244		esac
245	done
246	return 1
247}
248
249# syncdhcpif
250#	Returns 0 if the interface should be configured synchronously and
251#	1 otherwise.
252syncdhcpif()
253{
254	_tmpargs=`_ifconfig_getargs $1`
255	for _arg in $_tmpargs; do
256		case $_arg in
257		[Nn][Oo][Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
258			return 1
259			;;
260		[Ss][Yy][Nn][Cc][Dd][Hh][Cc][Pp])
261			return 0
262			;;
263		esac
264	done
265	if checkyesno synchronous_dhclient; then
266		return 0
267	else
268		return 1
269	fi
270}
271
272# wpaif if
273#	Returns 0 if the interface is a WPA interface and 1 otherwise.
274wpaif()
275{
276	_tmpargs=`_ifconfig_getargs $1`
277	for _arg in $_tmpargs; do
278		case $_arg in
279		[Ww][Pp][Aa])
280			return 0
281			;;
282		esac
283	done
284	return 1
285}
286
287# ipv6if if
288#	Returns 0 if the interface should be configured for IPv6 and
289#	1 otherwise.
290ipv6if()
291{
292	if ! checkyesno ipv6_enable; then
293		return 1
294	fi
295	case "${ipv6_network_interfaces}" in
296	[Aa][Uu][Tt][Oo])
297		return 0
298		;;
299	''|[Nn][Oo][Nn][Ee])
300		return 1
301		;;
302	esac
303	for v6if in ${ipv6_network_interfaces}; do
304		if [ "${v6if}" = "${1}" ]; then
305			return 0
306		fi
307	done
308	return 1
309}
310
311# ifexists if
312#	Returns 0 if the interface exists and 1 otherwise.
313ifexists()
314{
315	ifconfig -n $1 > /dev/null 2>&1
316}
317
318# ipv4_up if
319#  add IPv4 addresses to the interface $if 
320ipv4_up()
321{
322	_if=$1
323	ifalias_up ${_if}
324	ipv4_addrs_common ${_if} alias
325}
326
327# ipv4_down if
328#  remove IPv4 addresses from the interface $if
329ipv4_down()
330{
331	_if=$1
332	_ifs="^"
333	_ret=1
334
335	ifexists ${_if} || return 1
336
337	inetList="`ifconfig ${_if} | grep 'inet ' | tr "\n" "$_ifs"`"
338
339	oldifs="$IFS"
340	IFS="$_ifs"
341	for _inet in $inetList ; do
342		# get rid of extraneous line
343		[ -z "$_inet" ] && break
344
345		_inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'`
346
347		IFS="$oldifs"
348		ifconfig ${_if} ${_inet} delete
349		IFS="$_ifs"
350		_ret=0
351	done
352	IFS="$oldifs"
353
354	ifalias_down ${_if} && _ret=0
355	ipv4_addrs_common ${_if} -alias && _ret=0
356
357	return $_ret
358}
359
360# ipv4_addrs_common if action
361#   Evaluate the ifconfig_if_ipv4 arguments for interface $if
362#   and use $action to add or remove IPv4 addresses from $if.
363ipv4_addrs_common()
364{  
365	_ret=1
366	_if=$1
367	_action=$2
368    
369	# get ipv4-addresses
370	cidr_addr=`get_if_var $_if ipv4_addrs_IF`
371    
372	for _cidr in ${cidr_addr}; do
373		_ipaddr=${_cidr%%/*}
374		_netmask="/"${_cidr##*/}
375		_range=${_ipaddr##*.}
376		_ipnet=${_ipaddr%.*}
377		_iplow=${_range%-*}
378		_iphigh=${_range#*-}
379
380		# clear netmask when removing aliases
381		if [ "${_action}" = "-alias" ]; then
382			_netmask=""
383		fi
384        
385		_ipcount=${_iplow}
386		while [ "${_ipcount}" -le "${_iphigh}" ]; do
387			eval "ifconfig ${_if} ${_action} ${_ipnet}.${_ipcount}${_netmask}"
388			_ipcount=$((${_ipcount}+1))
389			_ret=0
390
391			# only the first ipaddr in a subnet need the real netmask
392			if [ "${_action}" != "-alias" ]; then
393				_netmask="/32"
394			fi
395		done
396	done
397	return $_ret
398}
399
400# ifalias_up if
401#	Configure aliases for network interface $if.
402#	It returns 0 if at least one alias was configured or
403#	1 if there were none.
404#
405ifalias_up()
406{
407	_ret=1
408	alias=0
409	while : ; do
410		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
411		if [ -n "${ifconfig_args}" ]; then
412			ifconfig $1 ${ifconfig_args} alias
413			alias=$((${alias} + 1))
414			_ret=0
415		else
416			break
417		fi
418	done
419	return $_ret
420}
421
422#ifalias_down if
423#	Remove aliases for network interface $if.
424#	It returns 0 if at least one alias was removed or
425#	1 if there were none.
426#
427ifalias_down()
428{
429	_ret=1
430	alias=0
431	while : ; do
432		ifconfig_args=`get_if_var $1 ifconfig_IF_alias${alias}`
433		if [ -n "${ifconfig_args}" ]; then
434			ifconfig $1 ${ifconfig_args} -alias
435			alias=$((${alias} + 1))
436			_ret=0
437		else
438			break
439		fi
440	done
441	return $_ret
442}
443
444# ifscript_up if
445#	Evaluate a startup script for the $if interface.
446#	It returns 0 if a script was found and processed or
447#	1 if no script was found.
448#
449ifscript_up()
450{
451	if [ -r /etc/start_if.$1 ]; then
452		. /etc/start_if.$1
453		return 0
454	fi
455	return 1
456}
457
458# ifscript_down if
459#	Evaluate a shutdown script for the $if interface.
460#	It returns 0 if a script was found and processed or
461#	1 if no script was found.
462#
463ifscript_down()
464{
465	if [ -r /etc/stop_if.$1 ]; then
466		. /etc/stop_if.$1
467		return 0
468	fi
469	return 1
470}
471
472# Create cloneable interfaces.
473#
474clone_up()
475{
476	_prefix=
477	_list=
478	for ifn in ${cloned_interfaces}; do
479		ifconfig ${ifn} create `get_if_var ${ifn} create_args_IF`
480		if [ $? -eq 0 ]; then
481			_list="${_list}${_prefix}${ifn}"
482			[ -z "$_prefix" ] && _prefix=' '
483		fi
484	done
485	debug "Cloned: ${_list}"
486}
487
488# Destroy cloned interfaces. Destroyed interfaces are echoed
489# to standard output.
490#
491clone_down()
492{
493	_prefix=
494	_list=
495	for ifn in ${cloned_interfaces}; do
496		ifconfig ${ifn} destroy
497		if [ $? -eq 0 ]; then
498			_list="${_list}${_prefix}${ifn}"
499			[ -z "$_prefix" ] && _prefix=' '
500		fi
501	done
502	debug "Destroyed clones: ${_list}"
503}
504
505# Create and configure child interfaces.
506# Return 0 if child interfaces are created.
507#
508childif_create()
509{
510	local cfg child child_wlans create_args ifn i
511	cfg=1
512
513	ifn=$1
514
515	# Create wireless interfaces
516	child_wlans=`get_if_var $ifn wlans_IF`
517	if [ -z "${child_wlans}" ]; then
518		child_wlans=`get_if_var $ifn vaps_IF`
519		if [ -n "${child_wlans}" ]; then
520			warn "soon to be deleted vaps_$ifn variable defined use wlans_$ifn"
521		fi
522	fi
523
524	for child in ${child_wlans}; do
525		create_args="wlandev $ifn `get_if_var $child create_args_IF` `get_if_var $child vap_create_IF`"
526		if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
527			ifconfig $child create ${create_args} && cfg=0
528		else
529			i=`ifconfig wlan create ${create_args}`
530			ifconfig $i name $child && cfg=0
531		fi
532		ifn_start $child
533	done
534
535	return ${cfg}
536}
537
538# Destroy child interfaces.
539#
540childif_destroy()
541{
542	local cfg child child_wlans ifn
543
544	child_wlans="`get_if_var $ifn wlans_IF` `get_if_var $ifn vaps_IF`"
545	for child in ${child_wlans}; do
546		ifconfig $child destroy && cfg=0
547	done
548}
549
550# Create netgraph nodes.
551#
552ng_mkpeer() {
553	ngctl -f - 2> /dev/null <<EOF
554mkpeer $*
555msg dummy nodeinfo
556EOF
557}
558
559ng_create_one() {
560	ng_mkpeer $* | while read line; do
561		t=`expr "${line}" : '.* name="\([a-z]*[0-9]*\)" .*'`
562		if [ -n "${t}" ]; then
563			echo ${t}
564			return
565		fi
566	done
567}
568
569gif_up() {
570	for i in ${gif_interfaces}; do
571		peers=`get_if_var $i gifconfig_IF`
572		case ${peers} in
573		'')
574			continue
575			;;
576		*)
577			if expr $i : 'gif[0-9][0-9]*$' >/dev/null 2>&1; then
578				ifconfig $i create >/dev/null 2>&1
579			else
580				gif=`ifconfig gif create`
581				ifconfig $gif name $i
582			fi
583			ifconfig $i tunnel ${peers}
584			ifconfig $i up
585			;;
586		esac
587	done
588}
589
590# ng_fec_create ifn
591# Configure Fast EtherChannel for interface $ifn. Returns 0 if FEC
592# arguments were found and configured; returns !0 otherwise.
593ng_fec_create() {
594	 local req_iface iface bogus
595	 req_iface="$1"
596
597	 ngctl shutdown ${req_iface}: > /dev/null 2>&1
598
599	 bogus=""
600	 while true; do
601		 iface=`ng_create_one fec dummy fec`
602		 if [ -z "${iface}" ]; then
603			 exit 2
604		 fi
605		 if [ "${iface}" = "${req_iface}" ]; then
606			 break
607		 fi
608		 bogus="${bogus} ${iface}"
609	 done
610
611	 for iface in ${bogus}; do
612		 ngctl shutdown ${iface}:
613	 done
614}
615
616fec_up() {
617	for i in ${fec_interfaces}; do
618		ng_fec_create $i
619		for j in `get_if_var $i fecconfig_IF`; do
620			case ${j} in
621			'')
622				continue
623				;;
624			*)
625				ngctl msg ${i}: add_iface "\"${j}\""
626				;;
627			esac
628		done
629	done
630}
631
632#
633# ipx_up ifn
634# Configure any IPX addresses for interface $ifn. Returns 0 if IPX
635# arguments were found and configured; returns 1 otherwise.
636#
637ipx_up()
638{
639	ifn="$1"
640	ifconfig_args=`get_if_var $ifn ifconfig_IF_ipx`
641	if [ -n "${ifconfig_args}" ]; then
642		ifconfig ${ifn} ${ifconfig_args}
643		return 0
644	fi
645	return 1
646}
647
648# ipx_down ifn
649#	Remove IPX addresses for interface $ifn. Returns 0 if IPX
650#	addresses were found and unconfigured. It returns 1, otherwise.
651#
652ipx_down()
653{
654	[ -z "$1" ] && return 1
655	_ifs="^"
656	_ret=1
657
658	ifexists $1 || return 1
659
660	ipxList="`ifconfig $1 | grep 'ipx ' | tr "\n" "$_ifs"`"
661
662	oldifs="$IFS"
663	IFS="$_ifs"
664	for _ipx in $ipxList ; do
665		# get rid of extraneous line
666		[ -z "$_ipx" ] && break
667
668		_ipx=`expr "$_ipx" : '.*\(ipx [0-9a-h]\{1,8\}H*\.[0-9a-h]\{1,12\}\).*'`
669
670		IFS="$oldifs"
671		ifconfig $1 ${_ipx} delete
672		IFS="$_ifs"
673		_ret=0
674	done
675	IFS="$oldifs"
676
677	return $_ret
678}
679
680# ifnet_rename
681#	Rename all requested interfaces.
682#
683ifnet_rename()
684{
685
686	_ifn_list="`ifconfig -l`"
687	[ -z "$_ifn_list" ] && return 0
688	for _if in ${_ifn_list} ; do
689		_ifname=`get_if_var $_if ifconfig_IF_name`
690		if [ ! -z "$_ifname" ]; then
691			ifconfig $_if name $_ifname
692		fi
693	done
694	return 0
695}
696
697#
698# list_net_interfaces type
699#	List all network interfaces. The type of interface returned
700#	can be controlled by the type argument. The type
701#	argument can be any of the following:
702#		nodhcp - all interfaces, excluding DHCP configured interfaces
703#		dhcp   - list only DHCP configured interfaces
704#	If no argument is specified all network interfaces are output.
705#	Note that the list will include cloned interfaces if applicable.
706#	Cloned interfaces must already exist to have a chance to appear
707#	in the list if ${network_interfaces} is set to `auto'.
708#
709list_net_interfaces()
710{
711	type=$1
712
713	# Get a list of ALL the interfaces and make lo0 first if it's there.
714	#
715	case ${network_interfaces} in
716	[Aa][Uu][Tt][Oo])
717		_prefix=''
718		_autolist="`ifconfig -l`"
719		_lo=
720		for _if in ${_autolist} ; do
721			if autoif $_if; then
722				if [ "$_if" = "lo0" ]; then
723					_lo="lo0 "
724				else
725					_tmplist="${_tmplist}${_prefix}${_if}"
726					[ -z "$_prefix" ] && _prefix=' '
727				fi
728			fi
729		done
730		_tmplist="${_lo}${_tmplist}"
731		;;
732	*)
733		if [ -z "$type"]; then
734			warn "Values of network_interfaces other than" \
735			    "AUTO are deprecated"
736		fi
737		_tmplist="${network_interfaces} ${cloned_interfaces}"
738		;;
739	esac
740
741	if [ -z "$type" ]; then
742		echo $_tmplist
743		return 0
744	fi
745
746	# Separate out dhcp and non-dhcp interfaces
747	#
748	_aprefix=
749	_bprefix=
750	for _if in ${_tmplist} ; do
751		if dhcpif $_if; then
752			_dhcplist="${_dhcplist}${_aprefix}${_if}"
753			[ -z "$_aprefix" ] && _aprefix=' '
754		elif [ -n "`_ifconfig_getargs $_if`" ]; then
755			_nodhcplist="${_nodhcplist}${_bprefix}${_if}"
756			[ -z "$_bprefix" ] && _bprefix=' '
757		fi
758	done
759
760	case "$type" in
761	nodhcp)
762		echo $_nodhcplist
763		;;
764	dhcp)
765		echo $_dhcplist
766		;;
767	esac
768	return 0
769}
770
771# get_default_if -address_family
772#	Get the interface of the default route for the given address family.
773#	The -address_family argument must be suitable passing to route(8).
774#
775get_default_if()
776{
777	routeget="`route -n get $1 default 2>/dev/null`"
778	oldifs="$IFS"
779	IFS="
780"
781	defif=
782	for line in $routeget ; do
783		case $line in
784		*interface:*)
785			defif=${line##*: }
786			;;
787		esac
788	done
789	IFS=${oldifs}
790
791	echo $defif
792}
793
794hexdigit()
795{
796	if [ $1 -lt 10 ]; then
797		echo $1
798	else
799		case $1 in
800		10)	echo a ;;
801		11)	echo b ;;
802		12)	echo c ;;
803		13)	echo d ;;
804		14)	echo e ;;
805		15)	echo f ;;
806		esac
807	fi
808}
809
810hexprint()
811{
812	val=$1
813	str=''
814
815	dig=`hexdigit $((${val} & 15))`
816	str=${dig}${str}
817	val=$((${val} >> 4))
818	while [ ${val} -gt 0 ]; do
819		dig=`hexdigit $((${val} & 15))`
820		str=${dig}${str}
821		val=$((${val} >> 4))
822	done
823
824	echo ${str}
825}
826
827# Setup the interfaces for IPv6
828network6_interface_setup()
829{
830	interfaces=$*
831	rtsol_interfaces=''
832	case ${ipv6_gateway_enable} in
833	[Yy][Ee][Ss])
834		rtsol_available=no
835		;;
836	*)
837		rtsol_available=yes
838		;;
839	esac
840	for i in $interfaces; do
841		rtsol_interface=yes
842		prefix=`get_if_var $i ipv6_prefix_IF`
843		if [ -n "${prefix}" ]; then
844			rtsol_available=no
845			rtsol_interface=no
846			laddr=`network6_getladdr $i`
847			hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'`
848			for j in ${prefix}; do
849				address=$j\:${hostid}
850				ifconfig $i inet6 ${address} prefixlen 64 alias
851
852				case ${ipv6_gateway_enable} in
853				[Yy][Ee][Ss])
854					# subnet-router anycast address
855					# (rfc2373)
856					ifconfig $i inet6 $j:: prefixlen 64 \
857						alias anycast
858					;;
859				esac
860			done
861		fi
862		ipv6_ifconfig=`get_if_var $i ipv6_ifconfig_IF`
863		if [ -n "${ipv6_ifconfig}" ]; then
864			rtsol_available=no
865			rtsol_interface=no
866			ifconfig $i inet6 ${ipv6_ifconfig} alias
867		fi
868
869		if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ]
870		then
871			case ${i} in
872			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]*)
873				;;
874			*)
875				rtsol_interfaces="${rtsol_interfaces} ${i}"
876				;;
877			esac
878		else
879			ifconfig $i inet6
880		fi
881	done
882
883	if [ ${rtsol_available} = yes -a -n "${rtsol_interfaces}" ]; then
884		# Act as endhost - automatically configured.
885		# You can configure only single interface, as
886		# specification assumes that autoconfigured host has
887		# single interface only.
888		sysctl net.inet6.ip6.accept_rtadv=1
889		set ${rtsol_interfaces}
890		ifconfig $1 up
891		rtsol ${rtsol_flags} $1
892	fi
893
894	for i in $interfaces; do
895		alias=0
896		while : ; do
897			ipv6_ifconfig=`get_if_var $i ipv6_ifconfig_IF_alias${alias}`
898			if [ -z "${ipv6_ifconfig}" ]; then
899				break;
900			fi
901			ifconfig $i inet6 ${ipv6_ifconfig} alias
902			alias=$((${alias} + 1))
903		done
904	done
905}
906
907# Setup IPv6 to IPv4 mapping
908network6_stf_setup()
909{
910	case ${stf_interface_ipv4addr} in
911	[Nn][Oo] | '')
912		;;
913	*)
914		# assign IPv6 addr and interface route for 6to4 interface
915		stf_prefixlen=$((16+${stf_interface_ipv4plen:-0}))
916		OIFS="$IFS"
917		IFS=".$IFS"
918		set ${stf_interface_ipv4addr}
919		IFS="$OIFS"
920		hexfrag1=`hexprint $(($1*256 + $2))`
921		hexfrag2=`hexprint $(($3*256 + $4))`
922		ipv4_in_hexformat="${hexfrag1}:${hexfrag2}"
923		case ${stf_interface_ipv6_ifid} in
924		[Aa][Uu][Tt][Oo] | '')
925			for i in ${ipv6_network_interfaces}; do
926				laddr=`network6_getladdr ${i}`
927				case ${laddr} in
928				'')
929					;;
930				*)
931					break
932					;;
933				esac
934			done
935			stf_interface_ipv6_ifid=`expr "${laddr}" : \
936						      'fe80::\(.*\)%\(.*\)'`
937			case ${stf_interface_ipv6_ifid} in
938			'')
939				stf_interface_ipv6_ifid=0:0:0:1
940				;;
941			esac
942			;;
943		esac
944		ifconfig stf0 create >/dev/null 2>&1
945		ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \
946			prefixlen ${stf_prefixlen}
947		# disallow packets to malicious 6to4 prefix
948		route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
949		route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
950		route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
951		route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
952		;;
953	esac
954}
955
956# Setup static routes
957network6_static_routes_setup()
958{
959	# Set up any static routes.
960	case ${ipv6_defaultrouter} in
961	[Nn][Oo] | '')
962		;;
963	*)
964		ipv6_static_routes="default ${ipv6_static_routes}"
965		ipv6_route_default="default ${ipv6_defaultrouter}"
966		;;
967	esac
968	case ${ipv6_static_routes} in
969	[Nn][Oo] | '')
970		;;
971	*)
972		for i in ${ipv6_static_routes}; do
973			ipv6_route_args=`get_if_var $i ipv6_route_IF`
974			route add -inet6 ${ipv6_route_args}
975		done
976		;;
977	esac
978}
979
980# Setup faith
981network6_faith_setup()
982{
983	case ${ipv6_faith_prefix} in
984	[Nn][Oo] | '')
985		;;
986	*)
987		sysctl net.inet6.ip6.keepfaith=1
988		ifconfig faith0 create >/dev/null 2>&1
989		ifconfig faith0 up
990		for prefix in ${ipv6_faith_prefix}; do
991			prefixlen=`expr "${prefix}" : ".*/\(.*\)"`
992			case ${prefixlen} in
993			'')
994				prefixlen=96
995				;;
996			*)
997				prefix=`expr "${prefix}" : \
998					     "\(.*\)/${prefixlen}"`
999				;;
1000			esac
1001			route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1
1002			route change -inet6 ${prefix} -prefixlen ${prefixlen} \
1003				-ifp faith0
1004		done
1005		;;
1006	esac
1007}
1008
1009# Install the "default interface" to kernel, which will be used
1010# as the default route when there's no router.
1011network6_default_interface_setup()
1012{
1013	# Choose IPv6 default interface if it is not clearly specified.
1014	case ${ipv6_default_interface} in
1015	'')
1016		for i in ${ipv6_network_interfaces}; do
1017			case $i in
1018			lo0|faith[0-9]*)
1019				continue
1020				;;
1021			esac
1022			laddr=`network6_getladdr $i exclude_tentative`
1023			case ${laddr} in
1024			'')
1025				;;
1026			*)
1027				ipv6_default_interface=$i
1028				break
1029				;;
1030			esac
1031		done
1032		;;
1033	esac
1034
1035	# Disallow unicast packets without outgoing scope identifiers,
1036	# or route such packets to a "default" interface, if it is specified.
1037	route add -inet6 fe80:: -prefixlen 10 ::1 -reject
1038	case ${ipv6_default_interface} in
1039	[Nn][Oo] | '')
1040		route add -inet6 ff02:: -prefixlen 16 ::1 -reject
1041		;;
1042	*)
1043		laddr=`network6_getladdr ${ipv6_default_interface}`
1044		route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \
1045			-cloning
1046
1047		# Disable installing the default interface with the
1048		# case net.inet6.ip6.forwarding=0 and
1049		# net.inet6.ip6.accept_rtadv=0, due to avoid conflict
1050		# between the default router list and the manual
1051		# configured default route.
1052		case ${ipv6_gateway_enable} in
1053		[Yy][Ee][Ss])
1054			;;
1055		*)
1056			if [ `sysctl -n net.inet6.ip6.accept_rtadv` -eq 1 ]
1057			then
1058				ndp -I ${ipv6_default_interface}
1059			fi
1060			;;
1061		esac
1062		;;
1063	esac
1064}
1065
1066network6_getladdr()
1067{
1068	ifconfig $1 2>/dev/null | while read proto addr rest; do
1069		case ${proto} in
1070		inet6)
1071			case ${addr} in
1072			fe80::*)
1073				if [ -z "$2" ]; then
1074					echo ${addr}
1075					return
1076				fi
1077				case ${rest} in
1078				*tentative*)
1079					continue
1080					;;
1081				*)
1082					echo ${addr}
1083					return
1084				esac
1085			esac
1086		esac
1087	done
1088}
1089