network.subr revision 114942
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 114942 2003-05-12 11:36:50Z ume $
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.
38#
39ifconfig_up()
40{
41	eval ifconfig_args=\$ifconfig_$1
42	if [ -n "${ifconfig_args}" ]; then
43		ifconfig $1 ${ifconfig_args}
44		return 0
45	fi
46	return 1
47}
48
49# ifalias_up if
50#	Configure aliases for network interface $if.
51#	It returns 0 if at least one alias was configured or
52#	1 if there were none.
53#
54ifalias_up()
55{
56	_ret=1
57	alias=0
58	while : ; do
59		eval ifconfig_args=\$ifconfig_$1_alias${alias}
60		if [ -n "${ifconfig_args}" ]; then
61			ifconfig $1 ${ifconfig_args} alias
62			alias=$((${alias} + 1))
63			_ret=0
64		else
65			break
66		fi
67	done
68	return $_ret
69}
70
71# ifscript_up if
72#	Evaluate a startup script for the $if interface.
73#	It returns 0 if a script was found and processed or
74#	1 if no script was found.
75#
76ifscript_up()
77{
78	if [ -r /etc/start_if.$1 ]; then
79		. /etc/start_if.$1
80		return 0
81	fi
82	return 1
83}
84
85# Create cloneable interfaces.
86#
87clone_up()
88{
89	_prefix=
90	_list=
91	for ifn in ${cloned_interfaces}; do
92		ifconfig ${ifn} create
93		if $? ; then
94			_list="${_list}${_prefix}${ifn}"
95			[ -z "$_prefix" ] && _prefix=' '
96		fi
97	done
98	debug "Cloned: ${_list}"
99}
100
101# Destroy cloned interfaces. Destroyed interfaces are echoed
102# to standard output.
103#
104clone_down()
105{
106	_prefix=
107	_list=
108	for ifn in ${cloned_interfaces}; do
109		ifconfig ${ifn} destroy
110		if $? ; then
111			_list="${_list}${_prefix}${ifn}"
112			[ -z "$_prefix" ] && _prefix=' '
113		fi
114	done
115	debug "Destroyed clones: ${_list}"
116}
117
118gif_up() {
119	case ${gif_interfaces} in
120	[Nn][Oo] | '')
121		;;
122	*)
123		for i in ${gif_interfaces}; do
124			eval peers=\$gifconfig_$i
125			case ${peers} in
126			'')
127				continue
128				;;
129			*)
130				ifconfig $i create >/dev/null 2>&1
131				ifconfig $i tunnel ${peers}
132				ifconfig $i up
133				;;
134			esac
135		done
136		;;
137	esac
138}
139
140#
141# ipx_up ifn
142# Configure any IPX addresses for interface $ifn. Returns 0 if IPX
143# arguments were found and configured; returns 1 otherwise.
144#
145ipx_up()
146{
147	ifn="$1"
148	eval ifconfig_args=\$ifconfig_${ifn}_ipx
149	if [ -n "${ifconfig_args}" ]; then
150		ifconfig ${ifn} ${ifconfig_args}
151		return 0
152	fi
153	return 1
154}
155
156#
157# list_net_interfaces type
158#	List all network interfaces. The type of interface returned
159#	can be controlled by the type argument. The type
160#	argument can be any of the following:
161#		nodhcp - all interfaces, excluding DHCP configured interfaces
162#		dhcp   - list only DHCP configured interfaces
163#	If no argument is specified all network interfaces are output.
164#	Note that the list always includes cloned interfaces.
165#
166list_net_interfaces()
167{
168	type=$1
169
170	# Get a list of ALL the interfaces
171	#
172	case ${network_interfaces} in
173	[Aa][Uu][Tt][Oo])
174		_tmplist="`ifconfig -l`"
175		;;
176	*)
177		_tmplist="${network_interfaces}"
178		;;
179	esac
180	_tmplist="${_tmplist} ${cloned_interfaces}"
181
182	if [ -z "$type" ]; then
183		echo $_tmplist
184		return 0
185	fi
186
187	# Separate out dhcp and non-dhcp intefraces
188	#
189	_aprefix=
190	_brefix=
191	for _if in ${_tmplist} ; do
192		eval _ifarg="\$ifconfig_${_if}"
193		case "$_ifarg" in
194		[Dd][Hh][Cc][Pp])
195			_dhcplist="${_dhcplist}${_aprefix}${_if}"
196			[ -z "$_aprefix" ] && _aprefix=' '
197			;;
198		''|*)
199			_nodhcplist="${_nodhcplist}${_bprefix}${_if}"
200			[ -z "$_bprefix" ] && _bprefix=' '
201			;;
202		esac
203	done
204
205	case "$type" in
206	nodhcp)
207		echo $_nodhcplist
208		;;
209	dhcp)
210		echo $_dhcplist
211		;;
212	esac
213	return 0			
214}
215
216hexdigit()
217{
218	if [ $1 -lt 10 ]; then
219		echo $1
220	else
221		case $1 in
222		10)	echo a ;;
223		11)	echo b ;;
224		12)	echo c ;;
225		13)	echo d ;;
226		14)	echo e ;;
227		15)	echo f ;;
228		esac
229	fi
230}
231
232hexprint()
233{
234	val=$1
235	str=''
236
237	dig=`hexdigit $((${val} & 15))`
238	str=${dig}${str}
239	val=$((${val} >> 4))
240	while [ ${val} -gt 0 ]; do
241		dig=`hexdigit $((${val} & 15))`
242		str=${dig}${str}
243		val=$((${val} >> 4))
244	done
245
246	echo ${str}
247}
248
249# Setup the interfaces for IPv6
250network6_interface_setup()
251{
252	interfaces=$*
253	rtsol_interfaces=''
254	case ${ipv6_gateway_enable} in
255	[Yy][Ee][Ss])
256		rtsol_available=no
257		;;
258	*)
259		rtsol_available=yes
260		;;
261	esac
262	for i in $interfaces; do
263		rtsol_interface=yes
264		eval prefix=\$ipv6_prefix_$i
265		if [ -n "${prefix}" ]; then
266			rtsol_available=no
267			rtsol_interface=no
268			laddr=`network6_getladdr $i`
269			hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'`
270			for j in ${prefix}; do
271				address=$j\:${hostid}
272				ifconfig $i inet6 ${address} prefixlen 64 alias
273
274				case ${ipv6_gateway_enable} in
275				[Yy][Ee][Ss])
276					# subnet-router anycast address
277					# (rfc2373)
278					ifconfig $i inet6 $j:: prefixlen 64 \
279						alias anycast
280					;;
281				esac
282			done
283		fi
284		eval ipv6_ifconfig=\$ipv6_ifconfig_$i
285		if [ -n "${ipv6_ifconfig}" ]; then
286			rtsol_available=no
287			rtsol_interface=no
288			ifconfig $i inet6 ${ipv6_ifconfig} alias
289		fi
290
291		if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ]
292		then
293			case ${i} in
294			lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*)
295				;;
296			*)
297				rtsol_interfaces="${rtsol_interfaces} ${i}"
298				;;
299			esac
300		else
301			ifconfig $i inet6
302		fi
303	done
304
305	if [ ${rtsol_available} = yes -a -n "${rtsol_interfaces}" ]; then
306		# Act as endhost - automatically configured.
307		# You can configure only single interface, as
308		# specification assumes that autoconfigured host has
309		# single interface only.
310		sysctl net.inet6.ip6.accept_rtadv=1
311		set ${rtsol_interfaces}
312		ifconfig $1 up
313		rtsol $1
314	fi
315
316	for i in $interfaces; do
317		alias=0
318		while : ; do
319			eval ipv6_ifconfig=\$ipv6_ifconfig_${i}_alias${alias}
320			if [ -z "${ipv6_ifconfig}" ]; then
321				break;
322			fi
323			ifconfig $i inet6 ${ipv6_ifconfig} alias
324			alias=$((${alias} + 1))
325		done
326	done
327}
328
329# Setup IPv6 to IPv4 mapping
330network6_stf_setup()
331{
332	case ${stf_interface_ipv4addr} in
333	[Nn][Oo] | '')
334		;;
335	*)
336		# assign IPv6 addr and interface route for 6to4 interface
337		stf_prefixlen=$((16+${stf_interface_ipv4plen:-0}))
338		OIFS="$IFS"
339		IFS=".$IFS"
340		set ${stf_interface_ipv4addr}
341		IFS="$OIFS"
342		hexfrag1=`hexprint $(($1*256 + $2))`
343		hexfrag2=`hexprint $(($3*256 + $4))`
344		ipv4_in_hexformat="${hexfrag1}:${hexfrag2}"
345		case ${stf_interface_ipv6_ifid} in
346		[Aa][Uu][Tt][Oo] | '')
347			for i in ${ipv6_network_interfaces}; do
348				laddr=`network6_getladdr ${i}`
349				case ${laddr} in
350				'')
351					;;
352				*)
353					break
354					;;
355				esac
356			done
357			stf_interface_ipv6_ifid=`expr "${laddr}" : \
358						      'fe80::\(.*\)%\(.*\)'`
359			case ${stf_interface_ipv6_ifid} in
360			'')
361				stf_interface_ipv6_ifid=0:0:0:1
362				;;
363			esac
364			;;
365		esac
366		ifconfig stf0 create >/dev/null 2>&1
367		ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \
368			prefixlen ${stf_prefixlen}
369		# disallow packets to malicious 6to4 prefix
370		route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
371		route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
372		route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
373		route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
374		;;
375	esac
376}
377
378# Setup static routes
379network6_static_routes_setup()
380{
381	# Set up any static routes.
382	case ${ipv6_defaultrouter} in
383	[Nn][Oo] | '')
384		;;
385	*)
386		ipv6_static_routes="default ${ipv6_static_routes}"
387		ipv6_route_default="default ${ipv6_defaultrouter}"
388		;;
389	esac
390	case ${ipv6_static_routes} in
391	[Nn][Oo] | '')
392		;;
393	*)
394		for i in ${ipv6_static_routes}; do
395			eval ipv6_route_args=\$ipv6_route_${i}
396			route add -inet6 ${ipv6_route_args}
397		done
398		;;
399	esac
400}
401
402# Setup faith
403network6_faith_setup()
404{
405	case ${ipv6_faith_prefix} in
406	[Nn][Oo] | '')
407		;;
408	*)
409		sysctl net.inet6.ip6.keepfaith=1
410		ifconfig faith0 create >/dev/null 2>&1
411		ifconfig faith0 up
412		for prefix in ${ipv6_faith_prefix}; do
413			prefixlen=`expr "${prefix}" : ".*/\(.*\)"`
414			case ${prefixlen} in
415			'')
416				prefixlen=96
417				;;
418			*)
419				prefix=`expr "${prefix}" : \
420					     "\(.*\)/${prefixlen}"`
421				;;
422			esac
423			route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1
424			route change -inet6 ${prefix} -prefixlen ${prefixlen} \
425				-ifp faith0
426		done
427		;;
428	esac
429}
430
431# Install the "default interface" to kernel, which will be used
432# as the default route when there's no router.
433network6_default_interface_setup()
434{
435	# Choose IPv6 default interface if it is not clearly specified.
436	case ${ipv6_default_interface} in
437	'')
438		for i in ${ipv6_network_interfaces}; do
439			case $i in
440			lo0|faith[0-9]*)
441				continue
442				;;
443			esac
444			laddr=`network6_getladdr $i exclude_tentative`
445			case ${laddr} in
446			'')
447				;;
448			*)
449				ipv6_default_interface=$i
450				break
451				;;
452			esac
453		done
454		;;
455	esac
456
457	# Disallow unicast packets without outgoing scope identifiers,
458	# or route such packets to a "default" interface, if it is specified.
459	route add -inet6 fe80:: -prefixlen 10 ::1 -reject
460	case ${ipv6_default_interface} in
461	[Nn][Oo] | '')
462		route add -inet6 ff02:: -prefixlen 16 ::1 -reject
463		;;
464	*)
465		laddr=`network6_getladdr ${ipv6_default_interface}`
466		route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \
467			-cloning
468
469		# Disable installing the default interface with the
470		# case net.inet6.ip6.forwarding=0 and
471		# net.inet6.ip6.accept_rtadv=0, due to avoid conflict
472		# between the default router list and the manual
473		# configured default route.
474		case ${ipv6_gateway_enable} in
475		[Yy][Ee][Ss])
476			;;
477		*)
478			if [ `sysctl -n net.inet6.ip6.accept_rtadv` -eq 1 ]
479			then
480				ndp -I ${ipv6_default_interface}
481			fi
482			;;
483		esac
484		;;
485	esac
486}
487
488network6_getladdr()
489{
490	ifconfig $1 2>/dev/null | while read proto addr rest; do
491		case ${proto} in
492		inet6)
493			case ${addr} in
494			fe80::*)
495				if [ -z "$2" ]; then
496					echo ${addr}
497					return
498				fi
499				case ${rest} in
500				*tentative*)
501					continue
502					;;
503				*)
504					echo ${addr}
505					return
506				esac
507			esac
508		esac
509	done
510}
511