xref: /freebsd/libexec/rc/rc.d/routing (revision 9f80c8b90bdaa8ffac887a8c478a16c84d74a87b)
1#!/bin/sh
2#
3# Configure routing and miscellaneous network tunables
4#
5#
6
7# PROVIDE: routing
8# REQUIRE: netif ppp stf
9# KEYWORD: nojailvnet
10
11. /etc/rc.subr
12. /etc/network.subr
13
14name="routing"
15desc="Routing setup"
16start_cmd="routing_start doall"
17stop_cmd="routing_stop"
18extra_commands="options static"
19static_cmd="routing_start static"
20options_cmd="routing_start options"
21
22ROUTE_CMD="/sbin/route"
23
24routing_start()
25{
26	local _cmd _af _if _a _ret
27	_cmd=$1
28	_af=$2
29	_if=$3
30	_ret=0
31
32	case $_if in
33	""|[Aa][Ll][Ll]|[Aa][Nn][Yy])	_if="" ;;
34	esac
35
36	case $_af in
37	""|[Aa][Ll][Ll]|[Aa][Nn][Yy])
38		for _a in inet inet6; do
39			afexists $_a || continue
40			setroutes $_cmd $_a $_if || _ret=1
41		done
42	;;
43	*)
44		if afexists $_af; then
45			setroutes $_cmd $_af $_if || _ret=1
46		else
47			err 1 "Unsupported address family: $_af."
48		fi
49	;;
50	esac
51
52	return $_ret
53}
54
55routing_stop()
56{
57	local _af _if _a
58	_af=$1
59	_if=$2
60
61	case $_if in
62	""|[Aa][Ll][Ll]|[Aa][Nn][Yy])	_if="" ;;
63	esac
64
65	case $_af in
66	""|[Aa][Ll][Ll]|[Aa][Nn][Yy])
67		for _a in inet inet6; do
68			afexists $_a || continue
69			eval static_${_a} delete $_if
70			# When $_if is specified, do not flush routes.
71			if ! [ -n "$_if" ]; then
72				eval routing_stop_${_a}
73			fi
74		done
75	;;
76	*)
77		if afexists $_af; then
78			eval static_${_af} delete $_if
79			# When $_if is specified, do not flush routes.
80			if ! [ -n "$_if" ]; then
81				eval routing_stop_${_af}
82			fi
83		else
84			err 1 "Unsupported address family: $_af."
85		fi
86	;;
87	esac
88}
89
90setroutes()
91{
92	local _ret
93	_ret=0
94	case $1 in
95	static)
96		static_$2 add $3
97		_ret=$?
98		;;
99	options)
100		options_$2
101		;;
102	doall)
103		static_$2 add $3
104		_ret=$?
105		options_$2
106		;;
107	esac
108	return $_ret
109}
110
111routing_stop_inet()
112{
113	${ROUTE_CMD} -n flush -inet
114}
115
116routing_stop_inet6()
117{
118	local i
119
120	${ROUTE_CMD} -n flush -inet6
121	for i in `list_net_interfaces`; do
122		if ipv6if $i; then
123			ifconfig $i inet6 -defaultif
124		fi
125	done
126}
127
128get_fibmod()
129{
130	local _fibs
131
132	_fibs=$((`${SYSCTL_N} net.fibs` - 1))
133	if [ ${_fibs} -gt 0 ]; then
134		echo "-fib 0-${_fibs}"
135	else
136		echo
137	fi
138}
139
140static_inet()
141{
142	local _action _if _skip _fibmod _fibs
143	_action=$1
144	_if=$2
145
146	_fibmod=`get_fibmod`
147	_fibs=$((`${SYSCTL_N} net.fibs` - 1))
148
149	# Provide loopback route in all routing tables.  This has to come
150	# first so that any following routes can be added.
151	static_routes="_loopback ${static_routes}"
152	route__loopback="-inet 127.0.0.1 -iface lo0 ${_fibmod}"
153
154	# Add default route.
155	case ${defaultrouter} in
156	[Nn][Oo] | '')
157		;;
158	*)
159		static_routes="${static_routes} _default"
160		route__default="default ${defaultrouter}"
161		;;
162	esac
163
164	# Add default routes for fibs
165	if [ ${_fibs} -gt 0 ]; then
166		for _fibnum in `jot ${_fibs}` ; do
167			eval _fib_gw=\${defaultrouter_fib${_fibnum}}
168			case ${_fib_gw} in
169			[Nn][Oo] | '')
170				;;
171			*)
172				static_routes="${static_routes} _default_fib${_fibnum}"
173				eval route__default_fib${_fibnum}="'default ${_fib_gw} -fib ${_fibnum}'"
174				;;
175			esac
176		done
177	fi
178
179
180	# Install configured routes.
181	if [ -n "${static_routes}" ]; then
182		for i in ${static_routes}; do
183			_skip=0
184			if [ -n "$_if" ]; then
185				case $i in
186				*:$_if)	;;
187				*)	_skip=1 ;;
188				esac
189			fi
190			if [ $_skip = 0 ]; then
191				route_args=`get_if_var ${i%:*} route_IF`
192				if [ -n "$route_args" ]; then
193					# Loopback routes may already be added by the kernel; ignore EEXIST.
194					if [ "${i%:*}" = "_loopback" ]; then
195						${ROUTE_CMD} ${_action} ${route_args} 2>&1 >/dev/null |
196						    sed -e '/route: message indicates error: File exists/d' >&2
197					else
198						${ROUTE_CMD} ${_action} ${route_args}
199					fi
200				else
201					warn "route_${i%:*} not found."
202				fi
203			fi
204		done
205	fi
206}
207
208static_inet6()
209{
210	local _action _if _skip fibmod _fibs
211	_action=$1
212	_if=$2
213
214	fibmod=`get_fibmod`
215	_fibs=$((`${SYSCTL_N} net.fibs` - 1))
216
217	# Add pre-defined static routes first.
218	ipv6_static_routes="_v4mapped _v4compat ${ipv6_static_routes}"
219	ipv6_static_routes="_lla _llma ${ipv6_static_routes}"
220	ipv6_static_routes="_loopback ${ipv6_static_routes}"
221
222	# disallow "internal" addresses to appear on the wire
223	ipv6_route__v4mapped="::ffff:0.0.0.0 -prefixlen 96 ::1 -reject ${fibmod}"
224	ipv6_route__v4compat="::0.0.0.0 -prefixlen 96 ::1 -reject ${fibmod}"
225
226	# Create a loopback route in every fib
227	ipv6_route__loopback="::1 -prefixlen 128 -iface lo0 ${fibmod}"
228
229	# Disallow link-local unicast packets without outgoing scope
230	# identifiers.  However, if you set "ipv6_default_interface",
231	# for the host case, you will allow to omit the identifiers.
232	# Under this configuration, the packets will go to the default
233	# interface.
234	ipv6_route__lla="fe80:: -prefixlen 10 ::1 -reject ${fibmod}"
235	ipv6_route__llma="ff02:: -prefixlen 16 ::1 -reject ${fibmod}"
236
237	# Add default route.
238	case ${ipv6_defaultrouter} in
239	[Nn][Oo] | '')
240		;;
241	*)
242		ipv6_static_routes="${ipv6_static_routes} _default"
243		ipv6_route__default="default ${ipv6_defaultrouter}"
244		;;
245	esac
246
247	# Add default routes for fibs
248	if [ ${_fibs} -gt 0 ]; then
249		for _fibnum in `jot ${_fibs}` ; do
250			eval _fib_gw=\${ipv6_defaultrouter_fib${_fibnum}}
251			case ${_fib_gw} in
252			[Nn][Oo] | '')
253				;;
254			*)
255				ipv6_static_routes="${ipv6_static_routes} _default_fib${_fibnum}"
256				eval ipv6_route__default_fib${_fibnum}="'default ${_fib_gw} -fib ${_fibnum}'"
257				;;
258			esac
259		done
260	fi
261
262
263	# Install configured routes.
264	if [ -n "${ipv6_static_routes}" ]; then
265		for i in ${ipv6_static_routes}; do
266			_skip=0
267			if [ -n "$_if" ]; then
268				case $i in
269				*:$_if)	;;
270				*)	_skip=1 ;;
271				esac
272			fi
273			if [ $_skip = 0 ]; then
274				ipv6_route_args=`get_if_var ${i%:*} ipv6_route_IF`
275				if [ -n "$ipv6_route_args" ]; then
276					# Loopback routes may already be added by the kernel; ignore EEXIST.
277					if [ "${i%:*}" = "_loopback" ]; then
278						${ROUTE_CMD} ${_action} -inet6 \
279						    ${ipv6_route_args} 2>&1 >/dev/null |
280						    sed -e '/route: message indicates error: File exists/d' >&2
281					else
282						${ROUTE_CMD} ${_action} \
283						    -inet6 ${ipv6_route_args}
284					fi
285				else
286					warn "route_${i%:*} not found"
287				fi
288			fi
289		done
290	fi
291
292	# Install the "default interface" to kernel, which will be used
293	# as the default route when there's no router.
294
295	# Disable installing the default interface when we act
296	# as router to avoid conflict between the default
297	# router list and the manual configured default route.
298	if checkyesno ipv6_gateway_enable; then
299		return
300	fi
301
302	case "${ipv6_default_interface}" in
303	[Nn][Oo] | [Nn][Oo][Nn][Ee])
304		return
305		;;
306	[Aa][Uu][Tt][Oo] | "")
307		for i in ${ipv6_network_interfaces}; do
308			case $i in
309			[Nn][Oo][Nn][Ee])
310				return
311				;;
312			lo0)
313				continue
314				;;
315			esac
316			laddr=`network6_getladdr $i exclude_tentative`
317			case ${laddr} in
318			'')
319				;;
320			*)
321				ipv6_default_interface=$i
322				break
323				;;
324			esac
325		done
326		;;
327	esac
328
329	ifconfig ${ipv6_default_interface} inet6 defaultif
330	${SYSCTL} net.inet6.ip6.use_defaultzone=1 > /dev/null
331}
332
333ropts_init()
334{
335	if [ -z "${_ropts_initdone}" ]; then
336		echo -n "Additional $1 routing options:"
337		_ropts_initdone=yes
338	fi
339}
340
341_check_dynamicrouting()
342{
343	local skip file name rcvar
344
345	# copied from /etc/rc
346	skip="-s nostart"
347	if check_jail jailed; then
348		skip="$skip -s nojail"
349	fi
350	[ -n "$local_startup" ] && find_local_scripts_new
351	[ -n "$system_rc" ] && find_system_scripts
352
353	for file in $( rcorder ${skip} ${system_rc} ${local_rc} 2>/dev/null |
354		       xargs grep -lE '^# PROVIDE:.*\<dynamicrouting\>' ); do
355		(set -- enabled; . $file) && return 0;
356	done
357
358	return 1
359}
360
361options_inet()
362{
363	local _icmp_drop_redirect
364
365	_ropts_initdone=
366	if checkyesno icmp_bmcastecho; then
367		ropts_init inet
368		echo -n ' broadcast ping responses=YES'
369		${SYSCTL} net.inet.icmp.bmcastecho=1 > /dev/null
370	else
371		${SYSCTL} net.inet.icmp.bmcastecho=0 > /dev/null
372	fi
373
374	_icmp_drop_redirect="${icmp_drop_redirect}"
375	case "${_icmp_drop_redirect}" in
376	[Aa][Uu][Tt][Oo] | "")
377		if _check_dynamicrouting; then
378			_icmp_drop_redirect="yes"
379		else
380			_icmp_drop_redirect="no"
381		fi
382		;;
383	esac
384	if checkyesno _icmp_drop_redirect; then
385		ropts_init inet
386		echo -n ' ignore ICMP redirect=YES'
387		${SYSCTL} net.inet.icmp.drop_redirect=1 > /dev/null
388	else
389		${SYSCTL} net.inet.icmp.drop_redirect=0 > /dev/null
390	fi
391
392	if checkyesno icmp_log_redirect; then
393		ropts_init inet
394		echo -n ' log ICMP redirect=YES'
395		${SYSCTL} net.inet.icmp.log_redirect=1 > /dev/null
396	else
397		${SYSCTL} net.inet.icmp.log_redirect=0 > /dev/null
398	fi
399
400	if checkyesno gateway_enable; then
401		ropts_init inet
402		echo -n ' gateway=YES'
403		${SYSCTL} net.inet.ip.forwarding=1 > /dev/null
404	else
405		${SYSCTL} net.inet.ip.forwarding=0 > /dev/null
406	fi
407
408	if checkyesno forward_sourceroute; then
409		ropts_init inet
410		echo -n ' do source routing=YES'
411		${SYSCTL} net.inet.ip.sourceroute=1 > /dev/null
412	else
413		${SYSCTL} net.inet.ip.sourceroute=0 > /dev/null
414	fi
415
416	if checkyesno accept_sourceroute; then
417		ropts_init inet
418		echo -n ' accept source routing=YES'
419		${SYSCTL} net.inet.ip.accept_sourceroute=1 > /dev/null
420	else
421		${SYSCTL} net.inet.ip.accept_sourceroute=0 > /dev/null
422	fi
423
424	if checkyesno arpproxy_all; then
425		ropts_init inet
426		echo -n ' ARP proxyall=YES'
427		${SYSCTL} net.link.ether.inet.proxyall=1 > /dev/null
428	else
429		${SYSCTL} net.link.ether.inet.proxyall=0 > /dev/null
430	fi
431
432	[ -n "${_ropts_initdone}" ] && echo '.'
433}
434
435options_inet6()
436{
437	_ropts_initdone=
438
439	if checkyesno ipv6_gateway_enable; then
440		ropts_init inet6
441		echo -n ' gateway=YES'
442		${SYSCTL} net.inet6.ip6.forwarding=1 > /dev/null
443	else
444		${SYSCTL} net.inet6.ip6.forwarding=0 > /dev/null
445	fi
446
447	[ -n "${_ropts_initdone}" ] && echo '.'
448}
449
450load_rc_config $name
451
452# doesn't make sense to run in a svcj: config setting
453routing_svcj="NO"
454
455run_rc_command "$@"
456