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