#! /bin/sh
#
#   Filter script compiler for netscript 
#
#
# Ding Dong Dell, Pussy's in the well      Matthew 'Network Cowboy' Grant GPL2

# This script should barf on errors, as it does not manipulate the kernel 
# network configuration, and it produces output files - we don't want in 
# scribbling all over the place, and indisciminately deleting files...
set -e

# bail out if we are not root
if [ "`id -un`" != "root" ] ; then
        echo 1>&2
        echo "  `basename $0`: you must be root to run this command." 1>&2
        echo 1>&2
        exit 1
fi

qt () { "$@" >/dev/null 2>&1 ; }
vb () { "$@" ; }
source () { . $1 ; }
basename () { echo "${1##*/}"; }
PROGNAME=`basename $0`

# Process command line arguments

usage () {
	echo 1>&2
	echo "  Usage: $PROGNAME [-fhq] [-b max-backup-level]" 1>&2
	echo 1>&2
	exit 1
}

FORCE_COMPILE=0
QUIET=0
OPTIND=1
while getopts b:fhq F; do
	case $F in
	b)	
		BACKUP_LVLS="$OPTARG"
		;;
	h)
		usage
		;;
	f)	
		FORCE_COMPILE=1
		;;
	q)	
		QUIET=1
		;;
	\?)
		usage
		;;
	esac
done
shift $(( $OPTIND - 1)) 

# Start the output...
[ $QUIET -le 0 ] \
	&& echo -n "Compiling ipfilter-defs iptables filtering definitions..."

# Source the scripts used to load config information
ETCDIR="/etc/netscript"

# This NEEDS to be here. It is used in netscript-compile.conf
read_netdefn () {
	# local KEY ARGS

	while read KEY ARGS; do
                # Handle comments and empty lines
                [ -z "$KEY" ] && continue
                echo $KEY | grep -q '^#' && continue
		ARGS=`echo "$ARGS" | sed -e 's/\(.*\)#.*/\1/'`

		echo "${KEY}=\"${ARGS}\""
	done
}


source $ETCDIR/netscript-compile.conf

# override the default BACKUP_LEVELS setting in netscript-compile
[ -n "$BACKUP_LVLS" ] && BACKUP_LEVELS="$BACKUP_LVLS"


#
# Determine if things have changed since the last time compilation has happened
#
if [ $FORCE_COMPILE -le 0 ]; then
	CHANGED=0
	for FILE in $EVERYSOURCE; do
		[ $FILE -nt $OUTFILE ] && CHANGED=1
	done
	unset FILE

	if [ $CHANGED -le 0 ]; then
		[ $QUIET -le 0 ] \
			&& echo "up to date."
		exit 0
	fi
	unset CHANGED
fi

read_fn () {
	local KEY ARGS
	local RETCODE=0

	while read KEY ARGS; do
		
		# Handle comments and empty lines
                [ -z "$KEY" ] && continue
                echo $KEY | grep -q '^#' && continue
		ARGS=`echo "$ARGS" | sed -e 's/\(.*\)#.*/\1/'`

		case $KEY in
		ipv4_compile_*)
			if ! eval \${KEY} "$ARGS"; then
				RETCODE=1
			fi
			;;
		ipv6_compile_*)
			if ! eval \${KEY} "$ARGS"; then
				RETCODE=1
			fi
			;;
		*)
			;;
		esac

	done

	return $RETCODE

}

# This is the magic.  It will GROW!

# Some magic so that we do not overwrite good files
OOUTFILE="$OUTFILE"
OUTFILE="$OUTFILE.new"

# Set the umask so that only root can read this stuff
umask 0277

# Compile the files
RETCODE=0
echo -n "" > $OUTFILE
if ! IPV4_LOAD_CHAINS=`grep -h '^[ 	]*ipv._compile_' $INDEFS \
	| read_fn`
then
	RETCODE=1
fi

if [ $RETCODE -eq 0 ]; then 
	echo >> $OUTFILE
	echo "# List of chains to Load when Configuring iptables" >> $OUTFILE
	echo "unset IPV4_LOAD_LCL_CHAINS" >> $OUTFILE
	echo "unset IPV4_LOAD_FWD_CHAINS" >> $OUTFILE
	echo "$IPV4_LOAD_CHAINS" >> $OUTFILE
fi

# Compile masquerading support - don't do anything if nothing is in 
# there
if [ -f "$MASQFILE" ] && grep -q -v '^#\|^[    ]*$' "$MASQFILE";  then
	if ! cat $MASQFILE | ipv4_Compile_Masq; then 
		RETCODE=1
	fi
fi

if [ -f "$DNATFILE" ] && grep -q -v '^#\|^[    ]*$' "$DNATFILE";  then
	if ! cat $DNATFILE | ipv4_Compile_Dnat; then 
		RETCODE=1
	fi
fi

if [ $RETCODE -ne 0 ]; then
	LCOUNT=`cat $OUTFILE | wc -l` || true
	if [ -n "$LCOUNT" -a $LCOUNT -eq 0 ]; then
		echo 1>&2
		echo "  $PROGNAME: No output produced - any definitions set up?" 1>&2
		echo 1>&2
		exit 1
	fi
	exit 1
fi

# Do history rotation
#
# backup_rotate <filename> <maxlevel>
#
backup_rotate () {
	local MAX="$2"
	[ $MAX -lt 2 ] && MAX=2
	local COUNT=$(($MAX - 1))
	local PREV="$MAX"
	while [ $COUNT -gt 0 ]; do
		[ -f "${1}.${COUNT}" ] && mv "${1}.${COUNT}" "${1}.${PREV}"
		PREV=$COUNT
		COUNT=$(( $COUNT - 1 ))
	done
	[ -f "$1" ] && mv "$1" "${1}.1"
	return 0
}
backup_rotate "$OOUTFILE" "$BACKUP_LEVELS"

# Put new file in place
mv "$OUTFILE" "$OOUTFILE"


[ $QUIET -le 0 ] \
	&& echo "done."
