#! /bin/sh

### BEGIN INIT INFO
# Provides:          iptables
# Required-Start:
# Required-Stop:
# Should-Start:      $local_fs
# Should-Stop:       $local_fs
# Default-Start:     S
# Default-Stop:      0 6
# Short-Description: Load iptables at boot time
# Description:       Load pre-configured iptables at boot time
### END INIT INFO

PATH=/sbin:/bin

NAME=iptables

RULESETDIR="/etc/network/${NAME}"
default="/etc/default/${NAME}"

SAVE="/sbin/${NAME}-save"
RESTORE="/sbin/${NAME}-restore"

. /lib/lsb/init-functions

test -x ${RESTORE} || exit 5
test -x ${SAVE} || exit 5

umask 0077

IPTABLES_ENABLE="true"

if test -f $default; then
  . $default
fi

initd="$0"

current() {
	${SAVE}
}

flush() {
	POLICY="${1:-ALLOW}"
	# remove all custom chains and all rules and all comments
	# zero counters too -> [0:0] (/^:/s@\[[0-9]\{1,\}:[0-9]\{1,\}\]@[0:0]@g)
	# set policy for all built-in chains to $1 (defaults to ALLOW)
	#   custom chains always have policy "-", and rules always start with "-"
	#   built-in chains and built-in targets probably never have a "-" in their names,
	#   and only built-in targets can be used as policy for (built-in) chains,
	#   so we delete every line with "-" in it (and all lines starting with '#' - comments)
	sed -e "/-/d;/^#/d;/^:/s@\[[0-9]\{1,\}:[0-9]\{1,\}\]@[0:0]@g;/^:/s@ [^ ]\{1,\} @ ${POLICY} @g"
}

accept_all() {
	current | flush ACCEPT
}

drop_all() {
	current | flush DROP
}

iptables_load() {
	RULESET="$1"
	FILE="${RULESETDIR}/${RULESET}"
	NONINTERACTIVE="$2"

	log_daemon_msg "Loading ${NAME} ruleset" "'${RULESET}'"

	if test -z "${RULESET}"; then
		log_progress_msg "no ruleset specified"
		log_end_msg 1
	elif ! test -f "${FILE}"; then
		if test "x${NONINTERACTIVE}" = "x1"; then
			log_progress_msg "(not configured, fallback to ACCEPT policy)"
			accept_all | ${RESTORE}
			log_end_msg $?
		else
			log_progress_msg "ruleset not found"
			log_end_msg 1
		fi
	else
		${RESTORE} < "${FILE}"
		log_end_msg $?
	fi
}

iptables_save() {
	RULESET="$1"
	FILE="${RULESETDIR}/${RULESET}"

	log_daemon_msg "Saving ${NAME} ruleset" "'${RULESET}'"

	if test -z "${RULESET}"; then
		log_progress_msg "no ruleset specified"
		log_end_msg 1
	elif ${SAVE} > "${FILE}"; then
		# inplace zero counters
		sed -i -e '/^:/s@\[[0-9]\{1,\}:[0-9]\{1,\}\]@[0:0]@g' "${FILE}"
	fi
	log_end_msg $?
}

iptables_clear() {
	log_daemon_msg "Clearing ${NAME} ruleset" "default ACCEPT policy"
	accept_all | ${RESTORE}
	log_end_msg $?
}

iptables_halt() {
	log_daemon_msg "Clearing ${NAME} ruleset" "default DROP policy"
	drop_all | ${RESTORE}
	log_end_msg $?
}

usage () {
	current="$(ls -m ${RULESETDIR})"
cat <<END >&2
${initd} options:
  start|restart|reload|force-reload
     load the "active" ruleset
  save <ruleset>
     save the current ruleset
  load <ruleset>
     load a ruleset
  stop
     load the "inactive" ruleset
  clear
     remove all rules and user-defined chains, set default policy to ACCEPT
  halt
     remove all rules and user-defined chains, set default policy to DROP

Saved rulesets:
  $current

Please read: $default

END
}

case "$1" in
	start|restart|reload|force-reload)
		if ! test "x${IPTABLES_ENABLE}" = "xtrue"; then
			# disabled
			exit 0
		fi
		iptables_load "active" 1
		;;
	stop)
		if ! test "x${IPTABLES_ENABLE}" = "xtrue"; then
			# disabled
			exit 0
		fi
		iptables_load "inactive" 1
		;;
	save)
		iptables_save "$2"
		;;
	load)
		iptables_load "$2"
		;;
	clear)
		iptables_clear
		;;
	halt)
		iptables_halt
		;;
	*)
		if ! test -z "$@"; then
			echo "Aborting ${NAME} initd: unknown command(s): \"$@\"." >&2
		fi
		usage
		exit 3
		;;
esac
