#!/bin/bash
###############################################################################
#                                                                             #
# IPFire.org - A linux based firewall                                         #
# Copyright (C) 2011  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/>.       #
#                                                                             #
###############################################################################

IN_HOTPLUG_EVENT=1

# Setup logging.
LOG_FACILITY="network-hotplug"

. /usr/lib/network/functions

# Read network settings
network_settings_read

log DEBUG "Called with SUBSYSTEM='${SUBSYSTEM}', ACTION='${ACTION}', INTERFACE='${INTERFACE}', DEVPATH='${DEVPATH}'"

# Check if the udev environment variables are properly set.
assert isset ACTION

case "${SUBSYSTEM}" in
	ieee80211)
		PHY="$(basename "${DEVPATH}")"

		# Check if the PHY exists
		if ! phy_exists "${PHY}"; then
			exit ${EXIT_OK}
		fi

		case "${ACTION}" in
			add)
				# Load regulatory domain for wireless devices
				wireless_init_reg_domain

				# Configure LEDs
				phy_leds_autoconf "${PHY}"
				;;
		esac

		# Propagate the hotplug event to all configured port hooks
		hotplug_propagate_all_ports || exit ${EXIT_ERROR}

		# Everything went fine
		exit ${EXIT_OK}
		;;

	net)
		assert isset INTERFACE

		# Stop processing rules for the loopback device
		if device_is_loopback ${INTERFACE}; then
			exit ${EXIT_OK}

		# Skip all pppN interfaces (for pppoe-server)
		elif device_is_ppp "${INTERFACE}" && [[ ${INTERFACE} =~ ^ppp[0-9]+$ ]]; then
			log DEBUG "Ignoring PPP device"
			exit ${EXIT_OK}

		# Stop processing rules for wireless monitoring devices
		elif device_is_wireless_monitor ${INTERFACE}; then
			exit ${EXIT_OK}
		fi

		# Did we get called for a non-existing interface?
		if ! zone_exists "${INTERFACE}" && ! port_exists "${INTERFACE}"; then
			case "${ACTION}" in
				add)
					# Ignore this for some special devices
					case "${INTERFACE}" in
						gre0|ip6gre0|ip6tnl0|ip6_vti0|ip_vti0)
							log DEBUG "Ignoring special device ${INTERFACE}"
							exit ${EXIT_OK}
							;;
					esac

					log WARNING "Got to hotplug event for a port which does not exist: ${INTERFACE}"

					# Try to remove the device again

					# Bonding
					if device_is_bonding "${INTERFACE}"; then
						bonding_remove "${INTERFACE}"

					# Dummy
					elif device_is_dummy "${INTERFACE}"; then
						dummy_remove "${INTERFACE}"

					# Wireless
					elif device_is_wireless "${INTERFACE}"; then
						wireless_remove "${INTERFACE}"

					# Everything else
					else
						device_delete "${INTERFACE}"
					fi

					# Check if the device still exists and if so, log an error
					if device_exists "${INTERFACE}"; then
						log ERROR "Could not delete ${INTERFACE}"
						exit ${EXIT_ERROR}
					fi

					exit ${EXIT_OK}
					;;

				remove)
					# Don't propagate removal events for ports that don't exist
					exit ${EXIT_OK}
					;;
			esac
		fi

		# Propagate the hotplug event to all configured port hooks
		hotplug_propagate_all_ports || exit ${EXIT_ERROR}

		# Propagate the hotplug event to all configured zones
		hotplug_propagate_all_zones || exit ${EXIT_ERROR}

		exit ${EXIT_OK}
		;;

	*)
		log ERROR "Called for an unsupported subsystem: ${SUBSYSTEM}"
		exit ${EXIT_ERROR}
		;;
esac

exit ${EXIT_NOT_HANDLED}
