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