###############################################################################
# Code imported from /usr/share/shorewall/prog.footer6
###############################################################################
#
# Remove all Shorewall-added rules
#
clear_firewall() {
    stop_firewall

    setpolicy INPUT ACCEPT
    setpolicy FORWARD ACCEPT
    setpolicy OUTPUT ACCEPT

    run_iptables -F

    echo 1 > /proc/sys/net/ipv6/conf/all/forwarding

    run_clear_exit

    set_state "Cleared"

    logger -p kern.info "$PRODUCT Cleared"
}

#
# Issue a message and stop/restore the firewall
#
fatal_error()
{
    echo "   ERROR: $@" >&2

    if [ $LOG_VERBOSE -gt 1 ]; then
        timestamp="$(date +'%_b %d %T') "
        echo "${timestamp}  ERROR: $@" >> $STARTUP_LOG
    fi

    stop_firewall
    [ -n "$TEMPFILE" ] && rm -f $TEMPFILE
    exit 2
}

#
# Issue a message and stop
#
startup_error() # $* = Error Message
{
    echo "   ERROR: $@: Firewall state not changed" >&2
    case $COMMAND in
        start)
	    logger -p kern.err "ERROR:$PRODUCT start failed:Firewall state not changed"
	    ;;
	restart)
	    logger -p kern.err "ERROR:$PRODUCT restart failed:Firewall state not changed"
	    ;;
	restore)
	    logger -p kern.err "ERROR:$PRODUCT restore failed:Firewall state not changed"
	    ;;
    esac

    if [ $LOG_VERBOSE -gt 1 ]; then
        timestamp="$(date +'%_b %d %T') "

	case $COMMAND in
	    start)
		echo "${timestamp}  ERROR:$PRODUCT start failed:Firewall state not changed" >> $STARTUP_LOG
		;;
	    restart)
		echo "${timestamp}  ERROR:$PRODUCT restart failed:Firewall state not changed" >> $STARTUP_LOG
		;;
	    restore)
		echo "${timestamp}  ERROR:$PRODUCT restore failed:Firewall state not changed" >> $STARTUP_LOG
		;;
	esac
    fi

    kill $$
    exit 2
}

#
# Run iptables and if an error occurs, stop/restore the firewall
#
run_iptables()
{
    local status

    while [ 1 ]; do
	$IP6TABLES $@
	status=$?
	[ $status -ne 4 ] && break
    done

    if [ $status -ne 0 ]; then
        error_message "ERROR: Command \"$IP6TABLES $@\" Failed"
	stop_firewall
        exit 2
    fi
}

#
# Run iptables retrying exit status 4
#
do_iptables()
{
    local status

    while [ 1 ]; do
	$IP6TABLES $@
	status=$?
	[ $status -ne 4 ] && return $status;
    done
}

#
# Run iptables and if an error occurs, stop/restore the firewall
#
run_ip()
{
    if ! $IP -6 $@; then
	error_message "ERROR: Command \"$IP -6 $@\" Failed"
	stop_firewall
	exit 2
    fi
}

#
# Run tc and if an error occurs, stop/restore the firewall
#
run_tc() {
    if ! $TC $@ ; then
	error_message "ERROR: Command \"$TC $@\" Failed"
	stop_firewall
	exit 2
    fi
}

#
# Restore the rules generated by 'drop','reject','logdrop', etc.
#
restore_dynamic_rules() {
    if [ -f ${VARDIR}/save ]; then
	progress_message2 "Setting up dynamic rules..."
	rangematch='source IP range'
	while read target ignore1 ignore2 address ignore3 rest; do
	    case $target in
		DROP|reject|logdrop|logreject)
		    case $rest in
			$rangematch*)
			    run_iptables -A dynamic -m iprange --src-range ${rest#source IP range} -j $target
			    ;;
			*)
			    if [ -z "$rest" ]; then
				run_iptables -A dynamic -s $address -j $target
			    else
				error_message "WARNING: Unable to restore dynamic rule \"$target $ignore1 $ignore2 $address $ignore3 $rest\""
			    fi
			    ;;
		    esac
		    ;;
	    esac
	done < ${VARDIR}/save
    fi
}

#
# Run the .iptables_restore_input as a set of discrete iptables commands
#
debug_restore_input() {
    local first second rest table chain
    #
    # Clear the ruleset
    #
    qt1 $IP6TABLES -t mangle -F
    qt1 $IP6TABLES -t mangle -X

    for chain in PREROUTING INPUT FORWARD POSTROUTING; do
	qt1 $IP6TABLES -t mangle -P $chain ACCEPT
    done

    qt1 $IP6TABLES -t raw    -F
    qt1 $IP6TABLES -t raw    -X

    for chain in PREROUTING OUTPUT; do
	qt1 $IP6TABLES -t raw -P $chain ACCEPT
    done

    qt1 $IP6TABLES -t filter -F
    qt1 $IP6TABLES -t filter -X

    for chain in INPUT FORWARD OUTPUT; do
	qt1 $IP6TABLES -t filter -P $chain -P ACCEPT
    done

    while read first second rest; do
	case $first in
	    -*)
		#
		# We can't call run_iptables() here because the rules may contain quoted strings
		#
		eval $IP6TABLES -t $table $first $second $rest

		if [ $? -ne 0 ]; then
		    error_message "ERROR: Command \"$IP6TABLES $first $second $rest\" Failed"
		    stop_firewall
		    exit 2
		fi
		;;
	    :*)
		chain=${first#:}

		if [ "x$second" = x- ]; then
		    do_iptables -t $table -N $chain
		else
		    do_iptables -t $table -P $chain $second
		fi

		if [ $? -ne 0 ]; then
		    error_message "ERROR: Command \"$IP6TABLES $first $second $rest\" Failed"
		    stop_firewall
		    exit 2
		fi
		;;
	    #
	    # This grotesque hack with the table names works around a bug/feature with ash
	    #
	    '*'raw)
		table=raw
		;;
	    '*'mangle)
		table=mangle
		;;
	    '*'nat)
		table=nat
		;;
	    '*'filter)
		table=filter
		;;
	esac
    done
}

#
# Give Usage Information
#
usage() {
    echo "Usage: $0 [ -q ] [ -v ] [ -n ] [ start|stop|clear|reset|refresh|restart|status|version ]"
    exit $1
}
################################################################################
# E X E C U T I O N    B E G I N S   H E R E				       #
################################################################################
#
# Start trace if first arg is "debug" or "trace"
#
if [ $# -gt 1 ]; then
    if [ "x$1" = "xtrace" ]; then
	set -x
	shift
    elif [ "x$1" = "xdebug" ]; then
	DEBUG=Yes
	shift
    fi
fi

initialize

if [ -n "$STARTUP_LOG" ]; then
    if [ ${SHOREWALL_INIT_SCRIPT:-0} -eq 1 ]; then
	#
	# We're being run by a startup script that isn't redirecting STDOUT
	# Redirect it to the log
	#
	exec 2>>$STARTUP_LOG
    fi
fi

finished=0

while [ $finished -eq 0 -a $# -gt 0 ]; do
    option=$1
    case $option in
	-*)
	    option=${option#-}

	    [ -z "$option" ] && usage 1

	    while [ -n "$option" ]; do
		case $option in
		    v*)
			VERBOSE=$(($VERBOSE + 1 ))
			option=${option#v}
			;;
		    q*)
			VERBOSE=$(($VERBOSE - 1 ))
			option=${option#q}
			;;
		    n*)
			NOROUTES=Yes
			option=${option#n}
			;;
		    *)
			usage 1
			;;
		esac
	    done
	    shift
	    ;;
	*)
	    finished=1
            ;;
    esac
done

COMMAND="$1"

[ -n "${PRODUCT:=Shorewall6}" ]

kernel=$(printf "%2d%02d%02d\n" $(echo $(uname -r) 2> /dev/null | sed 's/-.*//' | tr '.' ' ' ) | head -n1)
if [ $kernel -lt 20624 ]; then
    error_message "ERROR: $PRODUCT requires Linux kernel 2.6.24 or later"
    status=2
else
    case "$COMMAND" in
	start)
	    [ $# -ne 1 ] && usage 2
	    if shorewall6_is_started; then
		error_message "$PRODUCT is already Running"
		status=0
	    else
		progress_message3 "Starting $PRODUCT...."
		define_firewall
		status=$?
		[ -n "$SUBSYSLOCK" -a $status -eq 0 ] && touch $SUBSYSLOCK
		progress_message3 "done."
	    fi
	    ;;
	stop)
	    [ $# -ne 1 ] && usage 2
	    progress_message3 "Stopping $PRODUCT...."
	    stop_firewall
	    status=0
	    [ -n "$SUBSYSLOCK" ] && rm -f $SUBSYSLOCK
	    progress_message3 "done."
	    ;;
	reset)
	    if ! shorewall6_is_started ; then
		error_message "$PRODUCT is not running"
		status=2
	    elif [ $# -eq 1 ]; then
		$IP6TABLES -Z
		$IP6TABLES -t mangle -Z
		date > ${VARDIR}/restarted
		status=0
		progress_message3 "$PRODUCT Counters Reset"
	    else
		shift
		status=0
		for chain in $@; do
		    if chain_exists $chain; then
			if qt $IP6TABLES -Z $chain; then
			    progress_message3 "Filter $chain Counters Reset"
			else
			    error_message "ERROR: Reset of chain $chain failed"
			    status=2
			    break
			fi
		    else
			error_message "WARNING: Filter Chain $chain does not exist"
		    fi
		done
	    fi
	    ;;
	restart)
	    [ $# -ne 1 ] && usage 2
	    if shorewall6_is_started; then
		progress_message3 "Restarting $PRODUCT...."
	    else
		error_message "$PRODUCT is not running"
		progress_message3 "Starting $PRODUCT...."
	    fi

	    define_firewall
	    status=$?
	    if [ -n "$SUBSYSLOCK" ]; then
 		[ $status -eq 0 ] && touch $SUBSYSLOCK || rm -f $SUBSYSLOCK
            fi
	    progress_message3 "done."
	    ;;
	refresh)
	    [ $# -ne 1 ] && usage 2
	    if shorewall6_is_started; then
		progress_message3 "Refreshing $PRODUCT...."
		define_firewall
		status=$?
		progress_message3 "done."
	    else
		echo "$PRODUCT is not running" >&2
		status=2
	    fi
	    ;;
	restore)
	    [ $# -ne 1 ] && usage 2
	    define_firewall
	    status=$?
	    if [ -n "$SUBSYSLOCK" ]; then
 		[ $status -eq 0 ] && touch $SUBSYSLOCK || rm -f $SUBSYSLOCK
            fi
	    ;;
	clear)
	    [ $# -ne 1 ] && usage 2
	    progress_message3 "Clearing $PRODUCT...."
	    clear_firewall
	    status=0
	    [ -n "$SUBSYSLOCK" ] && rm -f $SUBSYSLOCK
	    progress_message3 "done."
	    ;;
	status)
	    [ $# -ne 1 ] && usage 2
	    echo "$PRODUCT-$VERSION Status at $HOSTNAME - $(date)"
	    echo
	    if shorewall6_is_started; then
		echo "$PRODUCT is running"
		status=0
	    else
		echo "$PRODUCT is stopped"
		status=4
	    fi

	    if [ -f ${VARDIR}/state ]; then
		state="$(cat ${VARDIR}/state)"
		case $state in
		    Stopped*|Clear*)
			status=3
			;;
		esac
	    else
		state=Unknown
	    fi
	    echo "State:$state"
	    echo
	    ;;
	version)
	    [ $# -ne 1 ] && usage 2
	    echo $VERSION
	    status=0
	    ;;
	help)
	    [ $# -ne 1 ] && usage 2
	    usage 0
	    ;;
	*)
	    usage 2
	    ;;
    esac
fi

exit $status