#!/usr/bin/ksh -p
#
# ident "@(#)utdhcpservice.ksh	1.7 05/08/12 SMI"
#
# Copyright 2004,2005 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

#
# Options:
#	enable	- enable the DHCP service
#	disable	- disable the DHCP service
#	start	- start the DHCP daemon
#	stop	- stop the DHCP daemon
#	restart	- restart the DHCP daemon
#	status	- (undocumented) list current DHCP status
#
# allows undocumented status option in case this gets included
# in the activation framework yet to be defined
#
#
# Return values:
#
#	0	- Successful completion
#	1	- Failed
#	2	- DHCP not installed
#	3	- DHCP not enabled
#		  (or already enabled if the option is enable)
#

export LC_ALL=C

export PATH=/bin:/usr/bin:/sbin:/usr/sbin

UT_ETC="/etc/opt/SUNWut"
UT_BASEDIR=`(cd /etc/opt/SUNWut/basedir ; /bin/pwd)`
UT_DHCP_BASEDIR=`(cd ${UT_ETC}/dhcp ; /bin/pwd)`
INIT_DHCP="/etc/init.d/dhcp";
DHCP_SVC_CONF="/etc/inet/dhcpsvc.conf"
SVCS="/bin/svcs"
SVCADM="/usr/sbin/svcadm"
DHCP_FMRI="svc:/network/dhcp-server:default"

PROGRAM_ID=$(basename $0)

#
# get literal ${SUBNETFILEPREFIX} to test for configured state
#
#. ${UT_DHCP_BASEDIR}/dhcp_config_linux
. ${UT_DHCP_BASEDIR}/../../support_lib/dhcp_config

# names of files and directories that will be touched by this script
#
TMPDIR="/var/opt/SUNWut/tmp"
CORONA_NAME="SunRay";
CORONA_TITLE="Sun Ray";

#
# These booleans keep track of:
#	if the DHCP package is installed
#	if the DHCP package is enabled
#	if the DHCP configuration includes a Sun Ray subnet / inteface
#	if the DHCP daemon was running at the time this script was invoked.
#
typeset DHCP_INSTALLED=true
typeset DHCP_ENABLED=true
typeset DHCP_CONFIGURED=true
typeset DHCP_RUNNING=true
typeset DHCP_PACKAGE="SUNWdhcsb"
typeset DHCP_STATE="online"

DHTADM_P="${TMPDIR}/dhtadm-P.$$"

LEASE_DAYS=1;
LOG_KERN=6;
LOG_NET=6;
LOG_USB=6;
LOG_VID=6;
LOG_APPL=6;
AUTH_PORT=7009;

# get this server's name and ipaddr, use this as the Sunray Central server
HOSTNAME=`hostname`;

if [ -z "${HOSTNAME}" ]; then
  print -u2 "Error: hostname must be set"
  print -u2 "Set host name and try again"
  exit 1;
fi

HOSTIP=`getent hosts ${HOSTNAME} | awk '{print $1}'`
if [ -z "${HOSTIP}" ]; then
  print -u2 "Error: host IP address must be set"
  print -u2 "Set host IP address in ${HOSTS} files and try again"
  exit 1;
fi

#
# This variable is used as a flag during dhcp configuration.
# If it is "true" then it means that prior to S8U5 there
# was no mechanism of using dhcpconfig non-interactively.
# So we manipulate the /etc/default/dhcp file directly.
# If it "false" then we know that this is a post S8U5
# machine and so we have a mechanism for non-interactive
# dhcpconfig. In this case we do not depend on the
# location of the dhcp files.
#
USE_FILES=true

DHCP_DIR="/var/dhcp";

#
# Variables that will be used ONLY if USE_FILES=true
#
DHCPTAB="${DHCP_DIR}/dhcptab";
DHCP_CONFIG="/etc/default/dhcp";

function DetermineRelease
{
    if [ -d /usr/lib/inet/dhcp ]; then
	USE_FILES=false
    fi
}

#
# Usage message
#
function Usage {

print "
Usage:
$PROGRAM_ID [ enable | disable ]
$PROGRAM_ID [ start | stop | restart ]
"

exit 1
}

#
# Setup the DHCP configuration file
#  usage:  SetupCfgFile
# write a new dhcp config file for SunRay use.
#
function SetupCfgFile {

  #
  # If this is a post S8U5 then use the non-interactive
  # dhcpconfig command to setup dhcp configuration file
  # in the correct location
  #
  if ! $USE_FILES ; then
    if ! $DHCP_ENABLED; then
	dhcpconfig -D -r SUNWbinfiles -p ${DHCP_DIR} >/dev/null 2>&1
	# NOTE: this will start up the dhcp daemon automatically
    fi
    return 0
  fi

  #
  # This is a pre-S8U5 system. So we use the file location
  #
  # check if the config file exists
  if [ -f ${DHCP_CONFIG} ]; then
    TMPDIR=`sed -n 's/^PATH=//p' ${DHCP_CONFIG}`
    if [ ${TMPDIR} != ${DHCP_DIR} ]; then
	print -u2 "Warning: DHCP_DIR changed to ${TMPDIR}"
	DHCP_DIR=${TMPDIR};
	DHCPTAB="${DHCP_DIR}/dhcptab";
    fi
    return 0;
  fi

  # create a new ${DHCP_CONFIG} file that forces files and path for SunRay
  print "# This file controls the defaults for datastore type and location.\n# for the DHCP service. Two directives are currently supported,\n# 'RESOURCE' and 'PATH'. 'RESOURCE' can be either 'files' or 'nisplus'.\n# 'PATH' can be a unix pathname for 'files' resources, or a legal\n# nisplus directory for 'nisplus' resources." > ${DHCP_CONFIG};
  print "RESOURCE=files" >> ${DHCP_CONFIG};
  print "PATH=${DHCP_DIR}" >> ${DHCP_CONFIG};
}

#
# make the dhcptab file
#  usage:  SetupDhcptab <interfaces>
# create the table and add all the macros
#
function SetupDhcptab {

  if $USE_FILES ; then
    # check if the dhcp dir exists in the proper place
    if [ ! -d ${DHCP_DIR} ]; then
	#
        # In the case of a freshly installed pre S8U5 machine
	# DHCP_DIR will not be present.
	# dhcp dir doesnt exist, so make it
	#
        mkdir -m 655 -p ${DHCP_DIR};
	if [ ${?} -ne 0 ]; then
	print -u2 "Error:  unable to create dhcp dir \"${DHCP_DIR}\".  check and retry"
	return 1;
	fi
    fi
  fi

  #
  # create a new dhcptab if there isn't one
  # 
  if ! dhtadm -C >/dev/null 2>&1; then
	# failed to create; lets check if it's already configured
	if ! $DHCP_ENABLED; then
	    # there was a failure, so complain and bail
	    print -u2 "Error:  unable to create dhcptab.  check and retry"
	    return 1;
	fi
  fi

  return 0;
}

#
# Set options in the dhcp startup file for the dhcp service.
#  usage:  SetupOptions <interfaces>
# Handle DHCP offer TTL, rescan interval, and BOOTP compatibility.
#
function SetupOptions {
  # cache extended offers for 10 seconds
  OPTIONS="-o 10";

  # modify the file
  StartFileUpdate ${INIT_DHCP};
  RestoreFile "${INIT_DHCP}.$$";
  sed -e "/^case \"\$1\" in\$/{
i\\
ulimit -n 1024 # SUNRAY ADD
}" "${INIT_DHCP}.$$" > ${TMPDIR}/tmpfile.$$;

  # don't use EndFileUpdate so links aren't broken
  cp -f ${TMPDIR}/tmpfile.$$ "${INIT_DHCP}";
  rm -f ${TMPDIR}/tmpfile.$$ "${INIT_DHCP}.$$";
}

function UnsetupOptions {
  # modify the file
  StartFileUpdate ${INIT_DHCP};
  RestoreFile "${INIT_DHCP}.$$";
  sed -e "/^ulimit*SUNRAY ADD/d" "${INIT_DHCP}.$$" > ${TMPDIR}/tmpfile.$$;
  # don't use EndFileUpdate so links aren't broken
  cp -f ${TMPDIR}/tmpfile.$$ "${INIT_DHCP}";
  rm -f ${TMPDIR}/tmpfile.$$ "${INIT_DHCP}.$$";
}

function StatusDHCP {
    typeset PACKAGE="SUNWdhcsb SUNWdhcsu SUNWdhcsr"
   
    if [ -x $SVCS ] && [ $DHCP_STATE != "unconfigured" ]; then
	SVCS_INFO_F="${TMPDIR}/svcs.$$"
	rm -rf $SVCS_INFO_F 2> /dev/null
	$SVCS -l $DHCP_FMRI > $SVCS_INFO_F 2> /dev/null
	DHCP_STATE_INFO=$(awk '{if ($1 == "state") print $2}' $SVCS_INFO_F)
	DHCP_ENABLE_INFO=$(awk '{if ($1 == "enabled") print $3} ' $SVCS_INFO_F | sed -e s/\(//g | sed -e s/\)//g )
	if [ -n "$DHCP_ENABLE_INFO" ] &&  [ -n "$DHCP_STATE_INFO" ] ; then
		DHCP_STATE=$(echo $DHCP_STATE_INFO-$DHCP_ENABLE_INFO)
	elif [ -n "$DHCP_STATE_INFO" ]; then
		DHCP_STATE=$DHCP_STATE_INFO
	fi
    else
	if ! $DHCP_RUNNING && [ $DHCP_STATE = "online" ] ; then
		DHCP_STATE="disabled"
	fi
    fi
    print "begin dhcpstate"
    print "installed=${DHCP_INSTALLED}"
    print "enabled=${DHCP_ENABLED}"
    print "configured=${DHCP_CONFIGURED}"
    print "running=${DHCP_RUNNING}"
    print "packages=${PACKAGE}"
    print "status=${DHCP_STATE}"
    print "end"
}

function EnableDHCP {
    if $DHCP_ENABLED ; then
	return 3
    fi
    SetupCfgFile;
    SetupDhcptab;
    SetupOptions;
    if [[ $? != "0" ]]; then
	return 1
    fi
    return 0
}

function DisableDHCP {
    if ! $DHCP_ENABLED ; then
      return 3
    fi

    if $DHCP_CONFIGURED || $DHCP_RUNNING ; then
      return 1
    fi
    UnsetupOptions
    typeset OTHER_CONF=$(dhtadm -P 2>/dev/null | sed 1,2d)
    if [[ -z $OTHER_CONF ]]; then
      dhtadm -R >/dev/null 2>&1
    fi
    return 0
}

#
# StartDHCP - start the dhcp daemon
#
#  usage:  StartDHCP
#
#  Returns: 0 - if successful or daemon is already running
#		    1 - if failed to start
#
function StartDHCP {

    GetDHCPpid
    if [ -n "${dhcppid}" ]; then
		# dhcp is already running, can't start a new one
	return 0
    fi
    "${INIT_DHCP}" start
    sleep 1
    GetDHCPpid
    if [ -z "${dhcppid}" ]; then
		print -u2 "Error: unable to start dhcp services."
	 print -u2 "	  Please restart the dhcp manually after utadm has completed."
	 return 1
    fi
    print "### started DHCP daemon";
    return 0
}

function GetDHCPpid {
  dhcppid=`pgrep in.dhcpd`
}

#
# Stop current dhcp daemon
#  usage:  StopDHCP
#
#  Returns: 0 - if successful or daemon is not currently running
#	    1 - if failed to stop
#
function StopDHCP {
    GetDHCPpid
    if [ -z "${dhcppid}" ]; then
	return 0
    fi

    "${INIT_DHCP}" stop
    sleep 1
    GetDHCPpid
    if [ -n "${dhcppid}" ]; then
	print -u2 "Error: Unable to stop dhcp services."
	print -u2 "	  Please restart the dhcp manually after utadm has completed."
	return 1
    fi
    print "### stopped DHCP daemon";
    return 0
}

#
# RestartDHCP - restart the DHCP daemon using the /etc/init.d/dhcp script.
# We can't send a HUP signal to the dhcp daemon because it currently doesn't
# work reliably.
#
# Returns: 0 - if sucessfully restarted
#		   1 - if failed to restart
#
RestartDHCP () {

    if ! $DHCP_RUNNING; then
	GetDHCPpid
	if [ -n "${dhcppid}" ]; then
            # this can only happen if it failed to stop the DHCP daemon in
            # the DoInit routine.  Try to stop it again.
            # catching the stop message so that we don't confuse the user it's
            # stopped successfully.
            typeset TMPSTOP=${TMPDIR}/stopdhcp.$$
            rm -f ${TMPSTOP}
            if ! StopDHCP 2>&1 >${TMPSTOP}; then
		# failed with some other error. Print the error
		cat $TMPSTOP >&2
		rm -f $TMPSTOP
		return 1
            fi
            rm -f $TMPSTOP
	fi
    fi

    if ! StopDHCP; then
	# failed with some other error. Error message will be printed in StopDHCP
	 return 1
    fi
    if ! StartDHCP; then
	# failed with some error
	 return 1
    fi
    return 0
}
#
# main
#

trap "rm -f ${TMPDIR}/*.$$; exit" 0 1 2 3 14 15

DetermineRelease

${UT_BASEDIR}/lib/utprodinfo -t installed ${DHCP_PACKAGE}
if [[ $? -ne 0 ]] ; then
  DHCP_INSTALLED=false
  DHCP_ENABLED=false
  DHCP_CONFIGURED=false
  DHCP_RUNNING=false
  DHCP_STATE="uninstalled"
else
  rm -f $DHTADM_P 2> /dev/null
  dhtadm -P 2>/dev/null > $DHTADM_P
  if [[ $? != "0" ]]; then
    DHCP_ENABLED=false
    DHCP_CONFIGURED=false
    DHCP_RUNNING=false
    if [ ! -f $DHCP_SVC_CONF ]; then
      DHCP_STATE="unconfigured"
    fi
  else
    grep "SunRay-" $DHTADM_P >/dev/null 2>&1
    if [[ $? != "0" ]]; then
      DHCP_CONFIGURED=false	# Interface / subnet not defined
    fi

    GetDHCPpid
    if [[ -z $dhcppid ]]; then
      DHCP_RUNNING=false
    fi

  fi
fi

if [[ $# -gt 1 ]] ; then
  Usage
fi

#
# allow undocumented status option for now in case this gets included
# in the activation framework yet to be defined
#
if [[ $# -eq 0 || "$1" = "status" ]] ; then
  StatusDHCP
  exit 0
fi

if ! $DHCP_INSTALLED ; then
  exit 2
fi

case $1 in
"enable")
  EnableDHCP ;;
"disable")
  DisableDHCP ;;
"start")
  StartDHCP ;;
"stop")
  StopDHCP ;;
"restart")
  RestartDHCP ;;
*)
  Usage ;;
esac

return $?
