Home | History | Annotate | Download | only in milestone
      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 2008 Sun Microsystems, Inc.  All rights reserved.
     24 # Use is subject to license terms.
     25 #
     26 # Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T.
     27 # All rights reserved.
     28 #
     29 #
     30 # ident	"%Z%%M%	%I%	%E% SMI"
     31 
     32 . /lib/svc/share/smf_include.sh
     33 . /lib/svc/share/net_include.sh
     34 
     35 #
     36 # In a shared-IP zone we need this service to be up, but all of the work
     37 # it tries to do is irrelevant (and will actually lead to the service 
     38 # failing if we try to do it), so just bail out. 
     39 # In the global zone and exclusive-IP zones we proceed.
     40 #
     41 smf_configure_ip || exit $SMF_EXIT_OK
     42 
     43 # Print warnings to console
     44 warn_failed_ifs() {
     45 	echo "Failed to $1 interface(s): $2" >/dev/msglog
     46 }
     47 
     48 # Make sure that the libraries essential to this stage of booting can be found.
     49 LD_LIBRARY_PATH=/lib; export LD_LIBRARY_PATH
     50 
     51 #
     52 # Cause ifconfig to not automatically start in.mpathd when IPMP groups are
     53 # configured.  This is not strictly necessary but makes it so that in.mpathd
     54 # will always be started explicitly from /etc/init.d/inetinit, when we're
     55 # sure that /usr is mounted.
     56 #
     57 SUNW_NO_MPATHD=; export SUNW_NO_MPATHD
     58 
     59 smf_netstrategy
     60 
     61 if smf_is_globalzone; then
     62 	net_reconfigure || exit $SMF_EXIT_ERR_CONFIG
     63 
     64 	# 
     65 	# Upgrade handling. The upgrade file consists of a series of dladm(1M)
     66 	# commands. Note that after we are done, we cannot rename the upgrade
     67 	# script file as the file system is still read-only at this point.
     68 	# Defer this to the manifest-import service.
     69 	#
     70 	upgrade_script=/var/svc/profile/upgrade_datalink
     71 	if [ -f "${upgrade_script}" ]; then 
     72 		. "${upgrade_script}"
     73 	fi
     74 
     75 	#
     76 	# Bring up link aggregations and initialize security objects.
     77 	# Note that link property initialization is deferred until after
     78 	# IP interfaces are plumbed to ensure that the links will not
     79 	# be unloaded (and the property settings lost).
     80 	#
     81 	/sbin/dladm up-aggr
     82 	/sbin/dladm up-vlan
     83 	/sbin/dladm init-secobj
     84 fi
     85 
     86 #
     87 # If the system was net booted by DHCP, hand DHCP management off to the
     88 # DHCP agent (ifconfig communicates to the DHCP agent through the
     89 # loopback interface).
     90 #
     91 if [ -n "$_INIT_NET_IF" -a "$_INIT_NET_STRATEGY" = "dhcp" ]; then
     92 	/sbin/dhcpagent -a
     93 fi
     94 
     95 #
     96 # The network initialization is done early to support diskless and
     97 # dataless configurations.  For IPv4 interfaces that were configured by
     98 # the kernel (e.g.  those on diskless machines) and not configured by
     99 # DHCP, reset the netmask using the local "/etc/netmasks" file if one
    100 # exists, and then reset the broadcast address based on the netmask.
    101 #
    102 /sbin/ifconfig -auD4 netmask + broadcast +
    103 
    104 #
    105 # All the IPv4 and IPv6 interfaces are plumbed before doing any
    106 # interface configuration.  This prevents errors from plumb failures
    107 # getting mixed in with the configured interface lists that the script
    108 # outputs.
    109 #
    110 
    111 #
    112 # Get the list of IPv4 interfaces to configure by breaking
    113 # /etc/hostname.* into separate args by using "." as a shell separator
    114 # character.
    115 #
    116 interface_names="`echo /etc/hostname.*[0-9] 2>/dev/null`"
    117 if [ "$interface_names" != "/etc/hostname.*[0-9]" ]; then
    118 	ORIGIFS="$IFS"
    119 	IFS="$IFS."
    120 	set -- $interface_names
    121 	IFS="$ORIGIFS"
    122 	while [ $# -ge 2 ]; do
    123 		shift
    124 		if [ $# -gt 1 -a "$2" != "/etc/hostname" ]; then
    125 			while [ $# -gt 1 -a "$1" != "/etc/hostname" ]; do
    126 				shift
    127 			done
    128 		else
    129 			inet_list="$inet_list $1"
    130 			shift
    131 		fi
    132 	done
    133 fi
    134 
    135 #
    136 # Get the list of IPv6 interfaces to configure by breaking
    137 # /etc/hostname6.* into separate args by using "." as a shell separator
    138 # character.
    139 #
    140 interface_names="`echo /etc/hostname6.*[0-9] 2>/dev/null`"
    141 if [ "$interface_names" != "/etc/hostname6.*[0-9]" ]; then
    142 	ORIGIFS="$IFS"
    143 	IFS="$IFS."
    144 	set -- $interface_names
    145 	IFS="$ORIGIFS"
    146 	while [ $# -ge 2 ]; do
    147 		shift
    148 		if [ $# -gt 1 -a "$2" != "/etc/hostname6" ]; then
    149 			while [ $# -gt 1 -a "$1" != "/etc/hostname6" ]; do
    150 				shift
    151 			done
    152 		else
    153 			inet6_list="$inet6_list $1"
    154 			shift
    155 		fi
    156 	done
    157 fi
    158 
    159 
    160 #
    161 # Step through the IPv4 interface list and try to plumb every interface.
    162 # Generate list of plumbed and failed IPv4 interfaces.
    163 #
    164 if [ -n "$inet_list" ]; then
    165 	set -- $inet_list
    166 	while [ $# -gt 0 ]; do
    167 		/sbin/ifconfig $1 plumb
    168 		if /sbin/ifconfig $1 inet >/dev/null 2>&1; then
    169 			inet_plumbed="$inet_plumbed $1"
    170 		else
    171 			inet_failed="$inet_failed $1"
    172 		fi
    173 		shift
    174 	done
    175 	[ -n "$inet_failed" ] && warn_failed_ifs "plumb IPv4" $inet_failed
    176 fi
    177 
    178 # Run autoconf to connect to a WLAN if the interface is a wireless one
    179 if [ -x /sbin/wificonfig -a -n "$inet_plumbed" ]; then
    180 	set -- $inet_plumbed
    181 	while [ $# -gt 0 ]; do
    182 			if [ -r /dev/wifi/$1 ]; then
    183 				/sbin/wificonfig -i $1 startconf >/dev/null
    184 			fi
    185 		shift
    186 	done
    187 fi
    188 
    189 #
    190 # Step through the IPv6 interface list and plumb every interface.
    191 # Generate list of plumbed and failed IPv6 interfaces.  Each plumbed
    192 # interface will be brought up later, after processing any contents of
    193 # the /etc/hostname6.* file.
    194 #
    195 if [ -n "$inet6_list" ]; then
    196 	set -- $inet6_list
    197 	while [ $# -gt 0 ]; do
    198 		/sbin/ifconfig $1 inet6 plumb
    199 		if /sbin/ifconfig $1 inet6 >/dev/null 2>&1; then
    200 			inet6_plumbed="$inet6_plumbed $1"
    201 		else
    202 			inet6_failed="$inet6_failed $1"
    203 		fi
    204 		shift
    205 	done
    206 	[ -n "$inet6_failed" ] && warn_failed_ifs "plumb IPv6" $inet6_failed
    207 fi
    208 
    209 if smf_is_globalzone; then
    210 	#
    211 	# Wifi drivers use special property interfaces that are not supported
    212 	# by the existing property persistence mechanism, so if a wifi driver
    213 	# unloads and then is subsequently reloaded, associated links' properties
    214 	# will not be restored.  For now, wait until after interfaces have been
    215 	# plumbed (above) to initialize link properties.
    216 	#
    217 	/sbin/dladm init-linkprop -w
    218 fi
    219 
    220 #
    221 # Process the /etc/hostname.* files of plumbed IPv4 interfaces.  If an
    222 # /etc/hostname file is not present or is empty, the ifconfig auto-dhcp
    223 # / auto-revarp command will attempt to set the address, later.
    224 #
    225 # If /etc/hostname.lo0 exists the loop below will do additional
    226 # configuration of lo0.
    227 #
    228 if [ -n "$inet_plumbed" ]; then
    229 	i4s_fail=
    230 	echo "configuring IPv4 interfaces:\c"
    231 	set -- $inet_plumbed
    232 	while [ $# -gt 0 ]; do
    233 		inet_process_hostname /sbin/ifconfig $1 inet \
    234 		    </etc/hostname.$1 >/dev/null
    235 		[ $? != 0 ] && i4s_fail="$i4s_fail $1"
    236 		echo " $1\c"
    237 		shift
    238 	done
    239 	echo "."
    240 	[ -n "$i4s_fail" ] && warn_failed_ifs "configure IPv4" $i4s_fail
    241 fi
    242 
    243 #
    244 # Process the /etc/hostname6.* files of plumbed IPv6 interfaces.  After
    245 # processing the hostname6 file, bring the interface up.  If
    246 # /etc/hostname6.lo0 exists the loop below will do additional
    247 # configuration of lo0.
    248 #
    249 if [ -n "$inet6_plumbed" ]; then
    250 	i6_fail=
    251 	echo "configuring IPv6 interfaces:\c"
    252 	set -- $inet6_plumbed
    253 	while [ $# -gt 0 ]; do
    254 		inet6_process_hostname /sbin/ifconfig $1 inet6 \
    255 		    </etc/hostname6.$1 >/dev/null && 
    256 		    /sbin/ifconfig $1 inet6 up
    257 		[ $? != 0 ] && i6_fail="$i6_fail $1"
    258 		echo " $1\c"
    259 		shift
    260 	done
    261 	echo "."
    262 	[ -n "$i6_fail" ] && warn_failed_ifs "configure IPv6" $i6_fail
    263 fi
    264 
    265 # Run DHCP if requested. Skip boot-configured interface.
    266 interface_names="`echo /etc/dhcp.*[0-9] 2>/dev/null`"
    267 if [ "$interface_names" != '/etc/dhcp.*[0-9]' ]; then
    268 	#
    269 	# First find the primary interface. Default to the first
    270 	# interface if not specified. First primary interface found
    271 	# "wins". Use care not to "reconfigure" a net-booted interface
    272 	# configured using DHCP. Run through the list of interfaces
    273 	# again, this time trying DHCP.
    274 	#
    275 	i4d_fail=
    276 	firstif=
    277 	primary=
    278 	ORIGIFS="$IFS"
    279 	IFS="${IFS}."
    280 	set -- $interface_names
    281 
    282 	while [ $# -ge 2 ]; do
    283 		shift
    284 		[ -z "$firstif" ] && firstif=$1
    285 
    286 		for i in `shcat /etc/dhcp\.$1`; do
    287 			if [ "$i" = primary ]; then
    288 				primary=$1
    289 				break
    290 			fi
    291 		done
    292 
    293 		[ -n "$primary" ] && break
    294 		shift
    295 	done
    296 
    297 	[ -z "$primary" ] && primary="$firstif"
    298 	cmdline=`shcat /etc/dhcp\.${primary}`
    299 
    300 	if [ "$_INIT_NET_IF" != "$primary" ]; then
    301 		echo "starting DHCP on primary interface $primary"
    302 		/sbin/ifconfig $primary auto-dhcp primary $cmdline
    303 		# Exit code 4 means ifconfig timed out waiting for dhcpagent
    304 		[ $? != 0 ] && [ $? != 4 ] && i4d_fail="$i4d_fail $primary"
    305 	fi
    306 
    307 	set -- $interface_names
    308 
    309 	while [ $# -ge 2 ]; do
    310 		shift
    311 		cmdline=`shcat /etc/dhcp\.$1`
    312 		if [ "$1" != "$primary" -a \
    313 			"$1" != "$_INIT_NET_IF"  ]; then
    314 			echo "starting DHCP on interface $1"
    315 			/sbin/ifconfig $1 dhcp start wait 0 $cmdline
    316 			# Exit code can't be timeout when wait is 0
    317 			[ $? != 0 ] && i4d_fail="$i4d_fail $1"
    318 		fi
    319 		shift
    320 	done
    321 	IFS="$ORIGIFS"
    322 	unset ORIGIFS
    323 	[ -n "$i4d_fail" ] && warn_failed_ifs "configure IPv4 DHCP" $i4d_fail
    324 fi
    325 
    326 # In order to avoid bringing up the interfaces that have
    327 # intentionally been left down, perform RARP only if the system
    328 # has no configured hostname in /etc/nodename
    329 hostname="`shcat /etc/nodename 2>/dev/null`"
    330 if [ "$_INIT_NET_STRATEGY" = "rarp" -o -z "$hostname" ]; then
    331 	/sbin/ifconfig -adD4 auto-revarp netmask + broadcast + up
    332 fi
    333 
    334 #
    335 # Process IPv4 and IPv6 interfaces that failed to plumb.  Find an
    336 # alternative interface to host the addresses.
    337 #
    338 [ -n "$inet_failed" ] && move_addresses inet
    339 
    340 [ -n "$inet6_failed" ] && move_addresses inet6
    341 
    342 #
    343 # If the /etc/defaultrouter file exists, process it now so that the next
    344 # stage of booting will have access to NFS.
    345 #
    346 if [ -f /etc/defaultrouter ]; then
    347 	while read router rubbish; do
    348 		case "$router" in
    349 			'#'* | '') ;;	#  Ignore comments, empty lines
    350 			*)	/sbin/route -n add default -gateway $router ;;
    351 		esac
    352 	done </etc/defaultrouter
    353 fi
    354 
    355 #
    356 # If we get here and were not asked to plumb any IPv4 interfaces, look
    357 # for boot properties that direct us.
    358 #
    359 # - The "network-interface" property is required and indicates the
    360 #   interface name.
    361 # - The "xpv-hcp" property, if present, is used by the hypervisor
    362 #   tools to indicate how the specified interface should be configured.
    363 #   Permitted values are "dhcp" and "off", where "off" indicates static
    364 #   IP configuration.
    365 #
    366 # In the case where "xpv-hcp" is set to "dhcp", no further properties
    367 # are required or examined.
    368 #
    369 # In the case where "xpv-hcp" is not present or set to "off", the
    370 # "host-ip" and "subnet-mask" properties are used to configure
    371 # the specified interface.  The "router-ip" property, if present,
    372 # is used to add a default route.
    373 #
    374 nic="`/sbin/devprop network-interface`"
    375 if smf_is_globalzone && [ -z "$inet_list" ] && [ -n "$nic" ]; then
    376 	hcp="`/sbin/devprop xpv-hcp`"
    377 	case "$hcp" in
    378 	"dhcp")
    379 		/sbin/ifconfig $nic plumb 2>/dev/null
    380 		[ -n "`/sbin/ifconfig $nic 2>/dev/null`" ] && (
    381 			# The interface is successfully plumbed, so
    382 			# modify "inet_list" to force the exit code
    383 			# checks to work.
    384 			inet_list=$nic;
    385 			# Given that this is the only IPv4 interface,
    386 			# we assert that it is primary.
    387 			echo "starting DHCP on primary interface $primary";
    388 			/sbin/ifconfig $nic auto-dhcp primary;
    389 			# Exit code 4 means ifconfig timed out waiting
    390 			# for dhcpagent
    391 			[ $? != 0 ] && [ $? != 4 ] && \
    392 			    i4d_fail="$i4d_fail $nic";
    393 		)
    394 		;;
    395 
    396 	"off"|"")
    397 		/sbin/devprop host-ip subnet-mask router-ip | (
    398 			read ip;
    399 			read mask;
    400 			read router;
    401 			[ -n "$ip" ] && [ -n "$mask" ] && \
    402 				/sbin/ifconfig $nic plumb 2>/dev/null
    403 			[ -n "`/sbin/ifconfig $nic 2>/dev/null`" ] && (
    404 				# The interface is successfully
    405 				# plumbed, so modify "inet_list" to
    406 				# force the exit code checks to work.
    407 				inet_list=$nic;
    408 				/sbin/ifconfig $nic  inet $ip \
    409 				    netmask $mask broadcast + up 2>/dev/null;
    410 				[ -n "$router" ] && route add \
    411 				    default $router 2>/dev/null;
    412 			)
    413 		)
    414 		;;
    415 	esac
    416 fi
    417 
    418 #
    419 # We tell smf this service is online if any of the following is true:
    420 # - no interfaces were configured for plumbing and no DHCP failures
    421 # - any non-loopback IPv4 interfaces are up and have a non-zero address
    422 # - there are any DHCP interfaces started
    423 # - any non-loopback IPv6 interfaces are up
    424 #
    425 # If we weren't asked to configure any interfaces, exit
    426 if [ -z "$inet_list" ] && [ -z "$inet6_list" ]; then
    427 	# Config error if DHCP was attempted without plumbed interfaces
    428 	[ -n "$i4d_fail" ] && exit $SMF_EXIT_ERR_CONFIG
    429 	exit $SMF_EXIT_OK
    430 fi
    431 
    432 # Any non-loopback IPv4 interfaces with usable addresses up?
    433 if [ -n "`/sbin/ifconfig -a4u`" ]; then
    434     	/sbin/ifconfig -a4u | while read intf addr rest; do
    435 		[ $intf = inet ] && [ $addr != 127.0.0.1 ] &&
    436 		[ $addr != 0.0.0.0 ] && exit $SMF_EXIT_OK
    437 	done && exit $SMF_EXIT_OK
    438 fi
    439 
    440 # Any DHCP interfaces started?
    441 [ -n "`/sbin/ifconfig -a4 dhcp status 2>/dev/null`" ] && exit $SMF_EXIT_OK
    442 
    443 # Any non-loopback IPv6 interfaces up?
    444 if [ -n "`/sbin/ifconfig -au6`" ]; then
    445 	/sbin/ifconfig -au6 | while read intf addr rest; do
    446 		[ $intf = inet6 ] && [ $addr != ::1/128 ] && exit $SMF_EXIT_OK
    447 	done && exit $SMF_EXIT_OK
    448 fi
    449 
    450 # This service was supposed to configure something yet didn't.  Exit
    451 # with config error.
    452 exit $SMF_EXIT_ERR_CONFIG
    453