network revision 1.59
1#!/bin/sh
2#
3# $NetBSD: network,v 1.59 2009/09/08 08:56:33 cegger Exp $
4#
5
6# PROVIDE: network
7# REQUIRE: ipfilter ipsec mountcritlocal root tty sysctl
8# BEFORE:  NETWORKING
9
10$_rc_subr_loaded . /etc/rc.subr
11
12name="network"
13start_cmd="network_start"
14stop_cmd="network_stop"
15fstab_file="/etc/fstab"
16
17nl='
18' # a newline
19
20network_start()
21{
22	# set hostname, turn on network
23	#
24	echo "Starting network."
25
26	# If $hostname is set, use it for my Internet name,
27	# otherwise use /etc/myname
28	#
29	if [ -z "$hostname" ] && [ -f /etc/myname ]; then
30		hostname=$(cat /etc/myname)
31	fi
32	if [ -n "$hostname" ]; then
33		echo "Hostname: $hostname"
34		hostname $hostname
35	else
36		# Don't warn about it if we're going to run
37		# DHCP later, as we will probably get the
38		# hostname at that time.
39		#
40		if ! checkyesno dhclient && ! checkyesno dhcpcd && \
41			[ -z "$(hostname)" ]
42		then
43			warn "\$hostname not set."
44		fi
45	fi
46
47	# Check $domainname first, then /etc/defaultdomain,
48	# for NIS/YP domain name
49	#
50	if [ -z "$domainname" ] && [ -f /etc/defaultdomain ]; then
51		domainname=$(cat /etc/defaultdomain)
52	fi
53	if [ -n "$domainname" ]; then
54		echo "NIS domainname: $domainname"
55		domainname $domainname
56	fi
57
58	# Do not flush routes if root file system is nfs mounted in /etc/fstab,
59	# or the nfs server is unreachable if it is in a different subnet,
60	# otherwise.
61	while read fs_spec fs_file fs_vfstype fs_mntops fs_freq fs_passno
62	do
63		case "${fs_spec}:${fs_file}:${fs_passno}" in
64		\#*|'':*)
65			continue # skip comment or blank line
66			;;
67		*:/:*)  case "${fs_spec}" in
68			*:*)
69				echo "Not flushing routes. /: nfs mounted"
70				flushroutes="NO"
71				;;
72			esac
73			;;
74		esac
75	done <"${fstab_file}"
76
77
78	# Flush all routes just to make sure it is clean
79	if checkyesno flushroutes; then
80		/sbin/route -qn flush
81	fi
82
83	# Set the address for the first loopback interface, so that the
84	# auto-route from a newly configured interface's address to lo0
85	# works correctly.
86	#
87	# NOTE: obscure networking problems will occur if lo0 isn't configured.
88	#
89	/sbin/ifconfig lo0 inet 127.0.0.1
90
91	# According to RFC1122, 127.0.0.0/8 must not leave the node.
92	#
93	/sbin/route -q add -inet 127.0.0.0 -netmask 0xff000000 127.0.0.1 -reject
94
95	# IPv6 routing setups, and host/router mode selection.
96	#
97	if /sbin/ifconfig lo0 inet6 >/dev/null 2>&1; then
98		# We have IPv6 support in kernel.
99
100		# disallow link-local unicast dest without outgoing scope
101		# identifiers.
102		#
103		/sbin/route -q add -inet6 fe80:: -prefixlen 10 ::1 -reject
104
105		# disallow the use of the RFC3849 documentation address
106		#
107		/sbin/route -q add -inet6 2001:db8:: -prefixlen 32 ::1 -reject
108
109		# IPv6 site-local scoped address prefix (fec0::/10)
110		# has been deprecated by RFC3879.
111		#
112		if [ -n "$ip6sitelocal" ]; then
113			warn "\$ip6sitelocal is no longer valid"
114		fi
115
116		# disallow "internal" addresses to appear on the wire.
117		#
118		/sbin/route -q add -inet6 ::ffff:0.0.0.0 -prefixlen 96 ::1 -reject
119
120		# disallow packets to malicious IPv4 compatible prefix
121		#
122		/sbin/route -q add -inet6 ::224.0.0.0 -prefixlen 100 ::1 -reject
123		/sbin/route -q add -inet6 ::127.0.0.0 -prefixlen 104 ::1 -reject
124		/sbin/route -q add -inet6 ::0.0.0.0 -prefixlen 104 ::1 -reject
125		/sbin/route -q add -inet6 ::255.0.0.0 -prefixlen 104 ::1 -reject
126
127		# disallow packets to malicious 6to4 prefix
128		#
129		/sbin/route -q add -inet6 2002:e000:: -prefixlen 20 ::1 -reject
130		/sbin/route -q add -inet6 2002:7f00:: -prefixlen 24 ::1 -reject
131		/sbin/route -q add -inet6 2002:0000:: -prefixlen 24 ::1 -reject
132		/sbin/route -q add -inet6 2002:ff00:: -prefixlen 24 ::1 -reject
133
134		# Completely disallow packets to IPv4 compatible prefix.
135		# This may conflict with RFC1933 under following circumstances:
136		# (1) An IPv6-only KAME node tries to originate packets to IPv4
137		#     compatible destination.  The KAME node has no IPv4
138		#     compatible support.  Under RFC1933, it should transmit
139		#     native IPv6 packets toward IPv4 compatible destination,
140		#     hoping it would reach a router that forwards the packet
141		#     toward auto-tunnel interface.
142		# (2) An IPv6-only node originates a packet to IPv4 compatible
143		#     destination.  A KAME node is acting as an IPv6 router, and
144		#     asked to forward it.
145		# Due to rare use of IPv4 compatible address, and security
146		# issues with it, we disable it by default.
147		#
148		/sbin/route -q add -inet6 ::0.0.0.0 -prefixlen 96 ::1 -reject
149
150		/sbin/sysctl -qw net.inet6.ip6.forwarding=0
151		/sbin/sysctl -qw net.inet6.ip6.accept_rtadv=0
152
153		case $ip6mode in
154		router)
155			echo 'IPv6 mode: router'
156			/sbin/sysctl -qw net.inet6.ip6.forwarding=1
157
158			# disallow unique-local unicast forwarding without
159			# explicit configuration.
160			if ! checkyesno ip6uniquelocal; then
161				/sbin/route -q add -inet6 fc00:: -prefixlen 7 \
162				    ::1 -reject
163			fi
164			;;
165
166		autohost)
167			echo 'IPv6 mode: autoconfigured host'
168			/sbin/sysctl -qw net.inet6.ip6.accept_rtadv=1
169			;;
170
171		host)	
172			echo 'IPv6 mode: host'
173			;;
174
175		*)	warn "invalid \$ip6mode value "\"$ip6mode\"
176			;;
177
178		esac
179	fi
180
181	# Configure all of the network interfaces listed in $net_interfaces;
182	# if $auto_ifconfig is YES, grab all interfaces from ifconfig.
183	# In the following, "xxN" stands in for interface names, like "le0".
184	#
185	# For any interfaces that has an $ifconfig_xxN variable
186	# associated, we break it into lines using ';' as a separator,
187	# then process it just like the contents of an /etc/ifconfig.xxN
188	# file.
189	#
190	# For each line from the $ifconfig_xxN variable or the
191	# /etc/ifconfig.xxN file, we ignore comments and blank lines,
192	# treat lines beginning with "!" as commands to execute, treat
193	# "dhcp" as a special case to invoke dhcpcd, and for any other
194	# line we run "ifconfig xxN", using each line of the file as the
195	# arguments for a separate "ifconfig" invocation.
196	#
197	# In order to configure an interface reasonably, you at the very least
198	# need to specify "[addr_family] [hostname]" (e.g "inet my.domain.org"),
199	# and probably a netmask (as in "netmask 0xffffffe0"). You will
200	# frequently need to specify a media type, as in "media UTP", for
201	# interface cards with multiple media connections that do not
202	# autoconfigure. See the ifconfig manual page for details.
203	#
204	# Note that /etc/ifconfig.xxN takes multiple lines.  The following
205	# configuration is possible:
206	#	inet 10.1.1.1 netmask 0xffffff00
207	#	inet 10.1.1.2 netmask 0xffffff00 alias
208	#	inet6 2001:db8::1 prefixlen 64 alias
209	#
210	# You can put shell script fragment into /etc/ifconfig.xxN by
211	# starting a line with "!".  Refer to ifconfig.if(5) for details.
212	#
213	if [ "$net_interfaces" != NO ]; then
214		if checkyesno auto_ifconfig; then
215			tmp=$(/sbin/ifconfig -l)
216			for cloner in $(/sbin/ifconfig -C 2>/dev/null); do
217				for int in /etc/ifconfig.${cloner}[0-9]*; do
218					[ ! -f $int ] && break
219					tmp="$tmp ${int##*.}"
220				done
221			done
222		else
223			tmp="$net_interfaces"
224		fi
225		echo -n 'Configuring network interfaces:'
226		for int in $tmp; do
227			eval argslist=\$ifconfig_$int
228
229			# Skip interfaces that do not have explicit
230			# configuration information.  If auto_ifconfig is
231			# false then also warn about such interfaces.
232			#
233			if [ -z "$argslist" ] && ! [ -f /etc/ifconfig.$int ]
234			then
235				if ! checkyesno auto_ifconfig; then
236					echo
237					warn \
238			"/etc/ifconfig.$int missing and ifconfig_$int not set;"
239					warn "interface $int not configured."
240				fi
241				continue
242			fi
243
244			echo -n " $int"
245
246			# Create the interface if necessary.
247			# If the interface did not exist before,
248			# then also resync ipf(4).
249			#
250			if /sbin/ifconfig $int create 2>/dev/null && \
251			   checkyesno ipfilter; then
252				/sbin/ipf -y >/dev/null
253			fi
254
255			# If $ifconfig_xxN is empty, then use
256			# /etc/ifconfig.xxN, which we know exists due to
257			# an earlier test.
258			#
259			# If $ifconfig_xxN is non-empty and contains a
260			# newline, then just use it as is.  (This allows
261			# semicolons through unmolested.)
262			#
263			# If $ifconfig_xxN is non-empty and does not
264			# contain a newline, then convert all semicolons
265			# to newlines.
266			#
267			case "$argslist" in
268			'')
269				cat /etc/ifconfig.$int
270				;;
271			*"${nl}"*)
272				echo "$argslist"
273				;;
274			*)
275				(
276					set -o noglob
277					IFS=';'; set -- $argslist
278					#echo >&2 "[$#] [$1] [$2] [$3] [$4]"
279					IFS="$nl"; echo "$*"
280				)
281				;;
282			esac |
283			while read -r args; do
284				case "$args" in
285				''|"#"*|create)
286					;;
287				"!"*)
288					# Run arbitrary command in a subshell.
289					( eval "${args#*!}" )
290					;;
291				dhcp)
292					if ! checkyesno dhcpcd; then
293						/sbin/dhcpcd -n \
294							${dhcpcd_flags} $int
295					fi
296					;;
297				*)
298					# Pass args to ifconfig.  Note
299					# that args may contain embedded
300					# shell metacharacters, such as
301					# "ssid 'foo;*>bar'". We eval
302					# one more time so that things
303					# like ssid "Columbia University" work.
304					(
305						set -o noglob
306						eval set -- $args
307						#echo >&2 "[$#] [$1] [$2] [$3]"
308						/sbin/ifconfig $int "$@"
309					)
310					;;
311				esac
312			done
313			configured_interfaces="$configured_interfaces $int"
314		done
315		echo "."
316	fi
317
318	echo -n "Adding interface aliases:"
319
320	# Check if each configured interface xxN has an $ifaliases_xxN variable
321	# associated, then configure additional IP addresses for that interface.
322	# The variable contains a list of "address netmask" pairs, with
323	# "netmask" set to "-" if the interface default netmask is to be used.
324	#
325	# Note that $ifaliases_xxN works only in certain cases and its
326	# use is not recommended.  Use /etc/ifconfig.xxN or multiple
327	# commands in $ifconfig_xxN instead.
328	#
329	for int in lo0 $configured_interfaces; do
330		eval args=\$ifaliases_$int
331		if [ -n "$args" ]; then
332			set -- $args
333			while [ $# -ge 2 ]; do
334				addr=$1 ; net=$2 ; shift 2
335				if [ "$net" = "-" ]; then
336					# for compatibility only, obsolete
337					/sbin/ifconfig $int inet alias $addr
338				else
339					/sbin/ifconfig $int inet alias $addr \
340					    netmask $net
341				fi
342				echo -n " $int:$addr"
343			done
344		fi
345	done
346
347	# /etc/ifaliases, if it exists, contains the names of additional IP
348	# addresses for each interface. It is formatted as a series of lines
349	# that contain
350	#	address interface netmask
351	#
352	# Note that /etc/ifaliases works only in certain cases and its
353	# use is not recommended.  Use /etc/ifconfig.xxN or multiple
354	# commands in $ifconfig_xxN instead.
355	#
356	if [ -f /etc/ifaliases ]; then
357		while read addr int net; do
358			if [ -z "$net" ]; then
359				# for compatibility only, obsolete
360				/sbin/ifconfig $int inet alias $addr
361			else
362				/sbin/ifconfig $int inet alias $addr netmask $net
363			fi
364		done < /etc/ifaliases
365	fi
366
367	echo "." # for "Adding interface aliases:"
368
369	# Check $defaultroute, then /etc/mygate, for the name or address
370	# of my IPv4 gateway host. If using a name, that name must be in
371	# /etc/hosts.
372	#
373	if [ -z "$defaultroute" ] && [ -f /etc/mygate ]; then
374		defaultroute=$(cat /etc/mygate)
375	fi
376	if [ -n "$defaultroute" ]; then
377		/sbin/route add default $defaultroute
378	fi
379
380	# Check $defaultroute6, then /etc/mygate6, for the name or address
381	# of my IPv6 gateway host. If using a name, that name must be in
382	# /etc/hosts.  Note that the gateway host address must be a link-local
383	# address if it is not using an stf* interface.
384	#
385	if [ -z "$defaultroute6" ] && [ -f /etc/mygate6 ]; then
386		defaultroute6=$(cat /etc/mygate6)
387	fi
388	if [ -n "$defaultroute6" ]; then
389		if [ "$ip6mode" = "autohost" ]; then
390			echo
391			warn \
392	    "ip6mode is set to 'autohost' and a v6 default route is also set."
393		fi
394		/sbin/route add -inet6 default $defaultroute6
395	fi
396
397	# IPv6 interface autoconfiguration.
398	#
399	if /sbin/ifconfig lo0 inet6 >/dev/null 2>&1; then
400		# wait till DAD is completed. always invoke it in case
401		# if are configured manually by ifconfig
402		#
403		dadcount=$(/sbin/sysctl -n net.inet6.ip6.dad_count 2>/dev/null)
404		sleep $dadcount
405		sleep 1
406
407		if checkyesno rtsol; then
408			if [ "$ip6mode" = "autohost" ]; then
409				echo 'Sending router solicitation...'
410				/sbin/rtsol $rtsol_flags
411			else
412				echo
413				warn \
414			    "ip6mode must be set to 'autohost' to use rtsol."
415			fi
416
417			# wait till DAD is completed, for global addresses
418			# configured by router advert message.
419			#
420			sleep $dadcount
421			sleep 1
422		fi
423	fi
424
425	# XXX this must die
426	if [ -s /etc/netstart.local ]; then
427		sh /etc/netstart.local start
428	fi
429}
430
431network_stop()
432{
433	echo "Stopping network."
434
435	# XXX this must die
436	if [ -s /etc/netstart.local ]; then
437		sh /etc/netstart.local stop
438	fi
439
440	echo "Deleting aliases."
441	if [ -f /etc/ifaliases ]; then
442		while read addr int net; do
443			/sbin/ifconfig $int inet delete $addr
444		done < /etc/ifaliases
445	fi
446
447	for int in $(/sbin/ifconfig -lu); do
448		eval args=\$ifaliases_$int
449		if [ -n "$args" ]; then
450			set -- $args
451			while [ $# -ge 2 ]; do
452				addr=$1 ; net=$2 ; shift 2
453				/sbin/ifconfig $int inet delete $addr
454			done
455		fi
456	done
457
458	# down interfaces
459	#
460	echo -n 'Downing network interfaces:'
461	if [ "$net_interfaces" != NO ]; then
462		if checkyesno auto_ifconfig; then
463			tmp=$(/sbin/ifconfig -l)
464		else
465			tmp="$net_interfaces"
466		fi
467		for int in $tmp; do
468			eval args=\$ifconfig_$int
469			if [ -n "$args" ] || [ -f /etc/ifconfig.$int ]; then
470				echo -n " $int"
471				if [ -f /var/run/dhcpcd-$int.pid ]; then
472					/sbin/dhcpcd -k $int 2> /dev/null
473				fi
474				/sbin/ifconfig $int down
475				if /sbin/ifconfig $int destroy 2>/dev/null && \
476				   checkyesno ipfilter; then
477					# resync ipf(4)
478					/sbin/ipf -y >/dev/null
479				fi
480			fi
481		done
482		echo "."
483	fi
484
485	# flush routes
486	#
487	/sbin/route -qn flush
488
489}
490
491load_rc_config $name
492load_rc_config_var dhclient dhclient
493load_rc_config_var dhcpcd dhcpcd
494load_rc_config_var ipfilter ipfilter
495run_rc_command "$1"
496