#!/bin/bash

PROG="ipt-regen v. 0.5.3 - IPTables REGENerator and reloader"
COPYRIGHT="(C) 2006-2009, Bartosz Lis <bartoszl@ics.p.lodz.pl>"
COPYLEFT="Licenced under GNU GPL v. 2.0"
#
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
WARN="CAUTION! This software is distributed AS IS with no warranties.
If you use it, you are doing so ON YOUR OWN RISK."
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#

TIMEOUT=15
IPTGEN=/usr/sbin/ipt-gen
IPTABLES=/usr/sbin/iptables
SAVE=/usr/sbin/iptables-save
RESTORE=/usr/sbin/iptables-restore
LOGGER=/usr/bin/logger
RULES=/etc/sysconfig/iptables
RULES_NEW="$RULES.`date +%Y-%m-%d_%T`"
MARKER="${0##*/}[$$]"

for F in "$IPTGEN" "$IPTABLES" "$SAVE" "$RESTORE" "$LOGGER"; do
    if [ ! -f "$F" -o ! -x "$F" ]; then
	echo "Cannot use program '$F'" >&2
	exit 1
    fi
done

IPTVER=`$IPTGEN -v`
if [ "$IPTVER"x != "0.5.3"x ]; then
    echo "Version mismatch: 0.5.3 vs. $IPTVER" >&2
    exit 1
fi

function log
{
    LEVEL=$1
    MSG=$2
    echo $MSG
    "$LOGGER" -p "user.$LEVEL" -t "$MARKER" "$MSG"
}

function read_timeout
{
    MSG=$1
    read -t "$TIMEOUT" -n 1 -s -p "$MSG" </dev/tty
    RET=$?
    echo
    return $RET
}

function save
{
    MSG=$1;
    log info "Saving current rules to '$RULES'$MSG."
    if ! "$SAVE" > "$RULES"; then
	log error "Cannot save rcurrent rules to '$RULES'"
	return 1
    fi
}

function load
{
    R=$1
    shift
    if [ -n "$R" ]; then
	log info "Loading rules from '$R'"
	if "$RESTORE" < "$R"; then
	    if ! read_timeout "To verify networking usability press any key: "; then
		log err "Timeout reached. Assuming that rules in '$R' are insane" >&2
		load "$@"
	    elif [ "$R"x = "$RULES"x ]; then
		log warning "New rules are insane. Old rules in '$RULES' are OK."
		exit 2
	    else
		log info "Renaming '$R' to '$RULES'"
		if cp -f "$R" "$RULES"; then
		    log info "Success." >&2
		    exit 0
		else
		    log err "Cannot copy '$R' to '$RULES'." >&2
		    echo
		    echo "!!! If you reboot not fixing it networking may be unusable !!!"
		    echo
		    exit 3
		fi
	    fi
	else
	    log err "Cannot load rules from '$R' . Insane?" >&2
	    load "$@"
	fi
    else
	log warning "Inserting emergency rule for SSH."
	if "$IPTABLES" -t filter -I INPUT 1 -p tcp -m tcp --dport 22 -j ACCEPT; then
	    log info "Renaming '$RULES' to '$RULES.damaged'."
	    cp -f "$RULES" "$RULES.damaged"
	    if save " in case of reboot"; then 
		echo
		echo "!!! Until you fix the rules networking is almost unusable !!!"
		echo
		exit 4
	    else
		echo
		echo "!!! Until you fix the rules networking is almost unusable !!!"
		echo "!!! Do not reboot or the networking is completly unusable !!!"
		echo
		exit 5
	    fi
	else
	    log err "Cannot insert emergency rule for SSH." >&2
	    echo
	    echo "!!! Until you fix the rules from console networking is unusable !!!"
	    echo
	    exit 6
	fi
    fi
}

log info "$PROG"
echo "$COPYRIGHT"
echo "$COPYLEFT"
echo "$WARN"
echo
if ! read_timeout "If sure to continue press any key: "; then
    log warn "No user reaction. This script is not suitable for batch mode. Exiting." >&2
    exit 7
fi
echo
echo "!!! Do not leave your terminal until rules are safely reloaded !!!"
echo
if [ -f "$RULES" ]; then
    log info "Assuming that '$RULES' has sane rules."
elif ! save; then
    exit 8
fi

log info "Generating iptables' rules to '$RULES_NEW'."
if ! "$IPTGEN" > "$RULES_NEW"; then
    log err "Error while generating rules to '$RULES_NEW'." >&2
    exit 9
fi

load "$RULES_NEW" "$RULES"
