#!/usr/bin/ksh -p
#
# ident "@(#)utadm.sh	1.147 02/12/05 SMI"
#
# Copyright 1998-2002 Sun Microsystems, Inc.  All rights reserved.
#

#
#  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:/sbin:/usr/sbin

UTLIB="$(/bin/pkginfo -r SUNWuto)/SUNWut/lib"
UTSBIN="$(/bin/pkginfo -r SUNWuto)/SUNWut/sbin"

DEF_NET_MASK="255.255.255.0";
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"

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

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

# names of files and directories that will be touched by this script
#
DHCP_DIR="/var/dhcp";
NSSWITCH="/etc/nsswitch.conf";
HOSTNAME_R="/etc/hostname";	# with suffix .{hme,qfe,vge}
HOSTS="/etc/inet/hosts";
NETMASKS="/etc/inet/netmasks";
NETWORKS="/etc/inet/networks";
INIT_DHCP="/etc/init.d/dhcp";
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"
GREP=/usr/xpg4/bin/grep
DHTADM_P="${TMPDIR}/dhtadm-P.$$"
AUTHPROPS="/etc/opt/SUNWut/auth.props"

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

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

ME=$0
ARGS=$*

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

#
# 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

  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}

  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}"}
    if [ "${ANS}" = "Y" -o "${ANS}" = "y" ]; then
      return 0;
    elif [ "${ANS}" = "N" -o "${ANS}" = "n" ]; then
      return 1;
    fi
  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=`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) {
						out = out dot a[i] - a[i] % j
						break
					} else if ((m[i] + j) > 256) {
						out = "BadMask"
						i = 5
						break
					}
				}
				dot = "."
			}
			printf "%s\n", out
		}'`
  if [ $NET = "BadMask" ]; then
    return 1;
  fi
  return 0;
}

#
# 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
}

#
# Get undotted host number from IP address
# Parameters:
#	$1 IP address
#	$2 netmask
# Sets:
#	H - host number
#
function IP2Host {
  H=`print "$1 $2" | awk '{
			split($1, a, ".")
			split($2, m, ".")
			dot = ""
			out = 0
			for (i = 1; i <= 4; i++) {
				out *= 256
				for (j = 1; j <= 256; j *= 2) {
					if ((m[i] + j) == 256) {
						out += a[i] % j
						break
					} else if ((m[i] + j) > 256) {
						print "BadMask"
						exit
					}
				}
			}
			printf "%d\n", out
		}'`
  if [ $H = "BadMask" ]; then
    return 1;
  fi
  return 0;
}

#
# Add dotted network and undotted host number together
# Parameters:
#	$1 network number
#	$2 host number
#	$3 max host number
# Sets:
#	IP - a dotted IP address
#
function NetPlusHost {
  if [[ $2 -ge $3 ]] || [[ $2 -eq 0 ]]; then
     # invalid host number
     print -u2 "Host number $2 is invalid for $1 subnet"
     IP="BadAdd"
     return 1
  fi
  IP=`print "$1 $2" | awk '{
			split($1, a, ".")
			dot = ""
			out = ""
			b = $2
			for (i = 4; i >= 1; i--) {
				c =  (a[i] + b) % 256
				b -= (b % 256)
				b /= 256
				out = c dot out
				dot = "."
			}
			printf "%s\n", out
		}'`
  return 0;
}

#
# Return the maximum host number for a given netmask
# Parameters:
#	$1 netmask
# Sets:
#	H - the maximum host number
#
function MaxHostNum {
  H=`print "$1" | awk '{
			split($1, m, ".")
			out = 0
			for (i = 1; i <= 4; i++) {
				out *= 256
				for (j = 1; j <= 256; j *= 2) {
					if ((m[i] + j) == 256) {
						out += j - 1
						break
					} else if ((m[i] + j) > 256) {
						print "BadMask"
						exit
					}
				}
			}
			printf "%d\n", out
		}'`
  if [ $H = "BadMask" ]; then
    return 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
			    }
			    break;
		}
		/^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
				}				
				break;
		}
		/^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
				}
				break;
		}
		/^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
				}
				break;
		}
		{ print $0 }
		END { }' $1 > ${TMPDIR}/tmpfile.$$;

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

#
# restore a file to it's non-newt state (handle both NEWT and SUNRAY)
#
function RestoreFile {
  rm -f ${TMPDIR}/tmpfile.$$;
  nawk 'BEGIN { omit = 0 }
		/^# SUNRAY DEL / {
		  sub("# SUNRAY DEL  *", "", $0)
		  print $0
		  break;
		};
		/^# NEWT DEL / {
		  sub("# NEWT DEL  *", "", $0)
		  print $0
		  break;
		};
		/# SUNRAY ADD/ {
		  break;
		};
		/# NEWT ADD/ {
		  break;
		};
		/^# SUNRAY BEGIN/ { omit = 1 };
		/^# NEWT BEGIN/ { omit = 1 };
		(omit == 0) { print $0 };
		/^# SUNRAY END/ { omit = 0 };
		/^# NEWT END/ { omit = 0 };
		END { }' $1 > ${TMPDIR}/tmpfile.$$;
  cp -f ${TMPDIR}/tmpfile.$$ $1;
  rm -f ${TMPDIR}/tmpfile.$$;
}


#
# lock a file in preparation for updating it
#  usage:  StartFileUpdate <path>
#  first tries to lock the file and if it succeeds, it makes a copy
# of the given file, which is to be used to modify the file.
#  the EndFileUpdate function is called after changes have been made
# to the file and it is ready to be put back in operation.
#
function StartFileUpdate {
  # try to lock the file to be changed

  # generate a tmp copy of the new file
  cp -f $1 $1.$$
  if [ ${?} -ne 0 ]; then
    print -u2 "Error:  unable to make tmp file"
    exit 1;
  fi
  chmod 600 $1.$$;
}


#
# end the update of a file
#  usage:  EndFileUpdate <path>
#  this is called after StartFileUpdate is called and atomically
# updates the given file and unlocks it
#
function EndFileUpdate {
  # save a copy of the original file
  rm -f $1.bak
  cp -p -f $1 $1.bak
  if [ ${?} -ne 0 ]; then
    print -u2 "Error:  unable to make backup file \"$1.bak\""
    exit 1;
  fi

  # Copy over the original, preserving ownership, links, and permissions
  cp -f $1.$$ $1
  rm -f $1.$$
}


#
# Restart the nscd daemon
#
Restart_nscd() {
    /etc/init.d/nscd stop 2>&1 >/dev/null
    /etc/init.d/nscd start 2>&1 >/dev/null
}


#
# Verify that dhcp is installed
#
function CheckDHCP {
  if [ ! -x "${INIT_DHCP}" ]; then
    print -u2 "Error:  DHCP cannot be run on this machine."
    print -u2 "        Ensure DHCP is installed, /etc/init.d/dhcp has the"
    print -u2 "        correct permissions and run \"utadm\" again."
    exit 1;
  fi
}

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


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

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

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

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

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


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


#
# Setup the DHCP configuration file
#  usage:  SetupCfgFile
# write a new dhcp config file for SunRay use.
#
function SetupCfgFile {
 
  #
  # If this is a post S8U5 then use the non-interactive
  # dhcpconfig command to setup dhcp configuration file
  # in the correct location
  #
  if ! $USE_FILES ; then
    dhtadm -P >/dev/null 2>&1
    if [ ${?} -ne 0 ]; then
	dhcpconfig -D -r SUNWbinfiles -p ${DHCP_DIR} >/dev/null 2>&1
	# NOTE: this will start up the dhcp daemon automatically
    fi
    return 0
  fi

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

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


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

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

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

function 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}";
}

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;
        }
      }
    }'
}

# Replaced by IP2Net
function getNetAddr {
  # make new network address
  J=0;
  NET="";
  while [ ${J} -lt 4 ]; do
    IPA=`print $1 | cut -d "." -f$((J + 1))`;
    MSK=`print $2 | cut -d "." -f$((J + 1))`;
    NET="${NET}$((${IPA} & ${MSK}))";
    let "J = J + 1";
    if [ ${J} -lt 4 ]; then
	NET="${NET}.";
    fi
    if [ ${MSK} -ne 0 ]; then
	NN=${IPA};
    fi
  done
}

#
# 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
#  INTF_ROUTER:  the address of the router for this network
#
#  this is only to be called after the interface has been setup (i.e., after
# the "ifconfig plumb" has been done), and the /etc/hosts table has been setup.
#  returns a 0 if all values are set properly and a 1 otherwise
#
function GetInterfaceInfo {
  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}\$" /etc/hostname.* | \
		sed -e "s/^..*\.\([^\.][^\.]*\)$/\1/"`
	if [[ -z "$intf_list" ]]; then
	    print -u2 "Error: unable to get information on primary interface"
	    exit 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} 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

  # get the intf's router address
  INTF_INFO=`netstat -n -r -f inet| grep "^${INTF_NET}" | awk '{ print $2; exit }'`
  if [ -z "${INTF_INFO}" ]; then
    return 1;
  fi
  INTF_ROUTER="${INTF_INFO}";
  
#####print "${INTF_IPA}, ${INTF_NAME}, ${INTF_MASK}, ${INTF_NET}, ${INTF_MTU}, ${INTF_BC}, ${INTF_ROUTER}";
  return 0;
}


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

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

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

  # add all the symbols
  # remove them first
  typeset TMPBATCH=${TMPDIR}/setupdhcp-batch.$$
  rm -f ${TMPBATCH} 2> /dev/null
  touch ${TMPBATCH}
  for i in `dhtadm -P | awk '/SUNW.NewT.SUNW/ { print $1 }'`; do
    print "dhtadm -D -s $i" >> ${TMPBATCH}
  done
  if [[ -s $TMPBATCH ]]; then
	dhtadm -B ${TMPBATCH} 2> /dev/null	# ignore errors
  fi
  rm -f ${TMPBATCH}

  print "dhtadm -A -s AuthSrvr -d 'Vendor=SUNW.NewT.SUNW,21,IP,1,1'" > ${TMPBATCH}
  print "dhtadm -A -s AltAuth -d 'Vendor=SUNW.NewT.SUNW,35,IP,1,0'" >> ${TMPBATCH}
  print "dhtadm -A -s AuthPort -d 'Vendor=SUNW.NewT.SUNW,22,NUMBER,2,1'" >> ${TMPBATCH}
  print "dhtadm -A -s NewTVer -d 'Vendor=SUNW.NewT.SUNW,23,ASCII,1,0'" >> ${TMPBATCH}
  print "dhtadm -A -s NewTBW -d 'Vendor=SUNW.NewT.SUNW,30,NUMBER,4,1'" >> ${TMPBATCH}
  print "dhtadm -A -s LogHost -d 'Vendor=SUNW.NewT.SUNW,24,IP,1,1'" >> ${TMPBATCH}
  print "dhtadm -A -s LogKern -d 'Vendor=SUNW.NewT.SUNW,25,NUMBER,1,1'" >> ${TMPBATCH}
  print "dhtadm -A -s LogNet -d 'Vendor=SUNW.NewT.SUNW,26,NUMBER,1,1'" >> ${TMPBATCH}
  print "dhtadm -A -s LogUSB -d 'Vendor=SUNW.NewT.SUNW,27,NUMBER,1,1'" >> ${TMPBATCH}
  print "dhtadm -A -s LogVid -d 'Vendor=SUNW.NewT.SUNW,28,NUMBER,1,1'" >> ${TMPBATCH}
  print "dhtadm -A -s LogAppl -d 'Vendor=SUNW.NewT.SUNW,29,NUMBER,1,1'" >> ${TMPBATCH}
  print "dhtadm -A -s FWSrvr -d 'Vendor=SUNW.NewT.SUNW,31,IP,1,1'" >> ${TMPBATCH}
  print "dhtadm -A -s NewTDispIndx -d 'Vendor=SUNW.NewT.SUNW,32,NUMBER,4,1'" >> ${TMPBATCH}
  print "dhtadm -A -s Intf -d 'Vendor=SUNW.NewT.SUNW,33,ASCII,1,0'" >> ${TMPBATCH}
  print "dhtadm -A -s NewTFlags -d 'Vendor=SUNW.NewT.SUNW,34,NUMBER,4,1'" >> ${TMPBATCH}
  print "dhtadm -A -s BarrierLevel -d 'Vendor=SUNW.NewT.SUNW,36,NUMBER,4,1'" >> ${TMPBATCH}
  dhtadm -B ${TMPBATCH} 2> ${TMPDIR}/Err.$$
  if [ ${?} -ne 0 ]; then
    print -u2 "Error:  cannot add SunRay symbols to dhcptab:\n    `cat ${TMPDIR}/Err.$$`"
    rm -f ${TMPBATCH} ${TMPDIR}/Err.$$;
    return 1;
  fi
  rm -f ${TMPBATCH} ${TMPDIR}/Err.$$;

  # add the Sunray default macro
  SetSRDefaultMacro ${HOSTIP}
  if [ ${?} -ne 0 ]; then
    return 1;
  fi

  return 0;
}

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

    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}
    else
	# adding interface
	INTF=${INTF_ADD}

	# 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
    fi

    # add server macro for each interface
    # (includes the sunray macro and contains auth server ipa and port,
    #  loghost, logkern/net/usb/vid/appl)
    AUTH_SRVR="AuthSrvr=${AUTHSRVR}";
    if [ "${ALT_AUTH}" != "" ]; then
	AUTH_SRVR="${AUTH_SRVR}:AltAuth=${ALT_AUTH}"
    fi
    SRV_MACRO=":Include=${CORONA_NAME}:${AUTH_SRVR}:";
    dhtadm -A -m ${INTF_NETNAME} -d "${SRV_MACRO}" 2> ${TMPDIR}/Err.$$;
    if [ ${?} -ne 0 ]; then
	print -u2 "Error:  cannot add interface macro \"${INTF_NETNAME}\" to dhcptab:\n    `cat ${TMPDIR}/Err.$$`"
	rm -f ${TMPDIR}/Err.$$;
	return 1;
    else
	rm -f ${TMPDIR}/Err.$$;
    fi

    # add a network macro for each interface
    # (contains broadcast ipa, subnet mask, mtu, router ipa)
    if [ "${MULTINET}" = "N" ]; then
	if [ -n "${ROUTER}" ]; then
	    INTF_ROUTER=${ROUTER}
	fi
    	if $SUBNETMODE; then
	    NET_MACRO=":Include=${INTF_NETNAME}:Broadcst=${INTF_BC}:\
Subnet=${INTF_MASK}:MTU=${INTF_MTU}:Router=${INTF_ROUTER}:FWSrvr=${FWSRVR}:"
	else
	    NET_MACRO=":Include=${INTF_NETNAME}:Broadcst=${INTF_BC}:\
Subnet=${INTF_MASK}:MTU=${INTF_MTU}:Router=${INTF_ROUTER}:FWSrvr=${FWSRVR}:\
Intf=${INTF}:";
	fi
	dhtadm -A -m ${INTF_NET} -d "${NET_MACRO}" 2> ${TMPDIR}/Err.$$;
	if [ ${?} -ne 0 ]; then
	    print -u2 "Error:  cannot add network macro \"${INTF_NET}\" to dhcptab:\n    `cat ${TMPDIR}/Err.$$`"
	    rm -f ${TMPDIR}/Err.$$;
	    return 1;
	else
	    rm -f ${TMPDIR}/Err.$$;
	fi
    fi
}

#
# initialize various dhcp network tables.
#  usage:  BuildNetworkTables
#  builds the network tables for all of the newtnet interfaces in ${NEWT_INTFS}
#  returns 0 on success, and 1 on failure
#
function BuildNetworkTables {

    if $SUBNETMODE; then
	GetInterfaceInfo
	# use MTU replace other info
	INTF_NET=${SUBNET_ADD}
	INTF_NETNAME=${CORONA_NAME}-${SUBNET_ADD}
    else
    	INTF=${INTF_ADD}
	# get info about the interface and make a DHCP network table for it
	GetInterfaceInfo "${INTF}";
    fi

    if [ ${START_NUM} -eq 0 ]; then
	# in order to support DHCPINFORM, an empty network table must
	# be created.
	pntadm -C ${INTF_NET} 2> ${TMPDIR}/Err.$$
	if [ ${?} -ne 0 ]; then
	    print -u2 "Error:  cannot create DHCP network table for \"${INTF_NET}\":\n     `cat ${TMPDIR}/Err.$$`"
	    rm -f ${TMPDIR}/Err.$$;
	    return 1
	fi
	rm -f ${TMPDIR}/Err.$$;
	return 0
    fi

    if [ "${MULTINET}" = "N" ]; then
	pntadm -C ${INTF_NET} 2> ${TMPDIR}/Err.$$
	if [ ${?} -ne 0 ]; then
	    print -u2 "Error:  cannot create DHCP network table for \"${INTF_NET}\":\n    `cat ${TMPDIR}/Err.$$`"
	    rm -f ${TMPDIR}/Err.$$;
	    return 1;
	else
	    rm -f ${TMPDIR}/Err.$$;
	fi
    fi

    # add entries to the dhcp network table
    NUM=${START_NUM};
    INPOOL=0;
    typeset TMPBATCH=${TMPDIR}/pntadm-batch.$$
    rm -f $TMPBATCH
    touch $TMPBATCH
    MaxHostNum ${NETMASK}
    MAXHOST=$H
    while [ ${NUM} -le ${END_NUM} ]; do
      NetPlusHost ${NETADDR} ${NUM} ${MAXHOST}
      ADDR=$IP
      if [ ${IPADDR} = ${ADDR} ]; then
	print "### Skipping host address ${IPADDR} in IP address pool";
        let NUM=${NUM}+1;
	continue;
      fi
      if [ ${FWSRVR} = ${ADDR} ]; then
	print "### Skipping firmware server address ${FWSRVR} in IP address pool";
        let NUM=${NUM}+1;
	continue;
      fi
      let INPOOL=${INPOOL}+1;
      print "pntadm -A ${ADDR} -m ${INTF_NETNAME} -s ${HOSTNAME} ${INTF_NET}" \
	>> $TMPBATCH
      let NUM=${NUM}+1;
    done

    pntadm -B $TMPBATCH 2> ${TMPDIR}/Err.$$;
    if [ ${?} -ne 0 ]; then
	print -u2 "Error:  failed to add the following IP addresses to network\
		\ntable for \"${INTF_NET}\":\n    `cat ${TMPDIR}/Err.$$`"
	rm -f ${TMPBATCH} ${TMPDIR}/Err.$$;
	return 1;
    fi
    rm -f ${TMPBATCH} ${TMPDIR}/Err.$$;

    if [ ${INPOOL} -eq 0 ]; then
      print -u2 "Warning: IP address pool for network ${INTF_NET} is empty";
    fi

    return 0;
}

function addNetwork {
  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 {
  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} >&- 2>&-; 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
}

#
# 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.
#	dhtadm-P.$$ contains the current dhtadm -P output without the first
#		2 header lines.
#	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 {

    rm -f $DHTADM_P 2> /dev/null
    dhtadm -P 2>/dev/null | sed -e "1,2d" > $DHTADM_P

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

    # get subnetworks that are currently configured for SunRay
    # this does not include the networks for interfaces.
    sed -n -e \
	"s/.*${CORONA_NAME}-\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\)[^0-9].*$/\1/p" \
	$DHTADM_P | sort -u >${TMPDIR}/allnets.$$

    # get all sunray networks, including the ones for the interfaces
    egrep "${CORONA_NAME}|Intf=" $DHTADM_P | \
    awk '/^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*/ { print $1 }' \
	>${TMPDIR}/dhcpallnets.$$
    sort -u ${TMPDIR}/dhcpallnets.$$ ${TMPDIR}/allnets.$$ \
	> ${TMPDIR}/allSRnets.$$

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

#
# generic routine to retrieve a macro from dhcp table
# DHTADM_P is the file containing dhtadm -P output generated from function
# GetCurrentCfg
# Parameter $1: is the macro to desired
#
GetDHCPMacro() {
    if [[ -s $DHTADM_P ]]; then
	cat ${DHTADM_P} |
	    nawk '
		{
		    if (($1 == macro) && ($2 == "Macro")) {
			print $3;
		    }
		}
		' macro=${1} - | \
		tr ':' '\012'
    fi
}

#
# generic routine to retrieve a symbol from a macro file that's generated
# by GetDHCPMacro.
# Parameter $1: is the symbol to extract
#	    $2: the filename containing fields for the macro
#
GetDHCPSymbol() {

    if [ $# -ne 2 -o ! -s "$2" ]; then
	return 1
    fi
    typeset VAL=`grep "^${1}\>" $2`
    if [ -n "$VAL" ]; then
    	print $VAL | sed -e "s/^${1}=\"*\(.*[^\"]\)\"*$/\1/"
    	return 0
    fi
    return 1
}

#
# sets up the default SunRay macro
# 
# Parameters:
#  $1 loghost value.  the IP for the primary interface will be used if not
#     specified.
#
SetSRDefaultMacro() {
    # add the Sunray-specific macro, included by all interfaces and subnetworks
    # (includes lease time and negotiate enable)
    let LEASE=${LEASE_DAYS}\*86400;
    CORONA_MACRO=":LeaseTim=${LEASE}:LeaseNeg:AuthPort=${AUTH_PORT}:\
LogHost=${1:-${HOSTIP}}:LogKern=${LOG_KERN}:LogNet=${LOG_NET}:\
LogUSB=${LOG_USB}:LogVid=${LOG_VID}:LogAppl=${LOG_APPL}:";
    dhtadm -D -m "${CORONA_NAME}" 2> /dev/null
    dhtadm -A -m "${CORONA_NAME}" -d "${CORONA_MACRO}" 2> ${TMPDIR}/Err.$$;

    if [ ${?} -ne 0 ]; then
	print -u2 "Error:  cannot add server macro \"${CORONA_NAME}\" to dhcptab:\n    `cat ${TMPDIR}/Err.$$`"
	rm -f ${TMPDIR}/Err.$$
	return 1;
    else
	rm -f ${TMPDIR}/Err.$$
    fi
    return 0
}


# get the current default SunRay macro parameters
GetSRDefaultMacro() {

    rm -f ${TMPDIR}/srdefaults.$ 2> /dev/null
    GetDHCPMacro ${CORONA_NAME} > ${TMPDIR}/srdefaults.$$
}


#
# get the value for the specified symbol from the srdefaults.$$ file
# it prints the value and reutrn status 0 if found.  Else, returns 1.
# $1 the specified symbol
# 
GetSRDefaultSym() {

    if [[ -z "$1" ]]; then
	print ""
	return 1
    fi
    GetDHCPSymbol "$1" "${TMPDIR}/srdefaults.$$"
    return $?
}


#
# check the default SR macro.  If one of the following symbols are not
# set, it will set them to the default value.  The symbols that should
# be in the default SunRay macro are:
# AuthPort, LogHost, LogKern, LogNet, LogUSB, LogVid, LogAppl
# If a value already exist, 
# It will NOT overwrite any existing default values if it's already 
# defined in the SunRay macro.
#
# It returns 0 if all defaults are found or are added successfully.
# Else returns 1.
#
CheckSRDefaultMacro() {

    if [[ ! -f ${TMPDIR}/srdefaults.$$ ]]; then
	GetSRDefaultMacro
    fi
    typeset TMPBATCH=${TMPDIR}/dhtadm-batch.$$
    rm -f $TMPBATCH 2> /dev/null
    touch $TMPBATCH
    typeset sym

    # check the default values in the SunRay macro
    if ! sym=$(GetSRDefaultSym "AuthPort"); then
	print "dhtadm -M -m ${CORONA_NAME} -e AuthPort=${AUTH_PORT}" \
		>> $TMPBATCH
    fi
    if ! sym=$(GetSRDefaultSym "LogHost"); then
	print "dhtadm -M -m ${CORONA_NAME} -e LogHost=${HOSTIP}" \
		>> $TMPBATCH
    fi
    if ! sym=$(GetSRDefaultSym "LogKern"); then
	print "dhtadm -M -m ${CORONA_NAME} -e LogKern=${LOG_KERN}" \
		>> $TMPBATCH
    fi
    if ! sym=$(GetSRDefaultSym "LogNet"); then
	print "dhtadm -M -m ${CORONA_NAME} -e LogNet=${LOG_NET}" \
		>> $TMPBATCH
    fi
    if ! sym=$(GetSRDefaultSym "LogUSB"); then
	print "dhtadm -M -m ${CORONA_NAME} -e LogUSB=${LOG_USB}" \
		>> $TMPBATCH
    fi
    if ! sym=$(GetSRDefaultSym "LogVid"); then
	print "dhtadm -M -m ${CORONA_NAME} -e LogVid=${LOG_VID}" \
		>> $TMPBATCH
    fi
    if ! sym=$(GetSRDefaultSym "LogAppl"); then
	print "dhtadm -M -m ${CORONA_NAME} -e LogAppl=${LOG_APPL}" \
		>> $TMPBATCH
    fi

    if [[ -s $TMPBATCH ]]; then
	# update the SunRay Macro
	dhtadm -B $TMPBATCH 2> ${TMPDIR}/Err.$$;
	if [ ${?} -ne 0 ]; then
	    print -u2 "Error:  failed to update the SunRay default Macro:\
		\n    `cat ${TMPDIR}/Err.$$`"
	    rm -f $TMPBATCH ${TMPDIR}/Err.$$;
	    return 1
	fi
	rm -f $TMPBATCH ${TMPDIR}/Err.$$;
	GetSRDefaultMacro
    fi
    return 0
}



# 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=`sed -n "/^${ip}/s/.*:Intf=\"*\([^:\"]*\)[:\"].*/\1/p" $DHTADM_P`

	if [ $name != ${CORONA_NAME}-${intf} ]; then
	    print "### fixing interface \"${INTF}\"."
	    dhtadm -M -m $name -n ${CORONA_NAME}-${intf} 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
	    pntadm -P $NET 2>/dev/null|cut -f3 >${TMPDIR}/pntadm.op.$$
	    while read clientIp
	    do
		pntadm -M $clientIp -m ${CORONA_NAME}-${intf} $NET 2>/dev/null
	    done <${TMPDIR}/pntadm.op.$$
	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() {

    if ! pkginfo -q SUNWdhcsb; then
	# the DHCP binary file format package is not installed - abort.
	print -u2 "Error: SUNWdhcsb 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."
	exit 1;
    fi
    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
	print "#\n# The networks file associates Internet Protocol (IP) network numbers\n# with network names.  The format of this file is:\n# \n#       network-name    network-number  nicnames . . .\n#\n\n#\n# The loopback network is used only for intra-machine communication\n#\nloopback        127\n\n#\n# Internet networks\n#\narpanet         10              arpa    # Historical\n" > ${NETWORKS};
	chmod 744 "${NETWORKS}";
    fi

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

    print "### Configuring Service information for ${CORONA_TITLE}";
    SetupCfgFile;
    SetupDhcptab;
    GetCurrentCfg	# re-read the DHCP info from dhtadm -P
    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

    #
    # 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

    print "### Disabling Routing";
    touch /etc/notrouter
    ndd -set /dev/ip ip_forwarding 0
}


#
# removes the DHCP info
#
DoRemoveDHCP() {

    if $SUBNETMODE; then
	# deleting subnetwork
	INTF_NETNAME=${CORONA_NAME}-${SUBNET_DEL}
	INTF_NET=${SUBNET_DEL}
    else
	# deleting interface
	INTF_NETNAME=${CORONA_NAME}-${DHCP_DEL}
	INTF_NET=`awk '{ if ($1 == interface) { print $2 } }' interface=${INTF_NETNAME} ${NETWORKS}`
    	if [ -z "${INTF_NET}" ]; then
	    # not defined in the networks file, try checking in dhtadm
	    INTF_NET=`$GREP -s ":Include=${INTF_NETNAME}:" $DHTADM_P | awk '{print $1}'`
    	    if [ -z "${INTF_NET}" ]; then
		print -u2 "Error: Cannot translate interface \"${DHCP_DEL}\" to a network number"
		return 1
	    fi
	fi
    fi

    typeset MULTINET=N
    typeset TMPFILE=${TMPDIR}/pntadm-multi.$$
    typeset retcode=0
    typeset pntstat

    rm -f ${TMPFILE} 2> /dev/null
    pntadm -P ${INTF_NET} | sed -e '1,2d' > ${TMPFILE}
    pntstat=${?}
    # check for MULTINET by looking into the network table, not the networks file
    if $GREP -q -s -v "${INTF_NETNAME}" ${TMPFILE}; then
	MULTINET=Y
    fi

    if $SUBNETMODE; then
    	print "### Removing ${CORONA_TITLE} information for subnetwork \"${SUBNET_DEL}\""
    else
    	print "### Removing ${CORONA_TITLE} information for interface \"${DHCP_DEL}\""
    fi
    if [ $MULTINET = "N" ]; then
	dhtadm -D -m "${INTF_NET}";
	if [[ $pntstat -eq  0 ]]; then
	    # remove the network table.
	    pntadm -R "${INTF_NET}"
	fi
    else
	typeset TMPBATCH=${TMPDIR}/pntadm-rm-batch.$$
	rm -f $TMPBATCH 2> /dev/null
	awk "/${INTF_NETNAME}/ { print \"pntadm -D \" \$3 \" ${INTF_NET}\" }" ${TMPFILE} \
		> $TMPBATCH
	if [[ -s $TMPBATCH ]]; then
	    pntadm -B $TMPBATCH 2> ${TMPDIR}/Err.$$
	    if [[ ${?} != 0 ]]; then
		print -u2 "Error:  failed to remove the entries for subnetwork \"${INTF_NET}\":\n\
			`cat ${TMPDIR}/Err.$$`"
	    	# even when it failed, continue with the removal
		retcode=1
	    fi
	    rm -f $TMPBATCH ${TMPDIR}/Err.$$ 2> /dev/null
	fi
    fi
    rm ${TMPFILE}
    if ! dhtadm -D -m ${INTF_NETNAME}; then
	retcode=1
    fi
    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
    M=`getent netmasks ${INTF_IPA} | awk '{print $2}'` 
    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
	    ifconfig ${INTF} down 2>&1 >/dev/null;
	    ifconfig ${INTF} unplumb 2>&1 >/dev/null;
	    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 "${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
    RestoreFile "${HOSTS}";
    RestoreFile "${NETWORKS}";
    RestoreFile "${NETMASKS}";

    typeset TMPBATCH=${TMPDIR}/rem_batch.$$
    rm $TMPBATCH 2> /dev/null
    # Remove the generic macro
    print "dhtadm -D -m ${CORONA_NAME}" > $TMPBATCH

    # now remove all of the DHCP symbols
    for i in `awk '/SUNW.NewT.SUNW/ { print $1 }' $DHTADM_P`; do
	print "dhtadm -D -s $i" >> $TMPBATCH
    done
    dhtadm -B $TMPBATCH 2> /dev/null	# ignore errors
    rm -f $TMPBATCH
	
    # 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
    $UTSBIN/utfwadm -R
}


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

    typeset noIPaddr=0
    if $SUBNETMODE; then
	# adding subnetwork
	SUBNET=${SUBNET_ADD}
    else
	# adding interface
	typeset INTF_ALL=`ifconfig -a inet | sed -n -e '/lo0/d' -e '/: flags=/s/:.*//p'`
	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_R}.${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_R}.${INTF} ]; then
		    print -u2 "Error: missing \"${HOSTNAME_R}.${INTF}\" file."
		    return 1
		fi
		NAME=`cat ${HOSTNAME_R}.${INTF}`
		if [ -z "${NAME}" ]; then
		    print -u2 "Error: interface ${INTF} is partially configured.  Hostname" \
			"not specified in the \"${HOSTNAME_R}.${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_R}.${INTF}\" file."
		    exit 1
		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"
    ALT_AUTH=""
    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
		rm -f ${TMPDIR}/netwcheck.$$ 2> /dev/null
		GetDHCPMacro ${DEF_NET_PFX}.${N}.0 > ${TMPDIR}/netwcheck.$$
		if [[ ! -s ${TMPDIR}/netwcheck.$$ ]]; then
		    # subnetwork not defined in the dhcp table
		    rm -f ${TMPDIR}/netwcheck.$$ 2> /dev/null
		    break;
		fi
		rm -f ${TMPDIR}/netwcheck.$$ 2> /dev/null
	    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}
	AUTHSRVR=${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})
	    SYS_NETMASK=`getent netmasks ${SUBNET} | awk '{print $2}'`
	    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} inet`
	    if [ $? -ne 0 ]; then
		print -u2 "Existing interface ${INTF} must be up to do configuration"
	    exit 1
	    fi
	    SYS_NETMASK=`getNetMask "${config}"`
	    NETMASK=$SYS_NETMASK
	    CLASS_NETMASK=$(GetNetmaskClass ${config})
	    ADD_NETMASK=false
	    SYS_NETMASK=`getent netmasks ${SUBNET} | awk '{print $2}'`
	    IP2Net ${IPADDR} ${NETMASK}
	    NETADDR=$NET
	    NETNAME="${CORONA_NAME}-${INTF}"
	    ROUTER=`netstat -rn -f inet| grep '^default' | awk '{print $2}'`
	    MaxHostNum ${NETMASK}
	    MHN=$H
	fi
	MaxHostNum ${CLASS_NETMASK}
	CLASS_MAXHOST=$H
	let "START_NUM = $H - 10"
	let "END_NUM = $H - 1"
	FWSRVR=${IPADDR}
	AUTHSRVR=${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:\t${AUTHSRVR}";
	print "    firmware server:\t${FWSRVR}";
	print "    router:\t\t${ROUTER}";
	print "    alternate servers:\t${ALT_AUTH}";

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

	ALT_AUTH=""

	# 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
		CheckIPA "${ANS}";
		if [ ${?} -eq 0 ]; then
		    IPADDR=${ANS};
		    FWSRVR=${ANS};
		    AUTHSRVR=${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
		    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
		    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};
			AUTHSRVR=${SVIP};
			NETMASK=${SVMSK};
			NETADDR=${SVNET};
			continue;
		    fi
		    MULTINET="Y"
		else
		    IPADDR=${SVIP};
		    FWSRVR=${SVIP};
		    AUTHSRVR=${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};
		AUTHSRVR=${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};
		AUTHSRVR=${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
		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
		    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
		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};
		    elif [ $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
	while :
	do		# auth server
	    print -n "  new auth server: [${AUTHSRVR}] ";
	    read ANS
	    :
	    if [ -z "${ANS}" ]; then
		ANS=${AUTHSRVR};
	    fi
	    CheckIPA "${ANS}";
	    if [ ${?} -eq 0 ]; then
		if [ ${ANS} = ${NETADDR} ]; then
		    print -u2 "Error: auth server is equal to network address";
		    continue;
		fi
		AUTHSRVR=${ANS};
		break;
	    else
		print -u2 "Error: invalid IP address\n";
		continue;
	    fi
	done		# auth server

	# get new firmware server
	while :
	do		# firmware server
	    print -n "  new firmware server: [${FWSRVR}] ";
	    read ANS
	    :
	    if [ -z "${ANS}" ]; then
		ANS=${FWSRVR};
	    fi
	    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

	# get new router
	while :
	do		# router
	    print -n "  new router: [${ROUTER}] ";
	    read ANS
	    :
	    if [ -z "${ANS}" ]; then
		    ANS=${ROUTER};
	    fi
	    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

	# get alternate auth server
	while :
	do		# alternate auth server
	    if [ -n "${ALT_AUTH}" ]; then
		print "  alternate servers:\t${ALT_AUTH}";
	    fi
	    YesOrNo "Specify alternate server list? " "N"
	    if [ $? -ne 0 ]; then
		ALT_AUTH=""
		break
	    fi
	    print -n "To read from file, enter file name: ";
	    read FILE

	    if [ -n "$FILE" ]; then
		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"
			ALT_AUTH=""
			IP_ERROR=0
			break
		    fi
		done
		if [ $IP_ERROR -ne 1 ]; then
		    continue
		fi
	    else
		while true
		do
		    print -n "Server IP address (enter <CR> to end list): ";
		    read ANS
		    :
		    if [ -z "${ANS}" ]; then
			break
		    fi
		    CheckIPA ${ANS}
		    if [ ${?} -ne 0 ]; then
			print "Invalid IP address"
			continue
		    fi
		    ALT_AUTH="${ALT_AUTH}$ANS "
		done
	    fi
	    ALT_AUTH=`print "${ALT_AUTH}" | sed 's/ $//'`
	    if [ -z "${ALT_AUTH}" ]; then
		print -u2 "Error: no servers in alternate list"
		continue
	    else
		break
	    fi
	done		# alternate auth server
    done	# prompt for new values

    # 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
	# ifconfig the new interface
	ifconfig ${INTF} plumb;
	ifconfig ${INTF} "${IPADDR}" up netmask "${NETMASK}" broadcast +;
	print "### finished install of \"${INTF}\" interface";
    fi
}


#
# get parameter in the following order:
# 1. macro referenced from network table (eg. SunRay-hme0)
# 2. macro included from referenced macro (eg. SunRay)
# 3. network macro (eg. 192.168.129.0)
# The caller is to provide the files generated from GetDHCPMacro and they 
# should be specified in the order specified above.
# Parameters:
# $1 the symbol to retrieve
# $2 the file containing info for #1
# $3 the file cotnaining info for #2
# $4 the file cotnaining info for #3
#
# Returns 0 if found, else 1
#
getDHCPSymbolFromList() {

    typeset value
    if value=`GetDHCPSymbol $1 $2`; then
	print $value
	return 0
    fi
    if value=`GetDHCPSymbol $1 $3`; then
	print $value
	return 0
    fi
    if value=`GetDHCPSymbol $1 $4`; then
	print $value
	return 0
    fi
    return 1
}


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

    if ! $ISSETUP; then
	print -u2 "${CORONA_TITLE} interconnect framework is not configured";
	exit 1;
    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 netmacro
    typeset Intf
    typeset IntfAddr
    typeset IPassign
    typeset FirstIP
    typeset NewTVer
    typeset today
    typeset network_macro="${TMPDIR}/network_tmp.$$"
    typeset refer_macro="${TMPDIR}/netrefer_tmp.$$"
    typeset sunray_macro="${TMPDIR}/sunray_tmp.$$"

    rm -f $sunray_macro 2> /dev/null
    GetDHCPMacro "$CORONA_NAME" > $sunray_macro
    if [[ ! -s $sunray_macro ]]; then
	print -u2 "No SunRay macro defined"
	rm -f $sunray_macro 2> /dev/null
	exit 1
    fi

    # see if LAN connections are allowed by checking allowLANConnections
    ALLOW=$(GetLowerValueByKey allowLANConnections $AUTHPROPS)
    if [ "${ALLOW}" = "true" ]; then
	print "LAN connections: 0n"
    else
	print "LAN connections: 0ff"
    fi

    for SUBNET in `cat ${TMPDIR}/allSRnets.$$`; do
	# setup the network macro file
	rm -f $network_macro 2> /dev/null
	GetDHCPMacro "$SUBNET" > $network_macro
	if [[ ! -s $network_macro ]]; then
	    print -u2 "No Subnet macro defined for \"${SUBNET}\""
	    rm -f ${TMPDIR}/net*_tmp.$$ 2> /dev/null
	    continue
	fi

	# check to see if it's a local interface
	if Intf=`GetDHCPSymbol Intf $network_macro`; 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
	fi

	# get the include macro
	if ! netmacro=`GetDHCPSymbol Include $network_macro`; then

	    if [ -z "${Intf}" ]; then
		print -u2 "missing Include macro in Subnet macro for \"${SUBNET}\""
		rm -f ${TMPDIR}/net*_tmp.$$ 2> /dev/null
		continue
	    fi
	    # for backward compatibility
	    netmacro="${CORONA_NAME}-${Intf}"
	fi

	# setup the referenced macro file
	rm -f $refer_macro 2> /dev/null
	GetDHCPMacro "$netmacro" > $refer_macro
	if [[ ! -s $refer_macro ]]; then
	    print -u2 "No \"${netmacro} macro defined for \"${SUBNET}\""
	    rm -f ${TMPDIR}/net*_tmp.$$ 2> /dev/null
	    continue
	fi

	# stablish the search order
	typeset PNTADM_PX="${TMPDIR}/pntadm_px.$$"
	rm -f $PNTADM_PX 2>/dev/null
	pntadm -Px ${SUBNET} 2>/dev/null | \
		nawk '
		    NR > 2 {
			if ($6 == macro) {
			    print $3, $5;
			}
		    }' macro=${netmacro} - | sort -u > $PNTADM_PX
	if [[ -s $PNTADM_PX ]]; then
	    # network table defined, the macro referenced in the network
	    # table has precedence.
	    typeset order="$refer_macro $sunray_macro $network_macro"
	else
	    # not defined in the network table, the network macro has
	    # precedence.
	    typeset order="$network_macro $refer_macro $sunray_macro"
	fi

	# retrieve broacast value
	if ! Broadcast=`getDHCPSymbolFromList Broadcst $order`; then
	    Broadcast="*MISSING*"
	fi

	# retrieve netmask value
	if ! Netmask=`getDHCPSymbolFromList Subnet $order`; then
	    Netmask="*MISSING*"
	fi

	# retrieve router value
	if ! Router=`getDHCPSymbolFromList Router $order`; then
	    Router="*MISSING*"
	fi

	# retrieve firmware server value
	if ! FWSrvr=`getDHCPSymbolFromList FWSrvr $order`; then
	    FWSrvr="*MISSING*"
	fi

	# retrieve NewTver value
	if ! NewTVer=`getDHCPSymbolFromList NewTVer $order`; then
	    NewTVer="*MISSING*"
	fi

	# retrieve auth server value
	if ! AuthSrvr=`getDHCPSymbolFromList AuthSrvr $order`; then
	    AuthSrvr="*MISSING*"
	fi
	rm -f ${TMPDIR}/net*_tmp.$$ 2> /dev/null

	if [[ -s $PNTADM_PX ]]; then
	    today=`/opt/SUNWut/lib/uttime`
	    IPassign=`nawk -v today=$today 'BEGIN { count = 0; total = 0 }
    		    {
		    if ($2 < 0 || today < $2) {
			count++
		    }
    		    total++
    		}
    		END {
    			print count, total
    		}' $PNTADM_PX`
	    FirstIP=`head -1 $PNTADM_PX | awk '{ print $1 }'`
	else
	    IPassign=""
	fi
	rm -f $PNTADM_PX
	printf "Subnetwork: %-10s\n" $SUBNET
	if [[ -n "$Intf" ]]; then
	    printf "\tInterface=\t%-s (%s)\n" $Intf $IntfAddr
	fi
	printf "\tNetmask=\t%-10s\n" $Netmask
	printf "\tBroadcast=\t%-10s\n" $Broadcast
	printf "\tRouter=\t\t%-10s\n" $Router
	printf "\tAuthSrvr=\t%-10s\n" $AuthSrvr
	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
    done
}


#
# 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}
}


#
# 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
    print "Interface	Host		Network		Netmask		Assigned IPs";
    for INTF in `cat ${TMPDIR}/allifs.$$`; do
	#
	# 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
	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
	today=`/opt/SUNWut/lib/uttime`
	C=`pntadm -Px ${NET} 2>/dev/null | \
		nawk -v netname="${CORONA_NAME}-${INTF}" -v today=$today 'BEGIN { count = 0; total = 0 }
    		($6 == netname) {
		    if ($5 < 0 || today < $5) {
			count++
		    }
    		    total++
    		}
    		END {
    			print count, total
    		}'`
	printf "%-10s\t%-10s\t%-10s\t%-10s\t%6s/%-6s\n" $INTF $H $NET $M $C;
    done
}

#
# 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
}



################################################################
#
# 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

DetermineRelease;
CheckDHCP;
GetCurrentCfg;
if pgrep in.dhcpd 2>&1 >/dev/null; 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:z ARGNAME 2>/dev/null; do
  case $ARGNAME in
    c)	setMode "c"
	CREATE="Y"
	;;
    a)  setMode "a"
	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
	STATUS=`ifconfig ${OPTARG} plumb 2>&1`
	if [ -n "$STATUS" ]; then
	  print -u2 "Error:  invalid interface name: \"${OPTARG}\"";
	  Usage;
        fi
    	INTF_ADD="${OPTARG}"
	;;
    d)	setMode "d"
	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"
	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"
	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
	rm -f ${TMPDIR}/intfscheck.$$ 2> /dev/null
	GetDHCPMacro ${SUBNET_DEL} > ${TMPDIR}/intfscheck.$$
	typeset intfcheck
	intfcheck=`GetDHCPSymbol Intf ${TMPDIR}/intfscheck.$$`
	#
	# 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}\"."
	    rm -f ${TMPDIR}/intfscheck.$$ 2> /dev/null
	    exit 1
	fi
	rm -f ${TMPDIR}/intfscheck.$$ 2> /dev/null
	SUBNETMODE=true
	;;
    r)	setMode "r"
	;;
    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}
	;;
    ?)	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 $GREP -q -w "${CORONA_NAME}" ${DHTADM_P}; then
    ISSETUP=true
fi

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

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

# turn on or off LAN connection
if [ ${MODE} = "L" ]; then
    DoAllowLan $ALLOW_LAN_CONN
    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

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

if [[ "${MODE}" = "r" ]]; then
    # ......... removal operation

    # 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

elif [[ "${REMOVE}" = "Y" ]]; then
    # ......... 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

elif [[ $MODE = "c" ]]; then
    # ......... initializing SunRay framework
    DoInit

elif [ "${MODE}" = "a" -o "${MODE}" = "A" ]; then
    # ......... add interface or subnetworks

    # force CREATE mode on if the Sunray macro is not defined
    if ! $ISSETUP; then
	DoInit
    fi

    if ! CheckSRDefaultMacro; then
	exit 1
    fi
    DoAddNetworkConfig

    # Force databases to be reread by cache
    Restart_nscd

    DoAddIntfsMacro

    print "### Building network tables - this will take a few minutes";
    BuildNetworkTables "${INTF_ADD}"

    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 -n "${INTF_ADD}" \
  	-s all -f user.info -d /var/opt/SUNWut/log/messages -z;
    $UTLIB/utlog -a -n "${INTF_ADD}" \
        -s all -f local1.info -d /var/opt/SUNWut/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
  
fi

RestartDHCP
rm ${TMPDIR}/*.$$ 2>/dev/null;
exit 0
