#!/bin/bash
############################################################################
#                                                                          #
# This file is part of the IPFire Firewall.                                #
#                                                                          #
# IPFire 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 2 of the License, or        #
# (at your option) any later version.                                      #
#                                                                          #
# IPFire 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 IPFire; if not, write to the Free Software                    #
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA #
#                                                                          #
# Copyright (C) 2016 IPFire Team <info@ipfire.org>                         #
#                                                                          #
############################################################################

[ -n "${INTERFACE}" ] || exit 2

eval $(/usr/local/bin/readhash /var/ipfire/ethernet/settings)

detect_zone() {
	local intf="${INTERFACE%?}"
	intf="${intf%phys}"
	intf="${intf^^}"

	local zone
	for zone in GREEN BLUE ORANGE RED; do
		# Try to find if INTERFACE is the *phys version of a zone
		if [ "${intf}" = "${zone}" ]; then
			echo "${zone}"
			return 0
		fi

		# Try to find out if this INTERFACE is a slave of a zone
		local slave
		for slave in $(get_value "${zone}_SLAVES"); do

			#Compare if the mac address matches or if the name matches
			if ([ "$(</sys/class/net/${INTERFACE}/address)" = "${slave}" ] || [ "${INTERFACE}" = "${slave}" ]); then
				echo "${zone}"
				return 0
			fi
		done
	done

	return 1
}

get_value() {
	echo "${!1}"
}

random_mac_address() {
	local address="02"

	for i in $(seq 5); do
		printf -v address "${address}:%02x" "$(( RANDOM % 256 ))"
	done

	echo "${address}"
}

# Try to detect which zone we are operating on
ZONE=$(detect_zone)

# Cannot proceed if we could not find a zone
if [ -z "${ZONE}" ]; then
	exit 0
fi

# Determine the mode of this zone
MODE="$(get_value "${ZONE}_MODE")"

# The name of the virtual bridge
BRIDGE="$(get_value "${ZONE}_DEV")"

case "${MODE}" in
	bridge)
		ADDRESS="$(get_value "${ZONE}_MACADDR")"
		[ -n "${ADDRESS}" ] || ADDRESS="$(random_mac_address)"

		# We need to create the bridge if it doesn't exist, yet
		if [ ! -d "/sys/class/net/${BRIDGE}" ]; then
			ip link add "${BRIDGE}" address "${ADDRESS}" type bridge
			#ip link set "${BRIDGE}" up
		fi

		# Attach the physical device
		ip link set dev "${INTERFACE}" master "${BRIDGE}"
		ip link set dev "${INTERFACE}" up
		;;

	macvtap)
		ADDRESS="$(</sys/class/net/${INTERFACE}/address)"
		GENERATED_ADDRESS=$(random_mac_address)

		ip link add link "${INTERFACE}" "${BRIDGE}" address "${ADDRESS}" type macvlan mode bridge
		ip link set "${INTERFACE}" address "${GENERATED_ADDRESS}"
		ip link set "${INTERFACE}" up
		;;

	"")
		exit 0
		;;

	*)
		logger -t "network" "Unhandled mode '${MODE}' for '${ZONE}' (${INTERFACE})"
		exit 1
		;;
esac
