xref: /onnv-gate/usr/src/cmd/svc/shell/net_include.sh (revision 9682:6573382ca7cc)
10Sstevel@tonic-gate#!/bin/sh
20Sstevel@tonic-gate#
30Sstevel@tonic-gate# CDDL HEADER START
40Sstevel@tonic-gate#
50Sstevel@tonic-gate# The contents of this file are subject to the terms of the
64121Samaguire# Common Development and Distribution License (the "License").
74121Samaguire# You may not use this file except in compliance with the License.
80Sstevel@tonic-gate#
90Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate# See the License for the specific language governing permissions
120Sstevel@tonic-gate# and limitations under the License.
130Sstevel@tonic-gate#
140Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate#
200Sstevel@tonic-gate# CDDL HEADER END
210Sstevel@tonic-gate#
220Sstevel@tonic-gate#
238485SPeter.Memishian@Sun.COM# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate# Use is subject to license terms.
250Sstevel@tonic-gate#
260Sstevel@tonic-gate# Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T.
270Sstevel@tonic-gate# All rights reserved.
280Sstevel@tonic-gate#
290Sstevel@tonic-gate
308485SPeter.Memishian@Sun.COM# Print warnings to console
318485SPeter.Memishian@Sun.COMwarn_failed_ifs() {
328485SPeter.Memishian@Sun.COM	echo "Failed to $1 interface(s):$2" >/dev/msglog
338485SPeter.Memishian@Sun.COM}
348485SPeter.Memishian@Sun.COM
350Sstevel@tonic-gate#
360Sstevel@tonic-gate# shcat file
370Sstevel@tonic-gate#   Simulates cat in sh so it doesn't need to be on the root filesystem.
380Sstevel@tonic-gate#
390Sstevel@tonic-gateshcat() {
400Sstevel@tonic-gate        while [ $# -ge 1 ]; do
410Sstevel@tonic-gate                while read i; do
420Sstevel@tonic-gate                        echo "$i"
430Sstevel@tonic-gate                done < $1
440Sstevel@tonic-gate                shift
450Sstevel@tonic-gate        done
460Sstevel@tonic-gate}
470Sstevel@tonic-gate
480Sstevel@tonic-gate#
498485SPeter.Memishian@Sun.COM# inet_list	list of IPv4 interfaces.
508485SPeter.Memishian@Sun.COM# inet6_list	list of IPv6 interfaces.
518485SPeter.Memishian@Sun.COM# ipmp_list	list of IPMP IPv4 interfaces.
528485SPeter.Memishian@Sun.COM# ipmp6_list	list of IPMP IPv6 interfaces.
538485SPeter.Memishian@Sun.COM# inet_plumbed	list of plumbed IPv4 interfaces.
548485SPeter.Memishian@Sun.COM# inet6_plumbed list of plumbed IPv6 interfaces.
558485SPeter.Memishian@Sun.COM# ipmp_created 	list of created IPMP IPv4 interfaces.
568485SPeter.Memishian@Sun.COM# ipmp6_created	list of created IPMP IPv6 interfaces.
578485SPeter.Memishian@Sun.COM# inet_failed	list of IPv4 interfaces that failed to plumb.
588485SPeter.Memishian@Sun.COM# inet6_failed	list of IPv6 interfaces that failed to plumb.
598485SPeter.Memishian@Sun.COM# ipmp_failed 	list of IPMP IPv4 interfaces that failed to be created.
608485SPeter.Memishian@Sun.COM# ipmp6_failed	list of IPMP IPv6 interfaces that failed to be created.
610Sstevel@tonic-gate#
620Sstevel@tonic-gateunset inet_list inet_plumbed inet_failed \
638485SPeter.Memishian@Sun.COM	inet6_list inet6_plumbed inet6_failed \
648485SPeter.Memishian@Sun.COM	ipmp_list ipmp_created ipmp_failed \
658485SPeter.Memishian@Sun.COM	ipmp6_list ipmp6_created ipmp6_failed
668485SPeter.Memishian@Sun.COM
670Sstevel@tonic-gate#
680Sstevel@tonic-gate# get_physical interface
690Sstevel@tonic-gate#
708485SPeter.Memishian@Sun.COM# Return physical interface corresponding to the given interface.
710Sstevel@tonic-gate#
720Sstevel@tonic-gateget_physical()
730Sstevel@tonic-gate{
740Sstevel@tonic-gate	ORIGIFS="$IFS"
750Sstevel@tonic-gate	IFS="${IFS}:"
760Sstevel@tonic-gate	set -- $1
770Sstevel@tonic-gate	IFS="$ORIGIFS"
780Sstevel@tonic-gate
790Sstevel@tonic-gate	echo $1
800Sstevel@tonic-gate}
810Sstevel@tonic-gate
820Sstevel@tonic-gate#
830Sstevel@tonic-gate# get_logical interface
840Sstevel@tonic-gate#
850Sstevel@tonic-gate# Return logical interface number.  Zero will be returned
868485SPeter.Memishian@Sun.COM# if there is no explicit logical number.
870Sstevel@tonic-gate#
880Sstevel@tonic-gateget_logical()
890Sstevel@tonic-gate{
900Sstevel@tonic-gate	ORIGIFS="$IFS"
910Sstevel@tonic-gate	IFS="${IFS}:"
920Sstevel@tonic-gate	set -- $1
930Sstevel@tonic-gate	IFS="$ORIGIFS"
940Sstevel@tonic-gate
950Sstevel@tonic-gate	if [ -z "$2" ]; then
960Sstevel@tonic-gate		echo 0
970Sstevel@tonic-gate	else
980Sstevel@tonic-gate		echo $2
990Sstevel@tonic-gate	fi
1000Sstevel@tonic-gate}
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate#
1030Sstevel@tonic-gate# if_comp if1 if2
1040Sstevel@tonic-gate#
1058485SPeter.Memishian@Sun.COM# Compare interfaces.  Do the physical interface names and logical interface
1060Sstevel@tonic-gate# numbers match?
1070Sstevel@tonic-gate#
1080Sstevel@tonic-gateif_comp()
1090Sstevel@tonic-gate{
1108485SPeter.Memishian@Sun.COM	physical_comp $1 $2 && [ `get_logical $1` -eq `get_logical $2` ]
1110Sstevel@tonic-gate}
1128485SPeter.Memishian@Sun.COM
1130Sstevel@tonic-gate#
1140Sstevel@tonic-gate# physical_comp if1 if2
1150Sstevel@tonic-gate#
1168485SPeter.Memishian@Sun.COM# Do the two interfaces share a physical interface?
1170Sstevel@tonic-gate#
1180Sstevel@tonic-gatephysical_comp()
1190Sstevel@tonic-gate{
1200Sstevel@tonic-gate	[ "`get_physical $1`" = "`get_physical $2`" ]
1210Sstevel@tonic-gate}
1220Sstevel@tonic-gate
1230Sstevel@tonic-gate#
1240Sstevel@tonic-gate# in_list op item list
1250Sstevel@tonic-gate#
1260Sstevel@tonic-gate# Is "item" in the given list?  Use "op" to do the test, applying it to
1270Sstevel@tonic-gate# "item" and each member of the list in turn until it returns success.
1280Sstevel@tonic-gate#
1290Sstevel@tonic-gatein_list()
1300Sstevel@tonic-gate{
1310Sstevel@tonic-gate	op=$1
1320Sstevel@tonic-gate	item=$2
1330Sstevel@tonic-gate	shift 2
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate	while [ $# -gt 0 ]; do
1360Sstevel@tonic-gate		$op $item $1 && return 0
1370Sstevel@tonic-gate		shift
1380Sstevel@tonic-gate	done
1390Sstevel@tonic-gate
1400Sstevel@tonic-gate	return 1
1410Sstevel@tonic-gate}
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate#
1448485SPeter.Memishian@Sun.COM# get_inactive_ifname groupname
1458485SPeter.Memishian@Sun.COM#
1468485SPeter.Memishian@Sun.COM# Return the name of an inactive interface in `groupname', if one exists.
1478485SPeter.Memishian@Sun.COM#
1488485SPeter.Memishian@Sun.COMget_inactive_ifname()
1498485SPeter.Memishian@Sun.COM{
1508485SPeter.Memishian@Sun.COM	ORIGIFS="$IFS"
1518485SPeter.Memishian@Sun.COM	/sbin/ipmpstat -gP -o groupname,interfaces |
1528485SPeter.Memishian@Sun.COM	while IFS=: read groupname ifnames; do
1538485SPeter.Memishian@Sun.COM		#
1548485SPeter.Memishian@Sun.COM		# Skip other IPMP groups.
1558485SPeter.Memishian@Sun.COM	        #
1568485SPeter.Memishian@Sun.COM		[ "$groupname" != "$1" ] && continue
1578485SPeter.Memishian@Sun.COM
1588485SPeter.Memishian@Sun.COM		#
1598485SPeter.Memishian@Sun.COM		# Standby interfaces are always enclosed in ()'s, so look
1608485SPeter.Memishian@Sun.COM		# for the first interface name starting with a "(", and
1618485SPeter.Memishian@Sun.COM		# strip those off.
1628485SPeter.Memishian@Sun.COM		#
1638485SPeter.Memishian@Sun.COM		IFS=" "
1648485SPeter.Memishian@Sun.COM		for ifname in $ifnames; do
1658485SPeter.Memishian@Sun.COM			case "$ifname" in
1668485SPeter.Memishian@Sun.COM			'('*)	IFS="()"
1678485SPeter.Memishian@Sun.COM				echo $ifname
1688485SPeter.Memishian@Sun.COM				IFS="$ORIGIFS"
1698485SPeter.Memishian@Sun.COM				return
1708485SPeter.Memishian@Sun.COM				;;
1718485SPeter.Memishian@Sun.COM			*)	;;
1728485SPeter.Memishian@Sun.COM			esac
1738485SPeter.Memishian@Sun.COM		done
1748485SPeter.Memishian@Sun.COM	done
1758485SPeter.Memishian@Sun.COM	IFS="$ORIGIFS"
1768485SPeter.Memishian@Sun.COM}
1778485SPeter.Memishian@Sun.COM
1788485SPeter.Memishian@Sun.COM#
1798485SPeter.Memishian@Sun.COM# get_groupifname groupname
1808485SPeter.Memishian@Sun.COM#
1818485SPeter.Memishian@Sun.COM# Return the IPMP meta-interface name for the group, if it exists.
1820Sstevel@tonic-gate#
1838485SPeter.Memishian@Sun.COMget_groupifname()
1848485SPeter.Memishian@Sun.COM{
1858485SPeter.Memishian@Sun.COM	/sbin/ipmpstat -gP -o groupname,group | while IFS=: read name ifname; do
1868485SPeter.Memishian@Sun.COM		if [ "$name" = "$1" ]; then
1878485SPeter.Memishian@Sun.COM			echo "$ifname"
1888485SPeter.Memishian@Sun.COM			return
1898485SPeter.Memishian@Sun.COM		fi
1908485SPeter.Memishian@Sun.COM	done
1918485SPeter.Memishian@Sun.COM}
1928485SPeter.Memishian@Sun.COM
1938485SPeter.Memishian@Sun.COM#
1948485SPeter.Memishian@Sun.COM# create_ipmp ifname groupname type
1958485SPeter.Memishian@Sun.COM#
1968485SPeter.Memishian@Sun.COM# Helper function for create_groupifname() that returns zero if it's able
1978485SPeter.Memishian@Sun.COM# to create an IPMP interface of the specified type and place it in the
1988485SPeter.Memishian@Sun.COM# specified group, or non-zero otherwise.
1998485SPeter.Memishian@Sun.COM#
2008485SPeter.Memishian@Sun.COMcreate_ipmp()
2018485SPeter.Memishian@Sun.COM{
2028485SPeter.Memishian@Sun.COM	/sbin/ifconfig $1 >/dev/null 2>&1 && return 1
2038485SPeter.Memishian@Sun.COM	/sbin/ifconfig $1 inet6 >/dev/null 2>&1 && return 1
2048485SPeter.Memishian@Sun.COM	/sbin/ifconfig $1 $3 ipmp group $2 2>/dev/null
2058485SPeter.Memishian@Sun.COM}
2068485SPeter.Memishian@Sun.COM
2078485SPeter.Memishian@Sun.COM#
2088485SPeter.Memishian@Sun.COM# create_groupifname groupname type
2098485SPeter.Memishian@Sun.COM#
2108485SPeter.Memishian@Sun.COM# Create an IPMP meta-interface name for the group.  We only use this
2118485SPeter.Memishian@Sun.COM# function if all of the interfaces in the group failed at boot and there
2128485SPeter.Memishian@Sun.COM# were no /etc/hostname[6].<if> files for the IPMP meta-interface.
2138485SPeter.Memishian@Sun.COM#
2148485SPeter.Memishian@Sun.COMcreate_groupifname()
2158485SPeter.Memishian@Sun.COM{
2168485SPeter.Memishian@Sun.COM	#
2178485SPeter.Memishian@Sun.COM	# This is a horrible way to count from 0 to 999, but in sh and
2188485SPeter.Memishian@Sun.COM	# without necessarily having /usr mounted, what else can we do?
2198485SPeter.Memishian@Sun.COM	#
2208485SPeter.Memishian@Sun.COM	for a in "" 1 2 3 4 5 6 7 8 9; do
2218485SPeter.Memishian@Sun.COM		for b in 0 1 2 3 4 5 6 7 8 9; do
2228485SPeter.Memishian@Sun.COM			for c in 0 1 2 3 4 5 6 7 8 9; do
2238485SPeter.Memishian@Sun.COM				# strip leading zeroes
2248485SPeter.Memishian@Sun.COM				[ "$a" = "" ] && [ "$b" = 0 ] && b=""
2258485SPeter.Memishian@Sun.COM				if create_ipmp ipmp$a$b$c $1 $2; then
2268485SPeter.Memishian@Sun.COM					echo ipmp$a$b$c
2278485SPeter.Memishian@Sun.COM					return
2288485SPeter.Memishian@Sun.COM				fi
2298485SPeter.Memishian@Sun.COM			done
2308485SPeter.Memishian@Sun.COM		done
2318485SPeter.Memishian@Sun.COM	done
2328485SPeter.Memishian@Sun.COM}
2338485SPeter.Memishian@Sun.COM
2348485SPeter.Memishian@Sun.COM#
2358485SPeter.Memishian@Sun.COM# get_hostname_ipmpinfo interface type
2368485SPeter.Memishian@Sun.COM#
2378485SPeter.Memishian@Sun.COM# Return all requested IPMP keywords from hostname file for a given interface.
2380Sstevel@tonic-gate#
2390Sstevel@tonic-gate# Example:
2408485SPeter.Memishian@Sun.COM#	get_hostname_ipmpinfo hme0 inet keyword [ keyword ... ]
2410Sstevel@tonic-gate#
2428485SPeter.Memishian@Sun.COMget_hostname_ipmpinfo()
2430Sstevel@tonic-gate{
2440Sstevel@tonic-gate	case "$2" in
2458485SPeter.Memishian@Sun.COM		inet)	file=/etc/hostname.$1
2460Sstevel@tonic-gate			;;
2478485SPeter.Memishian@Sun.COM		inet6)	file=/etc/hostname6.$1
2480Sstevel@tonic-gate			;;
2490Sstevel@tonic-gate		*)
2500Sstevel@tonic-gate			return
2510Sstevel@tonic-gate			;;
2520Sstevel@tonic-gate	esac
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate	[ -r "$file" ] || return
2550Sstevel@tonic-gate
2568485SPeter.Memishian@Sun.COM	type=$2
2578485SPeter.Memishian@Sun.COM	shift 2
2588485SPeter.Memishian@Sun.COM
2590Sstevel@tonic-gate	#
2608485SPeter.Memishian@Sun.COM	# Read through the hostname file looking for the specified
2618485SPeter.Memishian@Sun.COM	# keywords.  Since there may be several keywords that cancel
2628485SPeter.Memishian@Sun.COM	# each other out, the caller must post-process as appropriate.
2630Sstevel@tonic-gate	#
2640Sstevel@tonic-gate	while read line; do
2650Sstevel@tonic-gate		[ -z "$line" ] && continue
2668485SPeter.Memishian@Sun.COM		/sbin/ifparse -s "$type" $line
2678485SPeter.Memishian@Sun.COM	done < "$file" | while read one two; do
2688485SPeter.Memishian@Sun.COM		for keyword in "$@"; do
2698485SPeter.Memishian@Sun.COM			[ "$one" = "$keyword" ] && echo "$one $two"
2708485SPeter.Memishian@Sun.COM		done
2710Sstevel@tonic-gate	done
2720Sstevel@tonic-gate}
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate#
2750Sstevel@tonic-gate# get_group_for_type interface type list
2760Sstevel@tonic-gate#
2770Sstevel@tonic-gate# Look through the set of hostname files associated with the same physical
2780Sstevel@tonic-gate# interface as "interface", and determine which group they would configure.
2790Sstevel@tonic-gate# Only hostname files associated with the physical interface or logical
2800Sstevel@tonic-gate# interface zero are allowed to set the group.
2810Sstevel@tonic-gate#
2820Sstevel@tonic-gateget_group_for_type()
2830Sstevel@tonic-gate{
2840Sstevel@tonic-gate	physical=`get_physical $1`
2850Sstevel@tonic-gate	type=$2
2860Sstevel@tonic-gate	group=""
2870Sstevel@tonic-gate
2880Sstevel@tonic-gate	#
2890Sstevel@tonic-gate	# The last setting of the group is the one that counts, which is
2900Sstevel@tonic-gate	# the reason for the second while loop.
2910Sstevel@tonic-gate	#
2920Sstevel@tonic-gate	shift 2
2938485SPeter.Memishian@Sun.COM	for ifname in "$@"; do
2948485SPeter.Memishian@Sun.COM		if if_comp "$physical" $ifname; then
2958485SPeter.Memishian@Sun.COM			get_hostname_ipmpinfo $ifname $type group
2960Sstevel@tonic-gate		fi
2970Sstevel@tonic-gate	done | while :; do
2988485SPeter.Memishian@Sun.COM		read keyword grname || {
2990Sstevel@tonic-gate			echo "$group"
3000Sstevel@tonic-gate			break
3010Sstevel@tonic-gate		}
3028485SPeter.Memishian@Sun.COM		group="$grname"
3030Sstevel@tonic-gate	done
3040Sstevel@tonic-gate}
3050Sstevel@tonic-gate
3060Sstevel@tonic-gate#
3078485SPeter.Memishian@Sun.COM# get_standby_for_type interface type list
3080Sstevel@tonic-gate#
3098485SPeter.Memishian@Sun.COM# Look through the set of hostname files associated with the same physical
3108485SPeter.Memishian@Sun.COM# interface as "interface", and print the standby value ("standby",
3118485SPeter.Memishian@Sun.COM# "-standby", or nothing).  Only hostname files associated with the
3128485SPeter.Memishian@Sun.COM# physical interface or logical interface zero can set this flag.
3130Sstevel@tonic-gate#
3148485SPeter.Memishian@Sun.COMget_standby_for_type()
3150Sstevel@tonic-gate{
3168485SPeter.Memishian@Sun.COM	physical=`get_physical $1`
3178485SPeter.Memishian@Sun.COM	type=$2
3180Sstevel@tonic-gate
3198485SPeter.Memishian@Sun.COM	#
3208485SPeter.Memishian@Sun.COM	# The last setting of "standby" or "-standby" is the one that
3218485SPeter.Memishian@Sun.COM	# counts, which is the reason for the second while loop.
3228485SPeter.Memishian@Sun.COM	#
3238485SPeter.Memishian@Sun.COM	shift 2
3248485SPeter.Memishian@Sun.COM	for ifname in "$@"; do
3258485SPeter.Memishian@Sun.COM		if if_comp "$physical" $ifname; then
3268485SPeter.Memishian@Sun.COM			get_hostname_ipmpinfo $ifname $type standby -standby
3270Sstevel@tonic-gate		fi
3288485SPeter.Memishian@Sun.COM	done | while :; do
3298485SPeter.Memishian@Sun.COM		read keyword || {
3308485SPeter.Memishian@Sun.COM		    	echo "$iftype"
3318485SPeter.Memishian@Sun.COM			break
3328485SPeter.Memishian@Sun.COM		}
3338485SPeter.Memishian@Sun.COM		iftype="$keyword"
3348485SPeter.Memishian@Sun.COM	done
3350Sstevel@tonic-gate}
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate#
3388485SPeter.Memishian@Sun.COM# get_group interface
3390Sstevel@tonic-gate#
3408485SPeter.Memishian@Sun.COM# If there is both an inet and inet6 version of an interface, the group
3418485SPeter.Memishian@Sun.COM# could be set in either set of hostname files.  Since inet6 is configured
3428485SPeter.Memishian@Sun.COM# after inet, if there's a setting in both files, inet6 wins.
3430Sstevel@tonic-gate#
3448485SPeter.Memishian@Sun.COMget_group()
3450Sstevel@tonic-gate{
3468485SPeter.Memishian@Sun.COM	group=`get_group_for_type $1 inet6 $inet6_list`
3478485SPeter.Memishian@Sun.COM	[ -z "$group" ] && group=`get_group_for_type $1 inet $inet_list`
3488485SPeter.Memishian@Sun.COM	echo $group
3490Sstevel@tonic-gate}
3500Sstevel@tonic-gate
3510Sstevel@tonic-gate#
3520Sstevel@tonic-gate# is_standby interface
3530Sstevel@tonic-gate#
3548485SPeter.Memishian@Sun.COM# If there is both an inet and inet6 version of an interface, the
3558485SPeter.Memishian@Sun.COM# "standby" or "-standby" flag could be set in either set of hostname
3568485SPeter.Memishian@Sun.COM# files.  Since inet6 is configured after inet, if there's a setting in
3578485SPeter.Memishian@Sun.COM# both files, inet6 wins.
3580Sstevel@tonic-gate#
3590Sstevel@tonic-gateis_standby()
3600Sstevel@tonic-gate{
3618485SPeter.Memishian@Sun.COM	standby=`get_standby_for_type $1 inet6 $inet6_list`
3628485SPeter.Memishian@Sun.COM	[ -z "$standby" ] && standby=`get_standby_for_type $1 inet $inet_list`
3630Sstevel@tonic-gate	[ "$standby" = "standby" ]
3640Sstevel@tonic-gate}
3650Sstevel@tonic-gate
3660Sstevel@tonic-gate#
3670Sstevel@tonic-gate# doDHCPhostname interface
3680Sstevel@tonic-gate# Pass to this function the name of an interface.  It will return
3690Sstevel@tonic-gate# true if one should enable the use of DHCP client-side host name
3700Sstevel@tonic-gate# requests on the interface, and false otherwise.
3710Sstevel@tonic-gate#
3720Sstevel@tonic-gatedoDHCPhostname()
3730Sstevel@tonic-gate{
3740Sstevel@tonic-gate	if [ -f /etc/dhcp.$1 ] && [ -f /etc/hostname.$1 ]; then
3750Sstevel@tonic-gate                set -- `shcat /etc/hostname.$1`
3760Sstevel@tonic-gate                [ $# -eq 2 -a "$1" = "inet" ]
3770Sstevel@tonic-gate                return $?
3780Sstevel@tonic-gate        fi
3790Sstevel@tonic-gate        return 1
3800Sstevel@tonic-gate}
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate#
3830Sstevel@tonic-gate# inet_process_hostname processor [ args ]
3840Sstevel@tonic-gate#
3850Sstevel@tonic-gate# Process an inet hostname file.  The contents of the file
3860Sstevel@tonic-gate# are taken from standard input. Each line is passed
3870Sstevel@tonic-gate# on the command line to the "processor" command.
3880Sstevel@tonic-gate# Command line arguments can be passed to the processor.
3890Sstevel@tonic-gate#
3900Sstevel@tonic-gate# Examples:
3910Sstevel@tonic-gate#	inet_process_hostname /sbin/ifconfig hme0 < /etc/hostname.hme0
3920Sstevel@tonic-gate#
3930Sstevel@tonic-gate#	inet_process_hostname /sbin/ifparse -f < /etc/hostname.hme0
3940Sstevel@tonic-gate#
3950Sstevel@tonic-gate# If there is only line in an hostname file we assume it contains
3960Sstevel@tonic-gate# the old style address which results in the interface being brought up
3978485SPeter.Memishian@Sun.COM# and the netmask and broadcast address being set ($inet_oneline_epilogue).
3980Sstevel@tonic-gate#
3990Sstevel@tonic-gate# If there are multiple lines we assume the file contains a list of
4000Sstevel@tonic-gate# commands to the processor with neither the implied bringing up of the
4010Sstevel@tonic-gate# interface nor the setting of the default netmask and broadcast address.
4020Sstevel@tonic-gate#
4030Sstevel@tonic-gate# Return non-zero if any command fails so that the caller may alert
4040Sstevel@tonic-gate# users to errors in the configuration.
4050Sstevel@tonic-gate#
4068485SPeter.Memishian@Sun.COMinet_oneline_epilogue="netmask + broadcast + up"
4078485SPeter.Memishian@Sun.COM
4080Sstevel@tonic-gateinet_process_hostname()
4090Sstevel@tonic-gate{
4100Sstevel@tonic-gate	if doDHCPhostname $2; then
4110Sstevel@tonic-gate		:
4120Sstevel@tonic-gate	else
4130Sstevel@tonic-gate		#
4140Sstevel@tonic-gate		# Redirecting input from a file results in a sub-shell being
4150Sstevel@tonic-gate		# used, hence this outer loop surrounding the "multiple_lines"
4160Sstevel@tonic-gate		# and "ifcmds" variables.
4170Sstevel@tonic-gate		#
4180Sstevel@tonic-gate		while :; do
4190Sstevel@tonic-gate			multiple_lines=false
4200Sstevel@tonic-gate			ifcmds=""
4210Sstevel@tonic-gate			retval=0
4220Sstevel@tonic-gate
4238485SPeter.Memishian@Sun.COM			while read one rest; do
4240Sstevel@tonic-gate				if [ -n "$ifcmds" ]; then
4250Sstevel@tonic-gate					#
4260Sstevel@tonic-gate					# This handles the first N-1
4270Sstevel@tonic-gate					# lines of a N-line hostname file.
4280Sstevel@tonic-gate					#
4290Sstevel@tonic-gate					$* $ifcmds || retval=$?
4300Sstevel@tonic-gate					multiple_lines=true
4310Sstevel@tonic-gate				fi
4328485SPeter.Memishian@Sun.COM
4338485SPeter.Memishian@Sun.COM				#
4348485SPeter.Memishian@Sun.COM				# Strip out the "ipmp" keyword if it's the
4358485SPeter.Memishian@Sun.COM				# first token, since it's used to control
4368485SPeter.Memishian@Sun.COM				# interface creation, not configuration.
4378485SPeter.Memishian@Sun.COM				#
4388485SPeter.Memishian@Sun.COM				[ "$one" = ipmp ] && one=
4398485SPeter.Memishian@Sun.COM				ifcmds="$one $rest"
4400Sstevel@tonic-gate			done
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate			#
4430Sstevel@tonic-gate			# If the hostname file is empty or consists of only
4440Sstevel@tonic-gate			# blank lines, break out of the outer loop without
4450Sstevel@tonic-gate			# configuring the newly plumbed interface.
4460Sstevel@tonic-gate			#
4470Sstevel@tonic-gate			[ -z "$ifcmds" ] && return $retval
4480Sstevel@tonic-gate			if [ $multiple_lines = false ]; then
4498485SPeter.Memishian@Sun.COM				# The traditional one-line hostname file.
4508485SPeter.Memishian@Sun.COM				ifcmds="$ifcmds $inet_oneline_epilogue"
4510Sstevel@tonic-gate			fi
4520Sstevel@tonic-gate
4530Sstevel@tonic-gate			#
4540Sstevel@tonic-gate			# This handles either the single-line case or
4550Sstevel@tonic-gate			# the last line of the N-line case.
4560Sstevel@tonic-gate			#
4570Sstevel@tonic-gate			$* $ifcmds || return $?
4580Sstevel@tonic-gate			return $retval
4590Sstevel@tonic-gate		done
4600Sstevel@tonic-gate	fi
4610Sstevel@tonic-gate}
4620Sstevel@tonic-gate
4630Sstevel@tonic-gate#
4640Sstevel@tonic-gate# inet6_process_hostname processor [ args ]
4650Sstevel@tonic-gate#
4660Sstevel@tonic-gate# Process an inet6 hostname file.  The contents of the file
4670Sstevel@tonic-gate# are taken from standard input. Each line is passed
4680Sstevel@tonic-gate# on the command line to the "processor" command.
4690Sstevel@tonic-gate# Command line arguments can be passed to the processor.
4700Sstevel@tonic-gate#
4710Sstevel@tonic-gate# Examples:
4720Sstevel@tonic-gate#	inet6_process_hostname /sbin/ifconfig hme0 inet6 < /etc/hostname6.hme0
4730Sstevel@tonic-gate#
4740Sstevel@tonic-gate#	inet6_process_hostname /sbin/ifparse -f inet6 < /etc/hostname6.hme0
4750Sstevel@tonic-gate#
4760Sstevel@tonic-gate# Return non-zero if any of the commands fail so that the caller may alert
4770Sstevel@tonic-gate# users to errors in the configuration.
4780Sstevel@tonic-gate#
4790Sstevel@tonic-gateinet6_process_hostname()
4800Sstevel@tonic-gate{
4810Sstevel@tonic-gate    	retval=0
4828485SPeter.Memishian@Sun.COM	while read one rest; do
4838485SPeter.Memishian@Sun.COM		#
4848485SPeter.Memishian@Sun.COM	    	# See comment in inet_process_hostname for details.
4858485SPeter.Memishian@Sun.COM	        #
4868485SPeter.Memishian@Sun.COM		[ "$one" = ipmp ] && one=
4878485SPeter.Memishian@Sun.COM		ifcmds="$one $rest"
4888485SPeter.Memishian@Sun.COM
4890Sstevel@tonic-gate		if [ -n "$ifcmds" ]; then
4900Sstevel@tonic-gate			$* $ifcmds || retval=$?
4910Sstevel@tonic-gate		fi
4920Sstevel@tonic-gate	done
4930Sstevel@tonic-gate	return $retval
4940Sstevel@tonic-gate}
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate#
4978485SPeter.Memishian@Sun.COM# Process interfaces that failed to plumb.  Find the IPMP meta-interface
4988485SPeter.Memishian@Sun.COM# that should host the addresses.  For IPv6, only static addresses defined
4998485SPeter.Memishian@Sun.COM# in hostname6 files are moved, autoconfigured addresses are not moved.
5000Sstevel@tonic-gate#
5010Sstevel@tonic-gate# Example:
5020Sstevel@tonic-gate#	move_addresses inet6
5030Sstevel@tonic-gate#
5040Sstevel@tonic-gatemove_addresses()
5050Sstevel@tonic-gate{
5060Sstevel@tonic-gate	type="$1"
5070Sstevel@tonic-gate	eval "failed=\"\$${type}_failed\""
5080Sstevel@tonic-gate	eval "list=\"\$${type}_list\""
5098485SPeter.Memishian@Sun.COM	process_func="${type}_process_hostname"
5100Sstevel@tonic-gate	processed=""
5110Sstevel@tonic-gate
5120Sstevel@tonic-gate	if [ "$type" = inet ]; then
5138485SPeter.Memishian@Sun.COM	        typedesc="IPv4"
5140Sstevel@tonic-gate		zaddr="0.0.0.0"
5150Sstevel@tonic-gate		hostpfx="/etc/hostname"
5160Sstevel@tonic-gate	else
5178485SPeter.Memishian@Sun.COM	        typedesc="IPv6"
5180Sstevel@tonic-gate		zaddr="::"
5190Sstevel@tonic-gate		hostpfx="/etc/hostname6"
5200Sstevel@tonic-gate	fi
5210Sstevel@tonic-gate
5228485SPeter.Memishian@Sun.COM	echo "Moving addresses from missing ${typedesc} interface(s):\c" \
5238485SPeter.Memishian@Sun.COM	    >/dev/msglog
5248485SPeter.Memishian@Sun.COM
5258485SPeter.Memishian@Sun.COM	for ifname in $failed; do
5268485SPeter.Memishian@Sun.COM		in_list if_comp $ifname $processed && continue
5270Sstevel@tonic-gate
5288485SPeter.Memishian@Sun.COM		group=`get_group $ifname`
5298485SPeter.Memishian@Sun.COM		if [ -z "$group" ]; then
5308485SPeter.Memishian@Sun.COM			in_list physical_comp $ifname $processed || {
5318485SPeter.Memishian@Sun.COM				echo " $ifname (not moved -- not" \
5328485SPeter.Memishian@Sun.COM				    "in an IPMP group)\c" >/dev/msglog
5338485SPeter.Memishian@Sun.COM				processed="$processed $ifname"
5340Sstevel@tonic-gate			}
5350Sstevel@tonic-gate			continue
5360Sstevel@tonic-gate		fi
5378485SPeter.Memishian@Sun.COM
5388485SPeter.Memishian@Sun.COM		#
5398485SPeter.Memishian@Sun.COM		# Lookup the IPMP meta-interface name.  If one doesn't exist,
5408485SPeter.Memishian@Sun.COM		# create it.
5418485SPeter.Memishian@Sun.COM		#
5428485SPeter.Memishian@Sun.COM		grifname=`get_groupifname $group`
5438485SPeter.Memishian@Sun.COM		[ -z "$grifname" ] && grifname=`create_groupifname $group $type`
5448485SPeter.Memishian@Sun.COM
5450Sstevel@tonic-gate		#
5460Sstevel@tonic-gate		# The hostname files are processed twice.  In the first
5470Sstevel@tonic-gate		# pass, we are looking for all commands that apply
5480Sstevel@tonic-gate		# to the non-additional interface address.  These may be
5490Sstevel@tonic-gate		# scattered over several files.  We won't know
5500Sstevel@tonic-gate		# whether the address represents a failover address
5510Sstevel@tonic-gate		# or not until we've read all the files associated with the
5520Sstevel@tonic-gate		# interface.
5538485SPeter.Memishian@Sun.COM		#
5540Sstevel@tonic-gate		# In the first pass through the hostname files, all
5550Sstevel@tonic-gate		# additional logical interface commands are removed.
5560Sstevel@tonic-gate		# The remaining commands are concatenated together and
5570Sstevel@tonic-gate		# passed to ifparse to determine whether the
5580Sstevel@tonic-gate		# non-additional logical interface address is a failover
5590Sstevel@tonic-gate		# address.  If it as a failover address, the
5600Sstevel@tonic-gate		# address may not be the first item on the line,
5610Sstevel@tonic-gate		# so we can't just substitute "addif" for "set".
5620Sstevel@tonic-gate		# We prepend an "addif $zaddr" command, and let
5630Sstevel@tonic-gate		# the embedded "set" command set the address later.
5640Sstevel@tonic-gate		#
5650Sstevel@tonic-gate		/sbin/ifparse -f $type `
5668485SPeter.Memishian@Sun.COM			for item in $list; do
5678485SPeter.Memishian@Sun.COM				if_comp $ifname $item && $process_func \
5688485SPeter.Memishian@Sun.COM				    /sbin/ifparse $type < $hostpfx.$item
5698485SPeter.Memishian@Sun.COM			done | while read three four; do
5708485SPeter.Memishian@Sun.COM				[ "$three" != addif ] && echo "$three $four \c"
5718485SPeter.Memishian@Sun.COM			done` | while read one two; do
5728485SPeter.Memishian@Sun.COM				[ -z "$one" ] && continue
5738485SPeter.Memishian@Sun.COM				[ "$one $two" = "$inet_oneline_epilogue" ] && \
5748485SPeter.Memishian@Sun.COM				    continue
5758485SPeter.Memishian@Sun.COM				line="addif $zaddr $one $two"
5768485SPeter.Memishian@Sun.COM				/sbin/ifconfig $grifname $type $line >/dev/null
5778485SPeter.Memishian@Sun.COM			done
5780Sstevel@tonic-gate
5790Sstevel@tonic-gate		#
5800Sstevel@tonic-gate		# In the second pass, look for the the "addif" commands
5810Sstevel@tonic-gate		# that configure additional failover addresses.  Addif
5820Sstevel@tonic-gate		# commands are not valid in logical interface hostname
5830Sstevel@tonic-gate		# files.
5840Sstevel@tonic-gate		#
5858485SPeter.Memishian@Sun.COM		if [ "$ifname" = "`get_physical $ifname`" ]; then
5868485SPeter.Memishian@Sun.COM			$process_func /sbin/ifparse -f $type < $hostpfx.$ifname \
5878485SPeter.Memishian@Sun.COM			| while read one two; do
5888485SPeter.Memishian@Sun.COM				[ "$one" = addif ] && \
5898485SPeter.Memishian@Sun.COM					/sbin/ifconfig $grifname $type \
5908485SPeter.Memishian@Sun.COM				    	    addif $two >/dev/null
5910Sstevel@tonic-gate			done
5920Sstevel@tonic-gate		fi
5930Sstevel@tonic-gate
5948485SPeter.Memishian@Sun.COM		#
5958485SPeter.Memishian@Sun.COM		# Check if this was an active interface in the group.  If so,
5968485SPeter.Memishian@Sun.COM		# activate another IP interface (if possible)
5978485SPeter.Memishian@Sun.COM		#
5988485SPeter.Memishian@Sun.COM		is_standby $ifname || inactive=`get_inactive_ifname $group`
5998485SPeter.Memishian@Sun.COM		[ -n "$inactive" ] && /sbin/ifconfig $inactive $type -standby
6008485SPeter.Memishian@Sun.COM
6018485SPeter.Memishian@Sun.COM		in_list physical_comp $ifname $processed || {
6028485SPeter.Memishian@Sun.COM			processed="$processed $ifname"
6038485SPeter.Memishian@Sun.COM			echo " $ifname (moved to $grifname\c"	   > /dev/msglog
6048485SPeter.Memishian@Sun.COM			if [ -n "$inactive" ]; then
6058485SPeter.Memishian@Sun.COM				echo " and cleared 'standby' on\c" > /dev/msglog
6068485SPeter.Memishian@Sun.COM				echo " $inactive to compensate\c"  > /dev/msglog
6078485SPeter.Memishian@Sun.COM			fi
6088485SPeter.Memishian@Sun.COM			echo ")\c"				   > /dev/msglog
6090Sstevel@tonic-gate		}
6108485SPeter.Memishian@Sun.COM		inactive=""
6118485SPeter.Memishian@Sun.COM	done
6128485SPeter.Memishian@Sun.COM	echo "." >/dev/msglog
6138485SPeter.Memishian@Sun.COM}
6148485SPeter.Memishian@Sun.COM
6158485SPeter.Memishian@Sun.COM#
6168485SPeter.Memishian@Sun.COM# if_configure type class interface_list
6178485SPeter.Memishian@Sun.COM#
6188485SPeter.Memishian@Sun.COM# Configure all of the interfaces of type `type' (e.g., "inet6") in
6198485SPeter.Memishian@Sun.COM# `interface_list' according to their /etc/hostname[6].* files.  `class'
6208485SPeter.Memishian@Sun.COM# describes the class of interface (e.g., "IPMP"), as a diagnostic aid.
6218485SPeter.Memishian@Sun.COM# For inet6 interfaces, the interface is also brought up.
6228485SPeter.Memishian@Sun.COM#
6238485SPeter.Memishian@Sun.COMif_configure()
6248485SPeter.Memishian@Sun.COM{
6258485SPeter.Memishian@Sun.COM	fail=
6268485SPeter.Memishian@Sun.COM	type=$1
6278485SPeter.Memishian@Sun.COM	class=$2
6288485SPeter.Memishian@Sun.COM	process_func=${type}_process_hostname
6298485SPeter.Memishian@Sun.COM	shift 2
6308485SPeter.Memishian@Sun.COM
6318485SPeter.Memishian@Sun.COM	if [ "$type" = inet ]; then
6328485SPeter.Memishian@Sun.COM	        desc="IPv4"
6338485SPeter.Memishian@Sun.COM		hostpfx="/etc/hostname"
6348485SPeter.Memishian@Sun.COM	else
6358485SPeter.Memishian@Sun.COM	        desc="IPv6"
6368485SPeter.Memishian@Sun.COM		hostpfx="/etc/hostname6"
6378485SPeter.Memishian@Sun.COM	fi
6388485SPeter.Memishian@Sun.COM	[ -n "$class" ] && desc="$class $desc"
6398485SPeter.Memishian@Sun.COM
6408485SPeter.Memishian@Sun.COM	echo "configuring $desc interfaces:\c"
6418485SPeter.Memishian@Sun.COM	while [ $# -gt 0 ]; do
6428485SPeter.Memishian@Sun.COM		$process_func /sbin/ifconfig $1 $type < $hostpfx.$1 >/dev/null
6438485SPeter.Memishian@Sun.COM		if [ $? != 0 ]; then
6448485SPeter.Memishian@Sun.COM			fail="$fail $1"
6458485SPeter.Memishian@Sun.COM		elif [ "$type" = inet6 ]; then
6468485SPeter.Memishian@Sun.COM		    	/sbin/ifconfig $1 inet6 up || fail="$fail $1"
6478485SPeter.Memishian@Sun.COM		fi
6488485SPeter.Memishian@Sun.COM		echo " $1\c"
6490Sstevel@tonic-gate		shift
6500Sstevel@tonic-gate	done
6510Sstevel@tonic-gate	echo "."
6528485SPeter.Memishian@Sun.COM
6538485SPeter.Memishian@Sun.COM	[ -n "$fail" ] && warn_failed_ifs "configure $desc" "$fail"
6540Sstevel@tonic-gate}
6555895Syz147064
6565895Syz147064#
6575895Syz147064# net_reconfigure is called from the network/physical service (by the
6585895Syz147064# net-physical and net-nwam method scripts) to perform tasks that only
6595895Syz147064# need to be done during a reconfigure boot.  This needs to be
6605895Syz147064# isolated in a function since network/physical has two instances
6615895Syz147064# (default and nwam) that have distinct method scripts that each need
6625895Syz147064# to do these things.
6635895Syz147064#
6645895Syz147064net_reconfigure ()
6655895Syz147064{
6665895Syz147064	#
6675895Syz147064	# Is this a reconfigure boot?  If not, then there's nothing
6685895Syz147064	# for us to do.
6695895Syz147064	#
670*9682SCathy.Zhou@Sun.COM	reconfig=`svcprop -c -p system/reconfigure \
671*9682SCathy.Zhou@Sun.COM	    system/svc/restarter:default 2>/dev/null`
6727645Sjames.d.carlson@sun.com	if [ $? -ne 0 -o "$reconfig" = false ]; then
6735895Syz147064		return 0
6745895Syz147064	fi
6755895Syz147064
6765895Syz147064	#
6775895Syz147064	# Ensure that the datalink-management service is running since
6785895Syz147064	# manifest-import has not yet run for a first boot after
6795895Syz147064	# upgrade.  We wouldn't need to do that if manifest-import ran
6805895Syz147064	# earlier in boot, since there is an explicit dependency
6815895Syz147064	# between datalink-management and network/physical.
6825895Syz147064	#
6835895Syz147064	svcadm enable -ts network/datalink-management:default
6845895Syz147064
6855895Syz147064	#
6865895Syz147064	# There is a bug in SMF which causes the svcadm command above
6875895Syz147064	# to exit prematurely (with an error code of 3) before having
6885895Syz147064	# waited for the service to come online after having enabled
6895895Syz147064	# it.  Until that bug is fixed, we need to have the following
6905895Syz147064	# loop to explicitly wait for the service to come online.
6915895Syz147064	#
6925895Syz147064	i=0
6935895Syz147064	while [ $i -lt 30 ]; do
6945895Syz147064		i=`expr $i + 1`
6955895Syz147064		sleep 1
6965895Syz147064		state=`svcprop -p restarter/state \
6975895Syz147064		    network/datalink-management:default 2>/dev/null`
6985895Syz147064		if [ $? -ne 0 ]; then
6995895Syz147064			continue
7005895Syz147064		elif [ "$state" = "online" ]; then
7015895Syz147064			break
7025895Syz147064		fi
7035895Syz147064	done
7045895Syz147064	if [ "$state" != "online" ]; then
7055895Syz147064		echo "The network/datalink-management service \c"
7065895Syz147064		echo "did not come online."
7075895Syz147064		return 1
7085895Syz147064	fi
7095895Syz147064
7105895Syz147064	#
7115895Syz147064	# Initialize the set of physical links, and validate and
7125895Syz147064	# remove all the physical links which were removed during the
7135895Syz147064	# system shutdown.
7145895Syz147064	#
7155895Syz147064	/sbin/dladm init-phys
7165895Syz147064	return 0
7175895Syz147064}
718