#!/bin/sh
#
# Compiled firewall script generated by Shorewall-perl 4.0.3 - Mon Sep 10 14:17:57 2007
#
#     This program is under GPL [http://www.gnu.org/copyleft/gpl.htm]
#
#     (c) 1999,2000,2001,2002,2003,2004,2005,2006,2007 - Tom Eastep (teastep@shorewall.net)
#
#	Options are:
#
#	    -n				  Don't alter Routing
#	    -v and -q			  Standard Shorewall Verbosity control
#
#	Commands are:
#
#	   start			  Starts the firewall
#          refresh                        Refresh the firewall
#	   restart			  Restarts the firewall
#	   reload			  Reload the firewall
#	   clear			  Removes all firewall rules
#	   stop				  Stops the firewall
#	   status			  Displays firewall status
#	   version			  Displays the version of Shorewall that
#	   				  generated this program
#
################################################################################
# Functions imported from /usr/share/shorewall/lib.base
################################################################################
#
# Message to stderr
#
error_message() # $* = Error Message
{
   echo "   $@" >&2
}

#
# Conditionally produce message
#
progress_message() # $* = Message
{
    local timestamp=

    if [ $VERBOSE -gt 1 ]; then
	[ -n "$TIMESTAMP" ] && timestamp="$(date +%H:%M:%S) "
	echo "${timestamp}$@"
    fi
}

progress_message2() # $* = Message
{
    local timestamp=

    if [ $VERBOSE -gt 0 ]; then
	[ -n "$TIMESTAMP" ] && timestamp="$(date +%H:%M:%S) "
	echo "${timestamp}$@"
    fi
}

progress_message3() # $* = Message
{
    local timestamp=

    if [ $VERBOSE -ge 0 ]; then
	[ -n "$TIMESTAMP" ] && timestamp="$(date +%H:%M:%S) "
	echo "${timestamp}$@"
    fi
}

#
# Split a colon-separated list into a space-separated list
#
split() {
    local ifs=$IFS
    IFS=:
    echo $*
    IFS=$ifs
}

#
# Search a list looking for a match -- returns zero if a match found
# 1 otherwise
#
list_search() # $1 = element to search for , $2-$n = list
{
    local e=$1

    while [ $# -gt 1 ]; do
	shift
	[ "x$e" = "x$1" ] && return 0
    done

    return 1
}

#
# Suppress all output for a command
#
qt()
{
    "$@" >/dev/null 2>&1
}

#
# Determine if Shorewall is "running"
#
shorewall_is_started() {
    qt $IPTABLES -L shorewall -n
}

#
# Echos the fully-qualified name of the calling shell program
#
my_pathname() {
    cd $(dirname $0)
    echo $PWD/$(basename $0)
}

#
# Source a user exit file if it exists
#
run_user_exit() # $1 = file name
{
    local user_exit=$(find_file $1)

    if [ -f $user_exit ]; then
	progress_message "Processing $user_exit ..."
	. $user_exit
    fi
}

#
# Set a standard chain's policy
#
setpolicy() # $1 = name of chain, $2 = policy
{
    run_iptables -P $1 $2
}

#
# Set a standard chain to enable established and related connections
#
setcontinue() # $1 = name of chain
{
    run_iptables -A $1 -m state --state ESTABLISHED,RELATED -j ACCEPT
}

#
# Flush one of the NAT table chains
#
flushnat() # $1 = name of chain
{
    run_iptables -t nat -F $1
}

#
# Flush one of the Mangle table chains
#
flushmangle() # $1 = name of chain
{
    run_iptables -t mangle -F $1
}

#
# Flush and delete all user-defined chains in the filter table
#
deleteallchains() {
    run_iptables -F
    run_iptables -X
}

#
# Load a Kernel Module -- assumes that the variable 'moduledirectories' contains
#                         a space-separated list of directories to search for
#                         the module and that 'moduleloader' contains the
#                         module loader command.
#
loadmodule() # $1 = module name, $2 - * arguments
{
    local modulename=$1
    local modulefile
    local suffix

    if ! list_search $modulename $MODULES ; then
	shift

	for suffix in $MODULE_SUFFIX ; do
	    for directory in $moduledirectories; do
		modulefile=$directory/${modulename}.${suffix}

		if [ -f $modulefile ]; then
		    case $moduleloader in
			insmod)
			    insmod $modulefile $*
			    ;;
			*)
			    modprobe $modulename $*
			    ;;
		    esac
		    break 2
		fi
	    done
	done
    fi
}

#
# Reload the Modules
#
reload_kernel_modules() {

    local save_modules_dir=$MODULESDIR
    local directory
    local moduledirectories=
    local moduleloader=modprobe

    if ! qt mywhich modprobe; then
	moduleloader=insmod
    fi

    [ -n "${MODULE_SUFFIX:=o gz ko o.gz ko.gz}" ]

    [ -z "$MODULESDIR" ] && MODULESDIR=/lib/modules/$(uname -r)/kernel/net/ipv4/netfilter:/lib/modules/$(uname -r)/kernel/net/netfilter
    MODULES=$(lsmod | cut -d ' ' -f1)

    for directory in $(split $MODULESDIR); do
	[ -d $directory ] && moduledirectories="$moduledirectories $directory"
    done

    [ -n "$moduledirectories" ] && while read command; do
	eval $command
    done

    MODULESDIR=$save_modules_dir
}

#
# Load kernel modules required for Shorewall
#
load_kernel_modules() # $1 = Yes, if we are to save moduleinfo in $VARDIR
{
    local save_modules_dir=$MODULESDIR
    local directory
    local moduledirectories=
    local moduleloader=modprobe
    local savemoduleinfo=${1:-Yes} # So old compiled scripts still work

    if ! qt mywhich modprobe; then
	moduleloader=insmod
    fi

    [ -n "${MODULE_SUFFIX:=o gz ko o.gz ko.gz}" ]

    [ -z "$MODULESDIR" ] && \
	MODULESDIR=/lib/modules/$(uname -r)/kernel/net/ipv4/netfilter:/lib/modules/$(uname -r)/kernel/net/netfilter

    for directory in $(split $MODULESDIR); do
	[ -d $directory ] && moduledirectories="$moduledirectories $directory"
    done

    modules=$(find_file modules)

    if [ -f $modules -a -n "$moduledirectories" ]; then
	MODULES=$(lsmod | cut -d ' ' -f1)
	progress_message "Loading Modules..."
	. $modules
	if [ $savemoduleinfo = Yes ]; then
	    [ -d ${VARDIR} ] || mkdir -p ${VARDIR}
	    echo MODULESDIR="$MODULESDIR" > ${VARDIR}/.modulesdir
	    cp -f $modules ${VARDIR}/.modules
	fi
    elif [ $savemoduleinfo = Yes ]; then
	[ -d ${VARDIR} ] || mkdir -p ${VARDIR}
	> ${VARDIR}/.modulesdir
	> ${VARDIR}/.modules
    fi

    MODULESDIR=$save_modules_dir
}

#
#  Note: The following set of IP address manipulation functions have anomalous
#        behavior when the shell only supports 32-bit signed arithmetic and
#        the IP address is 128.0.0.0 or 128.0.0.1.
#

LEFTSHIFT='<<'

#
# Convert an IP address in dot quad format to an integer
#
decodeaddr() {
    local x
    local temp=0
    local ifs=$IFS

    IFS=.

    for x in $1; do
	temp=$(( $(( $temp $LEFTSHIFT 8 )) | $x ))
    done

    echo $temp

    IFS=$ifs
}

#
# convert an integer to dot quad format
#
encodeaddr() {
    addr=$1
    local x
    local y=$(($addr & 255))

    for x in 1 2 3 ; do
	addr=$(($addr >> 8))
	y=$(($addr & 255)).$y
    done

    echo $y
}

#
# Netmask from CIDR
#
ip_netmask() {
    local vlsm=${1#*/}

    [ $vlsm -eq 0 ] && echo 0 || echo $(( -1 $LEFTSHIFT $(( 32 - $vlsm )) ))
}

#
# Network address from CIDR
#
ip_network() {
    local decodedaddr=$(decodeaddr ${1%/*})
    local netmask=$(ip_netmask $1)

    echo $(encodeaddr $(($decodedaddr & $netmask)))
}

#
# The following hack is supplied to compensate for the fact that many of
# the popular light-weight Bourne shell derivatives don't support XOR ("^").
#
ip_broadcast() {
    local x=$(( 32 - ${1#*/} ))

    [ $x -eq 32 ] && echo -1 || echo $(( $(( 1 $LEFTSHIFT $x )) - 1 ))
}

#
# Calculate broadcast address from CIDR
#
broadcastaddress() {
    local decodedaddr=$(decodeaddr ${1%/*})
    local netmask=$(ip_netmask $1)
    local broadcast=$(ip_broadcast $1)

    echo $(encodeaddr $(( $(($decodedaddr & $netmask)) | $broadcast )))
}

#
# Test for network membership
#
in_network() # $1 = IP address, $2 = CIDR network
{
    local netmask=$(ip_netmask $2)

    test $(( $(decodeaddr $1) & $netmask)) -eq $(( $(decodeaddr ${2%/*}) & $netmask ))
}

#
# Query NetFilter about the existence of a filter chain
#
chain_exists() # $1 = chain name
{
    qt $IPTABLES -L $1 -n
}

#
# Find the value 'dev' in the passed arguments then echo the next value
#

find_device() {
    while [ $# -gt 1 ]; do
	[ "x$1" = xdev ] && echo $2 && return
	shift
    done
}

#
# Find the value 'via' in the passed arguments then echo the next value
#

find_gateway() {
    while [ $# -gt 1 ]; do
	[ "x$1" = xvia ] && echo $2 && return
	shift
    done
}

#
# Find the value 'mtu' in the passed arguments then echo the next value
#

find_mtu() {
    while [ $# -gt 1 ]; do
	[ "x$1" = xmtu ] && echo $2 && return
	shift
    done
}

#
# Find the value 'peer' in the passed arguments then echo the next value up to
# "/"
#

find_peer() {
    while [ $# -gt 1 ]; do
	[ "x$1" = xpeer ] && echo ${2%/*} && return
	shift
    done
}

#
# Find the interfaces that have a route to the passed address - the default
# route is not used.
#

find_rt_interface() {
    ip route list | while read addr rest; do
	case $addr in
	    */*)
		in_network ${1%/*} $addr && echo $(find_device $rest)
		;;
	    default)
		;;
	    *)
		if [ "$addr" = "$1" -o "$addr/32" = "$1" ]; then
		    echo $(find_device $rest)
		fi
		;;
	esac
    done
}

#
# Try to find the gateway through an interface looking for 'nexthop'

find_nexthop() # $1 = interface
{
    echo $(find_gateway `ip route list | grep "[[:space:]]nexthop.* $1"`)
}

#
# Find the default route's interface
#
find_default_interface() {
    ip route list | while read first rest; do
	[ "$first" = default ] && echo $(find_device $rest) && return
    done
}

#
# Echo the name of the interface(s) that will be used to send to the
# passed address
#

find_interface_by_address() {
    local dev="$(find_rt_interface $1)"
    local first rest

    [ -z "$dev" ] && dev=$(find_default_interface)

    [ -n "$dev" ] && echo $dev
}

#
# Find the interface with the passed MAC address
#

find_interface_by_mac() {
    local mac=$1 first second rest dev

    ip link list | while read first second rest; do
	case $first in
	    *:)
                dev=$second
		;;
	    *)
	        if [ "$second" = $mac ]; then
		    echo ${dev%:}
		    return
		fi
	esac
    done
}

#
# Determine if Interface is up
#
interface_is_up() {
    [ -n "$(ip link list dev $1 2> /dev/null | grep -e '[<,]UP[,>]')" ]
}

#
# Find interface address--returns the first IP address assigned to the passed
# device
#
find_first_interface_address() # $1 = interface
{
    #
    # get the line of output containing the first IP address
    #
    addr=$(ip -f inet addr show $1 2> /dev/null | grep 'inet .* global' | head -n1)
    #
    # If there wasn't one, bail out now
    #
    [ -n "$addr" ] || fatal_error "Can't determine the IP address of $1"
    #
    # Strip off the trailing VLSM mask (or the peer IP in case of a P-t-P link)
    # along with everything else on the line
    #
    echo $addr | sed 's/\s*inet //;s/\/.*//;s/ peer.*//'
}

find_first_interface_address_if_any() # $1 = interface
{
    #
    # get the line of output containing the first IP address
    #
    addr=$(ip -f inet addr show $1 2> /dev/null | grep 'inet .* global' | head -n1)
    #
    # Strip off the trailing VLSM mask (or the peer IP in case of a P-t-P link)
    # along with everything else on the line
    #
    [ -n "$addr" ] && echo $addr | sed 's/\s*inet //;s/\/.*//;s/ peer.*//' || echo 0.0.0.0
}

#
# Determine if interface is usable from a Netfilter prespective
#
interface_is_usable() # $1 = interface
{
    interface_is_up $1 && [ "$(find_first_interface_address_if_any $1)" != 0.0.0.0 ] && run_isusable_exit $1
}

#
# Find interface addresses--returns the set of addresses assigned to the passed
# device
#
find_interface_addresses() # $1 = interface
{
    ip -f inet addr show $1 2> /dev/null | grep inet\  | sed 's/\s*inet //;s/\/.*//;s/ peer.*//'
}

#
#  echo the list of networks routed out of a given interface
#
get_routed_networks() # $1 = interface name, $2-n = Fatal error message
{
    local address
    local rest

    ip route show dev $1 2> /dev/null |
	while read address rest; do
	    case "$address" in
		default)
		    if [ $# -gt 1 ]; then
			shift
			fatal_error "$@"
		    else
			echo "WARNING: default route ignored on interface $1" >&2
		    fi
		    ;;
		multicast|broadcast|prohibit|nat|throw|nexthop)
		    ;;
		*)
		    [ "$address" = "${address%/*}" ] && address="${address}/32"
		    echo $address
		    ;;
	    esac
        done
}

get_interface_bcasts() # $1 = interface
{
    local addresses=

    ip -f inet addr show dev $1 2> /dev/null | grep 'inet.*brd' | sed 's/inet.*brd //; s/scope.*//;' | sort -u
}

#
# Internal version of 'which'
#
mywhich() {
    local dir

    for dir in $(split $PATH); do
	if [ -x $dir/$1 ]; then
	    echo $dir/$1
	    return 0
	fi
    done

    return 2
}

#
# Find a File -- For relative file name, look in each ${CONFIG_PATH} then ${CONFDIR}
#
find_file()
{
    local saveifs= directory

    case $1 in
	/*)
	    echo $1
	    ;;
	*)
	    for directory in $(split $CONFIG_PATH); do
		if [ -f $directory/$1 ]; then
		    echo $directory/$1
		    return
		fi
	    done

	    echo ${CONFDIR}/$1
	    ;;
    esac
}

#
# Set the Shorewall state
#
set_state () # $1 = state
{
    echo "$1 ($(date))" > ${VARDIR}/state
}

#
# Perform variable substitution on the passed argument and echo the result
#
expand() # $@ = contents of variable which may be the name of another variable
{
    eval echo \"$@\"
}

#
# Function for including one file into another
#
INCLUDE() {
    . $(find_file $(expand $@))
}

#
# Delete IP address
#
del_ip_addr() # $1 = address, $2 = interface
{
    [ $(find_first_interface_address_if_any $2) = $1 ] || qt ip addr del $1 dev $2
}

# Add IP Aliases
#
add_ip_aliases() # $* = List of addresses
{
    local addresses external interface inet cidr rest val arping=$(mywhich arping)

    address_details()
    {
	#
	# Folks feel uneasy if they don't see all of the same
	# decoration on these IP addresses that they see when their
	# distro's net config tool adds them. In an attempt to reduce
	# the anxiety level, we have the following code which sets
	# the VLSM and BRD from an existing address in the same networks
	#
	# Get all of the lines that contain inet addresses with broadcast
	#
	ip -f inet addr show $interface 2> /dev/null | grep 'inet.*brd' | while read inet cidr rest ; do
	    case $cidr in
		*/*)
		    if in_network $external $cidr; then
			echo "/${cidr#*/} brd $(broadcastaddress $cidr)"
			break
		    fi
		    ;;
	    esac
	done
    }

    do_one()
    {
	val=$(address_details)

	ip addr add ${external}${val} dev $interface $label
	[ -n "$arping" ] && qt $arping -U -c 2 -I $interface $external
	echo "$external $interface" >> $VARDIR/nat
	[ -n "$label" ] && label="with $label"
	progress_message "   IP Address $external added to interface $interface $label"
    }

    progress_message "Adding IP Addresses..."

    while [ $# -gt 0 ]; do
	external=$1
	interface=$2
	label=

	if [ "$interface" != "${interface%:*}" ]; then
	    label="${interface#*:}"
	    interface="${interface%:*}"
	    label="label $interface:$label"
	fi

	shift 2

	list_search $external $(find_interface_addresses $interface) || do_one
    done
}

detect_gateway() # $1 = interface
{
    local interface=$1
    #
    # First assume that this is some sort of point-to-point interface
    #
    gateway=$( find_peer $(ip addr list $interface ) )
    #
    # Maybe there's a default route through this gateway already
    #
    [ -n "$gateway" ] || gateway=$(find_gateway $(ip route list dev $interface))
    #
    # Last hope -- is there a load-balancing route through the interface?
    #
    [ -n "$gateway" ] || gateway=$(find_nexthop $interface)
    #
    # Be sure we found one
    #
    [ -n "$gateway" ] && echo $gateway
}

#
# Disable IPV6
#
disable_ipv6() {
    local foo="$(ip -f inet6 addr list 2> /dev/null)"

    if [ -n "$foo" ]; then
	if qt mywhich ip6tables; then
	    ip6tables -P FORWARD DROP
	    ip6tables -P INPUT DROP
	    ip6tables -P OUTPUT DROP
	    ip6tables -F
	    ip6tables -X
	    ip6tables -A OUTPUT -o lo -j ACCEPT
	    ip6tables -A INPUT -i lo -j ACCEPT
	else
	    error_message "WARNING: DISABLE_IPV6=Yes in shorewall.conf but this system does not appear to have ip6tables"
	fi
    fi
}

# Function to truncate a string -- It uses 'cut -b -<n>'
# rather than ${v:first:last} because light-weight shells like ash and
# dash do not support that form of expansion.
#

truncate() # $1 = length
{
    cut -b -${1}
}

delete_tc1()
{
    clear_one_tc() {
        tc qdisc del dev $1 root 2> /dev/null
        tc qdisc del dev $1 ingress 2> /dev/null

    }

    run_user_exit tcclear

    run_ip link list | \
    while read inx interface details; do
        case $inx in
            [0-9]*)
                clear_one_tc ${interface%:}
                ;;
            *)
                ;;
        esac
    done
}

#
# Detect a device's MTU -- echos the passed device's MTU
#
get_device_mtu() # $1 = device
{
    local output="$(ip link list dev $1 2> /dev/null)" # quotes required for /bin/ash

    if [ -n "$output" ]; then
	echo $(find_mtu $output)
    else
	echo 1500
    fi
}

#
# Version of the above that doesn't generate any output for MTU 1500.
# Generates 'mtu <mtu+>' otherwise, where <mtu+> is the device's MTU + 100
#
get_device_mtu1() # $1 = device
{
    local output="$(ip link list dev $1 2> /dev/null)" # quotes required for /bin/ash
    local mtu

    if [ -n "$output" ]; then
	mtu=$(find_mtu $output)
	if [ -n "$mtu" ]; then
	    [ $mtu = 1500 ] || echo mtu $(($mtu + 100))
	fi
    fi

}

#
# Undo changes to routing
#
undo_routing() {

    if [ -z "$NOROUTES"  ]; then
	#
	# Restore rt_tables database
	#
	if [ -f ${VARDIR}/rt_tables ]; then
	    [ -w /etc/iproute2/rt_table -a -z "$KEEP_RT_TABLES" ] && cp -f ${VARDIR}/rt_tables /etc/iproute2/ && progress_message "/etc/iproute2/rt_tables database restored"
	    rm -f ${VARDIR}/rt_tables
	fi
	#
	# Restore the rest of the routing table
	#
	if [ -f ${VARDIR}/undo_routing ]; then
	    . ${VARDIR}/undo_routing
	    progress_message "Shorewall-generated routing tables and routing rules removed"
	    rm -f ${VARDIR}/undo_routing
	fi
    fi

}

restore_default_route() {
    if [ -z "$NOROUTES" -a -f ${VARDIR}/default_route ]; then
	local default_route= route

	while read route ; do
	    case $route in
		default*)
		    if [ -n "$default_route" ]; then
			case "$default_route" in
			    *metric*)
		                #
		                # Don't restore a route with a metric -- we only replace the one with metric == 0
		                #
				qt ip route delete default metric 0 && \
				    progress_message "Default Route with metric 0 deleted"
				;;
			    *)
				qt ip route replace $default_route && \
				    progress_message "Default Route (${default_route# }) restored"
				;;
			esac

			break
		    fi

		    default_route="$default_route $route"
		    ;;
		*)
		    default_route="$default_route $route"
		    ;;
	    esac
	done < ${VARDIR}/default_route

	rm -f ${VARDIR}/default_route
    fi
}

#
# Determine how to do "echo -e"
#

find_echo() {
    local result

    result=$(echo "a\tb")
    [ ${#result} -eq 3 ] && { echo echo; return; }

    result=$(echo -e "a\tb")
    [ ${#result} -eq 3 ] && { echo "echo -e"; return; }

    result=$(which echo)
    [ -n "$result" ] && { echo "$result -e"; return; }

    echo echo
}
################################################################################
# End of functions imported from /usr/share/shorewall/lib.base
################################################################################

run_init_exit() {
    
    progress_message2 Processing /etc/shorewall/init ...

    #
    # Shorewall version 4 - Init File
    #
    # /etc/shorewall/init
    #
    #	Add commands below that you want to be executed at the beginning of
    #	a "shorewall start" or "shorewall restart" command.
    #
    # For additional information, see
    # http://shorewall.net/shorewall_extension_scripts.htm
    #
    ###############################################################################
    #LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE
}

run_isusable_exit() {
    true
}

run_start_exit() {
    
    progress_message2 Processing /etc/shorewall/start ...

    #
    # Shorewall version 4 - Start File
    #
    # /etc/shorewall/start
    #
    #	Add commands below that you want to be executed after shorewall has
    #	been started or restarted.
    #
    # See http://shorewall.net/shorewall_extension_scripts.htm for additional
    # information.
    #
    ###############################################################################
    #LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE
}

run_tcclear_exit() {
    true
}

run_started_exit() {
    
    progress_message2 Processing /etc/shorewall/started ...

    #
    # Shorewall version 4 - Started File
    #
    # /etc/shorewall/started
    #
    #	Add commands below that you want to be executed after shorewall has
    #	been completely started or restarted. The difference between this
    #	extension script and /etc/shorewall/start is that this one is invoked
    #	after delayed loading of the blacklist (DELAYBLACKLISTLOAD=Yes) and
    #	after the 'shorewall' chain has been created (thus signaling that the
    #	firewall is completely up.
    #
    #	This script should not change the firewall configuration directly but
    #	may do so indirectly by running /sbin/shorewall with the 'nolock'
    #	option.
    #
    # See http://shorewall.net/shorewall_extension_scripts.htm for additional
    # information.
    #
    ###############################################################################
    #LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE
}

run_stop_exit() {
    
    progress_message2 Processing /etc/shorewall/stop ...

    #
    # Shorewall version 4 - Stop File
    #
    # /etc/shorewall/stop
    #
    #	Add commands below that you want to be executed at the beginning of a
    #	"shorewall stop" command.
    #
    # See http://shorewall.net/shorewall_extension_scripts.htm for additional
    # information.
    #
    ###############################################################################
    #LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE
}

run_stopped_exit() {
    
    progress_message2 Processing /etc/shorewall/stopped ...

    #
    # Shorewall version 4 - Stopped File
    #
    # /etc/shorewall/stopped
    #
    #	Add commands below that you want to be executed at the completion of a
    #	"shorewall stop" command.
    #
    # See http://shorewall.net/shorewall_extension_scripts.htm for additional
    # information.
    #
    ###############################################################################
    #LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE
}

run_clear_exit() {
    true
}

run_refresh_exit() {
    true
}

run_refreshed_exit() {
    true
}

#
# This function initializes the global variables used by the program
#
initialize()
{
    #
    # These variables are required by the library functions called in this script
    #
    SHAREDIR=/usr/share/shorewall
    CONFDIR=/etc/shorewall
    PRODUCT='Shorewall'
    [ -f ${CONFDIR}/vardir ] && . ${CONFDIR}/vardir
    CONFIG_PATH="/etc/shorewall:/usr/share/shorewall"
    [ -n "${VARDIR:=/var/lib/shorewall}" ]
    TEMPFILE=
    DISABLE_IPV6="Yes"
    MODULESDIR=""
    MODULE_SUFFIX=""
    LOGFORMAT="Shorewall:%s:%s:"
    SUBSYSLOCK="/var/lock/subsys/shorewall"
    LOCKFILE=""
    LOGLIMIT=""
    LOGTAGONLY=""
    LOGRULENUMBERS=""
    [ -n "${COMMAND:=restart}" ]
    [ -n "${VERBOSE:=0}" ]
    [ -n "${RESTOREFILE:=restore}" ]
    [ -n "$LOGFORMAT" ] || LOGFORMAT="Shorewall:%s:%s:"
    VERSION="4.0.3"
    PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin"
    TERMINATOR=fatal_error
    IPTABLES="/sbin/iptables"

    [ -x "$IPTABLES" ] || startup_error "IPTABLES=$IPTABLES does not exist or is not executable"
    IPTABLES_RESTORE=${IPTABLES}-restore
    [ -x "$IPTABLES_RESTORE" ] || startup_error "$IPTABLES_RESTORE does not exist or is not executable"

    STOPPING=

    #
    # The library requires that ${VARDIR} exist
    #
    [ -d ${VARDIR} ] || mkdir -p ${VARDIR}

    #
    # Recent kernels are difficult to configure -- we see state match omitted a lot so we check for it here
    #
    qt $IPTABLES -N foox1234
    qt $IPTABLES -A foox1234 -m state --state ESTABLISHED,RELATED -j ACCEPT
    result=$?
    qt $IPTABLES -F foox1234
    qt $IPTABLES -X foox1234
    [ $result = 0 ] || startup_error "Your kernel/iptables do not include state match support. No version of Shorewall will run on this system"

}

#
# Stop/restore the firewall after an error or because of a 'stop' or 'clear' command
#
stop_firewall() {

    deletechain() {
	qt $IPTABLES -L $1 -n && qt $IPTABLES -F $1 && qt $IPTABLES -X $1
    }

    deleteallchains() {
	$IPTABLES -F
	$IPTABLES -X
    }

    setcontinue() {
	$IPTABLES -A $1 -m state --state ESTABLISHED,RELATED -j ACCEPT
    }

    delete_nat() {
	$IPTABLES -t nat -F
	$IPTABLES -t nat -X

	if [ -f ${VARDIR}/nat ]; then
	    while read external interface; do
		del_ip_addr $external $interface
	    done < ${VARDIR}/nat

	    rm -f ${VARDIR}/nat
	fi
    }

    case $COMMAND in
	stop|clear|restore)
	    ;;
	*)
	    set +x

	    case $COMMAND in
		start)
		    logger -p kern.err "ERROR:$PRODUCT start failed"
		    ;;
		restart)
		    logger -p kern.err "ERROR:$PRODUCT restart failed"
		    ;;
		restore)
		    logger -p kern.err "ERROR:$PRODUCT restore failed"
		    ;;
	    esac

	    if [ "$RESTOREFILE" = NONE ]; then
		COMMAND=clear
		clear_firewall
		echo "$PRODUCT Cleared"

		kill $$
		exit 2
	    else
		RESTOREPATH=${VARDIR}/$RESTOREFILE

		if [ -x $RESTOREPATH ]; then

		    if [ -x ${RESTOREPATH}-ipsets ]; then
			progress_message2 Restoring Ipsets...
			#
			# We must purge iptables to be sure that there are no
			# references to ipsets
			#
			for table in mangle nat filter; do
			    $IPTABLES -t $table -F
			    $IPTABLES -t $table -X
			done

			${RESTOREPATH}-ipsets
		    fi

		    echo Restoring ${PRODUCT:=Shorewall}...

		    if $RESTOREPATH restore; then
			echo "$PRODUCT restored from $RESTOREPATH"
			set_state "Started"
		    else
			set_state "Unknown"
		    fi

		    kill $$
		    exit 2
		fi
	    fi
	    ;;
    esac

    set_state "Stopping"

    STOPPING="Yes"

    TERMINATOR=

    deletechain shorewall

    run_stop_exit;


    run_iptables -t mangle -F
    run_iptables -t mangle -X
    for chain in PREROUTING INPUT FORWARD POSTROUTING; do
	qt $IPTABLES -t mangle -P $chain ACCEPT
    done


    delete_nat
    for chain in PREROUTING POSTROUTING OUTPUT; do
	qt $IPTABLES -t nat -P $chain ACCEPT
    done


    if [ -f ${VARDIR}/proxyarp ]; then
	while read address interface external haveroute; do
	    qt arp -i $external -d $address pub
	    [ -z "${haveroute}${NOROUTES}" ] && qt ip route del $address dev $interface
	done < ${VARDIR}/proxyarp

	for f in /proc/sys/net/ipv4/conf/*; do
	    [ -f $f/proxy_arp ] && echo 0 > $f/proxy_arp
	done
    fi

    rm -f ${VARDIR}/proxyarp

    delete_tc1
    undo_routing
    restore_default_route
    for chain in INPUT FORWARD; do
	setpolicy $chain DROP
    done

    setpolicy OUTPUT ACCEPT

    deleteallchains

    for chain in INPUT FORWARD; do
	setcontinue $chain
    done

    $IPTABLES -A INPUT -i eth1   -j ACCEPT
    $IPTABLES -A OUTPUT -o eth1   -j ACCEPT
    $IPTABLES -A INPUT  -i lo -j ACCEPT
    $IPTABLES -A OUTPUT -o lo -j ACCEPT

    echo 1 > /proc/sys/net/ipv4/ip_forward
    progress_message2 IP Forwarding Enabled
    run_stopped_exit

    set_state "Stopped"

    logger -p kern.info "$PRODUCT Stopped"

    case $COMMAND in
    stop|clear)
	;;
    *)
	#
	# The firewall is being stopped when we were trying to do something
	# else. Kill the shell in case we're running in a subshell
	#
	kill $$
	;;
    esac
}

#
# Clear Proxy Arp
#
delete_proxyarp() {
    if [ -f ${VARDIR}/proxyarp ]; then
	while read address interface external haveroute; do
	    qt arp -i $external -d $address pub
	    [ -z "${haveroute}${NOROUTES}" ] && qt ip route del $address dev $interface
	done < ${VARDIR}/proxyarp

	for f in /proc/sys/net/ipv4/conf/*; do
	    [ -f $f/proxy_arp ] && echo 0 > $f/proxy_arp
	done
    fi

    rm -f ${VARDIR}/proxyarp
}

#
# 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/ipv4/ip_forward

    if [ -n "$DISABLE_IPV6" ]; then
	if qt mywhich ip6tables; then
	    ip6tables -P INPUT   ACCEPT 2> /dev/null
	    ip6tables -P OUTPUT  ACCEPT 2> /dev/null
	    ip6tables -P FORWARD ACCEPT 2> /dev/null
	fi
    fi

    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
    stop_firewall
    [ -n "$TEMPFILE" ] && rm -f $TEMPFILE
    exit 2
}

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

    kill $$
    exit 2
}

#
# Run iptables and if an error occurs, stop/restore the firewall
#
run_iptables()
{
    if [ -n "$COMMENT" ]; then
        $IPTABLES $@ -m comment --comment "$COMMENT"
    else
        $IPTABLES $@
    fi

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

#
# Run iptables and if an error occurs, stop/restore the firewall
#
run_ip()
{
    if ! ip $@; then
	error_message "ERROR: Command \"ip $@\" 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_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
}

#
# Get a list of all configured broadcast addresses on the system
#
get_all_bcasts()
{
    ip -f inet addr show 2> /dev/null | grep 'inet.*brd' | sed 's/inet.*brd //; s/scope.*//;' | sort -u
}
#
# Clear Routing and Traffic Shaping
#
clear_routing_and_traffic_shaping() {
    
    progress_message2 Initializing...

    load_kernel_modules Yes

    [ "$COMMAND" = refresh ] && run_refresh_exit || run_init_exit

    qt $IPTABLES -L shorewall -n && qt $IPTABLES -F shorewall && qt $IPTABLES -X shorewall

    delete_proxyarp

    if [ -f ${VARDIR}/nat ]; then
	while read external interface; do
	    del_ip_addr $external $interface
	done < ${VARDIR}/nat

	rm -f ${VARDIR}/nat
    fi

    delete_tc1

    disable_ipv6

}

#
# Setup Routing and Traffic Shaping
#
setup_routing_and_traffic_shaping() {
    
    progress_message2 Setting up ARP filtering...

    progress_message2 Setting up Route Filtering...

    for file in /proc/sys/net/ipv4/conf/*; do
	[ -f $file/rp_filter ] && echo 0 > $file/rp_filter
    done
    echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter
    echo 0 > /proc/sys/net/ipv4/conf/default/rp_filter
    [ -n "$NOROUTES" ] || ip route flush cache
    
    progress_message2 Setting up Martian Logging...

    for file in /proc/sys/net/ipv4/conf/*; do
	[ -f $file/log_martians ] && echo 0 > $file/log_martians
    done
    if [ -f /proc/sys/net/ipv4/conf/eth1/log_martians ]; then
	echo 1 > /proc/sys/net/ipv4/conf/eth1/log_martians
    else
	error_message "WARNING: Cannot set Martian logging on eth1"
    fi

    echo 0 > /proc/sys/net/ipv4/conf/all/log_martians
    echo 0 > /proc/sys/net/ipv4/conf/default/log_martians
    
    progress_message2 Setting up Accept Source Routing...

    echo 1 > /proc/sys/net/ipv4/ip_forward
    progress_message2 IP Forwarding Enabled

    progress_message2 Setting up Proxy ARP...

    undo_routing
    restore_default_route
    
    progress_message2 Setting up Traffic Control...

    if interface_is_up eth1; then
	eth1_exists=Yes
	qt tc qdisc del dev eth1 root
	qt tc qdisc del dev eth1 ingress
	run_tc qdisc add dev eth1 root handle 1: htb default 0
	eth1_mtu=$(get_device_mtu eth1)
	eth1_mtu1=$(get_device_mtu1 eth1)
	run_tc class add dev eth1 parent 1: classid 1:1 htb rate 500mbit $eth1_mtu1
	run_tc qdisc add dev eth1 handle ffff: ingress
	run_tc filter add dev eth1 parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate 500000kbit burst 10k drop flowid :1
	progress_message    TC Device eth1 defined.
    else
	error_message "WARNING: Device eth1 is not in the UP state -- traffic-shaping configuration skipped"
	eth1_exists=
    fi

    cat > ${VARDIR}/proxyarp << __EOF__
__EOF__

    if [ "$COMMAND" != refresh ]; then
	cat > ${VARDIR}/chains << __EOF__
__EOF__
	cat > ${VARDIR}/zones << __EOF__
fw firewall
dmz ipv4 eth1:172.16.254.0/24
__EOF__
    fi

    > ${VARDIR}/nat
}

setup_netfilter()
{
    
    progress_message2 Preparing iptables-restore input...

    exec 3>${VARDIR}/.iptables-restore-input

    cat >&3 << __EOF__
*nat
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:tcfor - [0:0]
:tcout - [0:0]
:tcpost - [0:0]
:tcpre - [0:0]
-A PREROUTING  -j tcpre
-A FORWARD -j tcfor
-A OUTPUT  -j tcout
-A POSTROUTING -j tcpost
COMMIT
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
:Drop - [0:0]
:Reject - [0:0]
:all2all - [0:0]
:dmz2all - [0:0]
:dmz2fw - [0:0]
:dropBcast - [0:0]
:dropInvalid - [0:0]
:dropNotSyn - [0:0]
:dynamic - [0:0]
:eth1_fwd - [0:0]
:eth1_in - [0:0]
:eth1_out - [0:0]
:fw2all - [0:0]
:fw2dmz - [0:0]
:logdrop - [0:0]
:logreject - [0:0]
:reject - [0:0]
:smurfs - [0:0]
-A INPUT -i eth1 -j eth1_in
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -j Reject
-A INPUT -j LOG --log-level 6 --log-prefix "Shorewall:INPUT:REJECT:" 
-A INPUT -j reject
-A FORWARD -i eth1 -j eth1_fwd
-A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -j Reject
-A FORWARD -j LOG --log-level 6 --log-prefix "Shorewall:FORWARD:REJECT:" 
-A FORWARD -j reject
-A OUTPUT -o eth1 -j eth1_out
-A OUTPUT -o lo -j ACCEPT
-A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -j Reject
-A OUTPUT -j LOG --log-level 6 --log-prefix "Shorewall:OUTPUT:REJECT:" 
-A OUTPUT -j reject
-A Drop -p 6 --dport 113 -j reject
-A Drop -j dropBcast
-A Drop -p icmp --icmp-type 3/4 -j ACCEPT
-A Drop -p icmp --icmp-type 11 -j ACCEPT
-A Drop -j dropInvalid
-A Drop -p 17 -m multiport --dports 135,445 -j DROP
-A Drop -p 17 --dport 137:139 -j DROP
-A Drop -p 17 --dport 1024:65535 --sport 137 -j DROP
-A Drop -p 6 -m multiport --dports 135,139,445 -j DROP
-A Drop -p 17 --dport 1900 -j DROP
-A Drop -p 6 -j dropNotSyn
-A Drop -p 17 --sport 53 -j DROP
-A Reject -p 6 --dport 113 -j reject
-A Reject -j dropBcast
-A Reject -p icmp --icmp-type 3/4 -j ACCEPT
-A Reject -p icmp --icmp-type 11 -j ACCEPT
-A Reject -j dropInvalid
-A Reject -p 17 -m multiport --dports 135,445 -j reject
-A Reject -p 17 --dport 137:139 -j reject
-A Reject -p 17 --dport 1024:65535 --sport 137 -j reject
-A Reject -p 6 -m multiport --dports 135,139,445 -j reject
-A Reject -p 17 --dport 1900 -j DROP
-A Reject -p 6 -j dropNotSyn
-A Reject -p 17 --sport 53 -j DROP
-A all2all -m state --state ESTABLISHED,RELATED -j ACCEPT
-A all2all -j Reject
-A all2all -j LOG --log-level 6 --log-prefix "Shorewall:all2all:REJECT:" 
-A all2all -j reject
-A dmz2all -m state --state ESTABLISHED,RELATED -j ACCEPT
-A dmz2all -j Reject
-A dmz2all -j LOG --log-level 6 --log-prefix "Shorewall:dmz2all:REJECT:" 
-A dmz2all -j reject
-A dmz2fw -m state --state ESTABLISHED,RELATED -j ACCEPT
-A dmz2fw -j Reject
-A dmz2fw -j LOG --log-level 6 --log-prefix "Shorewall:dmz2fw:REJECT:" 
-A dmz2fw -j reject
__EOF__

    for address in $ALL_BCASTS; do
	echo "-A dropBcast -d $address -j DROP" >&3
    done

    cat >&3 << __EOF__
-A dropBcast -d 224.0.0.0/4 -j DROP
-A dropInvalid -m state --state INVALID -j DROP
-A dropNotSyn -p tcp ! --syn -j DROP
-A eth1_fwd -m state --state NEW,INVALID  -j dynamic
-A eth1_in -m state --state NEW,INVALID  -j dynamic
-A eth1_in -s 172.16.254.0/24 -j dmz2fw
-A eth1_out -d 172.16.254.0/24 -j fw2dmz
__EOF__

    for address in $ETH1_BCASTS; do
       echo "-A eth1_out -d $address -j fw2dmz" >&3
    done

    cat >&3 << __EOF__
-A eth1_out -d 224.0.0.0/4 -j fw2dmz
-A fw2all -m state --state ESTABLISHED,RELATED -j ACCEPT
-A fw2all -j Reject
-A fw2all -j LOG --log-level 6 --log-prefix "Shorewall:fw2all:REJECT:" 
-A fw2all -j reject
-A fw2dmz -m state --state ESTABLISHED,RELATED -j ACCEPT
-A fw2dmz -p 6 --dport 30022 -j ACCEPT 
-A fw2dmz -j Reject
-A fw2dmz -j LOG --log-level 6 --log-prefix "Shorewall:fw2dmz:REJECT:" 
-A fw2dmz -j reject
-A logdrop  -j DROP
-A logreject  -j reject
__EOF__

    for address in $ALL_BCASTS; do
	echo "-A reject -d $address -j DROP" >&3
    done

    cat >&3 << __EOF__
-A reject -s 224.0.0.0/4 -j DROP
-A reject -p tcp -j REJECT --reject-with tcp-reset
-A reject -p udp -j REJECT
-A reject -p icmp -j REJECT --reject-with icmp-host-unreachable
-A reject -j REJECT --reject-with icmp-host-prohibited
__EOF__

    for address in $ALL_BCASTS; do
	echo "-A smurfs -s $address -j LOG --log-level 6 --log-prefix \"Shorewall:smurfs:DROP:\" " >&3
	echo "-A smurfs -s $address -j DROP" >&3
    done

    cat >&3 << __EOF__
-A smurfs -s 224.0.0.0/4 -j LOG --log-level 6 --log-prefix "Shorewall:smurfs:DROP:" 
-A smurfs -s 224.0.0.0/4 -j DROP
COMMIT
__EOF__

    exec 3>&-

    progress_message2 "Running iptables-restore..."

    cat ${VARDIR}/.iptables-restore-input | $IPTABLES_RESTORE # Use this nonsensical form to appease SELinux
    if [ $? != 0 ]; then
	fatal_error "iptables-restore Failed. Input is in ${VARDIR}/.iptables-restore-input"
    fi

}

#
# Start/Restart the Firewall
#
define_firewall() {
    
    clear_routing_and_traffic_shaping
    #
    # Establish the values of shell variables used in the following function calls
    #
    if [ "$COMMAND" != restore ]; then

	ALL_BCASTS="$(get_all_bcasts) 255.255.255.255"
	ETH1_BCASTS="$(get_interface_bcasts eth1) 255.255.255.255"
    fi

    setup_routing_and_traffic_shaping
    
    if [ $COMMAND = restore ]; then
	iptables_save_file=${VARDIR}/$(basename $0)-iptables
	if [ -f $iptables_save_file ]; then
	    iptables-restore < $iptables_save_file
	else
	    fatal_error "$iptables_save_file does not exist"
	fi
	set_state "Started"
    else
	if [ $COMMAND = refresh ]; then
	    chainlist_reload
	    run_refreshed_exit
	    $IPTABLES -N shorewall
	    set_state "Started"
	else
	    setup_netfilter
	    restore_dynamic_rules
	    run_start_exit
	    $IPTABLES -N shorewall
	    set_state "Started"
	    run_started_exit
	fi
    
	cp -f $(my_pathname) ${VARDIR}/.restore
    fi
    
    date > ${VARDIR}/restarted
    
    case $COMMAND in
	start)
	    logger -p kern.info "$PRODUCT started"
	    ;;
	restart)
	    logger -p kern.info "$PRODUCT restarted"
	    ;;
	refresh)
	    logger -p kern.info "$PRODUCT refreshed"
	    ;;
	restore)
	    logger -p kern.info "$PRODUCT restored"
	    ;;
    esac

}

#
# 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 ] && [ "x$1" = "xdebug" -o "x$1" = "xtrace" ]; then
    set -x
    shift
fi

initialize

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

if [ $# -ne 1 ]; then
    usage 2
else
    COMMAND="$1"
fi

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

case "$COMMAND" in
    start)
	if shorewall_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)
	progress_message3 "Stopping $PRODUCT...."
	stop_firewall
	status=0
	[ -n "$SUBSYSLOCK" ] && rm -f $SUBSYSLOCK
	progress_message3 "done."
	;;
    reset)
	if ! shorewall_is_started ; then
	    error_message "$PRODUCT is not running"
	    status=2
	else
	    $IPTABLES -Z
	    $IPTABLES -t nat -Z
	    $IPTABLES -t mangle -Z
	    date > ${VARDIR}/restarted
	    status=0
	    progress_message3 "$PRODUCT Counters Reset"
	fi
	;;
    restart)
	if shorewall_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)
	if shorewall_is_started; then
	    progress_message3 "Refreshing $PRODUCT...."
	    define_firewall
	    status=$?
	    progress_message3 "done."
	else
	    echo "$PRODUCT is not running" >&2
	    status=2
	fi
	;;
    restore)
	define_firewall
	status=$?
	if [ -n "$SUBSYSLOCK" ]; then
 	    [ $status -eq 0 ] && touch $SUBSYSLOCK || rm -f $SUBSYSLOCK
        fi
	;;
    clear)
	progress_message3 "Clearing $PRODUCT...."
	clear_firewall
	status=0
	[ -n "$SUBSYSLOCK" ] && rm -f $SUBSYSLOCK
	progress_message3 "done."
	;;
    status)
	echo "$PRODUCT-$VERSION Status at $HOSTNAME - $(date)"
	echo
	if shorewall_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)
	echo $VERSION
	status=0
	;;
    help)
	usage 0
	;;
    *)
	usage 2
	;;
esac

exit $status
