xref: /dragonfly/etc/network.subr (revision 71126e33)
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.151 2003/06/24 03:55:21 kuriyama Exp $
26# $DragonFly: src/etc/network.subr,v 1.1 2003/07/24 06:35:32 dillon 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 always includes cloned interfaces.
263#
264list_net_interfaces()
265{
266	type=$1
267
268	# Get a list of ALL the interfaces
269	#
270	case ${network_interfaces} in
271	[Aa][Uu][Tt][Oo])
272		_tmplist="`ifconfig -l`"
273		;;
274	*)
275		_tmplist="${network_interfaces}"
276		;;
277	esac
278	_tmplist="${_tmplist} ${cloned_interfaces}"
279
280	if [ -z "$type" ]; then
281		echo $_tmplist
282		return 0
283	fi
284
285	# Separate out dhcp and non-dhcp intefraces
286	#
287	_aprefix=
288	_brefix=
289	for _if in ${_tmplist} ; do
290		eval _ifarg="\$ifconfig_${_if}"
291		case "$_ifarg" in
292		[Dd][Hh][Cc][Pp])
293			_dhcplist="${_dhcplist}${_aprefix}${_if}"
294			[ -z "$_aprefix" ] && _aprefix=' '
295			;;
296		''|*)
297			_nodhcplist="${_nodhcplist}${_bprefix}${_if}"
298			[ -z "$_bprefix" ] && _bprefix=' '
299			;;
300		esac
301	done
302
303	case "$type" in
304	nodhcp)
305		echo $_nodhcplist
306		;;
307	dhcp)
308		echo $_dhcplist
309		;;
310	esac
311	return 0
312}
313
314hexdigit()
315{
316	if [ $1 -lt 10 ]; then
317		echo $1
318	else
319		case $1 in
320		10)	echo a ;;
321		11)	echo b ;;
322		12)	echo c ;;
323		13)	echo d ;;
324		14)	echo e ;;
325		15)	echo f ;;
326		esac
327	fi
328}
329
330hexprint()
331{
332	val=$1
333	str=''
334
335	dig=`hexdigit $((${val} & 15))`
336	str=${dig}${str}
337	val=$((${val} >> 4))
338	while [ ${val} -gt 0 ]; do
339		dig=`hexdigit $((${val} & 15))`
340		str=${dig}${str}
341		val=$((${val} >> 4))
342	done
343
344	echo ${str}
345}
346
347# Setup the interfaces for IPv6
348network6_interface_setup()
349{
350	interfaces=$*
351	rtsol_interfaces=''
352	case ${ipv6_gateway_enable} in
353	[Yy][Ee][Ss])
354		rtsol_available=no
355		;;
356	*)
357		rtsol_available=yes
358		;;
359	esac
360	for i in $interfaces; do
361		rtsol_interface=yes
362		eval prefix=\$ipv6_prefix_$i
363		if [ -n "${prefix}" ]; then
364			rtsol_available=no
365			rtsol_interface=no
366			laddr=`network6_getladdr $i`
367			hostid=`expr "${laddr}" : 'fe80::\(.*\)%\(.*\)'`
368			for j in ${prefix}; do
369				address=$j\:${hostid}
370				ifconfig $i inet6 ${address} prefixlen 64 alias
371
372				case ${ipv6_gateway_enable} in
373				[Yy][Ee][Ss])
374					# subnet-router anycast address
375					# (rfc2373)
376					ifconfig $i inet6 $j:: prefixlen 64 \
377						alias anycast
378					;;
379				esac
380			done
381		fi
382		eval ipv6_ifconfig=\$ipv6_ifconfig_$i
383		if [ -n "${ipv6_ifconfig}" ]; then
384			rtsol_available=no
385			rtsol_interface=no
386			ifconfig $i inet6 ${ipv6_ifconfig} alias
387		fi
388
389		if [ ${rtsol_available} = yes -a ${rtsol_interface} = yes ]
390		then
391			case ${i} in
392			lo0|gif[0-9]*|stf[0-9]*|faith[0-9]*|lp[0-9]*|sl[0-9]*|tun[0-9]*)
393				;;
394			*)
395				rtsol_interfaces="${rtsol_interfaces} ${i}"
396				;;
397			esac
398		else
399			ifconfig $i inet6
400		fi
401	done
402
403	if [ ${rtsol_available} = yes -a -n "${rtsol_interfaces}" ]; then
404		# Act as endhost - automatically configured.
405		# You can configure only single interface, as
406		# specification assumes that autoconfigured host has
407		# single interface only.
408		sysctl net.inet6.ip6.accept_rtadv=1
409		set ${rtsol_interfaces}
410		ifconfig $1 up
411		rtsol $1
412	fi
413
414	for i in $interfaces; do
415		alias=0
416		while : ; do
417			eval ipv6_ifconfig=\$ipv6_ifconfig_${i}_alias${alias}
418			if [ -z "${ipv6_ifconfig}" ]; then
419				break;
420			fi
421			ifconfig $i inet6 ${ipv6_ifconfig} alias
422			alias=$((${alias} + 1))
423		done
424	done
425}
426
427# Setup IPv6 to IPv4 mapping
428network6_stf_setup()
429{
430	case ${stf_interface_ipv4addr} in
431	[Nn][Oo] | '')
432		;;
433	*)
434		# assign IPv6 addr and interface route for 6to4 interface
435		stf_prefixlen=$((16+${stf_interface_ipv4plen:-0}))
436		OIFS="$IFS"
437		IFS=".$IFS"
438		set ${stf_interface_ipv4addr}
439		IFS="$OIFS"
440		hexfrag1=`hexprint $(($1*256 + $2))`
441		hexfrag2=`hexprint $(($3*256 + $4))`
442		ipv4_in_hexformat="${hexfrag1}:${hexfrag2}"
443		case ${stf_interface_ipv6_ifid} in
444		[Aa][Uu][Tt][Oo] | '')
445			for i in ${ipv6_network_interfaces}; do
446				laddr=`network6_getladdr ${i}`
447				case ${laddr} in
448				'')
449					;;
450				*)
451					break
452					;;
453				esac
454			done
455			stf_interface_ipv6_ifid=`expr "${laddr}" : \
456						      'fe80::\(.*\)%\(.*\)'`
457			case ${stf_interface_ipv6_ifid} in
458			'')
459				stf_interface_ipv6_ifid=0:0:0:1
460				;;
461			esac
462			;;
463		esac
464		ifconfig stf0 create >/dev/null 2>&1
465		ifconfig stf0 inet6 2002:${ipv4_in_hexformat}:${stf_interface_ipv6_slaid:-0}:${stf_interface_ipv6_ifid} \
466			prefixlen ${stf_prefixlen}
467		# disallow packets to malicious 6to4 prefix
468		route add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
469		route add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
470		route add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
471		route add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
472		;;
473	esac
474}
475
476# Setup static routes
477network6_static_routes_setup()
478{
479	# Set up any static routes.
480	case ${ipv6_defaultrouter} in
481	[Nn][Oo] | '')
482		;;
483	*)
484		ipv6_static_routes="default ${ipv6_static_routes}"
485		ipv6_route_default="default ${ipv6_defaultrouter}"
486		;;
487	esac
488	case ${ipv6_static_routes} in
489	[Nn][Oo] | '')
490		;;
491	*)
492		for i in ${ipv6_static_routes}; do
493			eval ipv6_route_args=\$ipv6_route_${i}
494			route add -inet6 ${ipv6_route_args}
495		done
496		;;
497	esac
498}
499
500# Setup faith
501network6_faith_setup()
502{
503	case ${ipv6_faith_prefix} in
504	[Nn][Oo] | '')
505		;;
506	*)
507		sysctl net.inet6.ip6.keepfaith=1
508		ifconfig faith0 create >/dev/null 2>&1
509		ifconfig faith0 up
510		for prefix in ${ipv6_faith_prefix}; do
511			prefixlen=`expr "${prefix}" : ".*/\(.*\)"`
512			case ${prefixlen} in
513			'')
514				prefixlen=96
515				;;
516			*)
517				prefix=`expr "${prefix}" : \
518					     "\(.*\)/${prefixlen}"`
519				;;
520			esac
521			route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1
522			route change -inet6 ${prefix} -prefixlen ${prefixlen} \
523				-ifp faith0
524		done
525		;;
526	esac
527}
528
529# Install the "default interface" to kernel, which will be used
530# as the default route when there's no router.
531network6_default_interface_setup()
532{
533	# Choose IPv6 default interface if it is not clearly specified.
534	case ${ipv6_default_interface} in
535	'')
536		for i in ${ipv6_network_interfaces}; do
537			case $i in
538			lo0|faith[0-9]*)
539				continue
540				;;
541			esac
542			laddr=`network6_getladdr $i exclude_tentative`
543			case ${laddr} in
544			'')
545				;;
546			*)
547				ipv6_default_interface=$i
548				break
549				;;
550			esac
551		done
552		;;
553	esac
554
555	# Disallow unicast packets without outgoing scope identifiers,
556	# or route such packets to a "default" interface, if it is specified.
557	route add -inet6 fe80:: -prefixlen 10 ::1 -reject
558	case ${ipv6_default_interface} in
559	[Nn][Oo] | '')
560		route add -inet6 ff02:: -prefixlen 16 ::1 -reject
561		;;
562	*)
563		laddr=`network6_getladdr ${ipv6_default_interface}`
564		route add -inet6 ff02:: ${laddr} -prefixlen 16 -interface \
565			-cloning
566
567		# Disable installing the default interface with the
568		# case net.inet6.ip6.forwarding=0 and
569		# net.inet6.ip6.accept_rtadv=0, due to avoid conflict
570		# between the default router list and the manual
571		# configured default route.
572		case ${ipv6_gateway_enable} in
573		[Yy][Ee][Ss])
574			;;
575		*)
576			if [ `sysctl -n net.inet6.ip6.accept_rtadv` -eq 1 ]
577			then
578				ndp -I ${ipv6_default_interface}
579			fi
580			;;
581		esac
582		;;
583	esac
584}
585
586network6_getladdr()
587{
588	ifconfig $1 2>/dev/null | while read proto addr rest; do
589		case ${proto} in
590		inet6)
591			case ${addr} in
592			fe80::*)
593				if [ -z "$2" ]; then
594					echo ${addr}
595					return
596				fi
597				case ${rest} in
598				*tentative*)
599					continue
600					;;
601				*)
602					echo ${addr}
603					return
604				esac
605			esac
606		esac
607	done
608}
609