#! /bin/sh
### BEGIN INIT INFO
# Provides:          psad
# Required-Start:    $remote_fs
# Required-Stop:     $remote_fs
# Should-Start:      netfilter-persistent
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Port Scan Attack Detector (psad)
# Description:       Enable the Port Scan Attack Detector (psad)
### END INIT INFO

# Author: Franck Joncourt <franck@debian.org>

PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="Port Scan Attack Detector"
NAME=psad
DAEMON=/usr/sbin/$NAME
PIDDIR=/var/run/psad
SCRIPTNAME=/etc/init.d/psad

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Load user options to pass to psad daemon
DAEMON_ARGS=""
[ -r /etc/default/psad ] && . /etc/default/psad

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

#
# Function that checks if all of the configuration files exist
#
# Return
#   0 : all of the configuration files exist
#   6 : at least one file is missing

check_config()
{
	local retval
	local file_list

	retval=0
	file_list="/etc/psad/psad.conf"

	for ConfFile in $file_list; do
		if [ ! -f "$ConfFile" ]; then
			retval=6	
		 	break	
		fi
	done

	return $retval
}

#
# Function to check if psad is running
#
#    0 : the psad.pid file has been found ; we assume the daemon is running
#    1 : no pid file has been found ; we assume the daemon is not running
#
is_psad_running()
{
        local pidfile="$PIDDIR/psad.pid"
        local retval

        retval=0
        if [ -r "$pidfile" ]; then
                retval=1
        fi

        return $retval
}

#
# Function that starts the daemon/service
#
#   0 : daemon has been started or was already running
#   1 : generic or unspecified errors (could not be started)
#   6 : program is not configured (missing configuration files)

do_start()
{
	local retval


        mkdir -p $PIDDIR
        chmod 755 $PIDDIR

	# Check psad configuration
	check_config
	retval=$?

	# Try to start psad
        is_psad_running
        if [ "$?" = 1 ]; then
            log_action_msg "The psad daemon is already running"
            retval=0

	elif [ "$retval"  = "0" ]; then
		start-stop-daemon --start --quiet --pidfile $PIDDIR/$NAME --exec $DAEMON -- $DAEMON_ARGS
		retval="$?"
	fi

	# Handle return status codes
	case "$retval" in
		0)	 
			;;
		6)	
			log_action_msg "You are missing the configuration file $ConfFile" || true
			;;
		9)	
			retval=0
			;;
		*)
			retval=1
			log_action_msg "Unable to start the daemon" || true
			;;
	esac

	log_daemon_msg "Starting Port Scan Attack Detector" "psad" || true
        log_end_msg $retval || true

	return $retval
}

#
# Function that stops the daemon/service
#
# The upstream author has allowed the daemon to be killed through the 
# following command-line : psad --Kill
#
# As psad starts kmsgsd, psadwatchd and psad_fw_read on its own, we need
# to stop them before.
#
# Return
#   0 : daemon has been stopped or was already stopped
#   1 : daemon could not be stopped

do_stop()
{
	local retval="0"
	local status kill_status
	local pid pidfile
	local process_list="psadwatchd kmsgsd psad psad_fw_read"

	# For each process
	for process in $process_list; do

		pidfile="$PIDDIR/$process.pid"
		status="0"
		kill_status="1"

		log_action_msg "Stopping the $process process"

		# Try to kill the process associated to the pid
		if [ -r "$pidfile" ]; then
			pid=`cat "$pidfile" 2>/dev/null`
			kill -0 "${pid:-}" 2>/dev/null
			kill_status="$?"
		fi

		# Stop the process
		if [ "$kill_status" = "0" ]; then
			start-stop-daemon --stop --oknodo --quiet --pidfile "$pidfile"
			status="$?"
		fi

		# Remove its pid file
		if [ -r "$pidfile" ] && [ "$status" = "0" ]; then
			 rm -f "$pidfile" 2>/dev/null
			 status="$?"
		fi

		[ "$status" = "0" ] || retval="1"

	done

	if [ "$retval" != "0" ]; then
		log_action_msg "One or more process could not be stopped" || true
	fi

        log_daemon_msg "Stopping Port Scan Attack Detector" "psad" || true
        log_end_msg $retval || true

	return $retval
}

#
# Function that returns the daemon status
#
do_status()
{
	echo "Status of $DESC:"
	$DAEMON --Status
}

case "$1" in
	start)
		do_start
		;;

	stop)
		do_stop
		;;

	restart|force-reload)
		do_stop
		sleep 1
		do_start
		;;

	status)
		do_status
		exit 0
		;;

	*)
		log_success_msg "Usage: $0 {start|stop|restart|status}" >&2
		exit 1 
		;;
esac

exit
