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

# DEVICE equals the actual MAC address of the device.
# If ADDRESS is set, the device will get ADDRESS set for its MAC address.

HOOK_SETTINGS="ADDRESS ADVERTISED_LINK_SPEEDS DEVICE OFFLOADING MTU"

hook_check_settings() {
	assert ismac DEVICE

	# Invalid MAC addresses are not allowed
	assert not isoneof DEVICE 00:00:00:00:00:00 ff:ff:ff:ff:ff:ff

	if isset ADDRESS; then
		assert ismac ADDRESS
	fi

	if isset MTU; then
		assert mtu_is_valid "ethernet" "${MTU}"
	fi

	if isset MODES; then
		local mode
		for mode in ${MODES}; do
			assert [ -n "${DEVICE_LINK_SPEEDS[${mode}]}" ]
		done
	fi
}

hook_parse_cmdline() {
	while [ $# -gt 0 ]; do
		case "${1}" in
			--address=*)
				ADDRESS="$(cli_get_val "${1}")"

				if ! mac_is_valid "${ADDRESS}"; then
					error "Invalid MAC address: ${ADDRESS}"
					return ${EXIT_ERROR}
				fi
				;;

			--advertised-link-speeds=*)
				ADVERTISED_LINK_SPEEDS="$(cli_get_val "${1}")"

				local speed
				for speed in ${ADVERTISED_LINK_SPEEDS}; do
					if [ -z "${DEVICE_LINK_SPEEDS[${speed}]}" ]; then
						error "Unsupported link speed: ${speed}"
						return ${EXIT_ERROR}
					fi
				done
				;;

			--mtu=*)
				MTU="$(cli_get_val "${1}")"

				if ! mtu_is_valid "ethernet" "${MTU}"; then
					error "Invalid MTU: ${MTU}"
					return ${EXIT_ERROR}
				fi
				;;

			--offloading=*)
				OFFLOADING="$(cli_get_val "${1}")"

				if enabled OFFLOADING; then
					OFFLOADING="on"
				elif disabled OFFLOADING; then
					OFFLOADING="off"
				else
					error "Invalid value for offloading: ${OFFLOADING}"
					return ${EXIT_ERROR}
				fi
				;;

			*)
				error "Unknown argument: ${1}"
				return ${EXIT_ERROR}
				;;
		esac
		shift
	done
}

# This function is only called automatically by hotplug to create
# a new ethernet port.
hook_new() {
	local port="${1}"
	assert isset port

	local device="${2}"
	assert isset device

	local DEVICE="$(device_get_address "${device}")"

	if ! port_settings_write "${port}" ${HOOK_SETTINGS}; then
		log ERROR "Could not write settings for port ${port}"
		return ${EXIT_ERROR}
	fi

	return ${EXIT_OK}
}

hook_create() {
	return ${EXIT_OK}
}

hook_up() {
	local port="${1}"

	local ${HOOK_SETTINGS}
	if ! port_settings_read "${port}" ${HOOK_SETTINGS}; then
		log ERROR "Could not read settings for port ${port}"
		return ${EXIT_ERROR}
	fi

	# Set MAC address, if needed
	if isset ADDRESS; then
		device_set_address "${port}" "${ADDRESS}"
	fi

	# Set MTU
	if isset MTU; then
		device_set_mtu "${port}" "${MTU}"
	else
		device_set_mtu "${port}" "${DEFAULT_MTU}"
	fi

	# Set link speeds
	if isset ADVERTISED_LINK_SPEEDS; then
		device_advertise_link_speeds "${port}" ${ADVERTISED_LINK_SPEEDS}
	fi

	# Auto-enable or disable hardware offloading
	if ! isset OFFLOADING || enabled OFFLOADING; then
		offloading_auto "${port}"
	else
		offloading_disable_all "${port}"
	fi

	# Bring up the device
	device_set_up "${port}"

	exit ${EXIT_OK}
}

hook_remove() {
	exit ${EXIT_OK}
}

hook_hotplug_rename() {
	local port=${1}
	assert isset port

	local device=${2}
	assert isset device

	# Read in the conifguration file.
	port_settings_read "${port}" ${HOOK_SETTINGS}

	# Get the current MAC address of the device.
	local address=$(device_get_address ${device})
	assert isset address

	# Check if the address matches with the configuration.
	if list_match "${address}" ${DEVICE} ${ADDRESS}; then
		log DEBUG "Device '${device}' equals port '${port}'."
		exit ${EXIT_OK}
	fi

	log DEBUG "Device '${device}' does not equal port '${port}'."
	exit ${EXIT_ERROR}
}
