#!/bin/sh

USAGE=$"Usage: ike [options] {commands}
  options:
     -c <file> : specify alternate configuration file
     -s <path> : override location of management scripts
     -b <path> : override location of binaries/modules
     -m <0|1>  : override default driver mode (0=pkt interceptor, 1=iptables)
  commands:
#     start [x] : load Netfilter modules, init SADB/SPD, start IKE daemon
                  debug level=x (0-3); if red/blk IP's are the same in
                  iked.conf, this will turn on proxy ARP for red/blk
     stop      : shutdown IKE daemon and reset SADB/SPD; if red/blk IP's
                  are the same in iked.conf, this will turn off proxy ARP
     restart   : stop/start this script
     print     : display internal Oakley state table
                  (must set bOakleyDumpTrace=#1 in iked.conf)
     dumppol   : display internal policy tables
     clr       : clear all SA's
     reload    : reload IKE policy; generate SPD rules
     reset     : reset IKE daemon; reload config files, clear all SA's
     help      : this message
"

# obsolete
#     defaults  : overwrite existing iked configuration files with defaults

# overrideable
SCRIPTDIR=/usr/sbin
BINDIR=/usr/iked
SADB_MODE=1

# DEBUGLEVEL set by start command
DEBUGLEVEL=0

CONFDIR=/etc/iked	# must point to r/w location
IKEDCONF=$CONFDIR/iked.conf

# static settings
SPDBIN=spd
SADBBIN=sadb
#NETFILTERBIN=netfilter
IKEDBIN=iked
DEFAULTS=iked-config.tar.gz

PROCAUTOSTART=/usr/sbin/procautostart

IKEDSYSLOG=authpriv.warning
IKEDSYSLOGTAG=ike

######################################################################

logit()
{
	logger -p $IKEDSYSLOG -t $IKEDSYSLOGTAG "$@"
}

get_confparam()
{
	if [ -f $IKEDCONF ]; then
		# remove the leading # and " from key values as well as
		#	trailing whitespace
		grep "^$1=" $IKEDCONF | sed -e "s/$1=[\"\#]*//" | sed -e "s/[ ]*$//"
	fi
}

######################################################################

getoptions()
{
	BLACKIP=`get_confparam blackip`
	REDIP=`get_confparam redip`
# @BA@alize300@XTSce55151@070705@lsa@
	RED1IP=`get_confparam red1ip`
	RED2IP=`get_confparam red2ip`
	RED3IP=`get_confparam red3ip`
	RED4IP=`get_confparam red4ip`
	RED5IP=`get_confparam red5ip`
	RED6IP=`get_confparam red6ip`
	RED7IP=`get_confparam red7ip`
# @EA@alize300@XTSce55151@070705@lsa@
	BLACKIF=`get_confparam blackif`
	REDIF=`get_confparam redif`
# @BA@alize300@XTSce55151@070705@lsa@
	RED1IF=`get_confparam red1if`
	RED2IF=`get_confparam red2if`
	RED3IF=`get_confparam red3if`
	RED4IF=`get_confparam red4if`
	RED5IF=`get_confparam red5if`
	RED6IF=`get_confparam red6if`
	RED7IF=`get_confparam red7if`
# @EA@alize300@XTSce55151@070705@lsa@
	IKEDPIDFILE=`get_confparam pidfile`
	IKEDUIFIFO=`get_confparam uirendezvous`
	DHCPAGENT=`get_confparam dhcpagentfile`
	DHCPAGENTFIFO=`get_confparam dhcpagentrendezvous`
	RADIUSAGENT=`get_confparam radiusagentfile`
	RADIUSAGENTFIFO=`get_confparam radiusagentrendezvous`
	RADIUSAGENTCONFFILE=`get_confparam radiusagentconfigfile`
	RADIUSAGENTON=`get_confparam radiusagent`

	# use defaults if necessary
	if [ -z "$IKEDPIDFILE" ]; then IKEDPIDFILE="/var/run/iked.pid"; fi
	if [ -z "$IKEDUIFIFO" ]; then IKEDUIFIFO="/var/run/ikedui.fifo"; fi
	if [ -z "$DHCPAGENTFIFO" ]; then DHCPAGENTFIFO="/var/run/dhcpagent.fifo"; fi
	if [ -z "$RADIUSAGENTFIFO" ]; then RADIUSAGENTFIFO="/var/run/radiusagent.fifo"; fi
	if [ -z "$DHCPAGENT" ]; then DHCPAGENT="dhcpagent"; fi
	if [ -z "$RADIUSAGENT" ]; then RADIUSAGENT="radiusagent"; fi
}

cleanfile()
{
	# make sure we can write modified file
	if [ -w $1 ]; then
		logit "$0: Cleaning file: $1 ..."
		cp -f $1 /tmp/`basename $1`.bak
		cat $1 | sed -e "s/[ ]*$//" | sed -e "s/\"$//" > /tmp/tmpconf
		cp -f /tmp/tmpconf $1; rm -f /tmp/tmpconf
	fi
}

cleanconf()
{
	IKEDPOLICY=`get_confparam policyfile`
	IKEDSECRET=`get_confparam secretsfile`
	if [ -f "$IKEDPOLICY" ]; then cleanfile $IKEDPOLICY; fi
	if [ -f "$IKEDSECRET" ]; then cleanfile $IKEDSECRET; fi
}

# obsolete
restoreconfig()
{
	# sanity check
	if [ -z "$BLACKIP" -o -z "$REDIP" -o -z "$BLACKIF" -o -z "$REDIF" ]; then
		logit "$0: Can't restore defaults; $IKEDCONF red/blk addresses and/or interfaces not set."
	else
		logit "$0: Restoring default configuration ..."
		if [ -f $BINDIR/$DEFAULTS ]; then
			rm -fr /tmp/iked_defaults; mkdir -p /tmp/iked_defaults; cd /tmp/iked_defaults
			cat $BINDIR/$DEFAULTS | gunzip - | tar xvf -
			if [ -f /tmp/iked_defaults/config/iked.conf -a -w $CONFDIR ]; then
				rm -fr $CONFDIR; mkdir -p $CONFDIR
				cp -af /tmp/iked_defaults/config/* $CONFDIR
			fi
			rm -fr /tmp/iked_defaults
			sed -e "s/@IKED_BLACKIF@/$BLACKIF/" | \
				sed -e "s/@IKED_REDIF@/$REDIF/" | \
				sed -e "s/@IKED_BLACK_IP@/$BLACKIP/" | \
				sed -e "s/@IKED_RED_IP@/$REDIP/" $CONFDIR/iked.conf.in > $CONFDIR/iked.conf
			sed -e "s/@IKED_BLACK_IP@/$BLACKIP/" $CONFDIR/policy.cfg.in > $CONFDIR/policy.cfg
		else
			logit "$0: Fatal, default config archive: $BINDIR/$DEFAULTS does not exist."
			exit 1
		fi
	fi
}

######################################################################

startsadb()
{
	logit "$0: Initializing SADB/SPD ..."

	# flush host rules, reset default policies
#	$SCRIPTDIR/$NETFILTERBIN reset
	# set default packet filter rules to allow traffic
#	$SCRIPTDIR/$NETFILTERBIN filter
	# set startup proxy rules
#	$SCRIPTDIR/$NETFILTERBIN proxy

	$SCRIPTDIR/$SADBBIN -c $IKEDCONF -s $SCRIPTDIR -b $BINDIR -m $SADB_MODE start

	# get return code from sadb script
	if [ "$?" != "0" ]; then
		logit "$0: Fatal, kernel modules initialization failed, hard shutdown."
		$0 -c $IKEDCONF -s $SCRIPTDIR -b $BINDIR -m $SADB_MODE stop
		exit 1
	fi
}

resetsadb()
{
	logit "$0: Resetting SADB/SPD ..."
	$SCRIPTDIR/$SADBBIN -c $IKEDCONF -s $SCRIPTDIR -b $BINDIR -m $SADB_MODE reset
}

reloadspdrules()
{
	logit "$0: Reloading SPD ..."
	$SCRIPTDIR/$SPDBIN -c $IKEDCONF -b $BINDIR restart
}

# OKR: routine added for XTSce04012
flushspddynrules()
{
	logit "$0: Flushing SPD DYN rules ..."
	$SCRIPTDIR/$SPDBIN -c $IKEDCONF -b $BINDIR flushdynrules
}

proxyarp()
{
	# sanity check
	if [ -z "$BLACKIF" -o -z "$REDIF" ]; then
		logit "$0: Can't set proxy-ARP status; $IKEDCONF red/blk interfaces not set."
	else
		if [ "$REDIP" = "$BLACKIP" ]; then
			case "$1" in
			on)
				logit "$0: Bridge emulation detected, enabling Proxy-ARP ..."
				echo 1 > /proc/sys/net/ipv4/conf/$BLACKIF/proxy_arp
				echo 1 > /proc/sys/net/ipv4/conf/$REDIF/proxy_arp
				;;
			off)
				logit "$0: Bridge emulation detected, disabling Proxy-ARP ..."
				echo 0 > /proc/sys/net/ipv4/conf/$BLACKIF/proxy_arp
				echo 0 > /proc/sys/net/ipv4/conf/$REDIF/proxy_arp
				;;
			esac
		fi
	fi
}

startike()
{
	# make sure expected binaries are there
	if [ ! -x $BINDIR/$IKEDBIN ]; then
		logit "$0: Fatal, iked binary: $BINDIR/$IKEDBIN does not exist."
		exit 1
	fi

	if [ ! -x $RADIUSAGENT ]; then
		logit "$0: Fatal, RADIUS authentication agent binary: $RADIUSAGENT does not exist."
		exit 1
	fi
	if [ ! -x $DHCPAGENT ]; then
		logit "$0: Fatal, DHCP agent binary: $DHCPAGENT does not exist."
		exit 1
	fi

	# double-check one little detail
	if [ ! -e /dev/random ]; then
		logit "$0: Fatal, cannot start IKE, system lacks /dev/random!"
		exit 1
	fi

	# don't allow core dumps
	#ulimit -c 0

	if [ -x $PROCAUTOSTART ]; then
		logit "$0: Starting IKE daemon (with monitor), debug level: $DEBUGLEVEL ..."
		LD_LIBRARY_PATH=$BINDIR:$LD_LIBRARY_PATH $PROCAUTOSTART -n 12 -c "$BINDIR/$IKEDBIN -d -c $IKEDCONF -l $DEBUGLEVEL" nohup &
	else
		logit "$0: Starting IKE daemon, debug level: $DEBUGLEVEL ..."
		#Call a failure param to prevent some albator strange behavior XTSce16585
		#/opt/itrnet/bin/iagw --cmd start "iked" "D" "$BINDIR/$IKEDBIN" "-c $IKEDCONF -l $DEBUGLEVEL >/dev/null 2>&1" -1 NO_PARAMS NO_PARAMS "T"
# @BA@alize300@XTSce42998@180205@vbu@
# This code is not for XTSce42998
# It allows to have a common code between OXO plateform and non-OXO plateform
# Detect if Albator is present or not and start ike accordingly
		if [ -x /opt/itrnet/bin/iagw ]; then
# @EA@alize300@XTSce42998@180205@vbu@
			/opt/itrnet/bin/iagw --cmd start "iked" "D" "$BINDIR/$IKEDBIN" "-c $IKEDCONF -l $DEBUGLEVEL >/dev/null 2>&1" -1 "/etc/iked/IkedFailure" "0" "T"
# @BA@alize300@XTSce42998@180205@vbu@
		else
			iked -c $IKEDCONF -l $DEBUGLEVEL >/dev/null 2>&1
		fi
# @EA@alize300@XTSce42998@180205@vbu@
	#	LD_LIBRARY_PATH=$BINDIR:$LD_LIBRARY_PATH $BINDIR/$IKEDBIN -c $IKEDCONF -l $DEBUGLEVEL
	fi
}

stopike()
{
	logit "$0: Stopping IKE daemon ..."

	killall -9 `basename $PROCAUTOSTART` 1>/dev/null 2>&1

	if [ ! -f $IKEDPIDFILE ]; then
		: nothing
	elif [ ! -s $IKEDPIDFILE ]; then
		# remove empty pidfile, process still running?
		rm -f $IKEDPIDFILE
	else 
#		kill -3 `cat $IKEDPIDFILE` 1>/dev/null 2>&1
# @BA@alize300@XTSce42998@180205@vbu@
# This code is not for XTSce42998
# It allows to have a common code between OXO plateform and non-OXO plateform
# Detect if Albator is present or not and stop ike accordingly
		if [ -x /opt/itrnet/bin/iagw ]; then
# @EA@alize300@XTSce42998@180205@vbu@
			/opt/itrnet/bin/iagw --cmd stop "iked"
# @BA@alize300@XTSce42998@180205@vbu@
		else
			kill -3 `cat $IKEDPIDFILE` 1>/dev/null 2>&1
		fi
# @EA@alize300@XTSce42998@180205@vbu@
		sleep 2
		rm -f $IKEDPIDFILE

		# grep process table too (no awk, so use clumy sed expressions to trim)
		#IKEDPID=`ps -ax | grep $BINDIR/$IKEDBIN | sed -e "s/root.*//" | sed -e "s/^[ ]*//" | sed -e "s/[ ]*$//"`
		#DHCPPID=`ps -ax | grep $DHCPAGENT | sed -e "s/root.*//" | sed -e "s/^[ ]*//" | sed -e "s/[ ]*$//"`
		DHCPPID=`ps -ax | grep $DHCPAGENT | sed '1!d' | sed -e 's/[ \t]\{1,\}/ /g' | cut -d ' ' -f1`
		#RADIUSPID=`ps -ax | grep $RADIUSAGENT | sed -e "s/root.*//" | sed -e "s/^[ ]*//" | sed -e "s/[ ]*$//"`
		RADIUSPID=`ps -ax | grep $RADIUSAGENT | sed '1!d' | sed -e 's/[ \t]\{1,\}/ /g' | cut -d ' ' -f1`

		#if [ ! -z "$IKEDPID" ]; then kill -3 $IKEDPID 1>/dev/null 2>&1; fi
		#OKR - XTSce05068. The killing of radius and dhcp agents is
		# handled by iked, which sends SIGQUITS itself. The RA shown 
		# that sending the QUIT twice makes the system freeze.
		#if [ ! -z "$DHCPPID" ]; then kill -3 $DHCPPID 1>/dev/null 2>&1; fi
		#if [ ! -z "$RADIUSPID" ]; then kill -3 $RADIUSPID 1>/dev/null 2>&1; fi
	fi

	# silenty clean up any processes if they're still around
	killall -9 $IKEDBIN 1>/dev/null 2>&1
	killall -9 `basename $DHCPAGENT` 1>/dev/null 2>&1
	killall -9 `basename $RADIUSAGENT` 1>/dev/null 2>&1
	#if [ ! -z "$IKEDPID" ]; then kill -9 $IKEDPID 1>/dev/null 2>&1; fi
	if [ ! -z "$DHCPPID" ]; then kill -9 $DHCPPID 1>/dev/null 2>&1; fi
	if [ ! -z "$RADIUSPID" ]; then kill -9 $RADIUSPID 1>/dev/null 2>&1; fi

	# silently clean up named pipes if they're still around
	rm -f $IKEDUIFIFO
	rm -f $DHCPAGENTFIFO
	rm -f $RADIUSAGENTFIFO
}

hupike()
{
	logit "$0: Resetting IKE daemon ..."
	if [ -f $IKEDPIDFILE ]; then kill -HUP `cat $IKEDPIDFILE` 1>/dev/null 2>&1; fi
}

hupdaemons()
{
	logit "$0: Resetting syslog and SNMP daemons ..."
	killall -1 syslogd 1>/dev/null 2>&1
	killall -1 snmpd 1>/dev/null 2>&1
}

######################################################################

while [ ! -z "$1" ]; do
	case "$1" in

### options:

	  c|-c|--c)
		if [ -n "$2" ]; then
			IKEDCONF=$2
			shift
		else
			echo "$USAGE"
			exit 2
		fi
		shift
		;;

	  s|-s|--s)
		if [ -n "$2" ]; then
			SCRIPTDIR=$2
			shift
		else
			echo "$USAGE"
			exit 2
		fi
		shift
		;;

	  b|-b|--b)
		if [ -n "$2" ]; then
			BINDIR=$2
			shift
		else
			echo "$USAGE"
			exit 2
		fi
		shift
		;;

	  m|-m|--m)
		if [ -n "$2" ]; then
			SADB_MODE=$2
			shift
		else
			echo "$USAGE"
			exit 2
		fi
		shift
		;;

### commands:

	  start|--start)
		if [ -n "$2" ]; then DEBUGLEVEL=$2; fi
		getoptions
		cleanconf
		startsadb
		# OKR: flush dyn chains in start because we may no go through
		# the stop event in case of iked crash. XTSce04012.
		flushspddynrules
		#proxyarp on
		#hupdaemons
		startike
#		[ -x /usr/sbin/led ] && /usr/sbin/led --secure=1
		exit 0
		;;

	  stop|--stop)
#		[ -x /usr/sbin/led ] && /usr/sbin/led --secure=0
		getoptions
		stopike
		#proxyarp off
		resetsadb
		exit 0
		;;

	  print|--print|dump|--dump)
		getoptions
		if [ -p $IKEDUIFIFO ]; then echo "DMP|" > $IKEDUIFIFO; fi
		exit 0
		;;

	  dumppol|--dumppol)
		if [ -n "$2" ]; then dumppol_flags=$2; else dumppol_flags=255; fi
		getoptions
		if [ -p $IKEDUIFIFO ]; then echo "DMPPOLICY|$dumppol_flags|" > $IKEDUIFIFO; fi
		exit 0
		;;

	  reload|--reload|huppol|--huppol)
		getoptions
		reloadspdrules
		if [ -p $IKEDUIFIFO ]; then echo "HUPPOLICY|" > $IKEDUIFIFO; fi
		exit 0
		;;

	  clr|--clr)
		getoptions
		if [ -p $IKEDUIFIFO ]; then echo "CLR|" > $IKEDUIFIFO; fi
		exit 0
		;;

	  reset|--reset|hup|--hup)
		getoptions
		#hupdaemons
		hupike
		exit 0
		;;

	  restart|--restart)
		getoptions
		$0 -c $IKEDCONF -s $SCRIPTDIR -b $BINDIR -m $SADB_MODE stop
		$0 -c $IKEDCONF -s $SCRIPTDIR -b $BINDIR -m $SADB_MODE start
		exit 0
		;;

	  -h|help|--help)
		echo "$USAGE"
		exit 0
		;;

	  *)
		echo "$USAGE"
		exit 2
		;;
	esac
done

exit 1
