#!/bin/sh -f
# Copyright 12/16/04 Sun Microsystems, Inc. All Rights Reserved.
#pragma ident  "@(#)esmultiip	1.10 04/12/16 Sun Microsystems"

######################################################
#
# display the command usage and exit, usually called
# when in error with parameter specifications
#
######################################################

usage_and_exit() {
         eval /usr/bin/echo "\"`/usr/bin/gettext  'Usage: $PROGNAME [ -lh ] | [ < -a | -d > HostIP ] \n Where the options represent:\n'`\""
        /usr/bin/gettext ' Default:     Enable Multi-IP feature on the SunMC server if it has\n              multiple interfaces.\n'
        /usr/bin/gettext ' -h:          Prints this usage.\n'
        /usr/bin/gettext ' -l:          List all the active interfaces of SunMC server.\n'
        /usr/bin/gettext ' -a <HostIP>: Adds the hostname corresponding to IP Address provided to the list\n              of servers active interfaces.\n'
        /usr/bin/gettext ' -d <HostIP>: Deletes the hostname corresponding to IP Address provided from the\n              list of servers active interfaces.\n' 

	exit 1
}

######################################################
#
# initialize interface list and other variables for 
# this script to run
#
######################################################

initialize_iflist () {
	# read the current list of active interfaces
	if [ ! -f "$MLTIP_FILE" ]; then 
		if [ $listFlag -eq 1 -o $deleteFlag -eq 1 ]; then
			echolog 'MultiIP not configured correctly'
			echo "\n"
			exit 1
		fi
		ifList=""
	else
		ifList=`$XGET $MLTIP_FILE 0`
		if [ -z "$ifList" -a $addFlag -eq 0 ]; then
			echolog 'MultiIP not configured correctly'
			echo "\n"
			exit 1
		fi
	fi

	# get the server name handy for putting it in error messages
	srvName=`$XGET $ESDIR/cfg/domain-config.x cfgserver.cfgserverServer`
}

######################################################
#
# List the interfaces which have been configured to be 
# active for Multi IP support
#
######################################################

list_active_smc_interfaces () {
	actInterfaces=`echo $ifList | sed s/:/\ /g`
	echolog 'Multi IP configured with active interfaces \\\"$2\\\"' \
		"$actInterfaces"
	echo "\n"
	return
}

########################
#
# gets the host name for this IP address from the local
# or the YP database.
#
############

get_ip_from_name () {
    valIPAddr=""
    valHostName=$1
    valIPAddr=`cat /etc/hosts | grep -w $valHostName | \
        awk '{prevMatch = $1} END { print prevMatch }'`
    if [ -z "$valIPAddr" ]; then
    # Try the YP database and verify if the entry is there or
    # not
        ypmatch $valHostName hosts.byname 1>/dev/null 2>&1
        if [ $? -eq 1 ]; then
        	# Possibly yp is not configured
        	# We couldn't find the IP in our database, therefore,
        	# we'll not proceed with this entry.
            echo "\n"
            echolog 'Host name - $2 : not found in the hosts database' $valHostName
            return 1
        else
            valIPAddr=""
            valIPAddr=`ypmatch $valHostName hosts.byname | awk '{print $1}'`
            if [ -z "$valIPAddr" ]; then
                echo "\n"
                echolog 'Host name $2 : not found in the hosts database' $valHostName
                return 1
            else
                hostIP=$valIPAddr
                return 0
            fi
        fi
    else
        hostIP=$valIPAddr
        return 0
    fi
}

########################
#
# Validate the IP Address to be an a.b.c.d address with
# a,b,c & d in a proper range
#
############

validate_ipaddress() {
    valIPAddr=$1
    noOfFields=`echo $valIPAddr | awk -F\. '{print NF}'`
    if [ $noOfFields -ne 4 ]; then
        echolog 'Invalid Host IP Address specified'
        return 1
    fi
    part1=`echo  $valIPAddr | cut -d\. -f1`
    part2=`echo  $valIPAddr | cut -d\. -f2`
    part3=`echo  $valIPAddr | cut -d\. -f3`
    part4=`echo  $valIPAddr | cut -d\. -f4`

    if [ -z "$part1" -o -z "$part2" -o \
         -z "$part3" -o -z "$part4" ]; then
        echolog 'Invalid Host IP Address specified'
        return 1
    fi
    if [ $part1 -lt 1 -o $part1 -gt 254 -o \
         $part4 -lt 1 -o $part4 -gt 254 ]; then
         echolog 'Host IP Address value is not in range.'
         multiline_echolog 'First and last dot separated values must be\nin the range of 1..254'
         return 1
    fi

    if [ $part2 -lt 0 -o $part2 -gt 255 -o \
         $part3 -lt 0 -o $part3 -gt 255 ]; then
         echolog 'Host IP Address value is not in range.'
         multiline_echolog 'Second and third dot separated values must be\nin the range of 0..255'
         return 1
    fi
    return 0
}

########################
#
# Figure out if the user specified an IP address or a host name
# for an IP address we must do extra validation and then get
# the host name because we only want to use the names here
#
############

validate_hostname_format () {
    valIPAddr=$1
    echo $valIPAddr | egrep -e '^[0-9][0-9\.]*$' 2>&1 > /dev/null
    if [ $? -eq 0 ]; then
        validate_ipaddress $valIPAddr
        if [ $? -ne 0 ]; then
            cmdStatus=1
        fi
		hostIP=$valIPAddr
    else
        echo $valIPAddr | egrep -e '^[0-9\.]' 2>&1 > /dev/null
        if [ $? -eq 0 ]; then
            echolog 'Invalid host name : specified host name begins with a numeric character'
            echo "\n"
            cmdStatus=1
        else
            echo $valIPAddr | egrep -e '^[a-zA-Z][-\.0-9a-zA-Z]*$' 2>&1 > /dev/null
            if [ $? -ne 0 ]; then
                echolog 'Invalid host name : specified host name contains invalid characters'
				echo "\n"
                cmdStatus=1
            else
				get_ip_from_name $valIPAddr
				if [ $? -ne 0 ]; then
					cmdStatus=1
				fi
                cmdStatus=0
            fi
        fi
    fi
}

######################################################
#
# validate_hostname will check for the format of the
# specified hostname/ip address and verify that the specified
# name is the address of one of the up interfaces
#
######################################################

validate_hostname () {
	tmpHostIP=$1
	get_all_ipv4_interfaces 

	# This will also set the hostName correctly if tmpHostName is an
	# IP Address

	validate_hostname_format $tmpHostIP
	if [ $cmdStatus -ne 0 ]; then
		return
	fi
	# use the hostname for checking in the allUpIfList. Relax
	# the check for delete because its possible that the sysadmin
	# had unconfigured the interface and is now running the SunMC
	# config. Therefore, do this check only for add.
	if [ $addFlag -eq 1 ]; then
		echo $allUpIfList | grep -w "$hostIP" 2>&1 > /dev/null
		if [ $? -ne 0 ]; then
			multiline_echolog 'Host address $2 is not the address of any\ninterface on this host' $tmpHostIP
			cmdStatus=1
		fi
	fi
}

######################################################
#
# create a list of space separated  all up IPv4 interfaces 
# on this host 
#
######################################################

get_all_ipv4_interfaces () {
	# PORTABILITY - This command will work fine on 2.8 and above
	# because of IPV6 support, however this being a server layer
	# script it should be allright, but we'll put a check nonetheless
	allUpIfList=`ifconfig -a4u | awk '/[<,]UP[,>]/ && ($0 !~ /LOOPBACK/) {  getline; if ($0 ~ /inet/) printf("%s ", $2);}'`
}

######################################################
#
# delete_interface is called with to delete an interface
# from the list of active interfaces
#
######################################################

delete_interface () {
	delInfIP=$1
	# validate_hostname will set the IP of the host in variable
	# hostIP, which will be used in this routine then
	validate_hostname $delInfIP
	if [ $cmdStatus -ne 0 ]; then
		return
	fi
	echo $ifList | grep $hostIP 2>&1 >/dev/null
	if [ $? -ne 0 ]; then
		echolog 'Host address \\\"$2\\\" not configured to be an active interface' $hostIP
		cmdStatus=1
		return
	fi
	skipColon=1
	for infIP in `echo $ifList | sed s/:/\ /g`
	do
		if [ "$infIP" = "$hostIP" ]; then
			continue
		fi
		if [ $skipColon -eq 0 ]; then
			newIfList="$newIfList:"
		fi
		newIfList="$newIfList$infIP"
		if [ $skipColon -eq 1 ]; then
			skipColon=0
		fi
	done
	if [ -z "$newIfList" ]; then
		multiline_echolog 'Atleast one interface must be configured as an active interface\nCannot remove $2 as this is the only active interface.' $hostIP
		echo "\n"
		cmdStatus=1
		return
	fi
	$XPUT $MLTIP_FILE 0 $newIfList
	echolog 'Host address \\\"$2\\\" removed from the list of active interfaces' $hostIP
	echo "\n"
}

######################################################
#
# do_default routine is called whent he script is invoked
# withouth any option. The subroutine will check for the
# the existence of the multiip.dat file if its present
# it will be lest as is, otherwise the file will be populated
# with all the interfaces to be in the active list
#
######################################################

do_default () {
	if [ -f "$MLTIP_FILE" ]; then
		#list_active_smc_interfaces
		return
	else
		get_all_ipv4_interfaces
		activeInterfaces=`echo $allUpIfList | sed s/\ /:/g`
		$XPUT $MLTIP_FILE 0 $activeInterfaces
	fi
}

######################################################
#
# adds an interface to the list of active interfaces
#
######################################################

add_interface () {
	addInfIP=$1
	# variable hostName will contain the name of the host  after
	# the call to validate_hostname for addInfIP which must
	# be used subsequently in this routine.
	validate_hostname $addInfIP
	if [ $cmdStatus -ne 0 ]; then
		return
	fi
	entryNotFound=0
	for infIP in `echo $ifList | sed s/:/\ /g`
	do
		if [ "$infIP" = "$hostIP" ]; then
			echolog 'Host address \\\"$2\\\" is already an active interface' $hostIP
			entryNotFound=1
			break
		fi
	done
	if [ $entryNotFound -eq 0 ]; then
		if [ -z "$ifList" ]; then
			$XPUT $MLTIP_FILE 0 "$hostIP"
		else
			$XPUT $MLTIP_FILE 0 "$ifList:$hostIP"
		fi
		echolog 'Host address \\\"$2\\\" added to the list of active interfaces' $hostIP
	fi
	cmdStatus=$entryNotFound
	echo "\n"
}

######################################################
#
#  Main entry point
#
######################################################

BASEDIR=`/usr/bin/pkgparam SUNWescom BASEDIR`
SCRIPT_DIR=${BASEDIR}/SUNWsymon/sbin

. ${SCRIPT_DIR}/es-common.sh

listFlag=0
deleteFlag=0
addFlag=0
cmdStatus=0
defaultMode=1

PROGNAME=$0

umask 022
# initialize from common files
set_inst_base_dir
set_basedir

while getopts hla:d: OPT
do
	case $OPT in
        h)      
                usage_and_exit
                ;;
	l)
		listFlag=1
		defaultMode=0
		;;
	a) 
		if [ $listFlag -eq 1 ]; then
			continue
		fi
		if [ $deleteFlag -eq 1 ]; then
			usage_and_exit			
		fi
		addFlag=1
		inpHostIP=$OPTARG
		defaultMode=0
		;;
	d)
		if [ $listFlag -eq 1 ]; then
			continue
		fi
		if [ $addFlag -eq 1 ]; then
			usage_and_exit			
		fi
		deleteFlag=1
		inpHostIP=$OPTARG
		defaultMode=0
		;;
        *)
                usage_and_exit
                ;;
	esac
done

check_root
set_paths
check_osver
set_xput
MLTIP_FILE="$ESDIR/cfg/multiip.dat"

OSREV=`/bin/echo $OSVERS | ${CMD_CUT} -d. -f2`
if [ $OSREV -lt 8 ] ; then 
	multiline_echolog 'The script is used by the Sun Management Center Server layer,\ntherefore, must be run on Solaris 8 and higher OS versions'
	echo "\n"
	exit 1
fi

# initialize from routines in this script
initialize_iflist

if [ $listFlag -eq 1 ]; then
	list_active_smc_interfaces
elif [ $addFlag -eq 1 ]; then
	add_interface $inpHostIP
elif [ $deleteFlag -eq 1 ]; then
	delete_interface $inpHostIP
elif [ $defaultMode -eq 1 ]; then
	do_default
else
	usage_and_exit
fi

exit $cmdStatus
