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