1 #!/sbin/sh
2 #
3 # CDDL HEADER START
4 #
5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License (the "License").
7 # You may not use this file except in compliance with the License.
8 #
9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 # or http://www.opensolaris.org/os/licensing.
11 # See the License for the specific language governing permissions
12 # and limitations under the License.
13 #
14 # When distributing Covered Code, include this CDDL HEADER in each
15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 # If applicable, add the following below this CDDL HEADER, with the
17 # fields enclosed by brackets "[]" replaced with your own identifying
18 # information: Portions Copyright [yyyy] [name of copyright owner]
19 #
20 # CDDL HEADER END
21 #
22
23 #
24 # Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T.
25 # All rights reserved.
26 # Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
27 # Copyright 2012 Milan Jurik. All rights reserved.
28 # Copyright 2016 Nexenta Systems, Inc.
29 #
30
31 . /lib/svc/share/smf_include.sh
32 . /lib/svc/share/net_include.sh
33
34 #
35 # In a shared-IP zone we need this service to be up, but all of the work
36 # it tries to do is irrelevant (and will actually lead to the service
37 # failing if we try to do it), so just bail out.
38 # In the global zone and exclusive-IP zones we proceed.
39 #
40 smf_configure_ip || exit $SMF_EXIT_OK
41
42
43 # Make sure that the libraries essential to this stage of booting can be found.
44 LD_LIBRARY_PATH=/lib; export LD_LIBRARY_PATH
45
46 smf_netstrategy
47
48 if smf_is_globalzone; then
49 net_reconfigure || exit $SMF_EXIT_ERR_CONFIG
50
51 # Update PVID on interfaces configured with VLAN 1
52 update_pvid
53
54 #
55 # Upgrade handling. The upgrade file consists of a series of dladm(1M)
56 # commands. Note that after we are done, we cannot rename the upgrade
57 # script file as the file system is still read-only at this point.
58 # Defer this to the manifest-import service.
59 #
60 upgrade_script=/var/svc/profile/upgrade_datalink
61 if [ -f "${upgrade_script}" ]; then
62 . "${upgrade_script}"
63 fi
64
65 #
66 # Upgrade handling for ibd:
67 # After we are done with the upgrade handling, we can not set the
68 # ibd/ibd_upgraded property to "true" as the file system is
69 # read-only at this point. It will be done later by ibd-post-upgrade
70 # service.
71 #
72 if [ -x /sbin/ibd_upgrade ]; then
73 ibd_upgraded=`/bin/svcprop -c -p ibd/ibd_upgraded \
74 $SMF_FMRI 2> /dev/null`
75 if [ "$ibd_upgraded" != "true" ]; then
76 /sbin/ibd_upgrade -v
77 fi
78 fi
79
80 #
81 # Bring up simnets, link aggregations and initialize security objects.
82 # Note that link property initialization is deferred until after
83 # IP interfaces are plumbed to ensure that the links will not
84 # be unloaded (and the property settings lost). We should bring
85 # up simnets prior to VLANs/Aggrs to enable creation of VLANs/Aggrs
86 # over simnets.
87 #
88 /sbin/dladm up-simnet
89 /sbin/dladm up-aggr
90 /sbin/dladm up-vlan
91 /sbin/dladm up-part
92 /sbin/dladm init-secobj
93 #
94 # Bring up VNICs
95 #
96 /sbin/dladm up-vnic
97 #
98 # Create flows via flowadm.
99 #
100 /sbin/flowadm init-flow
101 fi
102
103 #
104 # If the system was net booted by DHCP, hand DHCP management off to the
105 # DHCP agent (ifconfig communicates to the DHCP agent through the
106 # loopback interface).
107 #
108 if [ -n "$_INIT_NET_IF" -a "$_INIT_NET_STRATEGY" = "dhcp" ]; then
109 /sbin/dhcpagent -a
110 fi
111
112 #
113 # The network initialization is done early to support diskless and
114 # dataless configurations. For IPv4 interfaces that were configured by
115 # the kernel (e.g. those on diskless machines) and not configured by
116 # DHCP, reset the netmask using the local "/etc/netmasks" file if one
117 # exists, and then reset the broadcast address based on the netmask.
118 #
119 /sbin/ifconfig -auD4 netmask + broadcast +
120
121 is_iptun ()
122 {
123 intf=$1
124 # Is this a persistent IP tunnel link?
125 /sbin/dladm show-iptun -P $intf > /dev/null 2>&1
126 if [ $? -eq 0 ]; then
127 return 0
128 fi
129 # Is this an implicit IP tunnel (i.e., ip.tun0)
130 ORIGIFS="$IFS"
131 IFS="$IFS."
132 set -- $intf
133 IFS="$ORIGIFS"
134 if [ $# -eq 2 -a \( "$1" = "ip" -o "$1" = "ip6" \) ]; then
135 #
136 # It looks like one, but another type of link might be
137 # using a name that looks like an implicit IP tunnel.
138 # If dladm show-link -P finds it, then it's not an IP
139 # tunnel.
140 #
141 /sbin/dladm show-link -Pp $intf > /dev/null 2>&1
142 if [ $? -eq 0 ]; then
143 return 1
144 else
145 return 0
146 fi
147 fi
148 return 1
149 }
150
151 #
152 # All the IPv4 and IPv6 interfaces are plumbed before doing any
153 # interface configuration. This prevents errors from plumb failures
154 # getting mixed in with the configured interface lists that the script
155 # outputs.
156 #
157
158 #
159 # First deal with /etc/hostname
160 #
161 # Get the list of IPv4 interfaces to configure by breaking
162 # /etc/hostname.* into separate args by using "." as a shell separator
163 # character.
164 #
165 interface_names="`echo /etc/hostname.*[0-9] 2>/dev/null`"
166 if [ "$interface_names" != "/etc/hostname.*[0-9]" ]; then
167 ORIGIFS="$IFS"
168 IFS="$IFS."
169 set -- $interface_names
170 IFS="$ORIGIFS"
171 while [ $# -ge 2 ]; do
172 shift
173 intf_name=$1
174 while [ $# -gt 1 -a "$2" != "/etc/hostname" ]; do
175 intf_name="$intf_name.$2"
176 shift
177 done
178 shift
179
180 # skip IP tunnel interfaces plumbed by net-iptun.
181 if is_iptun $intf_name; then
182 continue
183 fi
184
185 read one rest < /etc/hostname.$intf_name
186 if [ "$one" = ipmp ]; then
187 ipmp_list="$ipmp_list $intf_name"
188 else
189 inet_list="$inet_list $intf_name"
190 fi
191 done
192 fi
193
194 #
195 # Get the list of IPv6 interfaces to configure by breaking
196 # /etc/hostname6.* into separate args by using "." as a shell separator
197 # character.
198 #
199 interface_names="`echo /etc/hostname6.*[0-9] 2>/dev/null`"
200 if [ "$interface_names" != "/etc/hostname6.*[0-9]" ]; then
201 ORIGIFS="$IFS"
202 IFS="$IFS."
203 set -- $interface_names
204 IFS="$ORIGIFS"
205 while [ $# -ge 2 ]; do
206 shift
207 intf_name=$1
208 while [ $# -gt 1 -a "$2" != "/etc/hostname6" ]; do
209 intf_name="$intf_name.$2"
210 shift
211 done
212 shift
213
214 # skip IP tunnel interfaces plumbed by net-iptun.
215 if is_iptun $intf_name; then
216 continue
217 fi
218
219 read one rest < /etc/hostname6.$intf_name
220 if [ "$one" = ipmp ]; then
221 ipmp6_list="$ipmp6_list $intf_name"
222 else
223 inet6_list="$inet6_list $intf_name"
224 fi
225 done
226 fi
227
228 #
229 # Create all of the IPv4 IPMP interfaces.
230 #
231 if [ -n "$ipmp_list" ]; then
232 set -- $ipmp_list
233 while [ $# -gt 0 ]; do
234 if /sbin/ifconfig $1 ipmp; then
235 ipmp_created="$ipmp_created $1"
236 else
237 ipmp_failed="$ipmp_failed $1"
238 fi
239 shift
240 done
241 [ -n "$ipmp_failed" ] && warn_failed_ifs "create IPv4 IPMP" \
242 "$ipmp_failed"
243 fi
244
245 #
246 # Step through the IPv4 interface list and try to plumb every interface.
247 # Generate list of plumbed and failed IPv4 interfaces.
248 #
249 if [ -n "$inet_list" ]; then
250 set -- $inet_list
251 while [ $# -gt 0 ]; do
252 /sbin/ifconfig $1 plumb
253 if /sbin/ifconfig $1 inet >/dev/null 2>&1; then
254 inet_plumbed="$inet_plumbed $1"
255 else
256 inet_failed="$inet_failed $1"
257 fi
258 shift
259 done
260 [ -n "$inet_failed" ] && warn_failed_ifs "plumb IPv4" "$inet_failed"
261 fi
262
263 # Run autoconf to connect to a WLAN if the interface is a wireless one
264 if [ -x /sbin/wificonfig -a -n "$inet_plumbed" ]; then
265 set -- $inet_plumbed
266 while [ $# -gt 0 ]; do
267 if [ -r /dev/wifi/$1 ]; then
268 /sbin/wificonfig -i $1 startconf >/dev/null
269 fi
270 shift
271 done
272 fi
273
274 #
275 # Step through the IPv6 interface list and plumb every interface.
276 # Generate list of plumbed and failed IPv6 interfaces. Each plumbed
277 # interface will be brought up later, after processing any contents of
278 # the /etc/hostname6.* file.
279 #
280 if [ -n "$inet6_list" ]; then
281 set -- $inet6_list
282 while [ $# -gt 0 ]; do
283 /sbin/ifconfig $1 inet6 plumb
284 if /sbin/ifconfig $1 inet6 >/dev/null 2>&1; then
285 inet6_plumbed="$inet6_plumbed $1"
286 else
287 inet6_failed="$inet6_failed $1"
288 fi
289 shift
290 done
291 [ -n "$inet6_failed" ] && warn_failed_ifs "plumb IPv6" "$inet6_failed"
292 fi
293
294 #
295 # Create all of the IPv6 IPMP interfaces.
296 #
297 if [ -n "$ipmp6_list" ]; then
298 set -- $ipmp6_list
299 while [ $# -gt 0 ]; do
300 if /sbin/ifconfig $1 inet6 ipmp; then
301 ipmp6_created="$ipmp6_created $1"
302 else
303 ipmp6_failed="$ipmp6_failed $1"
304 fi
305 shift
306 done
307 [ -n "$ipmp6_failed" ] && warn_failed_ifs "create IPv6 IPMP" \
308 "$ipmp6_failed"
309 fi
310
311 #
312 # Upgrade ipadm.conf.
313 #
314 if /usr/bin/grep -q _family /etc/ipadm/ipadm.conf; then
315 oldifs=$(/usr/bin/sed -En \
316 's/^_ifname=([a-z0-9]+);_family=[0-9]+;$/\1/p' \
317 /etc/ipadm/ipadm.conf | /usr/bin/sort -u)
318 /usr/bin/sed -i '/_family/d' /etc/ipadm/ipadm.conf
319 for oldif in $oldifs; do
320 /usr/bin/printf \
321 "_ifname=%s;_ifclass=0;_families=2,26;\n" \
322 $oldif >> /etc/ipadm/ipadm.conf
323 done
324 fi
325
326 #
327 # Finally configure interfaces set up with ipadm. Any /etc/hostname*.intf
328 # files take precedence over ipadm defined configurations except when
329 # we are in a non-global zone and Layer-3 protection of IP addresses is
330 # enforced on the interface by the global zone.
331 #
332 for showif_output in `/sbin/ipadm show-if -p -o ifname,state,current`; do
333 intf=`echo $showif_output | /usr/bin/cut -f1 -d:`
334 state=`echo $showif_output | /usr/bin/cut -f2 -d:`
335 current=`echo $showif_output | /usr/bin/cut -f3 -d:`
336 if [[ "$state" != "disabled" && $current != *Z* ]]; then
337 #
338 # skip if not a persistent interface, or if it should get IP
339 # configuration from the global zone ('Z' flag is set)
340 #
341 continue;
342 elif is_iptun $intf; then
343 # skip IP tunnel interfaces plumbed by net-iptun
344 continue;
345 elif [ -f /etc/hostname.$intf ] || [ -f /etc/hostname6.$intf ]; then
346 if [[ $current != *Z* ]]; then
347 echo "found /etc/hostname.$intf "\
348 "or /etc/hostname6.$intf, "\
349 "ignoring ipadm configuration" > /dev/msglog
350 continue;
351 else
352 echo "Ignoring /etc/hostname*.$intf" > /dev/msglog
353 /sbin/ifconfig $intf unplumb > /dev/null 2>&1
354 /sbin/ifconfig $intf inet6 unplumb > /dev/null 2>&1
355 fi
356 fi
357
358 # Enable the interface managed by ipadm
359 /sbin/ipadm enable-if -t $intf
360 done
361
362 #
363 # Process the /etc/hostname[6].* files for IPMP interfaces. Processing these
364 # before non-IPMP interfaces avoids accidental implicit IPMP group creation.
365 #
366 [ -n "$ipmp_created" ] && if_configure inet "IPMP" $ipmp_created
367 [ -n "$ipmp6_created" ] && if_configure inet6 "IPMP" $ipmp6_created
368
369 #
370 # Process the /etc/hostname[6].* files for non-IPMP interfaces.
371 #
372 [ -n "$inet_plumbed" ] && if_configure inet "" $inet_plumbed
373 [ -n "$inet6_plumbed" ] && if_configure inet6 "" $inet6_plumbed
374
375 #
376 # For the IPv4 and IPv6 interfaces that failed to plumb, find (or create)
377 # IPMP meta-interfaces to host their data addresses.
378 #
379 [ -n "$inet_failed" ] && move_addresses inet
380 [ -n "$inet6_failed" ] && move_addresses inet6
381
382 # Run DHCP if requested. Skip boot-configured interface.
383 interface_names="`echo /etc/dhcp.*[0-9] 2>/dev/null`"
384 if [ "$interface_names" != '/etc/dhcp.*[0-9]' ]; then
385 #
386 # First find the primary interface. Default to the first
387 # interface if not specified. First primary interface found
388 # "wins". Use care not to "reconfigure" a net-booted interface
389 # configured using DHCP. Run through the list of interfaces
390 # again, this time trying DHCP.
391 #
392 i4d_fail=
393 firstif=
394 primary=
395 ORIGIFS="$IFS"
396 IFS="${IFS}."
397 set -- $interface_names
398
399 while [ $# -ge 2 ]; do
400 shift
401 [ -z "$firstif" ] && firstif=$1
402
403 for i in `shcat /etc/dhcp\.$1`; do
404 if [ "$i" = primary ]; then
405 primary=$1
406 break
407 fi
408 done
409
410 [ -n "$primary" ] && break
411 shift
412 done
413
414 [ -z "$primary" ] && primary="$firstif"
415 cmdline=`shcat /etc/dhcp\.${primary}`
416
417 if [ "$_INIT_NET_IF" != "$primary" ]; then
418 echo "starting DHCP on primary interface $primary"
419 /sbin/ifconfig $primary auto-dhcp primary $cmdline
420 # Exit code 4 means ifconfig timed out waiting for dhcpagent
421 [ $? != 0 ] && [ $? != 4 ] && i4d_fail="$i4d_fail $primary"
422 fi
423
424 set -- $interface_names
425
426 while [ $# -ge 2 ]; do
427 shift
428 cmdline=`shcat /etc/dhcp\.$1`
429 if [ "$1" != "$primary" -a \
430 "$1" != "$_INIT_NET_IF" ]; then
431 echo "starting DHCP on interface $1"
432 /sbin/ifconfig $1 dhcp start wait 0 $cmdline
433 # Exit code can't be timeout when wait is 0
434 [ $? != 0 ] && i4d_fail="$i4d_fail $1"
435 fi
436 shift
437 done
438 IFS="$ORIGIFS"
439 unset ORIGIFS
440 [ -n "$i4d_fail" ] && warn_failed_ifs "configure IPv4 DHCP" "$i4d_fail"
441 fi
442
443 # In order to avoid bringing up the interfaces that have
444 # intentionally been left down, perform RARP only if the system
445 # has no configured hostname in /etc/nodename
446 hostname="`shcat /etc/nodename 2>/dev/null`"
447 if [ "$_INIT_NET_STRATEGY" = "rarp" -o -z "$hostname" ]; then
448 /sbin/ifconfig -adD4 auto-revarp netmask + broadcast + up
449 fi
450
451 #
452 # If the /etc/defaultrouter file exists, process it now so that the next
453 # stage of booting will have access to NFS.
454 #
455 if [ -f /etc/defaultrouter ]; then
456 while read router rubbish; do
457 case "$router" in
458 '#'* | '') ;; # Ignore comments, empty lines
459 *) /sbin/route -n add default -gateway $router ;;
460 esac
461 done </etc/defaultrouter
462 fi
463
464 #
465 # If we get here and were not asked to plumb any IPv4 interfaces, look
466 # for boot properties that direct us.
467 #
468 # - The "network-interface" property is required and indicates the
469 # interface name.
470 # - The "xpv-hcp" property, if present, is used by the hypervisor
471 # tools to indicate how the specified interface should be configured.
472 # Permitted values are "dhcp" and "off", where "off" indicates static
473 # IP configuration.
474 #
475 # In the case where "xpv-hcp" is set to "dhcp", no further properties
476 # are required or examined.
477 #
478 # In the case where "xpv-hcp" is not present or set to "off", the
479 # "host-ip" and "subnet-mask" properties are used to configure
480 # the specified interface. The "router-ip" property, if present,
481 # is used to add a default route.
482 #
483 nic="`/sbin/devprop network-interface`"
484 if smf_is_globalzone && [ -z "$inet_list" ] && [ -n "$nic" ]; then
485 hcp="`/sbin/devprop xpv-hcp`"
486 case "$hcp" in
487 "dhcp")
488 /sbin/ifconfig $nic plumb 2>/dev/null
489 [ -n "`/sbin/ifconfig $nic 2>/dev/null`" ] && (
490 # The interface is successfully plumbed, so
491 # modify "inet_list" to force the exit code
492 # checks to work.
493 inet_list=$nic;
494 # Given that this is the only IPv4 interface,
495 # we assert that it is primary.
496 echo "starting DHCP on primary interface $primary";
497 /sbin/ifconfig $nic auto-dhcp primary;
498 # Exit code 4 means ifconfig timed out waiting
499 # for dhcpagent
500 [ $? != 0 ] && [ $? != 4 ] && \
501 i4d_fail="$i4d_fail $nic";
502 )
503 ;;
504
505 "off"|"")
506 /sbin/devprop host-ip subnet-mask router-ip | (
507 read ip;
508 read mask;
509 read router;
510 [ -n "$ip" ] && [ -n "$mask" ] && \
511 /sbin/ifconfig $nic plumb 2>/dev/null
512 [ -n "`/sbin/ifconfig $nic 2>/dev/null`" ] && (
513 # The interface is successfully
514 # plumbed, so modify "inet_list" to
515 # force the exit code checks to work.
516 inet_list=$nic;
517 /sbin/ifconfig $nic inet $ip \
518 netmask $mask broadcast + up 2>/dev/null;
519 [ -n "$router" ] && route add \
520 default $router 2>/dev/null;
521 )
522 )
523 ;;
524 esac
525 fi
526
527 #
528 # We tell smf this service is online if any of the following is true:
529 # - no interfaces were configured for plumbing and no DHCP failures
530 # - any non-loopback IPv4 interfaces are up and have a non-zero address
531 # - there are any DHCP interfaces started
532 # - any non-loopback IPv6 interfaces are up
533 #
534 # If we weren't asked to configure any interfaces, exit
535 if [ -z "$inet_list" ] && [ -z "$inet6_list" ]; then
536 # Config error if DHCP was attempted without plumbed interfaces
537 [ -n "$i4d_fail" ] && exit $SMF_EXIT_ERR_CONFIG
538 exit $SMF_EXIT_OK
539 fi
540
541 # Any non-loopback IPv4 interfaces with usable addresses up?
542 if [ -n "`/sbin/ifconfig -a4u`" ]; then
543 /sbin/ifconfig -a4u | while read intf addr rest; do
544 [ $intf = inet ] && [ $addr != 127.0.0.1 ] &&
545 [ $addr != 0.0.0.0 ] && exit $SMF_EXIT_OK
546 done && exit $SMF_EXIT_OK
547 fi
548
549 # Any DHCP interfaces started?
550 [ -n "`/sbin/ifconfig -a4 dhcp status 2>/dev/null`" ] && exit $SMF_EXIT_OK
551
552 # Any non-loopback IPv6 interfaces up?
553 if [ -n "`/sbin/ifconfig -au6`" ]; then
554 /sbin/ifconfig -au6 | while read intf addr rest; do
555 [ $intf = inet6 ] && [ $addr != ::1/128 ] && exit $SMF_EXIT_OK
556 done && exit $SMF_EXIT_OK
557 fi
558
559 # This service was supposed to configure something yet didn't. Exit
560 # with config error.
561 exit $SMF_EXIT_ERR_CONFIG