#
# Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

# DHCP VARIABLES


CLINFO="/usr/sbin/clinfo -n"
LOCALNODENAME=`scha_cluster_get -O NODENAME_LOCAL`
IPMPSTATUS="/usr/cluster/bin/scstat -i -h ${LOCALNODENAME}"
INDHCPD="/usr/lib/inet/in.dhcpd -i"
PNTADM="/usr/sbin/pntadm"
PNMPTOR="/usr/cluster/bin/pnmptor"
S34DHCP=/etc/rc3.d/S34dhcp
DSVCLOCKD="/usr/lib/inet/dsvclockd"
TOUPPER=/opt/SUNWscdhc/bin/toupper
DHCPCLIENT=/opt/SUNWscdhc/bin/dhcpclient
DHCPCFG=/etc/inet/dhcpsvc.conf
NETWORKS_ALL="`echo $NETWORKS | tr '/' ' '`"
NETWORKTYPE=nafo
TMPFILE=/tmp/dhcp_${RESOURCE}.tmp
IPNR=`/bin/getent hosts ${LOCALNODENAME} | /bin/awk '{print $1}'`

# TFTP VARIABLES

TFTP=/bin/tftp
INETDCFG=/etc/inet/inetd.conf
TFTPDACTIVE=`/bin/cat ${INETDCFG} | /bin/grep -v '#' | /bin/grep tftp`
TFTPHOST=localhost
TFTPTIMEOUT=10

# DHCPCLIENT VARIABLES

DHCPCLIENT=/opt/SUNWscdhc/bin/dhcpclient
DHCPCLIENTTIMEOUT=15


# OTHER VARIABLES

SCLOGGER=/usr/cluster/lib/sc/scds_syslog
PKG=SUNWscdhc
METHOD=`basename $0`
HATIMERUN=/usr/cluster/bin/hatimerun

syslog_tag()
{
        #
        # Data Service message format
        #

        $SET_DEBUG

        print "SC[${PKG:-??}.${METHOD:-??}]:${RESOURCEGROUP:-??}:${RESOURCE:-??}"
}

scds_syslog()
{

        #
        # Log a message
        #

        $SET_DEBUG

        $SCLOGGER "$@" &
}

debug_message()
{
        #
        # Output a debug message to syslog if required
        #

        if [ "$DEBUG" = "$RESOURCE" -o "$DEBUG" = "ALL" ]
        then
                SET_DEBUG="set -x"

                DEBUG_TEXT=$1

                scds_syslog -p daemon.debug -t $(syslog_tag) -m \
                        "%s" "$DEBUG_TEXT"
        else
                SET_DEBUG=
        fi
}

validate_options()
{
        #
        # Ensure all options are set
        #

        for i in RESOURCE RESOURCEGROUP NETWORKS
        do
                case $i in
                        RESOURCE)
                        if [ -z $RESOURCE ]; then
                                logger -p daemon.err \
                                "ERROR: `basename $0` Option -R not set"
                                exit 1
                        fi;;

                        RESOURCEGROUP)
                        if [ -z $RESOURCEGROUP ]; then
                                logger -p daemon.err \
                                "ERROR: `basename $0` Option -G not set"
                                exit 1
                        fi;;

                        NETWORKS)
                        if [ -z ${STATICDHCP} -a -z $NETWORKS ]; then
                                logger -p daemon.err \
                                "ERROR: `basename $0` Option -N not set"
                                exit 1
                        fi;;

                esac
        done
}

validate()
{

	#
	# Validate DHCP
	#
	
        debug_message "Function: validate - Begin"
	$SET_DEBUG

	rc_validate=0

	#
	# Validate that dhcpsvc.conf exists
	#

	if [ ! -f "${DHCPCFG}" ]
	then
   		scds_syslog -p daemon.error -t $(syslog_tag) -m \
			"Validate - DHCP config file %s does not exist" \
			"${DHCPCFG}"
		rc_validate=1
		return 
	else
		debug_message "Validate - DHCP config file ${DHCPCFG} exists"
	fi

	#
	# Save the old Path and source the config file
	#

	# /etc/inet/dhcpsvc.conf has a PATH variable which gets overwritten
	# when we source /etc/inet/dhcpsvc.conf. PATH gets reinstated at the
	# end of validate or if rc_validate=1 

	OLDPATH=${PATH}

	. ${DHCPCFG}

	#
	# Validate Daemon_enabled is true
	#

	if [ "`${TOUPPER} ${DAEMON_ENABLED}`" != "TRUE" ]
	then
   		scds_syslog -p daemon.error -t $(syslog_tag) -m \
			"Validate - DHCP is not enabled (DAEMON_ENABLED)"
		rc_validate=1
		return 
	else
		debug_message "Validate - DHCP is enabled (DAEMON_ENABLED)"
	fi

	#
	# Validate SUNWfiles or SUNWbinfiles
	#

	if [ "`${TOUPPER} ${RESOURCE}`" != "SUNWFILES" -a "`${TOUPPER} ${RESOURCE}`" != "SUNWBINFILES" ]
	then
   		scds_syslog -p daemon.error -t $(syslog_tag) -m \
			"Validate - Only SUNWfiles or SUNWbinfiles are supported"
		rc_validate=1
		return 
	else
		debug_message "Validate - SUNWfiles or SUNWbinfiles are defined"
	fi

	#
	# Validate that Run_mode is server
	#

	if [ "`${TOUPPER} ${RUN_MODE}`" != "SERVER" ]
	then
   		scds_syslog -p daemon.error -t $(syslog_tag) -m \
			"Validate - RUN_MODE has to be server"
		rc_validate=1
		return 
	else
		debug_message "Validate - RUN_MODE is server"
	fi

	#
	# Validate the path is a directory
	#

	if [ ! -d "${PATH}" ]
	then
   		scds_syslog -p daemon.error -t $(syslog_tag) -m \
			"Validate - DHCP directory %s does not exist" \
			"${PATH}"
		rc_validate=1
		return 
	else
		debug_message "Validate - DHCP directory ${PATH} exists"
	fi
	
	#
	# Validate that S34dhcp is not active
	#

	if [ -f "${S34DHCP}" ]
	then
   		scds_syslog -p daemon.notice -t $(syslog_tag) -m \
			"Validate - De-activating %s, by removing it" \
			"${S34DHCP}"
	
   		/bin/rm -f ${S34DHCP}
	else
		debug_message "Validate - ${S34DHCP} does not exist which is ok"
	fi

	# USE OLDPATH
	PATH=${OLDPATH}

        #
	# Validate that if CGTPUSED is SET the variable INTERFACES has to be set
        #

        if [ ! -z "${CGTPUSED}" -a -z "${INTERFACES}" ]; then

                        scds_syslog -p daemon.notice -t $(syslog_tag) -m \
                        "Validate - The keyword INTERFACES have to be set in %s when -T is being used" \
                        "${DHCPCFG}"

			rc_validate=1
			return 

        else
                debug_message "Validate - The keyword INTERFACES is set when -T is being used"
        fi

        #
	# Validate tftp
	#

	if [ ! -z "${TFTPFILE}" ]; then

		if [ -z "${TFTPDACTIVE}" ]; then
                        scds_syslog -p daemon.notice -t $(syslog_tag) -m \
                        "Validate - tftpd daemon has to be activated in %s when -F is being used" \
                        "${INETDCFG}"

			rc_validate=1
			return

        	else
               		debug_message "Validate - tftpd is active"
        	fi


		if [ ! -s "${TFTPFILE}" ]; then
                        scds_syslog -p daemon.notice -t $(syslog_tag) -m \
                        "Validate - The tftp testfile (%s) don't exist in directory (%s) or has filesize of zero bytes" \
                        "`basename ${TFTPFILE}`" "`dirname ${TFTPFILE}`"

			rc_validate=1
			return

        	else
               		debug_message "Validate - tftp testfile (${TFTPFILE}) exists"
        	fi
        fi



	debug_message "Function: validate - End"
}

get_adapter_type()
{
	#
	# Test if we're running Solaris 8 or later and SC3.1 or later or CGTP
        # is being used
	#

	debug_message "Function: get_adapter_type - Begin"
	$SET_DEBUG

        if [ ! -z "${CGTPUSED}" ]; then
           NETWORKTYPE=cgtp

	elif [ `pkginfo -l SUNWscgds | grep VERSION | awk '{print $2}' | cut -d'.' -f1-2` = "3.1" ]
	then
		NETWORKTYPE=ipmp
	fi

	debug_message "Function: get_adapter_type - ${NETWORKTYPE} is being used"
	debug_message "Function: get_adapter_type - End"
}
		
get_nafo_adapter()
{
	#
	# Get active adapter and interface ip number
	#

	debug_message "Function: get_nafo_adapter - Begin"
	$SET_DEBUG

     	ADAPTER=`${PNMPTOR} ${NAFO_NODE}`

	debug_message "get_nafo_adapter - Interface=${ADAPTER}"

	debug_message "Function: get_nafo_adapter - End"
}

get_ipmp_adapter()
{
	#
	# Get all interfaces belonging to defined IPMP GROUP
	#
	
	debug_message "Function: get_ipmp_adapter - Begin"
	$SET_DEBUG

        ADAPTER=""

        for s1 in `${IPMPSTATUS} | /bin/grep "IPMP Group:" | /bin/awk '{print $4,$6,$7}' | /bin/grep ${NAFO_NODE} | /bin/grep Online | /bin/awk '{print $2}'`
        do
          
           if [ -z "${ADAPTER}" ]; then 
             ADAPTER=${s1}
           else
             ADAPTER=${ADAPTER}","${s1}
           fi

  	done

	debug_message "get_ipmp_adapter - Interface=${ADAPTER}"

	debug_message "Function: get_ipmp_adapter - End"
}

get_cgtp_adapter()
{
	#
	# Get all ip-adresses belonging to defined INTERFACES
	#
	
	debug_message "Function: get_cgtp_adapter - Begin"
	$SET_DEBUG

        ADAPTER=${INTERFACES}

	debug_message "get_cgtp_adapter - Interface=${ADAPTER}"

	debug_message "Function: get_cgtp_adapter - End"
}

get_server_ip()
{
	#
	# get the server ip number
	#
	
	debug_message "Function: get_server_ip - Begin"
	$SET_DEBUG

	SRVIPNR=`${PNTADM} -P ${NW} | /usr/bin/awk '{print $4}' | /bin/tail -1`

	rc_pntadm=$?

	if [ "${rc_pntadm}" -ne 0 ]
	then
		scds_syslog -p daemon.error -t $(syslog_tag) -m \ 
			"get_server_ip - pntadm failed rc<%s>" \
			"${rc_pntadm}"
	else
		debug_message "get-server_ip - Server IP=${SRVIPNR}"
	fi

	debug_message "Function: get_server_ip - End"
}

start_dhcp()
{
	#
	# Start DHCP
	#

        debug_message "Function: start_dhcp - Begin"
	$SET_DEBUG
	
	NODEID=`${CLINFO}`
	USED_ADAPTER=""

	if [ -f ${TMPFILE} ]
	then
   		rm -f ${TMPFILE}
	fi

	# IF CGTPUSED AND STATICDHCP IS BEING USED
	# SET USED_ADAPTER=${INTERFACES}

        if [ ! -z "${CGTPUSED}" -a ! -z "${STATICDHCP}" ]; then
          USED_ADAPTER=${INTERFACES}
	fi

	# GET ADEPTER TYPE

	get_adapter_type	

	# PARSE ${NETWORKS_ALL} OPTIONS TO RETRIVE IP-NUMBERS FOR
	# ACTIVE ADAPTERS

	NW_ALL=

	for tab in ${NETWORKS_ALL}
	do
   		NW=`/usr/bin/echo ${tab} | cut -d'@' -f1`
   		NAFO_NODE=`/usr/bin/echo ${tab} | cut -d'@' -f2`
   		ID=`/usr/bin/echo ${tab} | cut -d'@' -f3`

   		if [ "${ID}" = "${NODEID}" ]
		then

			if [ "${NETWORKTYPE}" = "ipmp" ]; then
				get_ipmp_adapter
			elif [ "${NETWORKTYPE}" = "nafo" ]; then
				get_nafo_adapter
                        else
                                get_cgtp_adapter
			fi

			# USED_ADAPTER allows for multiple interfaces so long as we match "${ID}" = "${NODEID}"

			if [ -z "${USED_ADAPTER}" ]
			then
       				USED_ADAPTER=${ADAPTER}
     			else
       				USED_ADAPTER=${USED_ADAPTER}","${ADAPTER}
			fi

			NW_ALL="$NW_ALL $NW"
		fi
	done

	# CHECK IF CHANGE OF OWNER SHIP IS NEEDED

	if [ -z "${STATICDHCP}" ]; then

		for NW in $NW_ALL
		do
			# GET OWNER OF DHCP-TABLES

			get_server_ip

			if [ ! -z "${SRVIPNR}" ]
			then
				# Check which node owns the DHCP table

                		echo ${IPNR} | grep ${SRVIPNR} > /dev/null

				if [ $? -ne 0 ]
				then

					debug_message "start_dhcp - Changing Server IP for network ${NW} from ${SRVIPNR} to ${IPNR}"

					# Dump each client and create a PNTADM batchfile to change the server ip number

					for client in `${PNTADM} -P ${NW} | /usr/bin/awk '{print $3}' | /usr/bin/grep '\.'`
       					do
          					/usr/bin/echo "pntadm -M ${client} -s ${IPNR} ${NW}" >> ${TMPFILE}
       					done
				else
					debug_message "start_dhcp - This node owns the DHCP table entries"
     				fi
			fi
		done
	fi

	# Run the ${TMPFILE} in batch mode to PNTADM

	if [ -f "${TMPFILE}" ]
	then
		debug_message "start_dhcp - Start DHCP batch job to change Server IP address"

  		${PNTADM} -B ${TMPFILE}

		rc_pntadm=$?

		if [ "${rc_pntadm}" -ne 0 ]
		then
			scds_syslog -p daemon.error -t $(syslog_tag) -m \ 
			"start_dhcp - DHCP batch job failed rc<%s>" \
			"${rc_pntadm}"
		else
			debug_message "start_dhcp - DHCP batchjob is finished"
		fi
	fi

	# Start Dhcp daemon

	${INDHCPD} ${USED_ADAPTER}
	St=$?

	if [ ${St} -ne 0 ]
	then
   		scds_syslog -p daemon.error -t $(syslog_tag) -m \
			"start_dhcp - %s %s failed" \
			"${INDHCPD}" "${USED_ADAPTER}"
	else
		debug_message "start_dhcp - DHCP started"
	fi

	debug_message "Function: start_dhcp - End"
}

stop_dhcp()
{
	#
	# Stop DHCP
	#

        debug_message "Function: stop_dhcp - Begin"
	$SET_DEBUG

	/bin/pkill -TERM `basename ${DSVCLOCKD}`

	debug_message "Function: stop_dhcp - End"
}

check_dhcp()
{
	# 
	# Probe DHCP
	#

        debug_message "Function: check_dhcp - Begin"
	$SET_DEBUG

	rc_check_dhcp=0
	#
	# Check if the agent is starting
	#

	if [ ! -z "`pgrep start_dhcp`" ]
	then
		debug_message "check_dhcp - DHCP is starting, exiting"
		rc_check_dhcp=100
		return
	fi

        # IF CGTPUSED IS BEING USED DISABLE NETWORKS

        if [ ! -z "${CGTPUSED}" ]; then
          NETWORKS_ALL=""
        fi

	# GET ADAPTER TYPE

	get_adapter_type

	#
	# Check if active adapter/interface in nafo has changed
	#

	NODEID=`${CLINFO}`

	for tab in ${NETWORKS_ALL}
	do
   		NW=`/usr/bin/echo ${tab} | cut -d'@' -f1`
   		NAFO_NODE=`/usr/bin/echo ${tab} | cut -d'@' -f2`
   		ID=`/usr/bin/echo ${tab} | cut -d'@' -f3`

		# Test the ${NETWORKS_ALL} ${ID} with the cluster node number

   		if [ "${ID}" = "${NODEID}" ]
		then

			if [ "${NETWORKTYPE}" = "nafo" ]
			then
				get_nafo_adapter

	     			NAFO_NODE_FILE=/var/tmp/`basename $0`.${NAFO_NODE}

				# The first time through we create ${NAFO_NODE_FILE} with the active interface
				# Subsequent restarts or failovers will then test to see if the interface has changed
	
     				if [ ! -f "${NAFO_NODE_FILE}" ]
				then
					debug_message "check_dhcp - Creating ${NAFO_NODE_FILE} with active interface ${ADAPTER}"

       		 			/bin/echo ${ADAPTER} > ${NAFO_NODE_FILE}
     				else
       		 			OLDADAPTER=`/bin/cat ${NAFO_NODE_FILE}`

					debug_message "check_dhcp - Check if active interface has changed"

       		 			if [ "${ADAPTER}" != "${OLDADAPTER}" ]
					then
       		    				scds_syslog -p daemon.notice -t $(syslog_tag) -m \
						"check_dhcp - Active interface has changed from %s to %s" \
						"${OLDADAPTER}" "${ADAPTER}"

						debug_message "check_dhcp - Updating ${NAFO_NODE_FILE} with new active interface ${ADAPTER}"

       		    				/bin/echo ${ADAPTER} > ${NAFO_NODE_FILE}

						rc_check_dhcp=100
						return
					else
						debug_message "check_dhcp - Active interface has not changed"
					fi
       		 		fi
			elif [ "${NETWORKTYPE}" = "ipmp" ]; then
				debug_message "check_dhcp - Don't check for adapter changes when ipmp is being used"
			else
				debug_message "check_dhcp - Don't check for adapter changes when cgtp is being used"
			fi
   		fi
	done

	#
	# Check Dhcp with dhcpclient if ClientID is supplied
	#

	if [ ! -z "${CLIENTID}" ]; then

		debug_message "Function: check_dhcp - Check if in.dhcpd can answer dhcp requests"

		DHCPCLIENTLOGFILE=/tmp/${RESOURCE}.tmp

		# Remove DHCPCLIENTLOGFILE

		rm -f ${DHCPCLIENTLOGFILE}

		# Run dhcpclient under timeout

		${HATIMERUN} -t ${DHCPCLIENTTIMEOUT} ${DHCPCLIENT} -q ${CLIENTID} >${DHCPCLIENTLOGFILE} 2>&1

		St=$?

		#
		# CHECK RESULTS
		#

		# Check for timeouts

		if [ $St -eq 99 ]; then
			scds_syslog -p daemon.error -t $(syslog_tag) -m \
			"check_dhcp - Dhcpclient test timed out exeeded %s seconds" \
			"${DHCPCLIENTTIMEOUT}"

			rc_check_dhcp=201
			return
		else
			debug_message "check_dhcp - Dhcpclient test didn't time out"
		fi

		# Check if Dhcpclient exited non-zero
		
		if [ $St -ne 0 ]; then
			scds_syslog -p daemon.error -t $(syslog_tag) -m \
			"check_dhcp - Dhcpclient test exited with %s" \
			"${St}"

			rc_check_dhcp=201
			return
		else
			debug_message "check_dhcp - Dhcpclient test exited with ${St}"
		fi

		# Check if Dhcpclient retrieved an IP-address
		
		if [ -z `/bin/grep SERVER ${DHCPCLIENTLOGFILE}` ]; then
			scds_syslog -p daemon.error -t $(syslog_tag) -m \
			"check_dhcp - Dhcpclient didn't retrieve any IP-number" 

			rc_check_dhcp=201
			return
		else
			debug_message "check_dhcp - Dhcpclient did retrieve an IP-number"
		fi
	 fi

	#
	# Check tftp
	#

	if [ ! -z "${TFTPFILE}" ]; then

		debug_message "Function: check_dhcp - Check tftpd"

		# Retrieve filename from TFTPFILE

		TFTPDFILE=`basename ${TFTPFILE}`

		RETRIEVEDFILE=/tmp/${TFTPDFILE}

		TFTPLOGFILE=/tmp/${RESOURCE}.tmp

		# REMOVE RETRIEVEDFILE TFTPLOGFILE

		rm -f ${TFTPLOGFILE} ${RETRIEVEDFILE}

		# Connect to tftp on localhost and retrieve the testfile

	        debug_message "Function: check_dhcp - Connect to ${TFTPHOST} and try to retrieve ${TFTPDFILE}"

		${HATIMERUN} -t ${TFTPTIMEOUT} ${TFTP} > ${TFTPLOGFILE} << EOF
		verbose
		connect ${TFTPHOST}
		mode binary
		get ${TFTPDFILE} ${RETRIEVEDFILE}
		quit
EOF

		#
		# CHECK RESULTS
		#

		# Check for timeouts

		if [ $? -eq 99 ]; then
			scds_syslog -p daemon.error -t $(syslog_tag) -m \
			"check_dhcp - tftp transfer test timed out exeeded %s seconds" \
			"${TFTPTIMEOUT}"

			rc_check_dhcp=201
			return
		else
			debug_message "check_dhcp - tftp transfer test didn't time out"
		fi

		# Check error codes in the logfile

		Msg=`/bin/grep Error ${TFTPLOGFILE}`

		if [ ! -z "${Msg}" ]; then
			scds_syslog -p daemon.error -t $(syslog_tag) -m \
			"check_dhcp - tftp transfer test generated an error code of (%s)" \
			"${Msg}"

			rc_check_dhcp=201
			return
		else
			debug_message "check_dhcp - tftp transfer test didn't generate any error codes"
		fi

		# Check if the retrieved file exist and is non-zero bytes

		if [ ! -s "${RETRIEVEDFILE}" ]; then
			scds_syslog -p daemon.error -t $(syslog_tag) -m \
			"check_dhcp - The retrieved file (%s) don't exist or is zero-bytes long." \
			"${RETRIEVEDFILE}"

			rc_check_dhcp=201
			return
		else
			debug_message "check_dhcp - The retrieved file (${RETRIEVEDFILE}) exist and is not non-zero bytes long"
		fi

	fi



	debug_message "Function: check_dhcp - End"
}


set_status()
{
        #
        # Set appropriate resource status
        #

        debug_message "Function: set_status - Begin"
        $SET_DEBUG

        STATUS_TYPE=$1

        scha_resource_setstatus -R $RESOURCE -G $RESOURCEGROUP -s $STATUS_TYPE

        rc_scha_resource_setstatus=$?

        if [ "$rc_scha_resource_setstatus" != 0 ]
        then
                scds_syslog -p daemon.error -t $(syslog_tag) -m \
                "set_status - rc<%s>  type<%s>" \
                "${rc_scha_resource_setstatus}" "${STATUS_TYPE}"
        fi

        debug_message "Function: set_status - End"
}

