#!/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/>.       #
#                                                                             #
###############################################################################

. /usr/lib/network/header-zone

HOOK_SETTINGS="HOOK SERVER_ADDRESS LOCAL_ADDRESS LOCAL_ADDRESS6 TUNNEL_ID"
HOOK_SETTINGS="${HOOK_SETTINGS} AUTO_UPDATE_ENDPOINT USERNAME PASSWORD"

# The IPv4 address of the tunnel endpoint where to connect to.
SERVER_ADDRESS=

# The local IPv4 address of the tunnel endpoint.
LOCAL_ADDRESS=

# The address that is assigned to the tunnel device (with prefix).
LOCAL_ADDRESS6=

# True if the endpoint IP address should be automatically
# updated each time the tunnel connects.
AUTO_UPDATE_ENDPOINT="false"

# The ID of the tunnel.
TUNNEL_ID=

# Credentials for the tunnelbroker.net service.
USERNAME=
PASSWORD=

hook_check_settings() {
	assert isset SERVER_ADDRESS
	assert isset LOCAL_ADDRESS
	assert isset LOCAL_ADDRESS6

	if enabled AUTO_UPDATE_ENDPOINT; then
		assert isset TUNNEL_ID
		assert isset USERNAME
		assert isset PASSWORD
	fi
}

hook_parse_cmdline() {
	local value

	while [ $# -gt 0 ]; do
		case "${1}" in
			--server-address=*)
				SERVER_ADDRESS=$(cli_get_val ${1})
				;;
			--local-ipv4-address=*)
				LOCAL_ADDRESS=$(cli_get_val ${1})
				;;
			--local-ipv6-address=*)
				LOCAL_ADDRESS6=$(cli_get_val ${1})
				;;
			--auto-update-endpoint=*)
				local val="$(cli_get_val ${1})"

				if enabled val; then
					AUTO_UPDATE_ENDPOINT="true"
				else
					AUTO_UPADTE_ENDPOINT="false"
				fi
				;;
			--tunnel-id=*)
				TUNNEL_ID="$(cli_get_val ${1})"
				;;
			--username=*)
				USERNAME="$(cli_get_val ${1})"
				;;
			--password=*)
				PASSWORD="$(cli_get_val ${1})"
				;;
			*)
				echo "Unknown option: ${1}" >&2
				exit ${EXIT_ERROR}
				;;
		esac
		shift
	done
}

hook_up() {
	local zone=${1}
	assert isset zone

	# Read configuration options.
	zone_settings_read "${zone}"

	if enabled AUTO_UPDATE_ENDPOINT; then
		log DEBUG "Updating tunnel endpoint"

		he_tunnelbroker_endpoint_update \
			--username="${USERNAME}" \
			--password="${PASSWORD}" \
			--tunnel-id="${TUNNEL_ID}"
	fi

	ip_tunnel_add ${zone} --ttl=255 \
		--remote-address="${SERVER_ADDRESS}" \
		--local-address="${LOCAL_ADDRESS}"

	# Bring up the device.
	device_set_up ${zone}

	# Assign IPv6 address.
	ip_address_add ${zone} ${LOCAL_ADDRESS6}

	# Update routing information.
	db_set "${zone}/ipv6/type" "${HOOK}"
	db_set "${zone}/ipv6/local-ip-address" "${LOCAL_ADDRESS6}"
	db_set "${zone}/ipv6/active" 1

	# Update the routing database.
	routing_update ${zone} ipv6
	routing_default_update

	exit ${EXIT_OK}
}

hook_down() {
	local zone=${1}
	assert isset zone

	# Remove everything from the routing db.
	db_delete "${zone}/ipv6"

	routing_update ${zone} ipv6
	routing_default_update

	# Remove the tunnel device.
	ip_tunnel_del ${zone}

	exit ${EXIT_OK}
}

hook_status() {
	local zone=${1}
	assert isset zone

	cli_device_headline ${zone}

	zone_settings_read "${zone}"

	local server_line="${SERVER_ADDRESS}"
	local server_hostname=$(dns_get_hostname ${SERVER_ADDRESS})
	if [ -n "${server_hostname}" ]; then
		server_line="${server_line} (Hostname: ${server_hostname})"
	fi

	cli_headline 2 "Configuration"
	cli_print_fmt1 2 "Server" "${server_line}"
	cli_print_fmt1 2 "Endpoint IPv4 address" "${LOCAL_ADDRESS}"
	cli_print_fmt1 2 "Endpoint IPv6 address" "${LOCAL_ADDRESS6}"
	cli_space

	exit ${EXIT_OK}
}
