#!/bin/bash
#
# Startup script to implement /etc/firehol/firehol.conf pre-defined rules.
#
# chkconfig: 2345 99 92
#
# description: creates stateful iptables packet filtering firewalls.
#
# by Costa Tsaousis <costa@tsaousis.gr>
#
# config: /etc/firehol/firehol.conf
#
# $Id: firehol.sh,v 1.231 2004/11/01 00:13:00 ktsaou Exp $
#

# Make sure only root can run us.
if [ ! "${UID}" = 0 ]
then
        echo >&2
        echo >&2
        echo >&2 "Only user root can run FireHOL."
        echo >&2
fi

# Remember who you are.
FIREHOL_FILE="${0}"
FIREHOL_DEFAULTFILE="/etc/default/firehol"
FIREHOL_DEFAULT_WORKING_DIRECTORY="${PWD}"
FIREHOL_LIB="/lib/firehol/firehol"
FIREHOL_DEFAULT_WORKING_DIRECTORY="/etc/firehol"

export PATH="${PATH}:/bin:/usr/bin:/sbin:/usr/sbin"

# Get all helper functions:

test -x $FIREHOL_LIB && . $FIREHOL_LIB

# ------------------------------------------------------------------------------
# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# ------------------------------------------------------------------------------
#
# START UP SCRIPT PROCESSING
#
# ------------------------------------------------------------------------------
# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# ------------------------------------------------------------------------------

# ------------------------------------------------------------------------------
# On non RedHat machines we need success() and failure()
success() {
	echo " OK"
}
failure() {
	echo " FAILED"
}

# Be nice on production environments
${RENICE_CMD} 10 $$ >/dev/null 2>/dev/null

# ------------------------------------------------------------------------------
# A small part bellow is copied from /etc/init.d/iptables

# On RedHat systems this will define success() and failure()
test -f /etc/init.d/functions && . /etc/init.d/functions

if [ -z "${IPTABLES_CMD}" -o ! -x "${IPTABLES_CMD}" ]; then
	echo >&2 "Cannot find an executables iptables command."
	exit 0
fi

KERNELMAJ=`${UNAME_CMD} -r | ${SED_CMD}                   -e 's,\..*,,'`
KERNELMIN=`${UNAME_CMD} -r | ${SED_CMD} -e 's,[^\.]*\.,,' -e 's,\..*,,'`

if [ "$KERNELMAJ" -lt 2 ] ; then
	echo >&2 "FireHOL requires a kernel version higher than 2.3."
	exit 0
fi
if [ "$KERNELMAJ" -eq 2 -a "$KERNELMIN" -lt 3 ] ; then
	echo >&2 "FireHOL requires a kernel version higher than 2.3."
	exit 0
fi

if  ${LSMOD_CMD} 2>/dev/null | ${GREP_CMD} -q ipchains ; then
	# Don't do both
	echo >&2 "ipchains is loaded in the kernel. Please remove ipchains to run iptables."
	exit 0
fi


# ------------------------------------------------------------------------------
# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# ------------------------------------------------------------------------------
#
# COMMAND LINE ARGUMENTS PROCESSING
#
# ------------------------------------------------------------------------------
# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# ------------------------------------------------------------------------------

me="${0}"
arg="${1}"
shift
                
case "${arg}" in
	explain)
		test ! -z "${1}" && softwarning "Arguments after parameter '${arg}' are ignored."
		FIREHOL_EXPLAIN=1
		;;
	
	try)
		FIREHOL_TRY=1
		;;
	
	start|restart|force-reload|condrestart)       
		if [ $arg = "start" ] || [ $arg = "condrestart" ] ; then
			if [ -f /var/lock/firehol ] ; then
				echo "Stopping: FireHOL is already running."
				exit 0
			fi
		fi
 		if [ -f $FIREHOL_DEFAULTFILE ]; then
 			. $FIREHOL_DEFAULTFILE
 			if [ $START_FIREHOL ]; then
 				if [ $START_FIREHOL = "NO" ] ; then
 					echo "Stopping: ${FIREHOL_DEFAULTFILE} forbids it."
 					exit 0;
 				fi
 			else
 			 	echo "Stopping: ${FIREHOL_DEFAULTFILE} forbids it."
 				exit 0;
 			fi
  		else 
 			 echo "Stopping: ${FIREHOL_DEFAULTFILE} missing."
 			 exit 0;
		fi
		FIREHOL_TRY=0
		;;	
	stop)
		test ! -z "${1}" && softwarning "Arguments after parameter '${arg}' are ignored."
		
		test -f /var/lock/firehol && ${RM_CMD} -f /var/lock/firehol
		test -f /var/lock/iptables && ${RM_CMD} -f /var/lock/iptables
		
		echo -n $"FireHOL: Clearing Firewall:"
		load_kernel_module ip_tables
		tables=`${CAT_CMD} /proc/net/ip_tables_names`
		for t in ${tables}
		do
			${IPTABLES_CMD} -t "${t}" -F
			${IPTABLES_CMD} -t "${t}" -X
			${IPTABLES_CMD} -t "${t}" -Z
			
			# Find all default chains in this table.
			chains=`${IPTABLES_CMD} -t "${t}" -nL | ${GREP_CMD} "^Chain " | ${CUT_CMD} -d ' ' -f 2`
			for c in ${chains}
			do
				${IPTABLES_CMD} -t "${t}" -P "${c}" ACCEPT
			done
		done
		success $"FireHOL: Clearing Firewall:"
		echo
		
		exit 0
		;;
		
	status)
		test ! -z "${1}" && softwarning "Arguments after parameter '${arg}' are ignored."
		(
			echo 
			echo "--- MANGLE ---------------------------------------------------------------------"
			echo 
			${IPTABLES_CMD} -t mangle -nxvL
			
			echo 
			echo 
			echo "--- NAT ------------------------------------------------------------------------"
			echo 
			${IPTABLES_CMD} -t nat -nxvL
			
			echo 
			echo 
			echo "--- FILTER ---------------------------------------------------------------------"
			echo 
			${IPTABLES_CMD} -nxvL
		) | ${LESS_CMD}
		exit $?
		;;
	
	panic)
		ssh_src=
		ssh_sport="0:65535"
		ssh_dport="0:65535"
		if [ ! -z "${SSH_CLIENT}" ]
		then
			set -- ${SSH_CLIENT}
			ssh_src="${1}"
			ssh_sport="${2}"
			ssh_dport="${3}"
		elif [ ! -z "${1}" ]
		then
			ssh_src="${1}"
		fi
		
		echo -n $"FireHOL: Blocking all communications:"
		load_kernel_module ip_tables
		tables=`${CAT_CMD} /proc/net/ip_tables_names`
		for t in ${tables}
		do
			${IPTABLES_CMD} -t "${t}" -F
			${IPTABLES_CMD} -t "${t}" -X
			${IPTABLES_CMD} -t "${t}" -Z
			
			# Find all default chains in this table.
			chains=`${IPTABLES_CMD} -t "${t}" -nL | ${GREP_CMD} "^Chain " | ${CUT_CMD} -d ' ' -f 2`
			for c in ${chains}
			do
				${IPTABLES_CMD} -t "${t}" -P "${c}" ACCEPT
				
				if [ ! -z "${ssh_src}" ]
				then
					${IPTABLES_CMD} -t "${t}" -A "${c}" -p tcp -s "${ssh_src}" --sport "${ssh_sport}" --dport "${ssh_dport}" -m state --state ESTABLISHED -j ACCEPT
					${IPTABLES_CMD} -t "${t}" -A "${c}" -p tcp -d "${ssh_src}" --dport "${ssh_sport}" --sport "${ssh_dport}" -m state --state ESTABLISHED -j ACCEPT
				fi
				${IPTABLES_CMD} -t "${t}" -A "${c}" -j DROP
			done
		done
		success $"FireHOL: Blocking all communications:"
		echo
		
		exit 0
		;;
	
	save)
		test ! -z "${1}" && softwarning "Arguments after parameter '${arg}' are ignored."
		FIREHOL_TRY=0
		FIREHOL_SAVE=1
		;;
		
	debug)
		test ! -z "${1}" && softwarning "Arguments after parameter '${arg}' are ignored."
		FIREHOL_TRY=0
		FIREHOL_DEBUG=1
		;;
	
	*)	if [ ! -z "${arg}" -a -f "${arg}" ]
		then
			FIREHOL_CONFIG="${arg}"
			arg="${1}"
			test "${arg}" = "--" && arg="" && shift
			test -z "${arg}" && arg="try"
			
			case "${arg}" in
				start)
					FIREHOL_TRY=0
					FIREHOL_DEBUG=0
					;;
					
				try)
					FIREHOL_TRY=1
					FIREHOL_DEBUG=0
					;;
					
				debug)
					FIREHOL_TRY=0
					FIREHOL_DEBUG=1
					;;
				
				*)
					echo "Cannot accept command line argument '${arg}' here."
					exit 1
					;;
			esac
		else
		
		${CAT_CMD} <<EOF
$Id: firehol.sh,v 1.231 2004/11/01 00:13:00 ktsaou Exp $
(C) Copyright 2003, Costa Tsaousis <costa@tsaousis.gr>
FireHOL is distributed under GPL.

EOF

		${CAT_CMD} <<EOF
FireHOL supports the following command line arguments (only one of them):

	start		to activate the firewall configuration.
			The configuration is expected to be found in
			/etc/firehol/firehol.conf
			
	try		to activate the firewall, but wait until
			the user types the word "commit". If this word
			is not typed within 30 seconds, the previous
			firewall is restored.
			
	stop		to stop a running iptables firewall.
			This will allow all traffic to pass unchecked.
		
	restart		this is an alias for start and is given for
			compatibility with /etc/init.d/iptables.
			
	condrestart	will start the firewall only if it is not
			already active. It does not detect a modified
			configuration file.
	
	status		will show the running firewall, as in:
			${IPTABLES_CMD} -nxvL | ${LESS_CMD}
			
	panic		will block all IP communication.
	
	save		to start the firewall and then save it to the
			place where /etc/init.d/iptables looks for it.
			
			Note that not all firewalls will work if
			restored with:
			/etc/init.d/iptables start
			
	debug		to parse the configuration file but instead of
			activating it, to show the generated iptables
			statements.
	
	explain		to enter interactive mode and accept configuration
			directives. It also gives the iptables commands
			for each directive together with reasoning.
			
	<a filename>	a different configuration file.
			If not other argument is given, the configuration
			will be "tried" (default = try).
			Otherwise the argument next to the filename can
			be one of 'start', 'debug' and 'try'.


-------------------------------------------------------------------------

FireHOL supports the following services (sorted by name):
EOF


		(
			# The simple services
			${CAT_CMD} "${me}"				|\
				${GREP_CMD} -e "^server_.*_ports="	|\
				${CUT_CMD} -d '=' -f 1			|\
				${SED_CMD} "s/^server_//"		|\
				${SED_CMD} "s/_ports\$//"
			
			# The complex services
			${CAT_CMD} "${me}"				|\
				${GREP_CMD} -e "^rules_.*()"		|\
				${CUT_CMD} -d '(' -f 1			|\
				${SED_CMD} "s/^rules_/(*) /"
		) | ${SORT_CMD} | ${UNIQ_CMD} |\
		(
			x=0
			while read
			do
				x=$[x + 1]
				if [ $x -gt 4 ]
				then
					printf "\n"
					x=1
				fi
				printf "% 16s |" "$REPLY"
			done
			printf "\n\n"
		)
		
		${CAT_CMD} <<EOF

Services marked with (*) are "smart" or complex services.
All the others are simple single socket services.

Please note that the service:
	
	all	matches all packets, all protocols, all of everything,
		while ensuring that required kernel modules are loaded.
	
	any	allows the matching of packets with unusual rules, like
		only protocol but no ports. If service any is used
		without other parameters, it does what service all does
		but it does not handle kernel modules.
		For example, to match GRE traffic use:
		
		server any mygre accept proto 47
		
		Service any does not handle kernel modules.
		
	custom	allows the definition of a custom service.
		The template is:
		
		server custom name protocol/sport cport accept
		
		where name is just a name, protocol is the protocol the
		service uses (tcp, udp, etc), sport is server port,
		cport is the client port. For example, IMAP4 is:
		
		server custom imap tcp/143 default accept


For more information about FireHOL, please refer to:

		http://firehol.sourceforge.net

-------------------------------------------------------------------------
FireHOL controls your firewall. You should want to get updates quickly.
Subscribe (at the home page) to get notified of new releases.
-------------------------------------------------------------------------

EOF
		exit 1
		
		fi
		;;
esac

# Remove the next arg if it is --
test "${1}" = "--" && shift

if [ ${FIREHOL_EXPLAIN} -eq 0 -a ! -f "${FIREHOL_CONFIG}" ]
then
	echo -n $"FireHOL config ${FIREHOL_CONFIG} not found:"
	failure $"FireHOL config ${FIREHOL_CONFIG} not found:"
	echo
	exit 1
fi


# ------------------------------------------------------------------------------
# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# ------------------------------------------------------------------------------
#
# MAIN PROCESSING - Interactive mode
#
# ------------------------------------------------------------------------------
# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# ------------------------------------------------------------------------------

if [ ${FIREHOL_EXPLAIN} -eq 1 ]
then
	FIREHOL_CONFIG="Interactive User Input"
	FIREHOL_LINEID="1"
	
	FIREHOL_TEMP_CONFIG="${FIREHOL_DIR}/firehol.conf"
	
	echo "version ${FIREHOL_VERSION}" >"${FIREHOL_TEMP_CONFIG}"
	version ${FIREHOL_VERSION}
	
	${CAT_CMD} <<EOF

$Id: firehol.sh,v 1.231 2004/11/01 00:13:00 ktsaou Exp $
(C) Copyright 2003, Costa Tsaousis <costa@tsaousis.gr>
FireHOL is distributed under GPL.
Home Page: http://firehol.sourceforge.net

--------------------------------------------------------------------------------
FireHOL controls your firewall. You should want to get updates quickly.
Subscribe (at the home page) to get notified of new releases.
--------------------------------------------------------------------------------

You can now start typing FireHOL configuration directives.
Special interactive commands: help, show, quit

EOF
	
	while [ 1 = 1 ]
	do
		read -p "# FireHOL [${work_cmd}:${work_name}] > " -e -r
		test -z "${REPLY}" && continue
		
		set_work_function -ne "Executing user input"
		
		while [ 1 = 1 ]
		do
		
		set -- ${REPLY}
		
		case "${1}" in
			help)
				${CAT_CMD} <<EOF
You can use anything a FireHOL configuration file accepts, including variables,
loops, etc. Take only care to write loops in one row.

Additionaly, you can use the following commands:
	
	help	to print this text on your screen.
	
	show	to show all the successfull commands so far.
	
	quit	to show the interactively given configuration file
		and quit.
	
	in	same as typing: interface eth0 internet
		This is used as a shortcut to get into the server/client
		mode in which you can test the rules for certain
		services.

EOF
				break
				;;
				
			show)
				echo
				${CAT_CMD} "${FIREHOL_TEMP_CONFIG}"
				echo
				break
				;;
				
			quit)
				echo
				${CAT_CMD} "${FIREHOL_TEMP_CONFIG}"
				echo
				exit 1
				;;
				
			in)
				REPLY="interface eth0 internet"
				continue
				;;
				
			*)
				${CAT_CMD} <<EOF

# \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
# Cmd Line : ${FIREHOL_LINEID}
# Command  : ${REPLY}
EOF
				eval "$@"
				if [ $? -gt 0 ]
				then
					printf "\n# > FAILED <\n"
				else
					if [ "${1}" = "interface" -o "${1}" = "router" ]
					then
						echo >>"${FIREHOL_TEMP_CONFIG}"
					else
						printf "	" >>"${FIREHOL_TEMP_CONFIG}"
					fi
					
					printf "%s\n" "${REPLY}" >>"${FIREHOL_TEMP_CONFIG}"
					
					FIREHOL_LINEID=$[FIREHOL_LINEID + 1]
					
					printf "\n# > OK <\n"
				fi
				break
				;;
		esac
		
		break
		done
	done
	
	exit 0
fi

# ------------------------------------------------------------------------------
# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# ------------------------------------------------------------------------------
#
# MAIN PROCESSING
#
# ------------------------------------------------------------------------------
# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
# ------------------------------------------------------------------------------

# --- Initialization -----------------------------------------------------------

fixed_iptables_save() {
	local tmp="${FIREHOL_DIR}/iptables-save-$$"
	local err=
	
	load_kernel_module ip_tables
	${IPTABLES_SAVE_CMD} -c >$tmp
	err=$?
	if [ ! $err -eq 0 ]
	then
		${RM_CMD} -f $tmp >/dev/null 2>&1
		return $err
	fi
	
	${CAT_CMD} ${tmp} |\
		${SED_CMD} "s/--uid-owner !/! --uid-owner /g"	|\
		${SED_CMD} "s/--gid-owner !/! --gid-owner /g"	|\
		${SED_CMD} "s/--pid-owner !/! --pid-owner /g"	|\
		${SED_CMD} "s/--sid-owner !/! --sid-owner /g"   |\
		${SED_CMD} "s/--cmd-owner !/! --cmd-owner /g"
	
	err=$?
	
	${RM_CMD} -f $tmp >/dev/null 2>&1
	return $err
}

fixed_iptables_save >${FIREHOL_SAVED}
if [ $? -ne 0 ] ; then
	test -f "${FIREHOL_SAVED}" && ${RM_CMD} -f "${FIREHOL_SAVED}"
	echo "Stopped: Couldn't save old rules."
	exit 1
fi


# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

# Place all the statements bellow to the beginning of the final firewall script.
${CAT_CMD} >"${FIREHOL_OUTPUT}" <<EOF
#!/bin/sh

load_kernel_module ip_tables
load_kernel_module ip_conntrack

# Find all tables supported
tables=\`${CAT_CMD} /proc/net/ip_tables_names\`
for t in \${tables}
do
	# Reset/empty this table.
	${IPTABLES_CMD} -t "\${t}" -F >${FIREHOL_OUTPUT}.log 2>&1
	r=\$?; test ! \${r} -eq 0 && runtime_error error \${r} INIT ${IPTABLES_CMD} -t "\${t}" -F
	
	${IPTABLES_CMD} -t "\${t}" -X >${FIREHOL_OUTPUT}.log 2>&1
	r=\$?; test ! \${r} -eq 0 && runtime_error error \${r} INIT ${IPTABLES_CMD} -t "\${t}" -X
	
	${IPTABLES_CMD} -t "\${t}" -Z >${FIREHOL_OUTPUT}.log 2>&1
	r=\$?; test ! \${r} -eq 0 && runtime_error error \${r} INIT ${IPTABLES_CMD} -t "\${t}" -Z
	
	# Find all default chains in this table.
	chains=\`${IPTABLES_CMD} -t "\${t}" -nL | ${GREP_CMD} "^Chain " | ${CUT_CMD} -d ' ' -f 2\`
	
	# If this is the 'filter' table, remember the default chains.
	# This will be used at the end to make it DROP all packets.
	test "\${t}" = "filter" && firehol_filter_chains="\${chains}"
	
	# Set the policy to ACCEPT on all default chains.
	for c in \${chains}
	do
		${IPTABLES_CMD} -t "\${t}" -P "\${c}" ACCEPT >${FIREHOL_OUTPUT}.log 2>&1
		r=\$?; test ! \${r} -eq 0 && runtime_error error \${r} INIT ${IPTABLES_CMD} -t "\${t}" -P "\${c}" ACCEPT
	done
done

${IPTABLES_CMD} -t filter -P INPUT "\${FIREHOL_INPUT_ACTIVATION_POLICY}" >${FIREHOL_OUTPUT}.log 2>&1
r=\$?; test ! \${r} -eq 0 && runtime_error error \${r} INIT ${IPTABLES_CMD} -t filter -P INPUT "\${FIREHOL_INPUT_ACTIVATION_POLICY}"

${IPTABLES_CMD} -t filter -P OUTPUT "\${FIREHOL_OUTPUT_ACTIVATION_POLICY}" >${FIREHOL_OUTPUT}.log 2>&1
r=\$?; test ! \${r} -eq 0 && runtime_error error \${r} INIT ${IPTABLES_CMD} -t filter -P OUTPUT "\${FIREHOL_OUTPUT_ACTIVATION_POLICY}"

${IPTABLES_CMD} -t filter -P FORWARD "\${FIREHOL_FORWARD_ACTIVATION_POLICY}" >${FIREHOL_OUTPUT}.log 2>&1
r=\$?; test ! \${r} -eq 0 && runtime_error error \${r} INIT ${IPTABLES_CMD} -t filter -P FORWARD "\${FIREHOL_FORWARD_ACTIVATION_POLICY}"

# Accept everything in/out the loopback device.
if [ "\${FIREHOL_TRUST_LOOPBACK}" = "1" ]
then
	${IPTABLES_CMD} -A INPUT -i lo -j ACCEPT
	${IPTABLES_CMD} -A OUTPUT -o lo -j ACCEPT
fi

# Drop all invalid packets.
# Netfilter HOWTO suggests to DROP all INVALID packets.
if [ "\${FIREHOL_DROP_INVALID}" = "1" ]
then
	${IPTABLES_CMD} -A INPUT -m state --state INVALID -j DROP
	${IPTABLES_CMD} -A OUTPUT -m state --state INVALID -j DROP
	${IPTABLES_CMD} -A FORWARD -m state --state INVALID -j DROP
fi

EOF

# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

ret=0

# ------------------------------------------------------------------------------
# Create a small awk script that inserts line numbers in the configuration file
# just before each known directive.
# These line numbers will be used for debugging the configuration script.

${CAT_CMD} >"${FIREHOL_TMP}.awk" <<"EOF"
/^[[:space:]]*blacklist[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*client[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*dnat[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*dscp[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*interface[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*iptables[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*mac[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*mark[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*masquerade[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*nat[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*policy[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*postprocess[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*protection[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*redirect[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*router[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*route[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*server[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*snat[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*tcpmss[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*tos[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*transparent_squid[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
/^[[:space:]]*transparent_proxy[[:space:]]/ { printf "FIREHOL_LINEID=${LINENO} " }
{ print }
EOF


${CAT_CMD} ${FIREHOL_CONFIG} | ${GAWK_CMD} -f "${FIREHOL_TMP}.awk" >${FIREHOL_TMP}
${RM_CMD} -f "${FIREHOL_TMP}.awk"

# ------------------------------------------------------------------------------
# Run the configuration file.

enable -n trap			# Disable the trap buildin shell command.
enable -n exit			# Disable the exit buildin shell command.
source ${FIREHOL_TMP} "$@"	# Run the configuration as a normal script.
FIREHOL_LINEID="FIN"
enable trap			# Enable the trap buildin shell command.
enable exit			# Enable the exit buildin shell command.


close_cmd					|| ret=$[ret + 1]
close_master					|| ret=$[ret + 1]

${CAT_CMD} >>"${FIREHOL_OUTPUT}" <<EOF

# Make it drop everything on table 'filter'.
for c in \${firehol_filter_chains}
do
	${IPTABLES_CMD} -t filter -P "\${c}" DROP >${FIREHOL_OUTPUT}.log 2>&1
	r=\$?; test ! \${r} -eq 0 && runtime_error error \${r} INIT ${IPTABLES_CMD} -t filter -P "\${c}" DROP
done

EOF

if [ ${work_error} -gt 0 -o $ret -gt 0 ]
then
	echo >&2
	echo >&2 "NOTICE: No changes made to your firewall."
	echo "Stopped: Processing file ${FIREHOL_CONFIG}."
	exit 1
fi


# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

for m in ${FIREHOL_KERNEL_MODULES}
do
	postprocess -ne load_kernel_module $m
done

# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

if [ $FIREHOL_ROUTING -eq 1 ]
then
	postprocess ${SYSCTL_CMD} -w "net.ipv4.ip_forward=1"
fi

# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

if [ ${FIREHOL_DEBUG} -eq 1 ]
then
	${CAT_CMD} ${FIREHOL_OUTPUT}
	
	exit 1
fi

# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

source ${FIREHOL_OUTPUT} "$@"

if [ ${work_final_status} -gt 0 ]
then
	echo "Stopped: Couldn't activate new firewall."
	
	# The trap will restore the firewall.
	
	exit 1
fi

if [ ${FIREHOL_TRY} -eq 1 ]
then
	read -p "Keep the firewall? (type 'commit' to accept - 30 seconds timeout) : " -t 30 -e
	ret=$?
	echo
	if [ ! $ret -eq 0 -o ! "${REPLY}" = "commit" ]
	then
		# The trap will restore the firewall.
		
		exit 1
	else
		echo "Successfull activation of FireHOL firewall."
	fi
fi

# Remove the saved firewall, so that the trap will not restore it.
${RM_CMD} -f "${FIREHOL_SAVED}"

${TOUCH_CMD} /var/lock/iptables
${TOUCH_CMD} /var/lock/firehol

# XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

if [ ${FIREHOL_SAVE} -eq 1 ]
then
	if [ -z "${FIREHOL_AUTOSAVE}" ]
	then
		if [ -d "/etc/sysconfig" ]
		then
			# RedHat
			FIREHOL_AUTOSAVE="/etc/sysconfig/iptables"
		elif [ -d "/var/lib/iptables" ]
		then
			if [ -f /etc/conf.d/iptables ]
			then
				# Gentoo
				IPTABLES_SAVE=
				
				. /etc/conf.d/iptables
				FIREHOL_AUTOSAVE="${IPTABLES_SAVE}"
			fi
			
			if [ -z "${FIREHOL_AUTOSAVE}" ]
			then
				# Debian
				FIREHOL_AUTOSAVE="/var/lib/iptables/autosave"
			fi
		else
			error "Cannot find where to save iptables file. Please set FIREHOL_AUTOSAVE."
			echo
			exit 1
		fi
	fi
	
	echo -n $"FireHOL: Saving firewall to ${FIREHOL_AUTOSAVE}:"
	
	fixed_iptables_save >"${FIREHOL_AUTOSAVE}"
	
	if [ ! $? -eq 0 ]
	then
		failure $"FireHOL: Saving firewall to ${FIREHOL_AUTOSAVE}:"
		echo
		exit 1
	fi
	
	success $"FireHOL: Saving firewall to ${FIREHOL_AUTOSAVE}:"
	echo
	exit 0
fi
