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