1*0Sstevel@tonic-gate#!/bin/sh 2*0Sstevel@tonic-gate# 3*0Sstevel@tonic-gate# CDDL HEADER START 4*0Sstevel@tonic-gate# 5*0Sstevel@tonic-gate# The contents of this file are subject to the terms of the 6*0Sstevel@tonic-gate# Common Development and Distribution License, Version 1.0 only 7*0Sstevel@tonic-gate# (the "License"). You may not use this file except in compliance 8*0Sstevel@tonic-gate# with the License. 9*0Sstevel@tonic-gate# 10*0Sstevel@tonic-gate# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11*0Sstevel@tonic-gate# or http://www.opensolaris.org/os/licensing. 12*0Sstevel@tonic-gate# See the License for the specific language governing permissions 13*0Sstevel@tonic-gate# and limitations under the License. 14*0Sstevel@tonic-gate# 15*0Sstevel@tonic-gate# When distributing Covered Code, include this CDDL HEADER in each 16*0Sstevel@tonic-gate# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17*0Sstevel@tonic-gate# If applicable, add the following below this CDDL HEADER, with the 18*0Sstevel@tonic-gate# fields enclosed by brackets "[]" replaced with your own identifying 19*0Sstevel@tonic-gate# information: Portions Copyright [yyyy] [name of copyright owner] 20*0Sstevel@tonic-gate# 21*0Sstevel@tonic-gate# CDDL HEADER END 22*0Sstevel@tonic-gate# 23*0Sstevel@tonic-gate# 24*0Sstevel@tonic-gate# Copyright 2004 Sun Microsystems, Inc. All rights reserved. 25*0Sstevel@tonic-gate# Use is subject to license terms. 26*0Sstevel@tonic-gate# 27*0Sstevel@tonic-gate#ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate# 29*0Sstevel@tonic-gate# Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T. 30*0Sstevel@tonic-gate# All rights reserved. 31*0Sstevel@tonic-gate# 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate# 34*0Sstevel@tonic-gate# shcat file 35*0Sstevel@tonic-gate# Simulates cat in sh so it doesn't need to be on the root filesystem. 36*0Sstevel@tonic-gate# 37*0Sstevel@tonic-gateshcat() { 38*0Sstevel@tonic-gate while [ $# -ge 1 ]; do 39*0Sstevel@tonic-gate while read i; do 40*0Sstevel@tonic-gate echo "$i" 41*0Sstevel@tonic-gate done < $1 42*0Sstevel@tonic-gate shift 43*0Sstevel@tonic-gate done 44*0Sstevel@tonic-gate} 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate# 47*0Sstevel@tonic-gate# Inet_list, list of IPv4 interfaces. 48*0Sstevel@tonic-gate# Inet_plumbed, list of plumbed IPv4 interfaces. 49*0Sstevel@tonic-gate# Inet_failed, list of IPv4 interfaces that failed to plumb. 50*0Sstevel@tonic-gate# Inet6_list, list of IPv6 interfaces. 51*0Sstevel@tonic-gate# Inet6_plumbed, list of plumbed IPv6 interfaces. 52*0Sstevel@tonic-gate# Inet6_failed, list of IPv6 interfaces that failed to plumb. 53*0Sstevel@tonic-gate# 54*0Sstevel@tonic-gateunset inet_list inet_plumbed inet_failed \ 55*0Sstevel@tonic-gate inet6_list inet6_plumbed inet6_failed 56*0Sstevel@tonic-gate# 57*0Sstevel@tonic-gate# get_physical interface 58*0Sstevel@tonic-gate# 59*0Sstevel@tonic-gate# Return physical interface corresponding to the given logical 60*0Sstevel@tonic-gate# interface. 61*0Sstevel@tonic-gate# 62*0Sstevel@tonic-gateget_physical() 63*0Sstevel@tonic-gate{ 64*0Sstevel@tonic-gate ORIGIFS="$IFS" 65*0Sstevel@tonic-gate IFS="${IFS}:" 66*0Sstevel@tonic-gate set -- $1 67*0Sstevel@tonic-gate IFS="$ORIGIFS" 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate echo $1 70*0Sstevel@tonic-gate} 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate# 73*0Sstevel@tonic-gate# get_logical interface 74*0Sstevel@tonic-gate# 75*0Sstevel@tonic-gate# Return logical interface number. Zero will be returned 76*0Sstevel@tonic-gate# if there is no explicit logical device number. 77*0Sstevel@tonic-gate# 78*0Sstevel@tonic-gateget_logical() 79*0Sstevel@tonic-gate{ 80*0Sstevel@tonic-gate ORIGIFS="$IFS" 81*0Sstevel@tonic-gate IFS="${IFS}:" 82*0Sstevel@tonic-gate set -- $1 83*0Sstevel@tonic-gate IFS="$ORIGIFS" 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate if [ -z "$2" ]; then 86*0Sstevel@tonic-gate echo 0 87*0Sstevel@tonic-gate else 88*0Sstevel@tonic-gate echo $2 89*0Sstevel@tonic-gate fi 90*0Sstevel@tonic-gate} 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate# 93*0Sstevel@tonic-gate# if_comp if1 if2 94*0Sstevel@tonic-gate# 95*0Sstevel@tonic-gate# Compare Interfaces. Do the physical interface names and logical interface 96*0Sstevel@tonic-gate# numbers match? 97*0Sstevel@tonic-gate# 98*0Sstevel@tonic-gateif_comp() 99*0Sstevel@tonic-gate{ 100*0Sstevel@tonic-gate [ "`get_physical $1`" = "`get_physical $2`" ] && \ 101*0Sstevel@tonic-gate [ `get_logical $1` -eq `get_logical $2` ] 102*0Sstevel@tonic-gate} 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate# 105*0Sstevel@tonic-gate# physical_comp if1 if2 106*0Sstevel@tonic-gate# 107*0Sstevel@tonic-gate# Do the two devices share a physical interface? 108*0Sstevel@tonic-gate# 109*0Sstevel@tonic-gatephysical_comp() 110*0Sstevel@tonic-gate{ 111*0Sstevel@tonic-gate [ "`get_physical $1`" = "`get_physical $2`" ] 112*0Sstevel@tonic-gate} 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate# 115*0Sstevel@tonic-gate# in_list op item list 116*0Sstevel@tonic-gate# 117*0Sstevel@tonic-gate# Is "item" in the given list? Use "op" to do the test, applying it to 118*0Sstevel@tonic-gate# "item" and each member of the list in turn until it returns success. 119*0Sstevel@tonic-gate# 120*0Sstevel@tonic-gatein_list() 121*0Sstevel@tonic-gate{ 122*0Sstevel@tonic-gate op=$1 123*0Sstevel@tonic-gate item=$2 124*0Sstevel@tonic-gate shift 2 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate while [ $# -gt 0 ]; do 127*0Sstevel@tonic-gate $op $item $1 && return 0 128*0Sstevel@tonic-gate shift 129*0Sstevel@tonic-gate done 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate return 1 132*0Sstevel@tonic-gate} 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate# 135*0Sstevel@tonic-gate# get_group_from_hostname interface type 136*0Sstevel@tonic-gate# 137*0Sstevel@tonic-gate# Return all group settings from hostname file for a given interface. 138*0Sstevel@tonic-gate# 139*0Sstevel@tonic-gate# Example: 140*0Sstevel@tonic-gate# get_group_from_hostname hme0 inet 141*0Sstevel@tonic-gate# 142*0Sstevel@tonic-gateget_group_from_hostname() 143*0Sstevel@tonic-gate{ 144*0Sstevel@tonic-gate case "$2" in 145*0Sstevel@tonic-gate inet) file=/etc/hostname.$1 146*0Sstevel@tonic-gate ;; 147*0Sstevel@tonic-gate inet6) file=/etc/hostname6.$1 148*0Sstevel@tonic-gate ;; 149*0Sstevel@tonic-gate *) 150*0Sstevel@tonic-gate return 151*0Sstevel@tonic-gate ;; 152*0Sstevel@tonic-gate esac 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate [ -r "$file" ] || return 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate # 157*0Sstevel@tonic-gate # Read through the hostname file looking for group settings 158*0Sstevel@tonic-gate # There may be several group settings in the file. It is up 159*0Sstevel@tonic-gate # to the caller to pick the right one (i.e. the last one). 160*0Sstevel@tonic-gate # 161*0Sstevel@tonic-gate while read line; do 162*0Sstevel@tonic-gate [ -z "$line" ] && continue 163*0Sstevel@tonic-gate /sbin/ifparse -s "$2" $line 164*0Sstevel@tonic-gate done < "$file" | while read one two three; do 165*0Sstevel@tonic-gate [ "$one" = "group" ] && echo "$two" 166*0Sstevel@tonic-gate done 167*0Sstevel@tonic-gate} 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate# 170*0Sstevel@tonic-gate# get_group_for_type interface type list 171*0Sstevel@tonic-gate# 172*0Sstevel@tonic-gate# Look through the set of hostname files associated with the same physical 173*0Sstevel@tonic-gate# interface as "interface", and determine which group they would configure. 174*0Sstevel@tonic-gate# Only hostname files associated with the physical interface or logical 175*0Sstevel@tonic-gate# interface zero are allowed to set the group. 176*0Sstevel@tonic-gate# 177*0Sstevel@tonic-gateget_group_for_type() 178*0Sstevel@tonic-gate{ 179*0Sstevel@tonic-gate physical=`get_physical $1` 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate type=$2 182*0Sstevel@tonic-gate group="" 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate # 185*0Sstevel@tonic-gate # The last setting of the group is the one that counts, which is 186*0Sstevel@tonic-gate # the reason for the second while loop. 187*0Sstevel@tonic-gate # 188*0Sstevel@tonic-gate shift 2 189*0Sstevel@tonic-gate while [ $# -gt 0 ]; do 190*0Sstevel@tonic-gate if if_comp "$physical" $1; then 191*0Sstevel@tonic-gate get_group_from_hostname $1 $type 192*0Sstevel@tonic-gate fi 193*0Sstevel@tonic-gate shift 194*0Sstevel@tonic-gate done | while :; do 195*0Sstevel@tonic-gate read next || { 196*0Sstevel@tonic-gate echo "$group" 197*0Sstevel@tonic-gate break 198*0Sstevel@tonic-gate } 199*0Sstevel@tonic-gate group="$next" 200*0Sstevel@tonic-gate done 201*0Sstevel@tonic-gate} 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate# 204*0Sstevel@tonic-gate# get_group interface [ configured | failed ] 205*0Sstevel@tonic-gate# 206*0Sstevel@tonic-gate# If there is both an inet and inet6 version of an interface, the group 207*0Sstevel@tonic-gate# could be set in either set of hostname files. 208*0Sstevel@tonic-gate# 209*0Sstevel@tonic-gate# Inet6 is configured after inet, so if the group is set in both 210*0Sstevel@tonic-gate# sets of hostname files, the inet6 file wins. 211*0Sstevel@tonic-gate# 212*0Sstevel@tonic-gate# The "configured" argument should be used to get the group for 213*0Sstevel@tonic-gate# an interface that has been plumbed into the stack and configured. Use 214*0Sstevel@tonic-gate# the "failed" argument to get the group for an interface that failed to 215*0Sstevel@tonic-gate# plumb. 216*0Sstevel@tonic-gate# 217*0Sstevel@tonic-gateget_group() 218*0Sstevel@tonic-gate{ 219*0Sstevel@tonic-gate group="" 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate case "$2" in 222*0Sstevel@tonic-gate configured) 223*0Sstevel@tonic-gate group=`get_group_for_type $1 inet6 $inet6_plumbed` 224*0Sstevel@tonic-gate ;; 225*0Sstevel@tonic-gate failed) 226*0Sstevel@tonic-gate group=`get_group_for_type $1 inet6 $inet6_list` 227*0Sstevel@tonic-gate ;; 228*0Sstevel@tonic-gate *) 229*0Sstevel@tonic-gate return 230*0Sstevel@tonic-gate ;; 231*0Sstevel@tonic-gate esac 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate if [ -z "$group" ]; then 234*0Sstevel@tonic-gate if [ "$2" = configured ]; then 235*0Sstevel@tonic-gate group=`get_group_for_type $1 inet $inet_plumbed` 236*0Sstevel@tonic-gate else 237*0Sstevel@tonic-gate group=`get_group_for_type $1 inet $inet_list` 238*0Sstevel@tonic-gate fi 239*0Sstevel@tonic-gate fi 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate echo $group 242*0Sstevel@tonic-gate} 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate# 245*0Sstevel@tonic-gate# get_standby_from_hostname interface type 246*0Sstevel@tonic-gate# 247*0Sstevel@tonic-gate# Return any "standby" or "-standby" flags in the hostname file. 248*0Sstevel@tonic-gate# 249*0Sstevel@tonic-gate# Example: 250*0Sstevel@tonic-gate# get_standby_from_hostname hme0 inet6 251*0Sstevel@tonic-gate# 252*0Sstevel@tonic-gate# 253*0Sstevel@tonic-gateget_standby_from_hostname() 254*0Sstevel@tonic-gate{ 255*0Sstevel@tonic-gate case "$2" in 256*0Sstevel@tonic-gate inet) file=/etc/hostname.$1 257*0Sstevel@tonic-gate ;; 258*0Sstevel@tonic-gate inet6) file=/etc/hostname6.$1 259*0Sstevel@tonic-gate ;; 260*0Sstevel@tonic-gate *) 261*0Sstevel@tonic-gate return 262*0Sstevel@tonic-gate ;; 263*0Sstevel@tonic-gate esac 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate [ -r "$file" ] || return 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate # 268*0Sstevel@tonic-gate # There may be several instances of the "standby" and 269*0Sstevel@tonic-gate # "-standby" flags in the hostname file. It is up to 270*0Sstevel@tonic-gate # the caller to pick the correct one. 271*0Sstevel@tonic-gate # 272*0Sstevel@tonic-gate while read line; do 273*0Sstevel@tonic-gate [ -z "$line" ] && continue 274*0Sstevel@tonic-gate /sbin/ifparse -s "$2" $line 275*0Sstevel@tonic-gate done < "$file" | while read one two; do 276*0Sstevel@tonic-gate [ "$one" = "standby" ] || [ "$one" = "-standby" ] \ 277*0Sstevel@tonic-gate && echo "$one" 278*0Sstevel@tonic-gate done 279*0Sstevel@tonic-gate} 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate# 282*0Sstevel@tonic-gate# get_standby_for_type interface type plumbed_list 283*0Sstevel@tonic-gate# 284*0Sstevel@tonic-gate# Look through the set of hostname files associated with the same physical 285*0Sstevel@tonic-gate# interface as "interface", and determine whether they would configure 286*0Sstevel@tonic-gate# the interface as a standby interface. 287*0Sstevel@tonic-gate# 288*0Sstevel@tonic-gateget_standby_for_type() 289*0Sstevel@tonic-gate{ 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate physical=`get_physical $1` 292*0Sstevel@tonic-gate type=$2 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate final="" 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate # 297*0Sstevel@tonic-gate # The last "standby" or "-standby" flag is the one that counts, 298*0Sstevel@tonic-gate # which is the reason for the second while loop. 299*0Sstevel@tonic-gate # 300*0Sstevel@tonic-gate shift 2 301*0Sstevel@tonic-gate while [ $# -gt 0 ]; do 302*0Sstevel@tonic-gate if [ "`get_physical $1`" = "$physical" ]; then 303*0Sstevel@tonic-gate get_standby_from_hostname $1 $type 304*0Sstevel@tonic-gate fi 305*0Sstevel@tonic-gate shift 306*0Sstevel@tonic-gate done | while :; do 307*0Sstevel@tonic-gate read next || { 308*0Sstevel@tonic-gate echo "$final" 309*0Sstevel@tonic-gate break 310*0Sstevel@tonic-gate } 311*0Sstevel@tonic-gate final="$next" 312*0Sstevel@tonic-gate done 313*0Sstevel@tonic-gate} 314*0Sstevel@tonic-gate 315*0Sstevel@tonic-gate# 316*0Sstevel@tonic-gate# is_standby interface 317*0Sstevel@tonic-gate# 318*0Sstevel@tonic-gate# Determine whether a configured interface is a standby interface. 319*0Sstevel@tonic-gate# 320*0Sstevel@tonic-gate# Both the inet and inet6 hostname file sets must be checked. 321*0Sstevel@tonic-gate# If "standby" or "-standby" is set in the inet6 hostname file set, 322*0Sstevel@tonic-gate# don't bother looking at the inet set. 323*0Sstevel@tonic-gate# 324*0Sstevel@tonic-gateis_standby() 325*0Sstevel@tonic-gate{ 326*0Sstevel@tonic-gate standby=`get_standby_for_type $1 inet6 $inet6_plumbed` 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate if [ -z "$standby" ]; then 329*0Sstevel@tonic-gate standby=`get_standby_for_type $1 inet $inet_plumbed` 330*0Sstevel@tonic-gate fi 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate # The return value is the value of the following test. 333*0Sstevel@tonic-gate [ "$standby" = "standby" ] 334*0Sstevel@tonic-gate} 335*0Sstevel@tonic-gate 336*0Sstevel@tonic-gate# 337*0Sstevel@tonic-gate# get_alternate interface plumbed_list 338*0Sstevel@tonic-gate# 339*0Sstevel@tonic-gate# Look for a plumbed interface in the same group as "interface". 340*0Sstevel@tonic-gate# A standby interface is preferred over a non-standby interface. 341*0Sstevel@tonic-gate# 342*0Sstevel@tonic-gate# Example: 343*0Sstevel@tonic-gate# get_alternate hme0 $inet_plumbed 344*0Sstevel@tonic-gate# 345*0Sstevel@tonic-gateget_alternate() 346*0Sstevel@tonic-gate{ 347*0Sstevel@tonic-gate mygroup=`get_group $1 failed` 348*0Sstevel@tonic-gate [ -z "$mygroup" ] && return 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate maybe="" 351*0Sstevel@tonic-gate 352*0Sstevel@tonic-gate shift 353*0Sstevel@tonic-gate while [ $# -gt 0 ]; do 354*0Sstevel@tonic-gate group=`get_group $1 configured` 355*0Sstevel@tonic-gate if [ "$group" = "$mygroup" ]; then 356*0Sstevel@tonic-gate if is_standby $1; then 357*0Sstevel@tonic-gate get_physical $1 358*0Sstevel@tonic-gate return 359*0Sstevel@tonic-gate else 360*0Sstevel@tonic-gate [ -z "$maybe" ] && maybe=$1 361*0Sstevel@tonic-gate fi 362*0Sstevel@tonic-gate fi 363*0Sstevel@tonic-gate shift 364*0Sstevel@tonic-gate done 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate get_physical $maybe 367*0Sstevel@tonic-gate} 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate# 370*0Sstevel@tonic-gate# doDHCPhostname interface 371*0Sstevel@tonic-gate# Pass to this function the name of an interface. It will return 372*0Sstevel@tonic-gate# true if one should enable the use of DHCP client-side host name 373*0Sstevel@tonic-gate# requests on the interface, and false otherwise. 374*0Sstevel@tonic-gate# 375*0Sstevel@tonic-gatedoDHCPhostname() 376*0Sstevel@tonic-gate{ 377*0Sstevel@tonic-gate if [ -f /etc/dhcp.$1 ] && [ -f /etc/hostname.$1 ]; then 378*0Sstevel@tonic-gate set -- `shcat /etc/hostname.$1` 379*0Sstevel@tonic-gate [ $# -eq 2 -a "$1" = "inet" ] 380*0Sstevel@tonic-gate return $? 381*0Sstevel@tonic-gate fi 382*0Sstevel@tonic-gate return 1 383*0Sstevel@tonic-gate} 384*0Sstevel@tonic-gate 385*0Sstevel@tonic-gate# 386*0Sstevel@tonic-gate# inet_process_hostname processor [ args ] 387*0Sstevel@tonic-gate# 388*0Sstevel@tonic-gate# Process an inet hostname file. The contents of the file 389*0Sstevel@tonic-gate# are taken from standard input. Each line is passed 390*0Sstevel@tonic-gate# on the command line to the "processor" command. 391*0Sstevel@tonic-gate# Command line arguments can be passed to the processor. 392*0Sstevel@tonic-gate# 393*0Sstevel@tonic-gate# Examples: 394*0Sstevel@tonic-gate# inet_process_hostname /sbin/ifconfig hme0 < /etc/hostname.hme0 395*0Sstevel@tonic-gate# 396*0Sstevel@tonic-gate# inet_process_hostname /sbin/ifparse -f < /etc/hostname.hme0 397*0Sstevel@tonic-gate# 398*0Sstevel@tonic-gate# If there is only line in an hostname file we assume it contains 399*0Sstevel@tonic-gate# the old style address which results in the interface being brought up 400*0Sstevel@tonic-gate# and the netmask and broadcast address being set. 401*0Sstevel@tonic-gate# 402*0Sstevel@tonic-gate# If there are multiple lines we assume the file contains a list of 403*0Sstevel@tonic-gate# commands to the processor with neither the implied bringing up of the 404*0Sstevel@tonic-gate# interface nor the setting of the default netmask and broadcast address. 405*0Sstevel@tonic-gate# 406*0Sstevel@tonic-gate# Return non-zero if any command fails so that the caller may alert 407*0Sstevel@tonic-gate# users to errors in the configuration. 408*0Sstevel@tonic-gate# 409*0Sstevel@tonic-gateinet_process_hostname() 410*0Sstevel@tonic-gate{ 411*0Sstevel@tonic-gate if doDHCPhostname $2; then 412*0Sstevel@tonic-gate : 413*0Sstevel@tonic-gate else 414*0Sstevel@tonic-gate # 415*0Sstevel@tonic-gate # Redirecting input from a file results in a sub-shell being 416*0Sstevel@tonic-gate # used, hence this outer loop surrounding the "multiple_lines" 417*0Sstevel@tonic-gate # and "ifcmds" variables. 418*0Sstevel@tonic-gate # 419*0Sstevel@tonic-gate while :; do 420*0Sstevel@tonic-gate multiple_lines=false 421*0Sstevel@tonic-gate ifcmds="" 422*0Sstevel@tonic-gate retval=0 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gate while read line; do 425*0Sstevel@tonic-gate if [ -n "$ifcmds" ]; then 426*0Sstevel@tonic-gate # 427*0Sstevel@tonic-gate # This handles the first N-1 428*0Sstevel@tonic-gate # lines of a N-line hostname file. 429*0Sstevel@tonic-gate # 430*0Sstevel@tonic-gate $* $ifcmds || retval=$? 431*0Sstevel@tonic-gate multiple_lines=true 432*0Sstevel@tonic-gate fi 433*0Sstevel@tonic-gate ifcmds="$line" 434*0Sstevel@tonic-gate done 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate # 437*0Sstevel@tonic-gate # If the hostname file is empty or consists of only 438*0Sstevel@tonic-gate # blank lines, break out of the outer loop without 439*0Sstevel@tonic-gate # configuring the newly plumbed interface. 440*0Sstevel@tonic-gate # 441*0Sstevel@tonic-gate [ -z "$ifcmds" ] && return $retval 442*0Sstevel@tonic-gate if [ $multiple_lines = false ]; then 443*0Sstevel@tonic-gate # The traditional single-line hostname file. 444*0Sstevel@tonic-gate ifcmds="$ifcmds netmask + broadcast + up" 445*0Sstevel@tonic-gate fi 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate # 448*0Sstevel@tonic-gate # This handles either the single-line case or 449*0Sstevel@tonic-gate # the last line of the N-line case. 450*0Sstevel@tonic-gate # 451*0Sstevel@tonic-gate $* $ifcmds || return $? 452*0Sstevel@tonic-gate return $retval 453*0Sstevel@tonic-gate done 454*0Sstevel@tonic-gate fi 455*0Sstevel@tonic-gate} 456*0Sstevel@tonic-gate 457*0Sstevel@tonic-gate# 458*0Sstevel@tonic-gate# inet6_process_hostname processor [ args ] 459*0Sstevel@tonic-gate# 460*0Sstevel@tonic-gate# Process an inet6 hostname file. The contents of the file 461*0Sstevel@tonic-gate# are taken from standard input. Each line is passed 462*0Sstevel@tonic-gate# on the command line to the "processor" command. 463*0Sstevel@tonic-gate# Command line arguments can be passed to the processor. 464*0Sstevel@tonic-gate# 465*0Sstevel@tonic-gate# Examples: 466*0Sstevel@tonic-gate# inet6_process_hostname /sbin/ifconfig hme0 inet6 < /etc/hostname6.hme0 467*0Sstevel@tonic-gate# 468*0Sstevel@tonic-gate# inet6_process_hostname /sbin/ifparse -f inet6 < /etc/hostname6.hme0 469*0Sstevel@tonic-gate# 470*0Sstevel@tonic-gate# Return non-zero if any of the commands fail so that the caller may alert 471*0Sstevel@tonic-gate# users to errors in the configuration. 472*0Sstevel@tonic-gate# 473*0Sstevel@tonic-gateinet6_process_hostname() 474*0Sstevel@tonic-gate{ 475*0Sstevel@tonic-gate retval=0 476*0Sstevel@tonic-gate while read ifcmds; do 477*0Sstevel@tonic-gate if [ -n "$ifcmds" ]; then 478*0Sstevel@tonic-gate $* $ifcmds || retval=$? 479*0Sstevel@tonic-gate fi 480*0Sstevel@tonic-gate done 481*0Sstevel@tonic-gate return $retval 482*0Sstevel@tonic-gate} 483*0Sstevel@tonic-gate 484*0Sstevel@tonic-gate# 485*0Sstevel@tonic-gate# Process interfaces that failed to plumb. Find an alternative 486*0Sstevel@tonic-gate# interface to host the addresses. For IPv6, only static addresses 487*0Sstevel@tonic-gate# defined in hostname6 files are moved, autoconfigured addresses are 488*0Sstevel@tonic-gate# not moved. 489*0Sstevel@tonic-gate# 490*0Sstevel@tonic-gate# Example: 491*0Sstevel@tonic-gate# move_addresses inet6 492*0Sstevel@tonic-gate# 493*0Sstevel@tonic-gatemove_addresses() 494*0Sstevel@tonic-gate{ 495*0Sstevel@tonic-gate type="$1" 496*0Sstevel@tonic-gate eval "failed=\"\$${type}_failed\"" 497*0Sstevel@tonic-gate eval "plumbed=\"\$${type}_plumbed\"" 498*0Sstevel@tonic-gate eval "list=\"\$${type}_list\"" 499*0Sstevel@tonic-gate process_hostname="${type}_process_hostname" 500*0Sstevel@tonic-gate processed="" 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate if [ "$type" = inet ]; then 503*0Sstevel@tonic-gate echo "moving addresses from failed IPv4 interfaces:\c" 504*0Sstevel@tonic-gate zaddr="0.0.0.0" 505*0Sstevel@tonic-gate hostpfx="/etc/hostname" 506*0Sstevel@tonic-gate else 507*0Sstevel@tonic-gate echo "moving addresses from failed IPv6 interfaces:\c" 508*0Sstevel@tonic-gate zaddr="::" 509*0Sstevel@tonic-gate hostpfx="/etc/hostname6" 510*0Sstevel@tonic-gate fi 511*0Sstevel@tonic-gate 512*0Sstevel@tonic-gate set -- $failed 513*0Sstevel@tonic-gate while [ $# -gt 0 ]; do 514*0Sstevel@tonic-gate in_list if_comp $1 $processed && { shift; continue; } 515*0Sstevel@tonic-gate 516*0Sstevel@tonic-gate alternate="`get_alternate $1 $plumbed`" 517*0Sstevel@tonic-gate if [ -z "$alternate" ]; then 518*0Sstevel@tonic-gate in_list physical_comp $1 $processed || { 519*0Sstevel@tonic-gate echo " $1 (couldn't move, no" \ 520*0Sstevel@tonic-gate "alternative interface)\c" 521*0Sstevel@tonic-gate processed="$processed $1" 522*0Sstevel@tonic-gate } 523*0Sstevel@tonic-gate shift 524*0Sstevel@tonic-gate continue 525*0Sstevel@tonic-gate fi 526*0Sstevel@tonic-gate # 527*0Sstevel@tonic-gate # The hostname files are processed twice. In the first 528*0Sstevel@tonic-gate # pass, we are looking for all commands that apply 529*0Sstevel@tonic-gate # to the non-additional interface address. These may be 530*0Sstevel@tonic-gate # scattered over several files. We won't know 531*0Sstevel@tonic-gate # whether the address represents a failover address 532*0Sstevel@tonic-gate # or not until we've read all the files associated with the 533*0Sstevel@tonic-gate # interface. 534*0Sstevel@tonic-gate 535*0Sstevel@tonic-gate # In the first pass through the hostname files, all 536*0Sstevel@tonic-gate # additional logical interface commands are removed. 537*0Sstevel@tonic-gate # The remaining commands are concatenated together and 538*0Sstevel@tonic-gate # passed to ifparse to determine whether the 539*0Sstevel@tonic-gate # non-additional logical interface address is a failover 540*0Sstevel@tonic-gate # address. If it as a failover address, the 541*0Sstevel@tonic-gate # address may not be the first item on the line, 542*0Sstevel@tonic-gate # so we can't just substitute "addif" for "set". 543*0Sstevel@tonic-gate # We prepend an "addif $zaddr" command, and let 544*0Sstevel@tonic-gate # the embedded "set" command set the address later. 545*0Sstevel@tonic-gate # 546*0Sstevel@tonic-gate /sbin/ifparse -f $type ` 547*0Sstevel@tonic-gate for item in $list; do 548*0Sstevel@tonic-gate if_comp $1 $item && \ 549*0Sstevel@tonic-gate $process_hostname /sbin/ifparse \ 550*0Sstevel@tonic-gate $type < $hostpfx.$item 551*0Sstevel@tonic-gate done | while read three four; do 552*0Sstevel@tonic-gate [ "$three" != addif ] && \ 553*0Sstevel@tonic-gate echo "$three $four \c" 554*0Sstevel@tonic-gate done` | while read one two; do 555*0Sstevel@tonic-gate [ -z "$one" ] && continue 556*0Sstevel@tonic-gate line="addif $zaddr $one $two" 557*0Sstevel@tonic-gate /sbin/ifconfig $alternate $type \ 558*0Sstevel@tonic-gate -standby $line >/dev/null 559*0Sstevel@tonic-gate done 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate # 562*0Sstevel@tonic-gate # In the second pass, look for the the "addif" commands 563*0Sstevel@tonic-gate # that configure additional failover addresses. Addif 564*0Sstevel@tonic-gate # commands are not valid in logical interface hostname 565*0Sstevel@tonic-gate # files. 566*0Sstevel@tonic-gate # 567*0Sstevel@tonic-gate if [ "$1" = "`get_physical $1`" ]; then 568*0Sstevel@tonic-gate $process_hostname /sbin/ifparse -f $type \ 569*0Sstevel@tonic-gate <$hostpfx.$1 | while read one two; do 570*0Sstevel@tonic-gate [ "$one" = addif ] && \ 571*0Sstevel@tonic-gate /sbin/ifconfig $alternate $type -standby \ 572*0Sstevel@tonic-gate addif $two >/dev/null 573*0Sstevel@tonic-gate done 574*0Sstevel@tonic-gate fi 575*0Sstevel@tonic-gate 576*0Sstevel@tonic-gate in_list physical_comp $1 $processed || { 577*0Sstevel@tonic-gate echo " $1 (moved to $alternate)\c" 578*0Sstevel@tonic-gate processed="$processed $1" 579*0Sstevel@tonic-gate } 580*0Sstevel@tonic-gate shift 581*0Sstevel@tonic-gate done 582*0Sstevel@tonic-gate echo "." 583*0Sstevel@tonic-gate} 584