#!/usr/bin/ksh -p
#
# ident "@(#)utadm.ksh	1.182 05/07/27 SMI"
#
# Copyright 1998-2004,2005 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

#
#  Configuring SunRay interfaces:
#  ------------------------------
#  Assumes host that this script is run on is being configured as a single
#  sunray central server, meant to serve a collection of sunray desktop units
#  connected via the interfaces listed in the command line.
#  The default subnet for the first interface is: 192.168.128.1
#  The user will be prompted if they are willing to accept the default address
#  for each interface, and if not, they have to give an new IP address and
#  netmask.  It is assumed that whatever net the user chooses will have 250 or
#  fewer contiguous addresses in the least significant byte (a less restrictive,
#  but equivalent, assumption than that it will be a class C network).
#
#  this script sets up the newtnet according to the following scheme:
#    255.255.255.0	-- netmask (Class C)
#    192.168.X.1	-- server's ip address for an interface
#			   (X={128,129,130...} mapped in order of args)
#    192.168.X.255	-- broadcast address on interface X
#    192.168.X.0	-- address of network for interface X
#    192.168.X.1	-- address of gateway/router on network X
#    192.168.X.16	-- address of the first sunray desktop unit on net X
#    192.168.X.240	-- address of the last sunray desktop unit on net X
#
#  When configuring an interface for private interconnect, the symbolic
#  hostname for network X is "<hostname>-<intf>" and the symbolic  name for
#  network X is "${CORONANAME}-<intf>".  The following files will be updated
#  with the above symbolic names:
#	/etc/inet/hosts, /etc/inet/netmasks, /etc/inet/networks
#
#  We don't add symbolic names to the /etc/hosts file for each desktop. We
#  get by with just the numeric names.
#
#  The dhcptab layout scheme is as follows:
#  * there is a sunray-specific macro that is included by all interfaces
#    which contains lease time and negotiate enable.  It als includes the
#    common log values like LogHost, LogKern, LogNet, LogUSB, LogVid, LogAppl,
#    BarrierLevel and the AuthPort.
#  * the remainder of the macros are per-interface, and include:
#      * the "<netname>" macro has the auth server and it includes the intf's
#        log macro.
#      * there is also a network macro for each interface. Its name is the
#        IP address and contains the broadcast IPA, the subnet mask, MTU,
#        router IPA, the inferface name, the firmware server and the NewT
#        version.  It also includes the "netname" macro above.
#
#  Configuring SunRay Subnetworks:
#  -------------------------------
#  Configures the server to serve a collection of DTUs connected on a public
#  LAN connection.  The user will be prompted for the subnetwork information 
#  such as the router, netmask, auth server, and IP address range for IP
#  address assignment.
#  The script will NOT update any of the files under /etc/inet directory.
#
#  The dhcptab layout scheme is as follows:
#  * there is a sunray-specific macro similar to the per interface case above.
#  * the remainder of the macros are per-subnetwork, and include:
#      * the "<netname>" macro has the auth server and it includes the intf's
#        log macro.  The netname macro is "<hostname>-<IPaddr>".
#      * there is also a network macro for each interface. Its name is the
#        IP address and contains the broadcast IPA, the subnet mask, MTU,
#        router IPA, the firmware server and the NewT version.  It also
#        includes the "netname" macro above.
#
#  When configuring a subnet as a SunRay subnetwork, the syb
#  * the defined symbols are:
#      * 21: AuthSrvr
#      * 22: AuthPort
#      * 23: NewtVer
#      * 24: LogHost
#      * 25: LogKern
#      * 26: LogNet
#      * 27: LogUSB
#      * 28: LogVid
#      * 29: LogAppl
#      * 30: NewTBW
#      * 31: FWSrvr
#      * 32: NewTDispIndx
#      * 33: Intf
#      * 34: NewTFlags
#      * 35: AltAuth
#      * 36: BarrierLevel
#
#### need to add script to add more desktops
#
export LC_ALL=C

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

ETC_OPT_UT="/etc/opt/SUNWut"
VAR_OPT_UT="/var/opt/SUNWut"
UT_BASEDIR=`(cd /etc/opt/SUNWut/basedir ; /bin/pwd)`
UT_DHCP_BASEDIR=`(cd ${ETC_OPT_UT}/dhcp ; /bin/pwd)`
UTDHCPSERVICE="${UT_DHCP_BASEDIR}/utdhcpservice"
UTDHCPNET="${UT_DHCP_BASEDIR}/utdhcpnet"
UTDHCPOPT="${UT_DHCP_BASEDIR}/utdhcpopt"

SVCADM="/usr/sbin/svcadm"
DHCP_FMRI="svc:/network/dhcp-server:default"

UTLIB="$(${UT_BASEDIR}/lib/utprodinfo -r SUNWuto)/SUNWut/lib"
UTSBIN="$(${UT_BASEDIR}/lib/utprodinfo -r SUNWuto)/SUNWut/sbin"
PROGRAM_ID=$(basename $0)

#
# Source common functions used to communicate with utdhcpnet
. ${UTLIB}/support_lib/dhcp_config

DEF_NET_PFX="192.168";
DEF_START_NET="128";
DEF_START_NUM=16;
DEF_END_NUM=240;
#DEF_END_NUM=20;
#echo "Reset DEF_END_NUM"

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

# names of files and directories that will be touched by this script
#
NSSWITCH="/etc/nsswitch.conf";
HOSTS="/etc/inet/hosts";
INIT_DTLOGIN="/etc/init.d/dtlogin";
INIT_SYSSUSPEND="/etc/default/sys-suspend";
INIT_SESSIONETC="/usr/dt/config/sessionetc"
INIT_OPENWINSYS="/usr/openwin/lib/openwin-sys"
CORONA_NAME="SunRay";
CORONA_TITLE="Sun Ray";
OFFLINE_FILE="/var/opt/SUNWut/offline"
TMPDIR="/var/opt/SUNWut/tmp"
CUR_CFG_F="${TMPDIR}/utdhcpnet-F.$$"
CUR_STATE_F="${TMPDIR}/utdhcpservice-F.$$"
AUTHPROPS="/etc/opt/SUNWut/auth.props"
SUSECONFIG="/etc/sysconfig/suseconfig"

#
# This boolean keeps track if the DHCP daemon was running at the time 
# this script was invoked.
#
DHCP_RUNNING=false

ME=$(basename $0)
ARGS=$*

#
# Platform dependencies set here
#
SetPlatformDependencies () {

  __AWK=$(whence nawk)
  if [[ -z $__AWK ]] ; then
    __AWK=$(whence gawk)
    if [[ -z $__AWK ]] ; then
      Fatal "No recognized awk implementation found on this host"
    fi
  fi

  OS=`/bin/uname -s`

  case "$OS" in
    SunOS)	# Define Solaris specific parameters

		#
		# Define Solaris specific filenames
		ETCSERVICES="/etc/inet/services"
		HOSTS="/etc/inet/hosts";
		HOSTNAME_R="/etc/hostname";	# with suffix .{hme,qfe,vge}
		HOSTNAME_C="/etc/hostname.";
		NETMASKS="/etc/inet/netmasks";
		NETWORKS="/etc/inet/networks";
		DHCPCONFIG="/var/dhcp/dhcptab"
		GREP=/usr/xpg4/bin/grep
		INIT_DHCP="/etc/init.d/dhcp";
		IFCFG_INET="inet";

		;;	# end case SunOS

    Linux)	# Define Linux specific parameters

		#
		# Define Linux specific filenames
		ETCSERVICES="/etc/services"
		HOSTS="/etc/hosts";
		HOSTNAME_R="${ETC_OPT_UT}/net/hostname"; # with suffix .{eth}
		HOSTNAME_C=""
		if [[ -d "/etc/sysconfig/network-scripts" ]]; then
			HOSTNAME_C="/etc/sysconfig/network-scripts/ifcfg-"
		elif [[ -d "/etc/sysconfig/network" ]]; then
			HOSTNAME_C="/etc/sysconfig/network/ifcfg-"
		fi
		NETMASKS="${ETC_OPT_UT}/net/netmasks";
		#
		#Linux may have /etc/networks but doesn't have to
		if [[ -r "/etc/networks" ]] ; then
		  NETWORKS="/etc/networks";
		else
		  NETWORKS="${ETC_OPT_UT}/net/networks";
		fi
		DHCPCONFIG="/etc/dhcpd.conf"
		GREP=grep	# XXX need to figure out which <===
		INIT_DHCP="/etc/init.d/dhcpd";
		if [[ -d "/etc/sysconfig/network-scripts" ]] ; then
		  IFCONFIG_SCRIPT="/etc/sysconfig/network-scripts/ifcfg-"
		  IFCONFIG_BOOT="ONBOOT=yes"
		  BOOTPROTO=none
		else
		  IFCONFIG_SCRIPT="/etc/sysconfig/network/ifcfg-"
		  IFCONFIG_BOOT="STARTMODE=onboot"
		  BOOTPROTO=static
		fi
		IFCFG_INET="";

		;;	# end case Linux

    *)		# Unknown OS
		Fatal "unknown OS name $OS"
  esac

}

#
# Usage message
#
function Usage {

print "
Usage:
$ME -c
$ME -a <intf_name>
$ME -d <intf_name>
$ME -A <subnetwork>
$ME -D <subnetwork>
$ME -f
$ME -n
$ME -p
$ME -l
$ME -r
$ME -L on | off
$ME -x

  Switches:
    -c			# create framework for ${CORONA_TITLE} interconnect
    -r			# remove all ${CORONA_TITLE} interconnects
    -a <intf_name>	# add <intf_name> as ${CORONA_TITLE} interconnect
    -d <intf_name>	# delete <intf_name> as ${CORONA_TITLE} interconnect
    -A <subnetwork>	# add <subnetwork> as ${CORONA_TITLE} interconnect
    -D <subnetwork>	# delete <subnetwork> as ${CORONA_TITLE} interconnect
    -p			# print current configuration
    -l			# print the current configuration for all the
			# ${CORONA_TITLE} subnetworks
    -f			# take server offline
    -n			# bring server online
    -L on | off		# turn on or off LAN connection from ${CORONA_TITLE}
    -x			# print the current configuration in a machine parseable
			# format

  Parameters:
    <intf_name>		# a network interface name, such as
			# hme[0-9], qfe[0-9], or vge[0-9]
    <subnetwork>	# a subnetwork number or name
"

exit 2
}

#
# prompt user for yes or no answer
#  usage:  YesOrNo <prompt> <default value>
# takes two arguments, a PROMPT and the default value (Y | N).
# Returns 0 if the user specified "Y", nonzero otherwise.
#
function YesOrNo {
  if [ ${#} -ne 2 ]; then
    return 1;
  fi

  if [ "${2}" = "Y" ]; then
    DEFPMPT="([Y]/N): \c "
    DEFVAL="Y"
  else
    DEFPMPT="(Y/[N]): \c "
    DEFVAL="N"
  fi

  while true
  do
    print "${1} ${DEFPMPT}";
    read ANS
    : ${ANS:="${DEFVAL}"}
    echo $ANS >> $LOGFILE
    case "$ANS" in
	[Yy] | [Yy][Ee][Ss]) return 0;;
	[Nn] | [Nn][Oo]) return 1;;
    esac
  done
}



#
# compare the netmask against the system defined if exists, or class default
# Parameter:
#	$1 the netmask
# Returns:
#	0 if successfull
#	1 if failed and need to re-enter
#
CheckNetmaskValue() {
	typeset NEW_NETMASK=$1
	typeset RETCODE

	#
	# if netmask is not defined in the naming database and class
	# based netmask is used
	#
	if [[ ${CLASS_NETMASK} != ${NEW_NETMASK} ]]; then
	    print "\tYou have specified a netmask different than the class"
	    print "\tbased netmask for this subnet."
	    YesOrNo "\tDo you want to keep this netmask? " "Y"
	    RETCODE=${?}
	    if [[ ${RETCODE} -eq 0 ]]; then
		ADD_NETMASK=true
	    fi
	    return ${RETCODE}
	fi
	return 0
}


#
# Verify a dotted IP address
#  usage:  CheckIPA <ipaddr>
# returns a 0 if a good ipa is given, and a 1 otherwise
#
function CheckIPA {
  IP_ADDR=`expr ${1} : '\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)$'`
  if [ ! "${IP_ADDR}" ]; then
    return 1
  fi
  NNO1=${1%%.*}
  tmp=${1#*.}
  NNO2=${tmp%%.*}
  tmp=${tmp#*.}
  NNO3=${tmp%%.*}
  tmp=${tmp#*.}
  NNO4=${tmp%%.*}
  if [ ${NNO1} -gt 255 -o ${NNO2} -gt 255 -o ${NNO3} -gt 255 -o ${NNO4} -gt 255 ]; then
    return 1
  fi
  return 0
}

# Translate a network address to its broadcast address
function Net2Broadcast {
  BRCST=`print "$1 $2" | awk '{
			split($1, a, ".")
			split($2, m, ".")
			dot = ""
			out = ""
			for (i = 1; i <= 4; i++) {
				for (j = 1; j <= 256; j *= 2) {
					if ((m[i] + j) == 256) {
						br = j - 1
						out = out dot a[i] - a[i] % j + br
						break
					} else if ((m[i] + j) > 256) {
						out = "BadMask"
						i = 5
						break
					}
				}
				dot = "."
			}
			printf "%s\n", out
		}'`
  if [ $BRCST = "BadMask" ]; then
    return 1;
  fi
  return 0;
}

#
# Translate a host IP address to its network address
# Parameters:
#	$1 IP address or network number
#	$2 netmask
# Sets:
#	NET - network address
#
function IP2Net {
  NET=`IP_Mask2Net $1 $2`
  return $?
}

#
# Translate a network subnet address to its netmask
# Parameters:
#	$1 IP address or network number
#	$2 netmask
# Sets:
#	NMASK - minimum netmask to include network address
# Depends on:
#	CLASS_NETMASK
#
function Net2Mask {
  NMASK=`print "$1 ${CLASS_NETMASK}" | awk '{
			split($1, a, ".")
			split($2, m, ".")
			dot = ""
			out = ""
			for (i = 4; i >= 1; i--) {
				if (m[i] == 0 && a[i] == 0) {
					out = m[i] dot out
				} else if (m[i] != 0) {
					out = m[i] dot out
				} else {
					for (j = 2; j <= 256; j *= 2) {
						if ((a[i] % j) != 0) {
							if (i == 4 && j <= 4) {
								out = "BadMask"
								i = 0
								break
							}
							out = 256-(j/2) dot out
							break
						}
					}
					dot = "."
					for (i-- ; i >= 1; i--) {
						out = 255 dot out
					}
					break
				}
				dot = "."
			}
			printf "%s\n", out
		}'`
  if [ $NMASK = "BadMask" ]; then
    return 1;
  fi
  return 0;
}

#
# Get the class based netmask for the subnet specified
# Parameters:
#	$1 Subnet
# Prints:
#	The netmask
# Returns:
#	0 if successful
#	1 if invalid subnet passed
# 
GetNetmaskClass () {
    typeset -i pref=${1%%.*}
    if [[ $pref -lt 128 ]]; then
	# class A
	print "255.0.0.0"
    elif [[ $pref -lt 192 ]]; then
	# class B
	print "255.255.0.0"
    elif [[ $pref -lt 224 ]]; then
	# class C
	print "255.255.255.0"
    else
	# invalid
	print -u2 "Error: failed to generate class based Netmask for"
	print -u2 "\tsubnet ${SUBNET}.  You must use a class A, B or C"
	print -u2 "\taddress."
	exit 1
    fi
    return 0
}

#
# modify nsswitch file 
#  usage:  UpdateNsswitch <path>
# force hosts, netmasks, and networks to come from local files
#
function UpdateNsswitch {
  rm -f ${TMPDIR}/tmpfile.$$;
  awk 'BEGIN { }
		/^hosts:/ { 
			    if ($2 != "files") {
				print "# SUNRAY DEL " $0;
				printf "hosts:\tfiles ";
				for (i = 2; i <= NF; i++) {
				    if ($i != "files") {
					printf "%s ", $i;
				    }
				}
				print "# SUNRAY ADD";
			    } else {
				print $0
			    }
			    next;
		}
		/^netmasks:/ {  
				if ($2 != "files") {
				    print "# SUNRAY DEL " $0;
				    printf "netmasks:\tfiles ";
				    for (i = 2; i <= NF; i++) {
					if ($i != "files") {
					    printf "%s ", $i;
					}
				    }
				    print "# SUNRAY ADD";
				} else {
				    print $0
				}				
				next;
		}
		/^networks:/ {  
				if ($2 != "files") {
				    print "# SUNRAY DEL " $0;
				    printf "networks:\tfiles ";
				    for (i = 2; i <= NF; i++) {
					if ($i != "files") {
					    printf "%s ", $i;
					}
				    }
				    print "# SUNRAY ADD";
				} else {
				    print $0
				}
				next;
		}
		/^services:/ {  
				if ($2 != "files") {
				    print "# SUNRAY DEL " $0;
				    printf "services:\tfiles ";
				    for (i = 2; i <= NF; i++) {
					if ($i != "files") {
					    printf "%s ", $i;
					}
				    }
				    print "# SUNRAY ADD";
				} else {
				    print $0
				}
				next;
		}
		{ print $0 }
		END { }' $1 > ${TMPDIR}/tmpfile.$$;

  mv -f ${TMPDIR}/tmpfile.$$ $1;
}


#
# Restart the nscd daemon
#
Restart_nscd() {
    pgrep nscd > /dev/null 2>&1
    if [[ $? -eq 0 ]] && [[ -x /etc/init.d/nscd ]] ; then
      /etc/init.d/nscd stop 2>&1 >/dev/null
      /etc/init.d/nscd start 2>&1 >/dev/null
    fi
}


#
# Verify that dhcp is installed
#
function CheckDHCP {
  rm -f $CUR_STATE_F 2> /dev/null
  ${UTDHCPSERVICE} > ${CUR_STATE_F} 2> /dev/null
  typeset INSTALLED=$($__AWK -F= '$1=/installed/ {print $2}' ${CUR_STATE_F})
  if ! $INSTALLED ; then
    typeset PKG=$($__AWK -F= '$1=/packages/ {print $2}' ${CUR_STATE_F})
    # the DHCP binary file format package is not installed - abort.
    print -u2 "Error: ${PKG} package is not installed.  This is the Binary" \
    "\n\tFile Format data module used to store the DHCP data.  This" \
    "\n\tpackage is required for SunRay interface configuration."
    return 1;
  fi
  UT_DHCP_ENABLED=$($__AWK -F= '$1=/enabled/ {print $2}' ${CUR_STATE_F})
  UT_DHCP_CONFIGURED=$($__AWK -F= '$1=/configured/ {print $2}' ${CUR_STATE_F})
  UT_DHCP_RUNNING=$($__AWK -F= '$1=/running/ {print $2}' ${CUR_STATE_F})
  UT_DHCP_STATE=$($__AWK -F= '$1=/status/ {print $2}' ${CUR_STATE_F})
  return 0
}

function GetDHCPpid {
  # On Solaris the daemon is in.dhcpd, on Linux it is dhcpd
  # This pgrep finds it on both platforms
  dhcppid=`pgrep 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

    ${UTDHCPSERVICE} stop > /dev/null 2>&1
    sleep 1
    GetDHCPpid
    if [ -n "${dhcppid}" ]; then
	print -u2 "### Error: Unable to stop dhcp services."
	print -u2 "    Please restart 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
	# dhcp was not running when the command started, do we need to start it?
	CheckDHCP	# DHCP status may have changed
	if ! $UT_DHCP_CONFIGURED; then
	  return 1		# don't restart if we didn't configure it
	fi
	print "\n"
	YesOrNo "DHCP is not currently running, should I start it?" "Y";
	if [ ${?} -ne 0 ]; then
	    fmt <<-!

		#### DHCP daemon not started.  You will need to manually start
		one using "${INIT_DHCP} start".

		!
	    return 1
	fi
    fi

    ${UTDHCPSERVICE} restart > /dev/null 2>&1
    if [[ $? -ne 0 ]] ; then
      print -u2 "### Error: unable to start dhcp services."
      print -u2 "    Please restart dhcp manually after utadm has completed."
      return 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
    ${UTDHCPSERVICE} start > /dev/null 2>&1
    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
}


#
# Setup the DHCP configuration file
#  usage:  SetupCfgFile
# write a new dhcp config file for SunRay use.
#
function SetupCfgFile {
 
  if ! $UT_DHCP_ENABLED ; then
    ${UTDHCPSERVICE} enable > /dev/null 2>&1

    UT_DHCP_ENABLED=$(${UTDHCPSERVICE} 2>/dev/null | $__AWK -F= '$1=/enabled/ {print $2}')
  fi
}


#
# Set options in the dhcp startup file for the dhcp service.
#  usage:  SetupOptions
# 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 NohupDtlogin {
  StartFileUpdate ${INIT_DTLOGIN};
  RestoreFile "${INIT_DTLOGIN}.$$";
  sed -e "/^[ 	]*.usr.dt.bin.dtlogin/{
s/^/# SUNRAY DEL /
a\\
		nohup /usr/dt/bin/dtlogin -daemon & # SUNRAY ADD
}" "${INIT_DTLOGIN}.$$" > ${TMPDIR}/tmpfile.$$;

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

function FixSysSuspend {
  StartFileUpdate ${INIT_SYSSUSPEND};
  RestoreFile "${INIT_SYSSUSPEND}.$$";
  sed -e "/^[ 	]*PERMS/{
s/^/# SUNRAY DEL /
a\\
# SUNRAY BEGIN
a\\
PERMS=-
a\\
# SUNRAY END
}" "${INIT_SYSSUSPEND}.$$" > ${TMPDIR}/tmpfile.$$;

  mv -f ${TMPDIR}/tmpfile.$$ "${INIT_SYSSUSPEND}.$$";
  EndFileUpdate ${INIT_SYSSUSPEND};
}

#
# Change sessionetc to skip starting sdtvolcheck for sunray sessions
#
function FixSessionEtc {
  StartFileUpdate ${INIT_SESSIONETC};
  RestoreFile "${INIT_SESSIONETC}.$$";
  sed -e '/^if \[ "$DTXSERVERLOCATION" != "remote" \]$/{
s/^/# SUNRAY DEL /
a\
UTDPY=${DISPLAY#*:} # SUNRAY ADD
a\
UTDPY=${UTDPY%.*} # SUNRAY ADD
a\
if [ "$DTXSERVERLOCATION" != "remote" -a "$UTDPY" = "0" ] # SUNRAY ADD
}' "${INIT_SESSIONETC}.$$" > ${TMPDIR}/tmpfile.$$;

  mv -f ${TMPDIR}/tmpfile.$$ "${INIT_SESSIONETC}.$$";
  EndFileUpdate ${INIT_SESSIONETC};
  #
  # Make up for past transgressions.
  #
  chmod a+x ${INIT_SESSIONETC}
}

#
# Change openwin-sys to skip starting console speckeysd for sunray sessions
#
function FixOpenwinSys {
  StartFileUpdate ${INIT_OPENWINSYS};
  RestoreFile "${INIT_OPENWINSYS}.$$";
  sed -e '/^if \[ -x $OPENWINHOME\/bin\/speckeysd \] ; then$/{
s/^/# SUNRAY DEL /
a\
# SUNRAY BEGIN
a\
utconsole=f
a\
case "$DISPLAY" in
a\
 *:0|*:0.0) utconsole=t ;;
a\
esac
a\
if [ -x $OPENWINHOME/bin/speckeysd -a "$utconsole" = "t" ] ; then
a\
# SUNRAY END
}' "${INIT_OPENWINSYS}.$$" > ${TMPDIR}/tmpfile.$$;

  mv -f ${TMPDIR}/tmpfile.$$ "${INIT_OPENWINSYS}.$$";
  EndFileUpdate ${INIT_OPENWINSYS};
  #
  # Make up for past transgressions.
  #
  chmod a+x ${INIT_OPENWINSYS}
}

#
# Get the UTC offset in minutes
#  usage:  GetTimeOffset
# calculates the offset in minutes from UTC and puts it into UTC_OFFSET
#
function GetTimeOffset {
  LOCAL=`date '+%H'`;
  GMT=`date -u '+%H'`;
  if [ ${LOCAL} -gt ${GMT} ]; then
    let TIME=24+${GMT}-${LOCAL};
  else
    let TIME=${GMT}-${LOCAL};
  fi
  let TIME=${TIME}\*3600;
  UTC_OFFSET="${TIME}";
}

#
# extract the netmask from  Solaris ifconfig output
#  usage:  getNetMask <"`ifconfig ${INTF} inet`">
# returns: netmask
#
function getNetMask {
  print "$1" | awk '{
      split($0, a);
      for (i = 0; i < NF; i++) {
	if (a[i] == "netmask") {
	  n = length(a[i + 1]);
	  m = "";
	  for (j = 1; j < n; j += 2) {
	    d = substr(a[i + 1], j, 1);
	    y = (index("0123456789abcdef", d) - 1) * 16;
	    d = substr(a[i + 1], j + 1, 1);
	    y += (index("0123456789abcdef", d) - 1);
	    if (m == "")
	      m = y;
	    else
	      m = m"."y;
          }
	  print m;
	  break;
        }
      }
    }'
}

#
# get information about a given network interface
#  usage:  GetInterfaceInfo <intf name>
# If <intf name> not specified, use the primary interface
#
# get the following info into the following variables:
#  INTF_IPA:     the IPA of the interface
#  INTF_NAME:    the symbolic name for this interface
#  INTF_MASK:    the subnet mask for this interface
#  INTF_NET:     the address of this network
#  INTF_NETPFX:  the subnet prefix of this network
#  INTF_NETNAME: the symbolic name of this network
#  INTF_MTU:     the MTU for this interface
#  INTF_BC:      the broadcast address for this network
#
#  this is only to be called after the interface has been setup (i.e., after
#  the "ifconfig plumb" has been done on Solaris), and the /etc/hosts table
#  has been setup.
#  returns a 0 if all values are set properly and a 1 otherwise
#
function GetInterfaceInfo {
  if [[ $OS = "Linux" ]] ; then
    if [[ $# -eq 0 ]]; then
      GetLinuxInterfaceInfo
    else
      GetLinuxInterfaceInfo $1
    fi
    return $?
  fi

  typeset intf
  if [[ $# -eq 0 ]]; then
	# Interface not specified.  Use the info from the primary interface for the MTU.
	typeset intf_list=`grep -l "^${HOSTNAME}\$" ${HOSTNAME_R}.* | \
		sed -e "s/^..*\.\([^\.][^\.]*\)$/\1/"`
	if [[ -z "$intf_list" ]]; then
	    print -u2 "Error: unable to get information on primary interface"
	    return 1
	fi

	# get the first interface that is configured
	for intf in $intf_list
	do
	    INTF_INFO=`netstat -n -I ${intf} -f inet`;
	    if [ -n "${INTF_INFO}" ]; then
		break
	    fi
	done
  else
	intf=$1
	# get the intf's mtu, network address, and IP address
	INTF_INFO=`netstat -n -I ${intf} -f inet`;
  fi

  if [ -z "${INTF_INFO}" ]; then
    return 1;
  fi
  INTF_MTU=`print "${INTF_INFO}" | awk 'NR == 2 { print $2 }'`;
  if [ -z "${INTF_MTU}" ]; then
    return 1;
  fi
  INTF_NET=`print "${INTF_INFO}" | awk 'NR == 2 { print $3 }'`;
  if [ -z "${INTF_NET}" ]; then
    return 1;
  fi
  INTF_IPA=`print "${INTF_INFO}" | awk 'NR == 2 { print $4 }'`;
  if [ -z "${INTF_IPA}" ]; then
    return 1;
  fi

  # get the intf's symbolic name
  INTF_NAME=`getent hosts ${INTF_IPA} | awk '{print $2}'`;
  if [ -z "${INTF_NAME}" ]; then
    print -u2 "Error: host name for ${INTF_IPA} not found"
    exit 1;
  fi

  # get the intf's netmask and broadcast address
  INTF_INFO=`ifconfig ${intf} ${IFCFG_INET}`;
  if [ ${?} -ne 0 ] || [ -z "${INTF_INFO}" ]; then
    return 1;
  fi
  INTF_MASK=`getNetMask "${INTF_INFO}"`
  INTF_BC=`print "${INTF_INFO}" | awk 'BEGIN { }
    {
      split($0, a);
      for (i = 0; i < NF; i++) {
	if (a[i] == "broadcast") {
	  print a[i + 1];
	}
      }
    }
    END { }'`;

  # get the intf's subnet prefix
  INTF_NETPFX=`print "${INTF_NET}" | sed -e 's/\.0//g'`;

  # get the net's symbolic name
  INTF_NETNAME=${CORONA_NAME}-${intf}
  if [ -z "${INTF_NETNAME}" ]; then
    print -u2 "Error: net name for ${INTF_NET} not found"
    exit 1;
  fi

#####print "${INTF_IPA}, ${INTF_NAME}, ${INTF_MASK}, ${INTF_NET}, ${INTF_MTU}, ${INTF_BC}";
  return 0;
}

#
# Must set up the same variables as GetInterfaceInfo
#
# netstat -i doesn't list most of what is wanted here.
# Get as much as possible from ifconfig.
#
function GetLinuxInterfaceInfo {
  typeset intf
  if [[ $# -eq 0 ]]; then
	# Interface not specified.  Use the info from the primary interface for the MTU.
	typeset intf_list=`netstat -n -A inet -i | \
		awk 'NR > 2 {if ($1 != "lo") print $1}'`
	if [[ -z "$intf_list" ]]; then
	    print -u2 "Error: unable to get information on primary interface"
	    return 1
	fi

	# get the first interface that is configured
	for intf in $intf_list
	do
	    INTF_INFO=`ifconfig ${intf} 2> /dev/null`;
	    if [ -n "${INTF_INFO}" ]; then
		break
	    fi
	done
  else
	intf=$1
	# get the intf's mtu, network address, and IP address
	INTF_INFO=`ifconfig ${intf} 2> /dev/null`;
  fi

  if [ -z "${INTF_INFO}" ]; then
    return 1;
  fi
  INTF_MTU=`GetLinuxIfconfigValue "${INTF_INFO}" "MTU"`;
  if [ -z "${INTF_MTU}" ]; then
    return 1;
  fi
  INTF_IPA=`GetLinuxIfconfigValue "${INTF_INFO}" "addr"`;
  if [ -z "${INTF_IPA}" ]; then
    return 1;
  fi
  INTF_BC=`GetLinuxIfconfigValue "${INTF_INFO}" "Bcast"`;
  if [ -z "${INTF_BC}" ]; then
    return 1;
  fi
  INTF_MASK=`GetLinuxIfconfigValue "${INTF_INFO}" "Mask"`;
  if [ -z "${INTF_MASK}" ]; then
    return 1;
  fi
  # Needs to get the network address, e.g. 10.6.132.0 for 10.6.132.45
  IP2Net $INTF_IPA $INTF_MASK
  if [ ${?} -ne 0 ]; then
    return 1;
  fi
  INTF_NET=$NET
  if [ -z "${INTF_NET}" ]; then
    return 1;
  fi

  # get the intf's symbolic name
  INTF_NAME=`getent hosts ${INTF_IPA} | awk '{print $2}'`;
  if [ -z "${INTF_NAME}" ]; then
    print -u2 "Error: host name for ${INTF_IPA} not found"
    exit 1;
  fi


  # get the intf's subnet prefix
  INTF_NETPFX=`print "${INTF_NET}" | sed -e 's/\.0//g'`;

  # get the net's symbolic name
  INTF_NETNAME=${CORONA_NAME}-${intf}
  if [ -z "${INTF_NETNAME}" ]; then
    print -u2 "Error: net name for ${INTF_NET} not found"
    exit 1;
  fi

  return 0;
}

#
# Given an ifconfig (on Linux) of a single interface, find the value
# for a field
#
# $1 - ifconfig result
# $2 - field to be found
#
function GetLinuxIfconfigValue {

  print "$1" | awk -v fldnm=$2 '{ for (i=1; i <= NF; i++) {
	if (split($i, fld, ":") == 2) {
	  if (fld[1] == fldnm) {
	    print fld[2]
	    exit
	  }
	}
      }
  }'
}

#
# Configure the interface
#
IfconfigLinux() {
    ifconfig ${INTF} > /dev/null 2>&1
    if [[ $? -ne 0 ]]; then
      print -u2 "Error:  invalid interface name: \"${INTF}\"";
      return 1
    fi
    Net2Broadcast ${NETADDR} ${NETMASK}
    typeset BROADCAST=${BRCST}
    ifconfig ${INTF} "${IPADDR}" up netmask "${NETMASK}" broadcast ${BROADCAST};
    RC=$?
    if [[ ${RC} -eq 0 ]] ; then
      rm -f ${TMPDIR}/tmpfile.$$;
      cat > ${TMPDIR}/tmpfile.$$ <<-!
DEVICE=${INTF} # SUNRAY ADD 
USERCTL=no # SUNRAY ADD 
${IFCONFIG_BOOT} # SUNRAY ADD 
BOOTPROTO=${BOOTPROTO} # SUNRAY ADD 
BROADCAST=${BROADCAST} # SUNRAY ADD
NETWORK=${NETADDR} # SUNRAY ADD
NETMASK=${NETMASK} # SUNRAY ADD
IPADDR=${IPADDR} # SUNRAY ADD
!
      if [[ -f ${IFCONFIG_SCRIPT}${INTF} ]] ; then
	sed -e "/.*/s/^/# SUNRAY DEL /" "${IFCONFIG_SCRIPT}${INTF}" > ${IFCONFIG_SCRIPT}${INTF}.$$
        #
        # change ether config so it starts on boot
	
	rm -f ${IFCONFIG_SCRIPT}${INTF}
	cat ${IFCONFIG_SCRIPT}${INTF}.$$ ${TMPDIR}/tmpfile.$$ > ${IFCONFIG_SCRIPT}${INTF}
	rm -f ${IFCONFIG_SCRIPT}${INTF}.$$ ${TMPDIR}/tmpfile.$$
      else
        mv -f ${TMPDIR}/tmpfile.$$ ${IFCONFIG_SCRIPT}${INTF};
      fi
    fi
    print "### finished install of \"${INTF}\" interface";
    return $RC

}


#
# Unconfigure the interface
#
IfconfigDownLinux() {
    ifconfig ${INTF} down;

    #
    # change ether config so it doesn't start on boot
    if [[ -f ${IFCONFIG_SCRIPT}${INTF} ]] ; then
      RestoreFile ${IFCONFIG_SCRIPT}${INTF};
      if [[ ! -s ${IFCONFIG_SCRIPT}${INTF} ]]; then
	rm -f ${IFCONFIG_SCRIPT}${INTF}
      fi
    else
      print -u2 "Warning: unable to update ${IFCONFIG_SCRIPT}${INTF}";
    fi
}


#
# makes sure the Sun Ray options are defined in DHCP
#
function SetupDHCPOptions {
  typeset TMPOPTIONS=${TMPDIR}/utdhcpoptions-out.$$
  rm -f ${TMPOPTIONS} 2> /dev/null

  ${UTDHCPOPT} > $TMPOPTIONS 2> /dev/null
  InitDHCPBlockParser $TMPOPTIONS
  if [[ $? -eq 0 ]] ; then
    GetNextDHCPBlock options
    if [[ $? -eq 0 ]] ; then
      DestroyDHCPBlockParser
      rm -f ${TMPOPTIONS} 2> /dev/null
      return 0
    fi
  fi
  DestroyDHCPBlockParser
  rm -f ${TMPOPTIONS} 2> /dev/null

  #
  # Sun Ray options not set, need to set them
  #
  InitOptionsBlock
  UT_DHCP_AUTHPORT=${AUTH_PORT}
  UT_DHCP_LOGHOST=${HOSTIP}
  UT_DHCP_LOGKERNEL=${LOG_KERN}
  UT_DHCP_LOGNET=${LOG_NET}
  UT_DHCP_LOGUSB=${LOG_USB}
  UT_DHCP_LOGVIDEO=${LOG_VID}
  UT_DHCP_LOGAPPLICATION=${LOG_APPL}

  GenerateOptionsBlock > $TMPOPTIONS
  DestroyDHCPBlockParser

  ${UTDHCPOPT} add < $TMPOPTIONS > /dev/null 2> ${TMPDIR}/Err.$$;
  typeset RET=$?
  if [ $RET -ne 0 ] ; then
    print -u2 "Error:  unable to add vendor options to dhcp:\n    `cat ${TMPDIR}/Err.$$`"
    RET=1;
  fi

  rm -f ${TMPOPTIONS} 2> /dev/null
  rm -f ${TMPDIR}/Err.$$ 2> /dev/null
  return $RET
}

#
# adds the macro for the interface or subnet
#
function DoAddIntfsMacro {

    typeset ADDBLOCK=${TMPDIR}/AddBlock.$$;
    rm -f ${ADDBLOCK} 2>/dev/null
    if $SUBNETMODE; then
	# adding subnetwork
	SUBNET=${SUBNET_ADD}

	# use the MTU info from the primary interface.  Other values will be set 
	# according to the info entered.
	GetInterfaceInfo
	if [ ${?} -ne 0 ]; then
	    print -u2 "Error:  unable to get information on the primary interface."
	    return 1;
	fi

	# override information from ifconfig
	INTF_NET=${SUBNET}
	INTF_NETNAME=${CORONA_NAME}-${SUBNET}
	INTF_MASK=${NETMASK}
	Net2Broadcast ${SUBNET} ${NETMASK}
	INTF_BC=${BRCST}
	InitSubnetBlock
    else
	# adding interface
	INTF=${INTF_ADD}
	INTF_NET=${NETADDR}

	# get all the info for this interface
	GetInterfaceInfo "${INTF}";
	if [ ${?} -ne 0 ]; then
	    print -u2 "Error:  unable to get information on interface \"${INTF}\""
	    return 1;
	fi

	InitInterfaceBlock
	UT_DHCP_INTERFACE=${INTF}
	UT_DHCP_HOSTNAME=${NAME}
	UT_DHCP_IP=${IPADDR}
    fi

    UT_DHCP_NETWORK=${INTF_NET}
    UT_DHCP_NETMASK=${INTF_MASK}
    UT_DHCP_FIRMWARESRVR=${FWSRVR}
    UT_DHCP_AUTHSRVR=${AUTHSRVR}
    UT_DHCP_ALTAUTHLIST=${ALTAUTH}
    if [[ ${START_NUM} != 0 ]] ; then
	UT_DHCP_RANGE="${START_ADDR} ${END_ADDR}"

	# add a network macro for each interface
	# (contains broadcast ipa, subnet mask, mtu, router ipa)
	UT_DHCP_BROADCAST=${INTF_BC}
	UT_DHCP_SUBNETMASK=${INTF_MASK}
	UT_DHCP_MTU=${INTF_MTU}
	if [ "${MULTINET}" = "N" ]; then
	    if [ -n "${ROUTER}" ]; then
		UT_DHCP_ROUTERS=${ROUTER}
	    fi
	fi
    fi
    if $SUBNETMODE; then
      GenerateSubnetBlock > ${ADDBLOCK}
    else
      GenerateInterfaceBlock > ${ADDBLOCK}
    fi
    ${UTDHCPNET} add < ${ADDBLOCK}
    if [ ${?} -ne 0 ]; then
      if $SUBNETMODE; then
	print -u2 "Error:  cannot add subnet \"${SUBNET_ADD}\" to dhcp:\n    `cat ${TMPDIR}/Err.$$`"
      else
	print -u2 "Error:  cannot add interface \"${INTF_NETNAME}\" to dhcp:\n    `cat ${TMPDIR}/Err.$$`"
      fi
    fi
    rm -f ${TMPDIR}/Err.$$;
    rm -f ${ADDBLOCK}
}

function addNetwork {
  if [ ! -f ${NETWORKS} ] ; then
    return
  fi
  while read name ip rest
  do
    if [ "${name}" = $1 -a "${ip}" = $2 ]; then
      return
    fi
  done <${NETWORKS}

  StartFileUpdate "${NETWORKS}";
  # remove anything that matches net prefix from ${NETWORKS} and add new line
  rm -f ${TMPDIR}/tmpfile.$$;
  sed -e "/^${1}/s/^/# SUNRAY DEL /" "${NETWORKS}.$$" > ${TMPDIR}/tmpfile.$$;
  print "${1}\t${2}\t${CORONA_NAME}\t# SUNRAY ADD - DO NOT MODIFY" \
	>>${TMPDIR}/tmpfile.$$;
  mv -f ${TMPDIR}/tmpfile.$$ "${NETWORKS}.$$";
  EndFileUpdate "${NETWORKS}";
}

# add netmask entry if needed
function addNetMask {
  if [ ! -f ${NETMASKS} ]; then
    return
  fi
  while read nw nm rest
  do
    if [ "$nw" = $1 -a "$nm" = $2 ]; then
	return
    fi
  done <${NETMASKS}

  # update the /etc/netmasks file
  StartFileUpdate "${NETMASKS}";

  # remove anything that matches the net address and add new line
  rm -f ${TMPDIR}/tmpfile.$$;
  sed -e "/^[ 	#]*${1}[ 	]/s/^/# SUNRAY DEL /" "${NETMASKS}.$$" \
	>${TMPDIR}/tmpfile.$$;
  print "${1}\t${2} # SUNRAY ADD - DO NOT MODIFY" >> ${TMPDIR}/tmpfile.$$;
  mv -f ${TMPDIR}/tmpfile.$$ "${NETMASKS}.$$";

  EndFileUpdate "${NETMASKS}";
}

#
# remove netmask entry by the network number
# Parameters:
#	$1 network number (ex: 192.168.128.0)
#
function rmvNetMask_byNetwork {
  if grep "^${1}[ 	].*# SUNRAY ADD" ${NETMASKS} >/dev/null 2>&1; then
  	sed "/^${1}[ 	].*# SUNRAY ADD/d" ${NETMASKS} >${NETMASKS}.$$
  	mv ${NETMASKS}.$$ ${NETMASKS}
  fi
}

#
# remove netmask entry by the interface name if needed?
# Parameters:
#	$1 interface name  (ex: SunRay-hme1)
#
function rmvNetMask_byIntf {
  while read name ip rest
  do
    if [ "$ip" = $1 ]; then
      return
    fi
  done <${NETWORKS}
      
  rmvNetMask_byNetwork $1
}

#
# find the network for a given interface
# Parameters:
#	$1 interface  (ex: hme1)
#
function GetNetByIntf {
    InitDHCPBlockParser $CUR_CFG_F
    if [[ $? -eq 0 ]] ; then
      while GetNextDHCPBlock all
      do
	if [[ $BLOCKTYPE = "interface" ]] ; then
	  if [[ ${UT_DHCP_INTERFACE} = $1 ]] ; then
	    DestroyDHCPBlockParser
	    print ${UT_DHCP_NETWORK}
	    return 0
	  fi
	fi
      done
    fi

    DestroyDHCPBlockParser
    return 1
}

#
# find the interface for a given network
# Parameters:
#	$1 network  (ex: 192.168.128.0)
#
function GetIntfByNet {
    InitDHCPBlockParser $CUR_CFG_F
    if [[ $? -eq 0 ]] ; then
      while GetNextDHCPBlock all
      do
	if [[ $BLOCKTYPE = "interface" ]] ; then
	  if [[ ${UT_DHCP_NETWORK} = $1 ]] ; then
	    DestroyDHCPBlockParser
	    print ${UT_DHCP_INTERFACE}
	    return 0
	  fi
	fi
      done
    fi

    DestroyDHCPBlockParser
    return 1
}

function PrepCurrentCfg {

    rm -f $CUR_CFG_F 2> /dev/null
    rm -f ${TMPDIR}/dhcpifs.$$ 2> /dev/null
    rm -f ${TMPDIR}/dhcpallnets.$$ 2> /dev/null
    rm -f ${TMPDIR}/allnets.$$ 2> /dev/null
    rm -f ${TMPDIR}/newtifs.$$ 2> /dev/null
    rm -f ${TMPDIR}/allifs.$$ 2> /dev/null
    rm -f ${TMPDIR}/allSRnets.$$ 2> /dev/null

    # now create empty files in case one isn't generated
    touch ${TMPDIR}/dhcpifs.$$
    touch ${TMPDIR}/dhcpallnets.$$
    touch ${TMPDIR}/allnets.$$
    touch ${TMPDIR}/newtifs.$$
    touch ${TMPDIR}/allifs.$$
    touch ${TMPDIR}/allSRnets.$$
}


#
# get a list of current Sunray interfaces and subnetworks.
# This routine also create many output files which will be used later on. 
# This is done to avoid having to call java commands like dhtadm again.
# Here are a list of files created under the ${TMPDIR} directory.
#	utdhcpnet-F.$$ contains the current utdhcpnet output
#	newtifs.$$ contains the list of sunray interfaces currently defined in
#		the /etc/networks file.
#	dhcpifs.$$ contains the list of sunray interfaces that are listed by
#		the SunRay-<intfs> macros in the dhcp table.
#	allifs.$$ contains all the interfaces for SunRay network.
#	allnets.$$ contains the list of sunray subnetworks that are listed
#		by the SunRay-<subnet> macros in the dhcp table. 
#	allSRnets.$$ contains the list of all sunray subnets, both subnetworks
#		and interfaces.
#
function GetCurrentCfg {

    PrepCurrentCfg	# initialize the config files

    ${UTDHCPNET} > $CUR_CFG_F
    awk -F= '/begin interface/,/end/ {if ($1 == "interface") print $2}' \
				$CUR_CFG_F >>${TMPDIR}/dhcpifs.$$
    awk -F= '/begin subnet/,/end/ {if ($1 == "network") print $2}' \
				$CUR_CFG_F >>${TMPDIR}/allnets.$$
    awk -F= '/begin interface/,/end/ {if ($1 == "network") print $2}' \
				$CUR_CFG_F >>${TMPDIR}/dhcpallnets.$$

    # get interfaces that currently configure to support SunRay
    if [[ -f ${NETWORKS} ]] ; then
      sed -n "s/^${CORONA_NAME}-\([^0-9 	][^ 	]*\)[ 	].*$/\1/p" \
	${NETWORKS} >>${TMPDIR}/newtifs.$$
    fi
    sort -u ${TMPDIR}/newtifs.$$ ${TMPDIR}/dhcpifs.$$ >>${TMPDIR}/allifs.$$

    # get all sunray networks, including the ones for the interfaces
    sort -u ${TMPDIR}/dhcpallnets.$$ ${TMPDIR}/allnets.$$ \
	>> ${TMPDIR}/allSRnets.$$

    rm ${TMPDIR}/dhcpallnets.$$ 2> /dev/null
}

# fix up network names to put interface name into the network name
function FixNetworks {

    typeset changed=false
    grep 'SUNRAY ADD' ${NETWORKS} | \
    while read name ip rest
    do
	if print $name | $GREP -q "^#"; then
	    # found commented out lines.  This should not happen unless someone
	    # manually edited the entries.  -- ignore the commented out lines
	    continue
	fi
	INTF=`print $name | sed -n "s/^${CORONA_NAME}-//p"`
	if [ -z "${INTF}" -o -f "${HOSTNAME_R}.${INTF}" ]; then
	    continue
	fi

	intf=`GetIntfByNet ${ip}`

	if [ $name != ${CORONA_NAME}-${intf} ]; then
	    print "### fixing interface \"${INTF}\"."
	    # XXX For Solaris it is changing the macro's name! <===
	    typeset TMPFILE=${TMPDIR}/utdhcpnet-delete.$$
	    rm -f ${TMPFILE} 2> /dev/null
	    print "begin interface"  >> ${TMPFILE}
	    print "interface=${intf}"  >> ${TMPFILE}
	    print "hostname=${CORONA_NAME}-${intf}"  >> ${TMPFILE}
	    print "end"  >> ${TMPFILE}
	    ${UTDHCPNET} change < ${TMPFILE}
	    rm -f ${TMPFILE} 2> /dev/null
	    sed -e "s/^\<$name\>/${CORONA_NAME}-${intf}/g" ${NETWORKS} >${NETWORKS}.new
	    cp ${NETWORKS}.new ${NETWORKS}
	    rm ${NETWORKS}.new
	    changed=true

	    M=`getent netmasks $ip | awk '{print $2}'` 
	    if [ -z $M ]; then
		print -u2 "Error: netmask for host $1 does not exist";
		continue;
	    fi
	    IP2Net $ip $M
	    if [ ${?} -ne 0 ]; then
		continue;
	    fi
	    # XXX fixed network IP assignment table with pntadm <===
	fi
    done

    if $changed ; then
	RestartDHCP
    fi
}


#
# initializes the framework for Sun Ray interconnect
# removes any old newt stuff and update the /etc/nsswitch.conf file
#
DoInit() {

    print "### Configuring ${NSSWITCH}";
    StartFileUpdate ${NSSWITCH};
    RestoreFile "${NSSWITCH}.$$";
    UpdateNsswitch "${NSSWITCH}.$$";
    EndFileUpdate "${NSSWITCH}";

    # check if the networks file exists
    if [ ! -f "${NETWORKS}" ]; then
	# doesnt exist, so make a default one
	cat > ${NETWORKS} <<-!
#
# The networks file associates Internet Protocol (IP) network numbers
# with network names.  The format of this file is:
# 
#       network-name    network-number  nicnames . . .
#

#
# The loopback network is used only for intra-machine communication
#
loopback        127

#
# Internet networks
#
arpanet         10              arpa    # Historical

!
	chmod 744 "${NETWORKS}";
    fi

    # check if the netmasks file exists
    if [ ! -f "${NETMASKS}" ]; then
	# doesnt exist, so make a default one
	cat > ${NETMASKS} <<-!
# The netmasks file associates Internet Protocol (IP) address
# masks with IP network numbers.
#
#       network-number  netmask
#
# The term network-number refers to a number obtained from the Internet Network
# Information Center.  Currently this number is restricted to being a class
# A, B, or C network number.  In the future we should be able to support
# arbitrary network numbers per the Classless Internet Domain Routing
# guidelines.
#
# Both the network-number and the netmasks are specified in
# \"decimal dot\" notation, e.g:
#
#               128.32.0.0 255.255.255.0
#

!
	chmod 744 "${NETMASKS}"
    fi

    print "### Configuring Service information for ${CORONA_TITLE}";
    SetupCfgFile;
    SetupDHCPOptions
    if [ $? -ne 0 ] ; then
      return 1;
    fi

    GetCurrentCfg	# re-read the DHCP info
    if [[ "$OS" = "SunOS" ]] ; then
      SetupOptions;
      # Remove this because the reason for it should be fixed in dtlogin
      #  NohupDtlogin;
      if [ -f "${INIT_SYSSUSPEND}" ]; then
	FixSysSuspend;
      fi
      FixSessionEtc;
      if [ -f ${INIT_OPENWINSYS} ]; then
	# S9 no longer supports OpenWindows, so this is not necessary
	FixOpenwinSys;
      fi
    fi

    #
    # check to see if the dhcp daemon is running.
    # If yes, this means that this server is being configured for the first time
    # (dhcpconfig starts the dhcp daemon automatically) or the daemon was already
    # running prior to utadm.  In this case, restart the dhcp daemon so that it
    # rereads the ulimit value in the dhcp startup script.
    # If no, this means the server was already configured to provide dhcp service
    # but the daemon was not running or the daemon failed to startup as part
    # of the dhcpconfig command.  In this case, we will warn the users at the end
    # of the utadm script that dhcp is not running and they should start it manually.
    #
    GetDHCPpid
    if [ "${dhcppid}" ]; then
	# DHCP daemon can be running because:
	# 1. it was started by dhcpconfig -D in SetupCfgFile(), or
	# 2. it was running before.  In this case, the $DHCP_RUNNING variable should
	#    already be set to true so that we can restart DHCP at the end without
	#    prompting the user.
	# For now, just stop the DHCP daemon.  If it fails, just ignore it for now.
	# It will try to stop it again later.
	StopDHCP 2>&1 >/dev/null
    fi

    #
    # By default, Linux does not configure itself as a router.
    # XXX Need to add a check to see if the administrator has
    # configured this as a router and generate an error message <===
    #
    if [[ "$OS" = "SunOS" ]] ; then
      print "### Disabling Routing";
      touch /etc/notrouter
      ndd -set /dev/ip ip_forwarding 0
    fi
}


#
# removes the DHCP info
#
DoRemoveDHCP() {

    typeset TMPFILE=${TMPDIR}/utdhcpnet-delete.$$
    typeset retcode=0

    rm -f ${TMPFILE} 2> /dev/null
    if $SUBNETMODE; then
    	print "### Removing ${CORONA_TITLE} information for subnetwork \"${SUBNET_DEL}\""
	print "begin subnet" > ${TMPFILE}
	print "network=${SUBNET_DEL}" >> ${TMPFILE}
	print "end" >> ${TMPFILE}
    else
    	print "### Removing ${CORONA_TITLE} information for interface \"${DHCP_DEL}\""
	print "begin interface" > ${TMPFILE}
	print "interface=${DHCP_DEL}" >> ${TMPFILE}
	print "end" >> ${TMPFILE}
    fi
    if ! ${UTDHCPNET} delete < ${TMPFILE}; then
	retcode=1
    fi
    rm -f ${TMPFILE} 2> /dev/null
    return $retcode
}


#
# removes interfaces
#
DoRemoveIntf() {

    typeset INTF=${INTF_DEL}

    # remove the entry in the networks file first.
    INTF_NETNAME=${CORONA_NAME}-${INTF}
    sed "/^${INTF_NETNAME}[ 	].*# SUNRAY ADD/d" ${NETWORKS} >${NETWORKS}.$$
    mv ${NETWORKS}.$$ ${NETWORKS}

    if [ ! -f ${HOSTNAME_R}.${INTF} ]; then
	print -u2 "Error: missing \"${HOSTNAME_R}.${INTF}\" file."
	return 1
    fi
    print "### Removing ${CORONA_TITLE} interface configuration for \"${INTF}\"";

    INTF_NAME=`cat ${HOSTNAME_R}.${INTF}`;
    if [ -z "${INTF_NAME}" ]; then
	print -u2 "Error: interface ${INTF} is partially configured.  Hostname not" \
		"specified in the \"${HOSTNAME_R}.${INTF}\" file."
	return 1
    fi

    INTF_IPA=`getent hosts ${INTF_NAME} | awk '{print $1}'`
    if [ -z "${INTF_IPA}" ]; then
	print -u2 "Error: unable to resolve the hostname \"${INTF_IPA}\" specified in the" \
		"\"${HOSTNAME_R}.${INTF}\" file."
	return 1
    fi
    if [[ $OS = "SunOS" ]] ; then
      M=`getent netmasks ${INTF_IPA} | awk '{print $2}'` 
    else
      INTF_INFO=`ifconfig ${INTF} 2> /dev/null`;
      if [ -z "${INTF_INFO}" ]; then
	return 1;
      fi
      M=`GetLinuxIfconfigValue "${INTF_INFO}" "Mask"`;
    fi
    if [ -z $M ]; then
	print -u2 "Error: netmask for host $1 does not exist";
	return 1
    fi
    IP2Net ${INTF_IPA} ${M}
    if [ ${?} -ne 0 ]; then
	print -u2 "Error: Cannot translate host \"${INTF_NAME}\" for interface \"${INTF}\" to a network number"
	return 1
    fi
    INTF_NET=$NET
    rmvNetMask_byIntf ${INTF_NET}

    grep "^${INTF_IPA}[ 	].*# SUNRAY ADD" ${HOSTS} >/dev/null 2>&1
    if [ $? -ne 0 ]; then
	print "### Leaving interface \"${INTF}\" up"
    else
	if [[ $OS = "SunOS" ]] ; then
	    ifconfig ${INTF} down 2>&1 >/dev/null;
	    ifconfig ${INTF} unplumb 2>&1 >/dev/null;
	else
	    IfconfigDownLinux
	fi
	sed "/^${INTF_IPA}[ 	].*# SUNRAY ADD/d" ${HOSTS} >${HOSTS}.$$
	mv ${HOSTS}.$$ ${HOSTS}
	rm -f ${HOSTNAME_R}.${INTF}
    fi

    Restart_nscd
    return 0
}


#
# removes the system configuration files
#
DoRemoveSysFiles() {
    RestoreFile "${NSSWITCH}";
    RestoreFile "${HOSTS}";
    if [ -f "${NETWORKS}" ]; then
      RestoreFile "${NETWORKS}";
    fi
    if [ -f "${NETMASKS}" ]; then
      RestoreFile "${NETMASKS}";
    fi

    if [[ "$OS" = "SunOS" ]] ; then
      RestoreFile "${INIT_DHCP}";
      RestoreFile "${INIT_DTLOGIN}";
      if [ -f "${INIT_SYSSUSPEND}" ]; then
	RestoreFile "${INIT_SYSSUSPEND}";
      fi
      RestoreFile "${INIT_SESSIONETC}";
      if [ -f ${INIT_OPENWINSYS} ]; then
	RestoreFile "${INIT_OPENWINSYS}";
      fi

      # in case of old links are left behind
      rm /etc/rcS.d/K35utdhcp 2> /dev/null
      rm /etc/rc0.d/K35utdhcp 2> /dev/null
      rm /etc/rc1.d/K35utdhcp 2> /dev/null
      rm /etc/rc2.d/K35utdhcp 2> /dev/null
      rm /etc/rc3.d/S35utdhcp 2> /dev/null
    fi

    typeset TMPOPTIONS=${TMPDIR}/utdhcpoptions-delete.$$
    rm -f ${TMPOPTIONS} 2> /dev/null

    # Remove the DHCP options
    if $ISSETUP; then
      print "begin options\nend\n" > ${TMPOPTIONS}
      ${UTDHCPOPT} delete < $TMPOPTIONS > /dev/null 2>&1
      rm -f ${TMPOPTIONS} 2> /dev/null
    fi

    $UTSBIN/utfwadm -R

    ${UTDHCPSERVICE} stop > /dev/null 2>&1
    ${UTDHCPSERVICE} disable > /dev/null 2>&1
}


#
# adds the SR network configuration for both interface and subnetwork only.
#
DoAddNetworkConfig() {
    ADD_NETMASK=false

    typeset noIPaddr=0
    typeset INTF_ALL=""
    typeset BRDCST=""

    if $SUBNETMODE; then
	# adding subnetwork
	SUBNET=${SUBNET_ADD}
    else
	# adding interface
	if [[ "$OS" = "SunOS" ]] ; then
	  INTF_ALL=`ifconfig -a ${IFCFG_INET} | sed -n -e '/lo0/d' -e '/: flags=/s/:.*//p'`
	else
	  INTF_ALL=`ifconfig -a | awk '/Ethernet/ {print $1}'`
	fi
	INTF=${INTF_ADD}
    fi

    # do all per-interface operations
    N=${DEF_START_NET};
    if $SUBNETMODE; then
	# adding subnet, so do dhcp only.  No need to configure the interface.
	DHCPONLY="Y"
    else
	# see if interface is already in use
	DHCPONLY="N"
	for test in ${INTF_ALL}; do
	    if [ "${INTF}" = "${test}" -a -f "${HOSTNAME_C}${INTF}" ]; then
		#
		# Need to catch the case where hostname.<intf> exists but the hostname
		# defined in the file may not be configured locally in the hosts file.
		#
		if [ ! -f ${HOSTNAME_C}${INTF} ]; then
		    print -u2 "Error: missing \"${HOSTNAME_R}${INTF}\" file."
		    return 1
		fi
		if [[ $OS == "SunOS" ]]; then
			NAME=`cat ${HOSTNAME_C}${INTF}`
			if [ -z "${NAME}" ]; then
                    		print -u2 "Error: interface ${INTF} is partially configured.  Hostname" \
                        	"not specified in the \"${HOSTNAME_C}${INTF}\" file."
                    		exit 1
                	fi
			if ! getent hosts ${NAME} 2>&1 >/dev/null; then
                    		print -u2 "Error: unable to resolve the hostname \"${NAME}\" specified" \
                        	"in the \"${HOSTNAME_C}${INTF}\" file."
                    		exit 1
                	fi
		else
			IPTEST=`cat ${HOSTNAME_C}${INTF} | grep "^IPADDR"`
			if [[ -z ${IPTEST} ]]; then
				continue
			fi
			IPTEST=${IPTEST#*=}
			IPTEST=${IPTEST#\'}
			IPTEST=${IPTEST%\'}
			NAME=`getent hosts ${IPTEST} | awk '{print $2}'`
			if [ -z "${NAME}" ]; then
				continue
			fi
			NAME=${NAME%%\.*}
		fi

		# check to see if it's a primary interface
		if [ "${NAME}" = ${HOSTNAME} ]; then
		    print -u2 "Interface \"${INTF}\" is the primary network connection"
		    print -u2 "configured as hostname \"${HOSTNAME}\"."
		    print -u2 "Use of -a is reserved to configure dedicated interconnects."
		else
		    print -u2 "Interface \"${INTF}\" is already configured as"
		    print -u2 "hostname \""${NAME}"\""
		    print -u2 "To configure ${INTF} as a dedicated interconnect:"
		    print -u2 "\tremove the file ${HOSTNAME_R}/${INTF} and"
		    print -u2 "\tremove the host entry ${NAME} or use a different hostname."
		fi
		print -u2 "Please use the -A option to configure support for shared networks."
		exit 1
	    fi
	done
    fi

    MULTINET="N"
    NODHCP="N"
    if [ "${DHCPONLY}" = "N" ]; then
	#
	# This section initializes the variables for the interface.
	#

	# look in ${NETWORKS} file until we find a subnet that's available
	while :
	do
	    fgrep "${DEF_NET_PFX}.${N}.0" ${NETWORKS} >/dev/null;
	    if [ ${?} -ne 0 ]; then
		# also check in the dchp table for the subnetwork
		grep "${DEF_NET_PFX}.${N}.0" ${CUR_CFG_F} 2> /dev/null
		if [[ $? -ne 0 ]] ; then
		    # subnetwork not defined in the dhcp table
		    break;
		fi
	    fi
	    let "N = N + 1";
	done

	NETADDR="${DEF_NET_PFX}.${N}.0";
	print "### configuring ${INTF} interface at subnet ${NETADDR}";

	# get interface network info
	IPADDR="${DEF_NET_PFX}.${N}.1";
	NAME="${HOSTNAME}-${INTF}";
	SYS_NETMASK=""
	CLASS_NETMASK=$(GetNetmaskClass ${NETADDR})
	NETMASK=$CLASS_NETMASK
	ADD_NETMASK=true
	NETNAME="${CORONA_NAME}-${INTF}";
	START_NUM=${DEF_START_NUM};
	END_NUM=${DEF_END_NUM};
	FWSRVR=${IPADDR}
	ALTAUTH=${IPADDR}
	ROUTER=${IPADDR}

	SVIP=${IPADDR}
	SVMSK=${NETMASK}
	SVNET=${NETADDR}
	MaxHostNum ${NETMASK}
	MHN=$H
    else
	#
	# This section initializes subnetwork variables
	#
	if $SUBNETMODE; then
	    # adding subnet
	    IPADDR=${HOSTIP}
	    CLASS_NETMASK=$(GetNetmaskClass ${SUBNET})
	    if [[ $OS = "SunOS" ]] ; then
	      SYS_NETMASK=`getent netmasks ${SUBNET} | awk '{print $2}'`
	    else
	      SYS_NETMASK=""
	    fi
	    if [ -z "$SYS_NETMASK" ]; then
		# netmask not defined in the naming database.
		# Use netmask that fits the subnet.
		Net2Mask ${SUBNET}
		if [ ${?} -ne 0 ] ; then
		    print -u2 "Error:  invalid subnet address \"${SUBNET}\"";
		    print -u2 "\tUnable to generate a netmask that would";
		    print -u2 "\tallow at least two IP addresses\n";
		    exit 1
		fi
		NETMASK=$NMASK
	    else
		NETMASK=$SYS_NETMASK
	    fi
	    NETADDR=${SUBNET}
	    NETNAME="${CORONA_NAME}"
	    MaxHostNum ${NETMASK}
	    MHN=$H
	    NetPlusHost ${NETADDR} "1" $MHN
	    ROUTER=$IP
	    noIPaddr=1
	else
	    # adding interface
	    IPADDR=`getent hosts ${NAME} | awk '{print $1}'`
	    config=`ifconfig ${INTF} ${IFCFG_INET}`
	    if [ $? -ne 0 ]; then
		print -u2 "Existing interface ${INTF} must be up to do configuration"
	    exit 1
	    fi
	    if [[ $OS = "SunOS" ]] ; then
	      SYS_NETMASK=`getNetMask "${config}"`
	    else
	      SYS_NETMASK=`GetLinuxIfconfigValue "${INTF_INFO}" "Mask"`;
	    fi
	    NETMASK=$SYS_NETMASK
	    CLASS_NETMASK=$(GetNetmaskClass ${config})
	    ADD_NETMASK=false
	    if [[ $OS = "SunOS" ]] ; then
	      SYS_NETMASK=`getent netmasks ${SUBNET} | awk '{print $2}'`
	    fi
	    IP2Net ${IPADDR} ${NETMASK}
	    NETADDR=$NET
	    NETNAME="${CORONA_NAME}-${INTF}"
	    if [[ $OS = "SunOS" ]] ; then
	      ROUTER=`netstat -rn -f inet| grep '^default' | awk '{print $2}'`
	    else
	      ROUTER=`netstat -rn | grep '^0.0.0.0' | awk '{print $2}'`
	    fi
	    MaxHostNum ${NETMASK}
	    MHN=$H
	fi
	MaxHostNum ${CLASS_NETMASK}
	CLASS_MAXHOST=$H
	let "START_NUM = $H - 10"
	let "END_NUM = $H - 1"
	FWSRVR=${IPADDR}
	ALTAUTH=${IPADDR}
    fi

    while :
    do		# prompt for new values
	if [ ${noIPaddr} -eq 0 ]; then
	    NetPlusHost ${NETADDR} ${START_NUM} ${MHN}
	    START_ADDR=$IP
	    NetPlusHost ${NETADDR} ${END_NUM} ${MHN}
	    END_ADDR=$IP
	fi

	if $SUBNETMODE; then
	    print "  Selected values for subnetwork \"${SUBNET}\" ";
	else
	    print "  Selected values for interface \"${INTF}\" ";
	    print "    host address:\t${IPADDR}";
	fi
	print "    net mask:\t\t${NETMASK}";
	if ! $SUBNETMODE; then
	    print "    net address:\t${NETADDR}";
	    print "    host name:\t\t${NAME}";
	    print "    net name:\t\t${NETNAME}";
	fi
	if [ ${noIPaddr} -eq 0 ]; then
		print "    first unit address:\t${START_ADDR}";
		print "    last unit address:\t${END_ADDR}";
	else
		print "    no IP addresses offered"
	fi
	print "    auth server list:\t${ALTAUTH}";
	print "    firmware server:\t${FWSRVR}";
	if [ ${noIPaddr} -eq 0 ]; then
		print "    router:\t\t${ROUTER}";
	fi

	YesOrNo "  Accept as is?" "Y";
	if [ ${?} -eq 0 ]; then
		break;
	fi

	# get new ip address from user
	if [ "${DHCPONLY}" = "N" ]; then
	    while :
	    do		# host ip
		print -n "  new host address: [${IPADDR}] ";
		read ANS
		:
		if [ -z "${ANS}" ]; then
		    ANS=${IPADDR};
		fi
		echo $ANS >> $LOGFILE
		CheckIPA "${ANS}";
		if [ ${?} -eq 0 ]; then
		    IPADDR=${ANS};
		    FWSRVR=${ANS};
		    ALTAUTH=${ANS}
		    ROUTER=${ANS};
		    CLASS_NETMASK=$(GetNetmaskClass ${IPADDR})
		    NETMASK=$CLASS_NETMASK
		    MaxHostNum ${CLASS_NETMASK}
		    CLASS_MAXHOST=$H
		    break;
		else
		    print -u2 "Error:  invalid IP address\n";
		fi
	    done	# host ip

	    MaxHostNum ${NETMASK}
	    MHN=$H
		 
	    if [[ -n "${SYS_NETMASK}" ]]; then
		print "  netmask: ${NETMASK} (cannot be changed - system defined netmask)";
	    else
		# get new netmask from user
		while :
		do		# netmask
		    print -n "  new netmask: [${NETMASK}] ";
		    read ANS
		    :
		    if [ -z "${ANS}" ]; then
			ANS=${NETMASK};
		    fi
		    echo $ANS >> $LOGFILE
		    CheckIPA "${ANS}";
		    if [ ${?} -ne 0 ]; then
			print -u2 "Error:  invalid netmask\n";
			continue
		    fi
		    MaxHostNum $ANS
		    if [ ${?} -ne 0 ]; then
			print -u2 "Error: invalid netmask \"$ANS\""; 
			continue;
		    fi
		    if [ ${H} -gt ${CLASS_MAXHOST} ]; then
			print -u2 "Error: invalid netmask for the specified IP \"${IPADDR}\""
			continue;
		    fi

		    # check netmask against the system one
		    HOLD_NETMASK=$ANS
		    if CheckNetmaskValue $HOLD_NETMASK; then
			# force to add netmask for private interconnect
			ADD_NETMASK=true
			NETMASK=${HOLD_NETMASK}
			MHN=$H
			break
		    fi
		done	# netmask

		IP2Net ${IPADDR} ${NETMASK}
		NETADDR=$NET
	    fi
  
	    # Check for network addresses that are already configured as
	    # SR subnetworks
	    fgrep "${NETADDR}" ${TMPDIR}/allnets.$$ >/dev/null
	    if [ $? -eq 0 ]; then
		# this same subnetwork already configured
		print -u2 "Error: subnetwork \"${NETADDR}\" already configured, cannot add"
		exit 1
	    fi

	    # check for interfaces that are configured with the same network
	    fgrep "${NETADDR}" ${TMPDIR}/allSRnets.$$ >/dev/null
	    if [ $? -eq 0 ]; then
		print -u2 "Warning: network address \"${NETADDR}\" is already in use";
		YesOrNo "Configure multiple interfaces on this network? " "N"
		if [ $? -eq 0 ]; then
		    #
		    # XXX For Linux <===
		    # XXX Need to add a check to see if the administrator has
		    # configured this to allow multiple interfaces on a network
		    # and generate an error message <===
		    #
		    if [[ $OS = "SunOS" ]] ; then
			locmac=`/usr/sbin/eeprom | sed -n 's/local-mac-address?=//p'`
			if [ "$locmac" != "true" ]; then
			    print -u2 "Error: must set prom variable local-mac-address? to \"true\""
			    print -u2 "See eeprom(1M)"
			    IPADDR=${SVIP};
			    FWSRVR=${SVIP};
			    ALTAUTH=${SVIP};
			    NETMASK=${SVMSK};
			    NETADDR=${SVNET};
			    continue;
			fi
		    fi
		    MULTINET="Y"
		else
		    IPADDR=${SVIP};
		    FWSRVR=${SVIP};
		    ALTAUTH=${SVIP};
		    ROUTER=${SVIP};
		    NETMASK=${SVMSK};
		    NETADDR=${SVNET};
		    continue;
		fi
	    fi
  
	    if [ ${NETADDR} = ${IPADDR} ]; then
		print -u2 "Error: host address \"${IPADDR}\" is equal to net address";
		IPADDR=${SVIP};
		FWSRVR=${SVIP};
		ALTAUTH=${SVIP};
		ROUTER=${SVIP};
		NETMASK=${SVMSK};
		NETADDR=${SVNET};
		continue;
	    fi
  
	    IP2Host ${IPADDR} ${NETMASK}
	    if [ $H -eq $MHN ]; then
		print -u2 "Error: host address \"${IPADDR}\" is subnet broadcast address";
		IPADDR=${SVIP};
		FWSRVR=${SVIP};
		ALTAUTH=${SVIP};
		ROUTER=${SVIP};
		NETMASK=${SVMSK};
		NETADDR=${SVNET};
		continue;
	    fi
  
	    NAME="${HOSTNAME}-${INTF}";
  
	    # get new host name from user
	    while :
	    do		# hostname
		print -n "  new host name: [${NAME}] ";
		read ANS
		:
		if [ -z "${ANS}" ]; then
		    ANS=${NAME};
		fi
		echo $ANS >> $LOGFILE
		getent hosts "${ANS}";
		if [ ${?} -ne 0 ]; then
		    NAME=${ANS};
		    break;
		else
		    print -u2 "Error:  host name already in use\n";
		fi
	    done	# hostname
  
		# make new net name
		NETNAME="${CORONA_NAME}-${INTF}";
  
	fi	# DHCPONLY = N

	if $SUBNETMODE; then
	    if [[ -n "${SYS_NETMASK}" ]]; then
		print "  netmask: ${NETMASK} (cannot be changed - system defined netmask)";
	    else
		# get new netmask from user - for Subnet case only
		while :
		do		# netmask
		    print -n "  new netmask: [${NETMASK}] ";
		    read ANS
		    :
		    if [ -z "${ANS}" ]; then
			ANS=${NETMASK};
		    fi
		    echo $ANS >> $LOGFILE
		    CheckIPA "${ANS}";
		    if [ ${?} -ne 0 ]; then
			print -u2 "Error:  invalid netmask\n";
			continue
		    fi
		    MaxHostNum $ANS
		    if [ ${?} -ne 0 ]; then
			print -u2 "Error: invalid netmask \"$ANS\""; 
			continue;
		    fi
		    if [ ${H} -gt ${CLASS_MAXHOST} ]; then
			print -u2 "Error: invalid netmask for the specified subnet \"${NETADDR}\""
			continue;
		    fi
		    Net2Broadcast ${SUBNET} ${ANS}
		    if [ ${?} -ne 0 ]; then
			print -u2 "Error: invalid netmask \"$ANS\""; 
			continue;
		    fi
		    IP2Net ${SUBNET} "${ANS}"
		    if [ $NET != ${NETADDR} ]; then
			print -u2 "Error: invalid netmask \"$ANS\"";
			continue;
		    fi

		    # check netmask against the system one
		    HOLD_NETMASK=$ANS
		    if CheckNetmaskValue $HOLD_NETMASK; then
			NETMASK=${HOLD_NETMASK}
			MHN=$H
			break
		    fi
		done	# netmask
	    fi
	fi

	if [ "${DHCPONLY}" = "Y" ]; then
	    #
	    # configure the LAN interface or subnet
	    # set default to "N" as the normal case the DHCP addresses will
	    # be handled by some other DHCP server.
	    #
	    if ${SUBNETMODE}; then
	    	YesOrNo "  Do you want to offer IP addresses for this subnet?" "N"
	    else
	    	YesOrNo "  Do you want to offer IP addresses for this interface?" "N"
	    fi
	    noIPaddr=${?}
	else
	    #
	    # configure the private interconnect
	    # set default to "Y" as the normal case the SR server will be 
	    # assigning addresses
	    #
	    YesOrNo "  Do you want to offer IP addresses for this interface?" "Y"
	    noIPaddr=${?}
	fi

	# check if want dhcp address allocation
	if [ ${noIPaddr} -eq 0 ]; then
	    # get new Sunray desktop unit starting ip address from user
	    if [ ${START_NUM} -ge $MHN ]; then
		let "START_NUM = 4"
	    fi
	    if [ ${START_NUM} -eq 0 ]; then
		START_ADDR=0
	    else
		NetPlusHost ${NETADDR} ${START_NUM} $MHN
		START_ADDR=$IP
	    fi
	    while :
	    do		# first IP
		print -n "  new first ${CORONA_TITLE} address: [${START_ADDR}] ";
		read ANS
		:
		if [ -z "${ANS}" ]; then
		    ANS=${START_ADDR};
		fi
		echo $ANS >> $LOGFILE
		if [ "$ANS" = "0" ]; then
		    if ${SUBNETMODE}; then
			YesOrNo "Disable offering IP addresses for this subnet? " "N"
		    else
			YesOrNo "Disable offering IP addresses for this interface? " "N"
		    fi
		    if [ $? -eq 0 ]; then
			noIPaddr=1
			break
		    fi
		    continue;
		fi
		CheckIPA "${ANS}";
		if [ ${?} -eq 0 ]; then
		    IP2Net "${ANS}" ${NETMASK}
		    if [ $NET != ${NETADDR} ]; then
			print -u2 "Error: new first address not in correct subnet";
			continue;
		    fi
		    IP2Host "${ANS}" ${NETMASK}
		    if [ $H -eq $MHN ]; then
			print -u2 "Error: new first address is subnet broadcast address"; 
			continue;
		    fi
		    if [ $H -eq 0 ]; then
			print -u2 "Error: new first address is subnet address"; 
			continue;
		    fi
		    START_NUM=$H
		    break;
		else
		    print -u2 "Error:  invalid IP address\n";
		fi
	    done		# first IP

	    # get new Sunray desktop unit ending ip address from user
	    if [ ${noIPaddr} -eq 0 ]; then
		let "END_NUM = $MHN - 1"
		let "NUM_IP = $END_NUM - $START_NUM + 1"
		# NetPlusHost ${NETADDR} ${END_NUM} $MHN
		# END_ADDR=$IP
		while :
		do		# last IP
		    print -n "  number of ${CORONA_TITLE} addresses to allocate: [${NUM_IP}] ";
		    read NEW_NUM
		    :
		    if [ -z "${NEW_NUM}" ]; then
			NEW_NUM=${NUM_IP};
		    fi
		    echo $NEW_NUM >> $LOGFILE
		    if [ $NEW_NUM -le 0 ]; then
			print -u2 "Error: invalid number of IP addresses to allocate";
			continue;
		    fi

		    if [ $NEW_NUM -gt $NUM_IP ]; then
			print -u2 "Error: number is larger than $NUM_IP maximum allowed allocation"; 
			continue;
		    fi

		    let "END_NUM = $NEW_NUM + $START_NUM - 1"
		    break;
		done	# last IP
	    fi
	fi

	# get new auth server list
	 while :
        do              # auth server list
            print "  auth server list:\t${ALTAUTH}";
            print -n "To read auth server list from file, enter file name: ";
            read FILE

            if [ -n "$FILE" ]; then
                echo $FILE >> $LOGFILE
                ALT_AUTH=`tr '\n' ' ' <$FILE`
                IP_ERROR=1
                for REPLY in ${ALT_AUTH}
                do
                    if [ -z "${REPLY}" ]; then
                        continue
                    fi
                    CheckIPA $REPLY
                    if [ ${?} -ne 0 ]; then
                        print "Invalid IP address ${REPLY} in file"
                        IP_ERROR=0
                        break
                    fi
                done
                if [ $IP_ERROR -ne 1 ]; then
                    continue
                fi
            else
                echo "" >> $LOGFILE
		ALT_AUTH=""
                while true
                do
                    print -n "Auth server IP address (enter <CR> to end list): ";
                    read ANS
                    :
                    if [ -z "${ANS}" ]; then
                        break
                    fi
                    echo $ANS >> $LOGFILE
                    CheckIPA ${ANS}
                    if [ ${?} -ne 0 ]; then
                        print "Invalid IP address"
                        continue
                    fi
                    ALT_AUTH="${ALT_AUTH}$ANS "
                done
                echo "" >> $LOGFILE
            fi
            ALT_AUTH=`print "${ALT_AUTH}" | sed 's/ $//'`
            BRDCST_IN_LIST=""
	    if [ -n "${ALT_AUTH}" ]; then
		ALTAUTH=${ALT_AUTH}
            	BRDCST_IN_LIST=$(print ${ALTAUTH} |  \
            		sed -n "/255.255.255.255/p")
	    fi
            if [ -z ${BRDCST_IN_LIST} ]; then
            	YesOrNo "If no server in the auth server list responds, 
should an auth server be located by broadcasting on the network?" "Y"
                if [ ${?} -eq 0 ]; then
                	BRDCST="255.255.255.255"
		else  
			BRDCST=""
                fi
            fi
            break
        done            # auth server list

	# get new firmware server
	while :
	do		# firmware server
	    print -n "  new firmware server: [${FWSRVR}] ";
	    read ANS
	    :
	    if [ -z "${ANS}" ]; then
		ANS=${FWSRVR};
	    fi
	    echo $ANS >> $LOGFILE
	    CheckIPA "${ANS}";
	    if [ ${?} -eq 0 ]; then
		if [ ${ANS} = ${NETADDR} ]; then
		    print -u2 "Error: firmware server is equal to network address";
		    continue;
		fi
		FWSRVR=${ANS};
		break;
	    else
		print -u2 "Error:  invalid IP address\n";
		continue;
	    fi
	done		# firmware server

	if [ ${noIPaddr} -eq 0 ]; then
	    # get new router
	    while :
	    do		# router
		print -n "  new router: [${ROUTER}] ";
		read ANS
		:
		if [ -z "${ANS}" ]; then
		    ANS=${ROUTER};
		fi
		echo $ANS >> $LOGFILE
		CheckIPA "${ANS}";
		if [ ${?} -eq 0 ]; then
		    if [ ${ANS} = ${NETADDR} ]; then
			print -u2 "Error: router is equal to network address";
			continue;
		    fi
		    IP2Net "${ANS}" ${NETMASK}
		    if [ $NET != ${NETADDR} ]; then
			print -u2 "Error: router is not in correct subnet";
			continue;
		    fi
		    IP2Host "${ANS}" ${NETMASK}
		    if [ $H -eq $MHN ]; then
			print -u2 "Error: router address is subnet broadcast address"; 
			continue;
		    fi
		    ROUTER=${ANS};
		    break;
		else
		    print -u2 "Error:  invalid IP address\n";
		    continue;
		fi
	    done		# router
	fi # if [ ${noIPaddr} -eq 0 ]

    done	# prompt for new values

    AUTHSRVR=$(echo ${ALTAUTH} | awk '{print $1}')
    if [ -n "${BRDCST}" ]; then
	ALTAUTH="${ALTAUTH} ${BRDCST}"
    fi
    # check if want dhcp address allocation
    if [ ${noIPaddr} -ne 0 ]; then
	START_NUM=0
	END_NUM=0
    fi

    # check if there are /etc/hostname.??? files for all of the given intfs
    if [ "${DHCPONLY}" = "N" ]; then
	if [ -f "${HOSTNAME_R}.${INTF}" ]; then
	    # exists, so check if it is setup for newt net service
	    RESULT=`cat "${HOSTNAME_R}.${INTF}"`;
	    if [ "${RESULT}" != "${NAME}" ]; then
		# not the right contents, so complain and bail
		print -u2 "Warning: hostfile \"${HOSTNAME_R}.${INTF}\" contents invalid"
		print -u2 "         contains \"${RESULT}\", should contain \"${NAME}\""
		YesOrNo "         should the file be updated?" "Y";
		if [ ${?} -eq 0 ]; then
		    print "${NAME}" > "${HOSTNAME_R}.${INTF}";
		else
		    print "      remove file and try again";
		    exit 1;
		fi
	    fi
	else
	    # doesnt exist, so create it
	    print "${NAME}" > "${HOSTNAME_R}.${INTF}";
	fi
	print "### successfully setup \"${HOSTNAME_R}.${INTF}\" file";
  
	# check if this name is in the /etc/hosts file
	FIX=0;
	RESULT=`getent hosts ${NAME}`
	if [ -z "${RESULT}" ]; then
	    # name isnt there, so check if this ipaddr is in the /etc/hosts file
	    RESULT=`getent hosts ${IPADDR}`
	    if [ -z "${RESULT}" ]; then
		# name and ipaddr arent there, so add this line to the
		# /etc/hosts file
		print "${IPADDR}\t${NAME} # SUNRAY ADD - DO NOT MODIFY" >> "${HOSTS}";
	    else
		# name isnt there, but ipaddr is, so fix this
		YesOrNo "Warning:  IP address \"${IPADDR}\" appears in \"${HOSTS}\" with another hostname, fix?" "Y";
		if [ ${?} -eq 0 ]; then
		    FIX=1;
		else
		    print -u2 "Error:  conflict in ${HOSTS} file, resolve and install again"
		    exit 1;
		fi
	    fi
	else
	    # name is already in /etc/hosts, so check if it has the right ipaddr
	    RESULT=`getent hosts ${IPADDR}`
	    if [ -z "${RESULT}"  ]; then
		# name is there but ipaddr is not correct, so fix it?
		YesOrNo "hostname \"${NAME}\" appears in \"${HOSTS}\" file with another IP address, fix?" "Y";
		if [ ${?} -eq 0 ]; then
		    FIX=1;
		else
		    print -u2 "Error:  conflict in ${HOSTS}, resolve and install again"
		    exit 1;
		fi
	    fi
	fi
  
	# update the /etc/hosts file
	if [ ${FIX} -eq 1 ]; then
	    StartFileUpdate "${HOSTS}";
  
	    # remove anything that matches netname and ipaddr and add new line
	    rm -f ${TMPDIR}/tmpfile.$$;
	    sed -e "/[ 	]${NAME}[ 	]*.*$/s/^/# SUNRAY DEL /" \
		    -e "/^[ 	]*${IPADDR}[ 	]/s/^/# SUNRAY DEL /" \
		    "${HOSTS}.$$" > ${TMPDIR}/tmpfile.$$;
	    print "${IPADDR}\t${NAME} # SUNRAY ADD - DO NOT MODIFY" >> ${TMPDIR}/tmpfile.$$;
	    mv -f ${TMPDIR}/tmpfile.$$ "${HOSTS}.$$";
  
	    EndFileUpdate "${HOSTS}";
	fi
	print "### successfully setup \"${HOSTS}\" file";
  
    fi		# DHCPONLY = N
  
    if $ADD_NETMASK; then
	# update the /etc/netmasks file
	addNetMask ${NETADDR} ${NETMASK}
	print "### successfully setup \"${NETMASKS}\" file";
    fi

    if ! $SUBNETMODE; then
	addNetwork ${NETNAME} ${NETADDR}
	print "### successfully setup \"${NETWORKS}\" file";
    fi
  
    if [ "${DHCPONLY}" = "N" ]; then
	if [[ $OS = "SunOS" ]] ; then
	  # ifconfig the new interface
	  ifconfig ${INTF} plumb >/dev/null 2>&1 ;
	  ifconfig ${INTF} "${IPADDR}" up netmask "${NETMASK}" broadcast +;
	  print "### finished install of \"${INTF}\" interface";
	else
	  IfconfigLinux
	fi
    fi
}


#
# Get the count of total IP addresses assigned in a range
#
GetIPCount() {
  if [[ -z $UT_DHCP_RANGE ]] ; then
    return 1
  fi
  typeset IPCount=$(echo ${UT_DHCP_RANGE} | awk '{
	na = split($1, a, ".")
	nb = split($2, b, ".")
	if (na = nb) {
	  count = b[nb] - a[na] + 1
	  print count
	}
      }')
  if [[ -z ${IPCount} || ${IPCount} = "0" ]] ; then
    return 1
  fi
  print ${IPCount}
  return 0
}


#
# list all the SR subnetworks currently configured
#
DoList() {

    typeset AllowLan
    typeset Online

    # see if the service is online by checking the existance of the
    # /var/opt/SUNWut/offline.  If it exists, it's offline.
    if [ -f $OFFLINE_FILE ]; then
	Online="false"
    else
	Online="true"
    fi

    # see if LAN connections are allowed by checking allowLANConnections
    AllowLan=$(GetLowerValueByKey allowLANConnections $AUTHPROPS)
    if [ -z "${AllowLan}" ]; then
	AllowLan=false
    fi

    if [ ${MODE} = "l" ]; then
	# display for -l option
	if [ "${AllowLan}" = "true" ]; then
	    print "LAN connections: On"
	else
	    print "LAN connections: Off"
	fi
    else
	# display for -x option
	print "begin general"
	print "allowlanconnection=${AllowLan}"
	print "serviceonline=${Online}"
	print "end"
    fi


    if ! $ISSETUP; then
	if [ ${MODE} = "x" ]; then
	    # we do not exit with error in the -x case
	    exit 0
	else
	    # any other case, this is considered an error
	    print -u2 "${CORONA_TITLE} interconnect framework is not configured";
	    exit 1;
	fi
    fi

    if [ ! -s ${TMPDIR}/allSRnets.$$ ]; then
	print -u2 "No ${CORONA_TITLE} network configured";
	exit 1;
    fi

    typeset Netmask
    typeset Broadcast
    typeset Router
    typeset FWsrvr
    typeset AuthSrvr
    typeset AltAuthSrvr
    typeset netmacro
    typeset Intf
    typeset IntfAddr
    typeset IPassign
    typeset FirstIP
    typeset NewTVer

    InitDHCPBlockParser $CUR_CFG_F
    if [[ $? -ne 0 ]] ; then
	print -u2 "${CORONA_TITLE} network configuration not readable";
	cat $CUR_CFG_F
	exit 1;
    fi
    while GetNextDHCPBlock "all"
    do
	# check to see if it's a local interface
	if [[ $BLOCKTYPE = "interface" ]] ; then
	  if Intf=${UT_DHCP_INTERFACE} ; then
	    if [[ ! -s ${HOSTNAME_R}.${Intf} ]]; then
		IntfAddr=""*MISSING*""
	    else
	    	typeset H=`cat ${HOSTNAME_R}.${Intf}`
	    	IntfAddr=`getent hosts $H | awk '{ print $1 }'`
	    	if [[ -z "$IntfAddr" ]]; then
		    IntfAddr="*MISSING*"
		fi
	    fi
	  else
	    Intf="*MISSING*"
	  fi
	elif [[ $BLOCKTYPE = "subnet" ]] ; then
	  Intf=""
	else
	  continue
	fi

	if ! SUBNET=${UT_DHCP_NETWORK} ; then
	    SUBNET="*MISSING*"
	fi


	# retrieve broacast value
	if ! Broadcast=${UT_DHCP_BROADCAST}; then
	    Broadcast="*MISSING*"
	fi

	# retrieve netmask value
	if ! Netmask=${UT_DHCP_NETMASK}; then
	    Netmask="*MISSING*"
	fi

	# retrieve router value
	if ! Router=${UT_DHCP_ROUTERS}; then
	    Router="*MISSING*"
	fi

	# retrieve firmware server value
	if ! FWSrvr=${UT_DHCP_FIRMWARESRVR}; then
	    FWSrvr="*MISSING*"
	fi

	# retrieve NewTver value
	if ! NewTVer=${UT_DHCP_NEWTVER}; then
	    NewTVer="*MISSING*"
	fi

	# retrieve auth server value
	if ! AuthSrvr=${UT_DHCP_AUTHSRVR}; then
	    AuthSrvr="*MISSING*"
	fi

	if [[ $OS = "Linux" ]]; then
		CountIPLeases ${UT_DHCP_NETWORK} ${UT_DHCP_NETMASK}	
	fi

	# retrieve altauth server list
	AltAuthSrvr=${UT_DHCP_ALTAUTHLIST}

	# IPassign should end up with 2 numbers, assigned and total
	IPassign=${UT_DHCP_ASSIGNED}
	if [[ -n $IPassign ]] ; then
	  # IPassign should end up with 2 numbers, assigned and total
	  typeset IPtotal=`GetIPCount`
	  if [[ ! -z $IPtotal ]] ; then
	    IPassign="${IPassign} ${IPtotal}"
	  else
	    # unable to calculate total count
	    IPassign=""
	  fi
	fi

	if [[ ! -z $IPassign ]]; then
	    # XXX need first address in range
	    FirstIP=`echo $UT_DHCP_RANGE | awk '{ print $1 }'`
	fi
	case ${MODE} in
	"l")
	    printf "Subnetwork: %-10s\n" $SUBNET
	    if [[ -n "$Intf" ]]; then
		printf "\tInterface=\t%-s (%s)\n" $Intf $IntfAddr
	    fi
	    printf "\tNetmask=\t%-10s\n" $Netmask
	    if [[ -n "$Broadcast" ]]; then
	    	printf "\tBroadcast=\t%-10s\n" $Broadcast
	    fi
	    if [[ -n "$Router" ]]; then
	    	printf "\tRouter=\t\t%-10s\n" $Router
	    fi
	    printf "\tAuthSrvr=\t%-10s\n" $AuthSrvr
	    if [[ -n "$AltAuthSrvr" ]]; then
		printf "\tAltAuth=\t"
		printf "%s " $AltAuthSrvr
		printf "\n"
	    fi
	    printf "\tFirmwareSrvr=\t%-10s\n" $FWSrvr
	    printf "\tNewTver=\t%-10s\n" $NewTVer
	    if [[ -n "$IPassign" ]]; then
		printf "\tIP assignment=\t%s/%s (%s)\n" $IPassign $FirstIP
	    fi;;
	"x")
	    typeset HostName=""
	    typeset ReqParams=""
	    typeset ErrStr="- missing the following required parameter(s):"
	    typeset ErrType=""
	    typeset ErrFound=false

	    # check for required parameters that are common for both private and lan
	    [[ -z "${SUBNET}" ]] && ReqParams=${ReqParams}" network" && ErrFound=true
	    [[ -z "${Netmask}" ]] && ReqParams=${ReqParams}" netmask" && ErrFound=true

	    if [[ -n "$Intf" ]]; then
		# private interconnect, need to get the hostname and ip
		if [[ -n "${IntfAddr}" ]]; then
		    HostName=$(getent hosts ${IntfAddr} | awk '{print $2}')
		fi

		# check for the required parameters for private interconnect only
	    	[[ -z "${Intf}" ]] && ReqParams=${ReqParams}" interface" && ErrFound=true
	    	[[ -z "${HostName}" ]] && ReqParams=${ReqParams}" hostname" && ErrFound=true
	    	[[ -z "${IntfAddr}" ]] && ReqParams=${ReqParams}" ip" && ErrFound=true

		# set the interface ErrType for error message
		ErrType="interface ${Intf}"
	    else
		# set the subnet ErrType for error message
		ErrType="subnet ${SUBNET}"
	    fi

	    if ${ErrFound}; then
		print -u2 "Error: ${ErrType} ${ErrStr}\n\t${ReqParams}"
		DestroyDHCPBlockParser
		exit 1
	    fi

	    if [[ -n "$Intf" ]]; then
		# private interconnect
	    	print "begin interface"
		print "interface=${Intf}"
		print "hostname=${HostName}"
		print "ip=${IntfAddr}"
	    else
		# subnetwork
		print "begin subnet"
	    fi
	    print "network=${SUBNET}"
	    print "netmask=${Netmask}"
	    if [[ -n ${Broadcast} ]]; then
	        print "broadcast=${Broadcast}"
	    fi
	    print "end"
	esac
    done
    DestroyDHCPBlockParser
}


#
# turns on or off the LAN connection
#
# Parameter:
#	$1 on or off
# Returns:
#	0 if success.  Otherwise, 1.
#
DoAllowLan() {
    typeset lanopt
    lanopt=$(print $1 | tr '[:upper:]' '[:lower:]')
    typeset rt=0

    case $lanopt in
    "on")
	# Allow LAN connection
	print "### Turning on ${CORONA_TITLE} LAN connection"
	SetValueByKey allowLANConnections true $AUTHPROPS
	rt=${?}
	if [ ${rt} -eq 0 ] ; then
	    print "\nNOTE: utrestart must be run before LAN connections will be allowed\n"
	else
	    print -u2 "Error:\tfailed to update ${AUTHPROPS} with"
	    print -u2 "\tallowLANConnections = true"
	fi
	chmod u-w $AUTHPROPS
	;;
    "off")
	# Disallow LAN connection
	print "### Turning off ${CORONA_TITLE} LAN connection"
	SetValueByKey allowLANConnections false $AUTHPROPS
	rt=${?}
	if [ ${rt} -eq 0 ] ; then
	    print "\nNOTE: LAN connections may be allowed until utrestart is run\n"
	else
	    print -u2 "Error:\tfailed to update ${AUTHPROPS} with"
	    print -u2 "\tallowLANConnections = false"
	fi
	chmod u-w $AUTHPROPS
	;;
    *)	# Invalid option
	print -u2 "Error: \"${1}\" is an invalid -L argument!"
	print -u2 "\tYou must specify either \"on\" or \"off\"."
	rt=1
	;;
    esac
    return ${rt}
}


#
# removes all Sun Ray interfaces
#
DoRemoveAllIntfs() {

    # turn off allowLANConnections if it is on
    ALLOW=$(GetLowerValueByKey allowLANConnections $AUTHPROPS)
    if [ "${ALLOW}" = "true" ]; then
	print "LAN connections are on to allow ${CORONA_TITLE} connections from shared networks"
	YesOrNo "Do you want to turn off LAN connections? " "Y"
	if [ ${?} -eq 0 ]; then
	    DoAllowLan "off"
	fi
    fi

    SUBNETMODE=true
    for SUBNET_DEL in `cat ${TMPDIR}/allnets.$$`
    do
	DoRemoveDHCP
    done

    SUBNETMODE=false
    for DHCP_DEL in `cat ${TMPDIR}/dhcpifs.$$`
    do
	DoRemoveDHCP
    done

    for INTF_DEL in `cat ${TMPDIR}/newtifs.$$`
    do
	DoRemoveIntf
    done


    DoRemoveSysFiles
    rm ${TMPDIR}/*ifs.$$ 2>/dev/null
}


#
# deletes Sun Ray interface or subnetwork
#
DoDelete() {
    # ......... delete interface or subnetworks

    rm ${TMPDIR}/*ifs.$$ 2>/dev/null

    # remove DHCP entries for both interface and subnetwork delete
    DoRemoveDHCP

    if [[ "${MODE}" = "d" ]]; then
	# remove SR interfaces
	DoRemoveIntf
    else
	# remove SR netmask
	rmvNetMask_byNetwork ${SUBNET_DEL}
	Restart_nscd
    fi
}


#
# adds Sun Ray interface or subnetwork
#
DoAdd() {
    # ......... add interface or subnetworks

    # force CREATE mode on if the Sunray macro is not defined
    if ! $ISSETUP; then
	DoInit
	if [[ $? -ne 0 ]] ; then
	    return 1;
	fi
    fi
    if [[ -f $SUSECONFIG ]]; then
        if ! grep "^# Sun Ray requires CHECK_ETC_HOSTS" "$SUSECONFIG" >/dev/null 2>&1 ; then
            TEMP=$SUSECONFIG.$$
            sed  -e "/^[ 	]*CHECK_ETC_HOSTS[ 	]*=/ {
i\\
# Sun Ray requires CHECK_ETC_HOSTS to be set to \"no\"
            }" $SUSECONFIG > $TEMP
            mv $TEMP $SUSECONFIG
        fi
        check_etc_hosts=$(awk -F= '/^[ 	]*CHECK_ETC_HOSTS/ {print $2}' $SUSECONFIG)
        if [[ $check_etc_hosts == \"yes\" ]]; then
            sed	 -e "/^[ 	]*CHECK_ETC_HOSTS[ 	]*=/ {
s/^/# Commented by Sun Ray - /
a\\
CHECK_ETC_HOSTS=\"no\"
            }" $SUSECONFIG > $TEMP
            mv $TEMP $SUSECONFIG
	    print "### Changed value of CHECK_ETC_HOSTS in $SUSECONFIG to no"
        fi
    fi

    DoAddNetworkConfig

    # Force databases to be reread by cache
    Restart_nscd

    DoAddIntfsMacro

    if [ "${MULTINET}" = "N" ]; then
    	print "### Configuring firmware version for ${CORONA_TITLE}";
	if $SUBNETMODE; then
	    $UTSBIN/utfwadm -A -a -N ${SUBNET_ADD} -z
	else
	    $UTSBIN/utfwadm -A -a -n ${INTF_ADD} -z
	fi
    fi

    # setup the automatic logging functions
    print "### Configuring ${CORONA_TITLE} Logging Functions";
    $UTLIB/utlog -a -f user.info -d ${VAR_OPT_UT}/log/messages -z;
    $UTLIB/utlog -a -f local1.info -d ${VAR_OPT_UT}/log/admin_log -z;
  
    # if adding a subnet turn on allowLANConnections
    if $SUBNETMODE; then
	ALLOW=$(GetLowerValueByKey allowLANConnections $AUTHPROPS)
	if [ -z "${ALLOW}" -o "${ALLOW}" != "true" ]; then
	    DoAllowLan "on"
	fi
    fi
}

#
# prints the current configuration
#
DoPrint() {
    if ! $ISSETUP; then
	print -u2 "${CORONA_TITLE} interconnect framework is not configured";
	exit 1;
    fi
    if [ ! -s ${TMPDIR}/allifs.$$ ]; then
	print -u2 "No ${CORONA_TITLE} interfaces configured";
	exit 1;
    fi
    InitDHCPBlockParser $CUR_CFG_F
    if [[ $? -ne 0 ]] ; then
	print -u2 "${CORONA_TITLE} interfaces configuration not readable";
	exit 1;
    fi
    print "Interface	Host		Network		Netmask		Assigned IPs";
    while GetNextDHCPBlock interface
    do
	# check to see if interface is present
	if [ -z ${UT_DHCP_INTERFACE} ] ; then
	    print -u2 "interface name missing for ${UT_DHCP_NETWORK}";
	    continue;
	fi

	INTF=${UT_DHCP_INTERFACE}

	#
	# Need to catch the case where hostname.<intf> exists but the hostname
	# defined in the file may not be configured locally in the hosts file.
	#
	if [ ! -f ${HOSTNAME_R}.${INTF} ]; then
	    print -u2 "Error: missing \"${HOSTNAME_R}.${INTF}\" file."
	    return 1
	fi
	H=`cat ${HOSTNAME_R}.${INTF}`
	if [ -z "${H}" ]; then
	    print -u2 "Error: interface ${INTF} is partially configured.  Hostname not" \
		"specified in the \"${HOSTNAME_R}.${INTF}\" file."
	    continue
	fi
	IP=`getent hosts $H | awk '{print $1}'`
	if [ -z "${IP}" ]; then
	    print -u2 "Error: unable to resolve the hostname \"${H}\" specified in the" \
			"\"${HOSTNAME_R}.${INTF}\" file."
	    continue
	fi
	if [[ $OS = "SunOS" ]] ; then
	  M=`getent netmasks $IP | awk '{print $2}'` 
	else
	  M=${UT_DHCP_NETMASK}
	fi
	if [ -z "${M}" ]; then
	    print -u2 "Error: netmask for host $H does not exist";
	    continue;
	fi
	IP2Net $IP $M
	if [ ${?} -ne 0 ]; then
	    continue;
	fi

	SAVED_NET=$NET

	if [[ $OS = "Linux" ]]; then
		CountIPLeases $SAVED_NET $M
	fi

	# C should end up with 2 numbers, assigned and total
	if ! C=${UT_DHCP_ASSIGNED}; then
	    C=""
	else
	  # C should end up with 2 numbers, assigned and total
	  typeset T=`GetIPCount`
	  if [[ ! -z $T ]] ; then
	    C="${C} ${T}"
	  else
	    # unable to calculate total count
	    C=""
	  fi
	fi

	printf "%-10s\t%-10s\t%-10s\t%-10s\t%6s/%-6s\n" $INTF $H $SAVED_NET $M $C;
    done
    DestroyDHCPBlockParser
}

CountIPLeases() {
	tmp_leases=/var/opt/SUNWut/tmp/tmpLeases.$$
	dhcpd_hosts=/var/opt/SUNWut/tmp/dhcpdHosts.$$
	lease_file=/var/lib/dhcp/dhcpd.leases

	rm -f $tmp_leases
        rm -f $dhcpd_hosts

	process_leases
	process_data $1 $2

	rm -f $tmp_leases
	rm -f $dhcpd_hosts
}

process_leases() {

        # Format:
        #
        # lease 192.168.123.12 {
        #        starts 6 2002/01/26 20:18:19;
        #        ends 0 2002/01/27 08:18:19;
        #        hardware ethernet 00:a0:24:e9:bb:f1;
        #        uid 01:00:a0:24:e9:bb:f1;
        # }

        sed -n '
                # Leading & trailing whitespace
                s/^[    ]*//
                s/[     ]*$//
                # Hold patterns
                /^lease[        ]/h
                /^\(ends\)[     ]/H
                # Closure
                /^\}/ {
                        g
                        s/\n//g
                        # Whitespace to hyphen
                        s/\("[^ "]\{1,\}\) \{1,\}\([^"]\{1,\}"\)/\1-\2/g
                        # Remove dots
                        s/\("[^."]\{1,\}\)\.\{1,\}\([^"]\{1,\}"\)/\1\2/g
                        # Eliminate unnecessary punctuation
                        s/[ "/:;{]//g
                        # lease192.168.123.13ends020020127132703
                        s/^lease\([.0-9]*\)ends[0-9]\([0-9]*\)$/\1\|\2/
                        p
                }
        ' $lease_file > $tmp_leases

        # Establish list of hosts
        for line in `cat $tmp_leases`
        do
                echo $line | sed 's/|.*$//'
                # [ ${debug:-0} -ne 0 ] && echo $line
        done |\
        sort -u > $dhcpd_hosts

}

parse() {
        _end=`echo $1 | sed 's/^.*|//'`
        _name=`echo $1 | sed 's/|.*$//'`
}

timestamp() {
        # Leases files are always GMT/UTC
        date -u +%Y_%m_%d_%H_%M_%S
}

process_data() {
        count=0
        current_date=`timestamp`
	current_date=`echo $current_date | sed 's/_//g'`
        [ ${debug:-0} -ne 0 ] && echo -e "\nCurrent UTC: $current_date\n"
        for host in `cat $dhcpd_hosts`
        do
                unset addr end name
                for line in `sed -n "/^$host|/p" $tmp_leases`
                do
                        parse $line
                        # Most current only
                        if [ ! ${end:+1} ] \
                                || [ $_end -gt $end ]
                        then
                                end=$_end
                                name=$_name
                        fi
                done
                [ ${debug:-0} -ne 0 ] && echo -e "\n$name $end $addr"

                # Lease expired?                        # 1
                [ $end -lt $current_date ] \
                        && continue
		IP2Net $name $2
		if [ ${?} -ne 0 ]; then
			continue
  		fi
		if [[ $NET == $1 ]]; then
			let "count = count + 1"
		fi
        done
	UT_DHCP_ASSIGNED=$count
}

#
# setMode - this routine is used to check if more than one option is
#       specified.  It will first check to see if the $MODE variable, the
#	current mode, is set.  If set, prints error message and exits.
#	Otherwise, it just assigns the new mode from argument $1, the 
#	current option from command line, to MODE.
#
setMode() {
    if [[ -z "$MODE" ]]; then
        MODE=$1
    elif [[ "$MODE" = "$1" ]]; then
	print -u2 "only one instance of -${1} is allowed"
	Usage
    else
        print -u2 "conflicting options -${MODE} and -${1}"
        Usage
    fi
}

#
# sets value for the specified key in the specified file.
# NOTE: only uses "=" as the separator.
#
# Parameters:
#	$1	key
#	$2	value
#	$3	filename
# Returns:
#	0 if successful.  1 otherwise.
#
SetValueByKey() {
    if [[ $# -ne 3 ]]; then
	return 1
    fi
    typeset key=$1
    typeset value=$2
    typeset filename=$3
    typeset ALLOW

    if [[ ! -f $filename ]]; then
	print -u2 "Error: filename $filename does not exist!"
	return 1
    fi
    TMP_FILE=${TMPDIR}/utadm.${filename##*/}.$$
    rm -f $TMP_FILE
    ALLOW=$(GetLowerValueByKey $key $filename)
    if [[ -z "${ALLOW}" ]]; then
	cp -p $filename $TMP_FILE
	ed - $TMP_FILE <<-! > /dev/null 2>&1
		/^#${key}/
		.a
		${key} = ${value}
		.
		w
		q
	!
	mv -f $TMP_FILE $filename
    elif [[ "${ALLOW}" != "${value}" ]]; then
	sed -e "s/^[ 	]*${key}[ 	]*[=:][ 	]*.*/${key} = ${value}/" \
	    $filename > $TMP_FILE
	mv -f $TMP_FILE $filename
    fi
}

#
# returns the lowercase value for the specified key in the specified file.
#
# NOTE:
#	allows either = or : between key and value
#	and value retains trailing white space
#	to be compatible with JAVA properties
#
# Parameters:
#	$1	key
#	$2	filename
#
GetLowerValueByKey() {
    if [[ $# -ne 2 ]]; then
	return
    fi
    typeset key=$1
    typeset filename=$2

    if [[ -f $filename ]]; then
	sed -n -e "s/^[ 	]*${key}[ 	]*[=:][ 	]*//p" \
	    $filename 2>/dev/null | tr "[:upper:]" "[:lower:]"
    fi
}

restoreSuseconfig()
{
    check_etc_hosts=$(awk -F= '/^[ 	]*CHECK_ETC_HOSTS/ {print $2}' $SUSECONFIG)
    TEMP=$SUSECONFIG.$$
    if grep "^# Sun Ray requires CHECK_ETC_HOSTS" $SUSECONFIG >/dev/null 2>&1;then
        sed -e "/^# Sun Ray requires CHECK_ETC_HOSTS/d" $SUSECONFIG > $TEMP
	mv $TEMP $SUSECONFIG
    fi
    if grep "^# Commented by Sun Ray" $SUSECONFIG >/dev/null 2>&1;then
        sed -e "/^# Commented by Sun Ray/s/.*\(CHECK_ETC_HOSTS.*\)/\1/p" \
	    -e "/^[ 	]*CHECK_ETC_HOSTS=/d" $SUSECONFIG > $TEMP
	 mv $TEMP $SUSECONFIG
	 if [[ $check_etc_hosts == \"no\" ]]; then
	     print "### Setting CHECK_ETC_HOSTS value to yes in $SUSECONFIG" | tee -a $LOGFILE
             print "    as it was previous to configuring Sun Ray Interface\n" | tee -a $LOGFILE
	 fi
    fi

}

checkDHCPService()
{

    if [ -x $SVCADM ]; then
      if [ "${UT_DHCP_STATE%%-*}" = "maintenance" ]; then
	print -u2 "### Warning: DHCP Service is in the maintenance mode"
	print -u2 "             There could be a problem with the DHCP configuration\n"
	print -u2 "### It is strongly recommended to fix the problem and then use:"
	print -u2 "### \"$SVCADM clear $DHCP_FMRI\" "
	print -u2 "### to get DHCP service out of the maintenance mode before running utadm\n"
	YesOrNo "Do you want to Continue? " "N"
	if [ ${?} -ne 0 ]; then
	  exit 1
	fi
      elif [ "$UT_DHCP_STATE" = "disabled" ] || [ "$UT_DHCP_STATE" = "online-temporary" ]; then
	print -u2 "### Warning: DHCP Service has been disabled"
	print -u2 "### It is strongly recommended to run:"
	print -u2 "### \"$SVCADM enable $DHCP_FMRI\" "
	print -u2 "### before running utadm"
	print -u2 "### else DHCP will not start after reboot\n"
	YesOrNo "Do you want to Continue? " "N"
	if [ ${?} -ne 0 ]; then
	  exit 1
	fi
      fi
    fi
}


################################################################
#
# MAIN
#
################################################################

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

# check if we're root
if [ `id | cut -c5` -ne 0 ]
then
  print -u2 "Error:  must have super user (root) privileges"
  Usage;
fi

if [[ -d /var/adm/log ]] ; then
  LOG_DIR="/var/adm/log"
elif [[ -d /var/log/SUNWut ]] ; then
  LOG_DIR="/var/log/SUNWut"
else
  LOG_DIR="/var/log"
fi


LOGFILE="${LOG_DIR}/${PROGRAM_ID}.$(date '+%Y_%m_%d_%H:%M:%S').log"

#
# Set platform dependencies
#
SetPlatformDependencies

if ! CheckDHCP; then
  exit 1
fi
GetCurrentCfg;
if $UT_DHCP_RUNNING; then
    DHCP_RUNNING=true
fi

# parse the cmd line switches
VERBOSE="N";
CREATE="N";
REMOVE="N";
OFFLINE="N";
SUBNETMODE=false
ISSETUP=false
INTF_ADD=""
INTF_DEL=""
DHCP_DEL=""
SUBNET_DEL=""
MODE=""
while getopts crA:D:a:d:pfnlL:xz ARGNAME 2>/dev/null; do
  case $ARGNAME in
    c)	setMode "c"
	checkDHCPService
	CREATE="Y"
	;;
    a)  setMode "a"
	checkDHCPService
	fgrep -x -- ${OPTARG} ${TMPDIR}/allifs.$$ >/dev/null;
	if [ $? -eq 0 ]; then
	  print -u2 "Error: Interface \"${OPTARG}\" already configured; cannot add"
	  exit 1;
	fi
	if [ ${OPTARG#-} != ${OPTARG} ]; then
	  print -u2 "Error:  invalid interface name: \"${OPTARG}\"";
	  Usage;
	fi

	# make sure interface name is valid
	if [ $OS = "Linux" ]; then
	  ifconfig ${OPTARG} > /dev/null 2>&1
	else
	  ifconfig ${OPTARG} plumb > /dev/null 2>&1
        fi
	if [[ $? -ne 0 ]]; then
	  print -u2 "Error:  invalid interface name: \"${OPTARG}\"";
	  Usage;
        fi
    	INTF_ADD="${OPTARG}"
	;;
    d)	setMode "d"
	checkDHCPService
	REMOVE="Y"
	fgrep -x -- ${OPTARG} ${TMPDIR}/allifs.$$ >/dev/null;
	if [ $? -ne 0 ]; then
	  print -u2 "Error: Interface \"${OPTARG}\" is not configured; cannot delete";
	  exit 1;
	fi
	if [ ${OPTARG#-} != ${OPTARG} ]; then
	  print -u2 "Error:  invalid interface name: \"${OPTARG}\"";
	  Usage;
	fi
	INTF_DEL="${OPTARG}"
	DHCP_DEL="${OPTARG}"
	;;
    A)	setMode "A"
	checkDHCPService
	if print $OPTARG | $GREP -v -q "^[0-9]"; then
	    SUBNET_ADD=$(getent networks $OPTARG | awk '{print $2}')
	    if [[ -z "$SUBNET_ADD" ]]; then
		print -u2 "Error: unable to resolve network name: \"${OPTARG}\""
		exit 1
	    fi
	else
	    SUBNET_ADD=${OPTARG}
	fi
        CheckIPA "${SUBNET_ADD}";
        if [ ${?} -ne 0 ]; then
	    print -u2 "Error:invalid subnetwork address: \"${SUBNET_ADD}\""
	    exit 1
	fi
	fgrep -x -- ${SUBNET_ADD} ${TMPDIR}/allSRnets.$$  > /dev/null
	if [ $? -eq 0 ]; then
	    print -u2 "Error: subnetwork \"${OPTARG}\" already configured; cannot add"
	    exit 1
	fi
	SUBNETMODE=true
	;;
    D)	setMode "D"
	checkDHCPService
	REMOVE="Y"
	if print $OPTARG | $GREP -v -q "^[0-9]"; then
	    SUBNET_DEL=$(getent networks $OPTARG | awk '{print $2}')
	    if [[ -z "$SUBNET_DEL" ]]; then
		print -u2 "Error: unable to resolve network name: \"${OPTARG}\""
		exit 1
	    fi
	else
	    SUBNET_DEL=${OPTARG}
	fi
        CheckIPA "${SUBNET_DEL}";
        if [ ${?} -ne 0 ]; then
	    print -u2 "Error:invalid subnetwork address: \"${SUBNET_DEL}\""
	    exit 1
	fi
	fgrep -x -- ${SUBNET_DEL} ${TMPDIR}/allSRnets.$$  > /dev/null
	if [ $? -ne 0 ]; then
	    print -u2 "Error: subnetwork \"${OPTARG}\" is not configured; cannot delete"
	    exit 1
	fi

	# now check if this is a subnetwork is par of an interface setup
	typeset intfcheck
	intfcheck=`GetIntfByNet ${SUBNET_DEL}`
	#
	# if $? = 0, this is a subnetwork configured for an interface.
	# So, display error message and quit.
	# Otherwise, go ahead and delete it.
	#
	if [ $? -eq 0 ]; then
	    # this subnetwork is not configured thru the network option
	    print -u2 "Error: subnetwork \"${SUBNET_DEL}\" is not configured as a subnet.\
	    	\nTry removing it using \"-d ${intfcheck}\"."
	    exit 1
	fi
	SUBNETMODE=true
	;;
    r)	setMode "r"
	checkDHCPService
	;;
    p)  setMode "p"
	;;
    l)	setMode "l"
	;;
    f)	setMode "f"
	OFFLINE="Y"
	;;
    n)	setMode "n"
	OFFLINE="Y"
	;;
    z)	setMode "z"
	;;
    L)	setMode "L"
	ALLOW_LAN_CONN=${OPTARG}
	;;
    x)	setMode "x"
	;;
    ?)	print -u2 "Error: invalid option"
	Usage;;
  esac
done

if [ $OPTIND -le $# ]; then
  shift `expr $OPTIND - 1`
  print -u2 "Unrecognized arguments: $*";
  Usage;
fi

if [[ -z "$MODE" ]]; then
    print -u2 "Error:  must supply at least one of -a, -d, -A, -D, -c, -L, -l, -f, -n, or -r"
    Usage
fi

# fix networks
if [[ $MODE = "z" ]]; then
    FixNetworks
    exit 0
fi

# do offline/online operation
if [[ $OFFLINE = "Y" ]]; then
    case $MODE in
	f)  touch $OFFLINE_FILE;;
	n)  rm $OFFLINE_FILE 2>/dev/null;;
    esac
    exit 0
fi

if $UT_DHCP_CONFIGURED ; then
    ISSETUP=true
fi

# do printing
if [ ${MODE} = "p" ]; then
    # printing...
    DoPrint
    exit 0
fi

# do printing of all SR subnetowrks
if [ ${MODE} = "l" -o ${MODE} = "x" ]; then
    DoList
    exit 0
fi

# turn on or off LAN connection
if [ ${MODE} = "L" ]; then
    DoAllowLan $ALLOW_LAN_CONN 2>&1 | tee -a $LOGFILE
    exit ${?}
fi

# 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

# On Linux getent hosts can return 127.0.0.1 because nothing else
# needs to be defined in /etc/hosts
if [ $OS = "Linux" ]; then
  HOSTIP=`hostname -i`
  if [ -z "${HOSTIP}" -o "${HOSTIP}" = "127.0.0.1" ]; then
    print -u2 "Error: host IP address must be set"
    print -u2 "Set host IP address and try again"
    exit 1;
  fi
else
  HOSTIP=`getent hosts ${HOSTNAME} | awk '{print $1}'`
  if [ -z "${HOSTIP}" -o "${HOSTIP}" = "127.0.0.1" ]; 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
fi

if [[ "${MODE}" = "r" ]]; then
    # ......... removal operation
    if ${ISSETUP}; then
    	DoRemoveAllIntfs 2>&1 | tee -a $LOGFILE
        if [[ -f $SUSECONFIG ]]; then
            restoreSuseconfig
        fi
    else
    	print "${CORONA_TITLE} interconnect framework is not configured" | tee -a $LOGFILE
    fi

elif [[ "${REMOVE}" = "Y" ]]; then
    # ......... delete interface or subnetworks
    DoDelete 2>&1 | tee -a $LOGFILE
    UT_DHCP_CONFIGURED=$($UTDHCPSERVICE | $__AWK -F= '$1=/configured/ {print $2}')
    if ! $UT_DHCP_CONFIGURED ; then
        DoRemoveSysFiles
	rm ${TMPDIR}/*ifs.$$ 2>/dev/null
        ALLOW=$(GetLowerValueByKey allowLANConnections $AUTHPROPS)
        if [ "${ALLOW}" = "true" ]; then
            print "LAN connections are on to allow ${CORONA_TITLE} connections from shared networks"
            YesOrNo "Do you want to turn off LAN connections? " "Y"
            if [ ${?} -eq 0 ]; then
                DoAllowLan "off"
            fi
        fi
        if [[ -f $SUSECONFIG ]] ; then
            restoreSuseconfig
        fi
    fi

elif [[ $MODE = "c" ]]; then
    # ......... initializing SunRay framework
    DoInit 2>&1 | tee -a $LOGFILE

elif [ "${MODE}" = "a" -o "${MODE}" = "A" ]; then
    # ......... add interface or subnetworks
    DoAdd 2>&1 | tee -a $LOGFILE
fi

RestartDHCP 2>&1 | tee -a $LOGFILE
rm ${TMPDIR}/*.$$ 2>/dev/null;
exit 0
