#!/bin/bash
###############################################################################
#                                                                             #
# IPFire.org - A linux based firewall                                         #
# Copyright (C) 2010  Michael Tremer & Christian Schmidt                      #
#                                                                             #
# This program is free software: you can redistribute it and/or modify        #
# it under the terms of the GNU General Public License as published by        #
# the Free Software Foundation, either version 3 of the License, or           #
# (at your option) any later version.                                         #
#                                                                             #
# This program is distributed in the hope that it will be useful,             #
# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
# GNU General Public License for more details.                                #
#                                                                             #
# You should have received a copy of the GNU General Public License           #
# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
#                                                                             #
###############################################################################
#
# Notes:
#   - All functions in this scope must start with an underline (_) to not
#     conflict with any functions that were defined somewhere else.
#

# _notimplemented
#   Returns a soft error if a function was not implemented, yet.
#
function _notimplemented() {
	warning "'$@' was not implemented."
	exit ${EXIT_CONF_ERROR}
}

function _info() {
	echo "HOOK=\"${HOOK}\""
}

function _create() {
	local zone=${1}
	shift

	config_read $(zone_dir ${zone})/settings

	_parse_cmdline $@

	config_write $(zone_dir ${zone})/settings ${HOOK_SETTINGS}

	exit ${EXIT_OK}
}

function _edit() {
	_create $@
}

function _rem() {
	_notimplemented _rem
}

function _status() {
	local zone=${1}

	if device_is_up ${zone}; then
		exit ${STATUS_UP}
	fi

	exit ${STATUS_DOWN}
}

function _up() {
	_notimplemented _up
}

function _down() {
	_notimplemented _down
}

function _discover() {
	# This hook does not support a discovery
	exit ${DISCOVER_NOT_SUPPORTED}
}

# The default help function.
function _help() {
	# If no man page has been configured, we print an error message.
	if [ -z "${HOOK_MANPAGE}" ]; then
		error "There is no help available for hook '${HOOK}'. Exiting."
		exit ${EXIT_ERROR}
	fi

	cli_show_man ${HOOK_MANPAGE}
}

# Do nothing
function _parse_cmdline() {
	return ${EXIT_OK}
}

function _port() {
	local zone=${1}
	local action=${2}
	shift 2

	local ret

	case "${action}" in
		add|create|edit|rem|show)
			_port_${action} ${zone} $@
			ret=$?
			;;
		*)
			error "Unrecognized argument: '${action}'"
			exit ${EXIT_ERROR}
			;;
	esac

	exit ${ret}
}

function _port_add() {
	_port_cmd add $@
}

function _port_edit() {
	_port_cmd edit $@
}

function _port_rem() {
	_port_cmd rem $@
}

function _port_show() {
	_notimplemented _port_show
}

function _port_status() {
	_port_cmd status $@
}

function _port_cmd() {
	local cmd=${1}
	local zone=${2}
	local port=${3}
	shift 3

	assert isset cmd
	assert isset zone
	assert isset port

	local hook_zone=$(zone_get_hook ${zone})
	local hook_port=$(port_get_hook ${port})

	assert isset hook_zone
	assert isset hook_port

	if ! listmatch ${hook_port} $(zone_get_supported_port_hooks ${zone}); then
		error_log "Zone '${zone}' does not support port of type '${hook_port}'."
		exit ${EXIT_ERROR}
	fi

	hook_zone_port_exec ${hook_zone} ${hook_port} ${cmd} ${zone} ${port} $@

	exit $?
}

function _port_up() {
	_port_cmd up $@
}

function _port_down() {
	_port_cmd down $@
}

function _config() {
	local zone=${1}
	local action=${2}
	shift 2

	local ret

	case "${action}" in
		create|edit|rem|show)
			_config_${action} ${zone} $@
			ret=$?
			;;
		*)
			error "Unrecognized argument: '${action}'"
			exit ${EXIT_ERROR}
			;;
	esac

	exit ${ret}
}

# This function is not a public one
function __configcmd() {
	local cmd=${1}
	local zone=${2}
	local hook_config=${3}
	shift 3

	local hook_zone=$(zone_get_hook ${zone})

	if ! hook_zone_exists ${hook_zone}; then
		error "Hook '${hook}' does not exist."
		exit ${EXIT_ERROR}
	fi

	if ! hook_config_exists ${hook_zone} ${hook_config}; then
		error "Hook '${hook_config}' is not supported for zone '${zone}'."
		exit ${EXIT_ERROR}
	fi

	hook_zone_config_exec ${hook_zone} ${hook_config} ${cmd} ${zone} $@
}

function _config_create() {
	local zone=${1}
	local hook_config=${2}
	shift 2

	assert isset zone
	assert isset hook_config
	assert zone_exists ${zone}

	if ! listmatch ${hook_config} $(zone_get_supported_config_hooks ${zone}); then
		error_log "Zone '${zone}' does not support configuration of type '${hook_config}'."
		exit ${EXIT_ERROR}
	fi

	local hook_zone=$(zone_get_hook ${zone})
	assert isset hook_zone

	hook_zone_config_exec ${hook_zone} ${hook_config} create ${zone} $@

	exit $?
}

function _config_edit() {
	__configcmd edit $@
}

function _config_rem() {
	_notimplemented _config_rem
}

function _config_show() {
	_notimplemented _config_show
}

function _ppp-write-config() {
	_notimplemented _ppp_write_config

	# Arguments: <zone> <filename>
}

function _ppp-ip-pre-up() {
	local zone=${1}
	shift

	if ! zone_exists ${zone}; then
		error "Zone '${zone}' does not exist."
		exit ${EXIT_ERROR}
	fi

	ppp_common_ip_pre_up ${zone} $@

	exit $?
}

function _ppp-ip-up() {
	local zone=${1}
	shift

	if ! zone_exists ${zone}; then
		error "Zone '${zone}' does not exist."
		exit ${EXIT_ERROR}
	fi

	ppp_common_ip_up ${zone} $@

	exit $?
}

function _ppp-ip-down() {
	local zone=${1}
	shift

	if ! zone_exists ${zone}; then
		error "Zone '${zone}' does not exist."
		exit ${EXIT_ERROR}
	fi

	ppp_common_ip_down ${zone} $@

	exit $?
}

function _ppp-ipv6-up() {
	local zone=${1}
	shift

	if ! zone_exists ${zone}; then
		error "Zone '${zone}' does not exist."
		exit ${EXIT_ERROR}
	fi

	ppp_common_ipv6_up ${zone} $@

	exit $?
}

function _ppp-ipv6-down() {
	local zone=${1}
	shift

	if ! zone_exists ${zone}; then
		error "Zone '${zone}' does not exist."
		exit ${EXIT_ERROR}
	fi

	ppp_common_ipv6_down ${zone} $@

	exit $?
}
