#!/bin/bash
#
# Startup script to implement /etc/sysconfig/ip6tables pre-defined rules.
#
# chkconfig: 2345 03 92
#
# description: Automates a packet filtering firewall with ip6tables.
#
# by bero@redhat.com, based on the ipchains script:
# Script Author:	Joshua Jensen <joshua@redhat.com>
#   -- hacked up by gafton with help from notting
# modified by Anton Altaparmakov <aia21@cam.ac.uk>:
# modified by Nils Philippsen <nils@redhat.de>
#   -- changed to ip6tables by Ben Reser <ben@reser.org>
#
# config: /etc/sysconfig/ip6tables
#
### BEGIN INIT INFO
# Provides: ip6tables firewall
# Default-Start: 2 3 4 5
# Short-Description: ip6tables packet filtering
# Description: Automates a packet filtering firewall with ip6tables,
#              using /etc/sysconfig/ip6tables pre-defined rules.
### END INIT INFO

# Source 'em up
. /etc/init.d/functions

IPTABLES=ip6tables #
IPTABLES_FILTER=cat
IPTABLES_RESTORE="$IPTABLES-restore"
IPTABLES_RESTORE_ARGS=
IPTABLES_SAVE="$IPTABLES-save"
IPTABLES_SAVE_ARGS=
IPTABLES_STATUS_ARGS=
IPTABLES_SAVE_ON_STOP=no
IPTABLES_SAVE_ON_RESTART=no
IPTABLES_DATA="/etc/sysconfig/$IPTABLES"
IPTABLES_MODULES="/etc/sysconfig/${IPTABLES}_modules"
IPTABLES_CONFIG="/etc/sysconfig/${IPTABLES}_params"
LOCKFILE="/var/lock/subsys/$IPTABLES"
IPV=ip6 # ip for ipv4 | ip6 for ipv6
IPTABLES_TABLES_NAMES="/proc/net/${IPV}_tables_names"

# Source config
#SourceIfNotEmpty "$IPTABLES_CONFIG"
#RETVAL=0

iftable() {
	if grep -Fqsx $1 /proc/net/${IPV}_tables_names; then
		$IPTABLES -t "$@"
	fi
}

check() {
	if [ -n "$1" ]; then
		rm -f /lib64/iptables
		ln -s /lib64/iptables.d/"${1}" /lib64/iptables
		iftable nat -N __T__${1##*-}__ >/dev/null 2>&1
		iftable nat -A __T__${1##*-}__ -j MASQUERADE >/dev/null 2>&1
		res=$?
		iftable nat -F __T__${1##*-}__ >/dev/null 2>&1
		iftable nat -X __T__${1##*-}__ >/dev/null 2>&1
		return $res
	else
		IPTABLES_LIST="$(/bin/ls /lib64/iptables.d)"
		if [ $(echo $IPTABLES_LIST | wc -w) -gt 1 ] || [ ! -e /lib64/iptables ]; then
			/sbin/modprobe ipt_MASQUERADE >/dev/null 2>&1
			for i in $IPTABLES_LIST ; do
				check "${i}" && break
			done
			/sbin/modprobe -r ipt_MASQUERADE >/dev/null 2>&1
		else
			return 0;
		fi
	fi
}

load_modules()
{
	[ -s "$IPTABLES_MODULES" ] || return 0

	# Loop over every line in $IPTABLES_MODULES
	(cat "$IPTABLES_MODULES"; echo) |while read module args; do
		# Ignore empty lines and comments
		[ -n "${module##\#*}" ] || continue

		action "Loading module %s for %s:" "$module" "$IPTABLES" \
			modprobe "$module" $args 2>/dev/null
	done
}

start()
{
	local tmp
	tmp=`mktemp -t "$IPTABLES.XXXXXXXX"` &&
	$IPTABLES_FILTER <"$IPTABLES_DATA" |
		egrep -v '^[[:space:]]*(#|$)' >"$tmp" &&
	[ -s "$tmp" ]
	RETVAL=$?
	if [ $RETVAL -ne 0 ]; then
		[ -z "$tmp" ] || rm -f "$tmp"
		printf %s $"$IPTABLES firewall is not configured"
		passed "%s start" "$IPTABLES"
		echo
		return $RETVAL
	fi

	if [ -e /proc/net/ip_fwchains ]; then
		printf %s $"ipchains and $IPTABLES can not be used together"
		passed "%s $*" "$IPTABLES"
		echo
		RETVAL=1
		return $RETVAL
	fi

	load_modules

	action $"Applying %s firewall rules:" "$IPTABLES" \
		$IPTABLES_RESTORE $IPTABLES_RESTORE_ARGS <"$tmp"
	RETVAL=$?
	rm -f "$tmp"
	if [ $RETVAL = 0 ]; then
		touch "$LOCKFILE"
	else
		rm -f "$LOCKFILE"
	fi

	return $RETVAL
}

tables=
read_tables()
{
	tables="$(cat "$IPTABLES_TABLES_NAMES" 2>/dev/null)"
	[ -n "$tables" ]
}

set_policy()
{
	local policy i
	policy="$1"

	printf %s $"Setting chains policy to $policy: "
	RETVAL=0
	for i in $tables; do
		printf %s "$i "
		case "$i" in
			raw)
				$IPTABLES -t raw -P PREROUTING $policy &&
				$IPTABLES -t raw -P OUTPUT $policy ||
				RETVAL=1
				;;
			filter)
				$IPTABLES -t filter -P INPUT $policy &&
				$IPTABLES -t filter -P OUTPUT $policy &&
				$IPTABLES -t filter -P FORWARD $policy ||
				RETVAL=1
				;;
			nat)
				$IPTABLES -t nat -P PREROUTING $policy &&
				$IPTABLES -t nat -P POSTROUTING $policy &&
				$IPTABLES -t nat -P OUTPUT $policy ||
				RETVAL=1
				;;
			mangle)
				$IPTABLES -t mangle -P PREROUTING $policy &&
				$IPTABLES -t mangle -P POSTROUTING $policy &&
				$IPTABLES -t mangle -P INPUT $policy &&
				$IPTABLES -t mangle -P OUTPUT $policy &&
				$IPTABLES -t mangle -P FORWARD $policy ||
				RETVAL=1
				;;
	        esac
	done
	[ "$RETVAL" -eq 0 ] &&
		success "Setting chains policy to %s" "$policy" ||
		failure "Setting chains policy to %s" "$policy"
	echo
	return $RETVAL
}

flush_delete()
{
	local i
	RETVAL=0

	printf %s $"Flushing firewall rules: "
	for i in $tables; do
		printf %s "$i "
		$IPTABLES -t $i -F || RETVAL=1
	done
	[ "$RETVAL" -eq 0 ] &&
		success "Flushing firewall rules" ||
		failure "Flushing firewall rules"
	echo
	[ "$RETVAL" -eq 0 ] || return $RETVAL

	printf %s $"Removing user defined chains: "
	for i in $tables; do
		printf %s "$i "
		$IPTABLES -t $i -X || RETVAL=1
	done
	[ "$RETVAL" -eq 0 ] &&
		success "Removing user defined chains" ||
		failure "Removing user defined chains"
	echo
	[ "$RETVAL" -eq 0 ] || return $RETVAL

	printf %s $"Zeroing packet and byte counters: "
	for i in $tables; do
		printf %s "$i "
		$IPTABLES -t $i -Z || RETVAL=1
	done
	[ "$RETVAL" -eq 0 ] &&
		success "Zeroing packet and byte counters" ||
		failure "Zeroing packet and byte counters"
	echo
	return $RETVAL
}

unload_modules()
{
	local t

	for t in $tables; do
		local m="${IPV}table_${t}"
		action "Unloading module %s:" "$m" modprobe -r "$m"
	done
	return 0
}

fwstatus()
{
	local i

	if read_tables; then
		for i in $tables; do
			printf %s\\n $"Table: $i"
			$IPTABLES -t $i --list $IPTABLES_STATUS_ARGS && echo
		done
		RETVAL=0
	else
		printf %s\\n $"$IPTABLES firewall is not started"
		RETVAL=1
	fi

	return $RETVAL
}

save()
{
	local tmp

	if read_tables; then
		printf %s $"Saving current rules to $IPTABLES_DATA: "
		if tmp=`mktemp "$IPTABLES_DATA.XXXXXXXX"` &&
		   $IPTABLES_SAVE $IPTABLES_SAVE_ARGS >"$tmp"; then
			[ -s "$IPTABLES_DATA" ] &&
				ln -f "$IPTABLES_DATA" "$IPTABLES_DATA.save"
			mv -f "$tmp" "$IPTABLES_DATA"
			RETVAL=$?
		else
			RETVAL=1
		fi
		if [ $RETVAL -eq 0 ]; then
			success "Saving current rules to %s" "$IPTABLES_DATA"
		else
			failure "Saving current rules to %s" "$IPTABLES_DATA"
			[ -z "$tmp" ] || rm -f "$tmp"
		fi
		echo
	else
		printf %s $"$IPTABLES firewall is not started"
		passed "%s save" "$IPTABLES"
		echo
		RETVAL=1
	fi

	return $RETVAL
}

stop()
{
	if read_tables; then
		set_policy ACCEPT &&
		flush_delete &&
		unload_modules
		RETVAL=$?
	else
		printf %s $"$IPTABLES firewall is not started"
		passed "%s stop" "$IPTABLES"
		echo
		RETVAL=1
	fi

	rm -f "$LOCKFILE"
	return $RETVAL
}

panic()
{
	if read_tables; then
		set_policy DROP &&
		flush_delete &&
		RETVAL=$?
	else
		printf %s $"$IPTABLES firewall is not started"
		passed "%s panic" "$IPTABLES"
		echo
		RETVAL=1
	fi

	return $RETVAL
}

case "$1" in
	start)
        check
		start
		;;
	save)
		save
		;;
	status)
		fwstatus
		;;
    check)
        check
	;;
	panic)
		panic
		;;
	stop)
		[ "x$IPTABLES_SAVE_ON_STOP" = "xyes" ] && save
		stop
		;;
	restart|reload)
		[ "x$IPTABLES_SAVE_ON_RESTART" = "xyes" ] && save
		stop
		start
		;;
	condrestart)
		[ -e "$LOCKFILE" ] && start
		;;
	condstop)
		[ -e "$LOCKFILE" ] && stop
		;;
	*)
		gprintf "Usage: %s {condrestart|condstop|check|panic|restart|save|start|status|stop}\n" "$0"
		RETVAL=1
esac

exit $RETVAL
