From: Michael Tremer Date: Fri, 25 May 2012 09:02:08 +0000 (+0000) Subject: Fix hotplugging with udev. X-Git-Tag: 004~83 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8c63fa1376cce38511496ee1b5e7403a0eab6fef;p=network.git Fix hotplugging with udev. New devices will now be correctly named and brought up after plugging them in. --- diff --git a/functions.constants b/functions.constants index 04da262f..40f306df 100644 --- a/functions.constants +++ b/functions.constants @@ -79,4 +79,4 @@ TIMEOUT_RESTART=2 DEVICE_PRINT_LINE1=" %-24s %s\n" -PORT_PATTERN=portN +PORT_PATTERN="pN" diff --git a/functions.device b/functions.device index ff141270..238cb06a 100644 --- a/functions.device +++ b/functions.device @@ -560,13 +560,18 @@ function device_hotplug() { shift assert isset device - #assert device_exists ${device} + assert device_exists ${device} if ! device_is_free ${device}; then log ERROR "The device '${device}' is in use." return ${EXIT_ERROR} fi + if ! device_is_real ${device}; then + log DEBUG "Don't rename any virtual devices." + return ${EXIT_OK} + fi + for port in $(ports_get_all); do port_cmd hotplug ${port} ${device} if [ $? -eq ${EXIT_OK} ]; then @@ -575,6 +580,13 @@ function device_hotplug() { fi done - port_find_free ${PORT_PATTERN} - return $? + # If no port configuration could be found, we search for the next + # unused name and return that. + local port=$(port_find_free ${PORT_PATTERN}) + + log DEBUG "Could not find an existing port configuration for '${device}'." + log DEBUG "${device} --> ${port}" + + echo "${port}" + return ${EXIT_OK} } diff --git a/functions.lock b/functions.lock new file mode 100644 index 00000000..72414054 --- /dev/null +++ b/functions.lock @@ -0,0 +1,58 @@ +#!/bin/bash +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2012 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 . # +# # +############################################################################### + +function lock_acquire() { + local lockfile="${1}" + assert isset lockfile + + # timeout value in seconds + local timeout=60 + timeout=$(( ${timeout} * 10 )) + + log DEBUG "Acquiring lock '${lockfile}'." + + local free="false" + while [ ${timeout} -gt 0 ]; do + if [ ! -e "${lockfile}" ]; then + free="true" + break + fi + + timeout=$(( ${timeout} - 1 )) + sleep 0.1 + done + + assert ${free} "Could not acquire lock '${lockfile}'." + + # Write out pid to the lockfile and make sure that + # nobody else can access it. + echo "$$" > ${lockfile} + chmod 600 ${lockfile} +} + +function lock_release() { + local lockfile="${1}" + + log DEBUG "Releasing lock '${lockfile}'." + + # Remove the lockfile (okay if it does not exist). + rm -f ${lockfile} +} diff --git a/functions.logging b/functions.logging index 76b3bdc7..6cb82781 100644 --- a/functions.logging +++ b/functions.logging @@ -19,9 +19,16 @@ # # ############################################################################### -LOG_FACILITY="network" +if [ -z "${LOG_FACILITY}" ]; then + LOG_FACILITY="network" +fi + LOG_LEVEL="DEBUG" +if [ -z "${LOG_DISABLE_STDOUT}" ]; then + LOG_DISABLE_STDOUT=false +fi + function log() { local level=${1} shift @@ -38,6 +45,9 @@ function log() { logger -t ${LOG_FACILITY} "${message}" + # Leave here, when there should be no output on the console. + [ "${LOG_DISABLE_STDOUT}" = "true" ] && return 0 + case "${level}" in DEBUG|INFO|WARNING|ERROR) message="${COLOUR_LOG[${level}]}${message}${COLOUR_NORMAL}" diff --git a/functions.util b/functions.util index 953df22a..f990362f 100644 --- a/functions.util +++ b/functions.util @@ -314,6 +314,8 @@ function exec_cmd() { log DEBUG "Running command: ${cmd}" DEBUG=${DEBUG} \ + LOG_DISABLE_STDOUT="${LOG_DISABLE_STDOUT}" \ + LOG_FACILITY="${LOG_FACILITY}" \ ${SHELL} ${cmd} local ret=$? diff --git a/hooks/ports/ethernet b/hooks/ports/ethernet index cf37aa05..499889ad 100755 --- a/hooks/ports/ethernet +++ b/hooks/ports/ethernet @@ -19,7 +19,7 @@ # # ############################################################################### -. /lib/network/header-port +. /usr/lib/network/header-port HOOK_SETTINGS="HOOK DEVICE_MAC" @@ -70,9 +70,11 @@ function _hotplug() { config_read $(port_file ${port}) if [ "${DEVICE_MAC}" = "$(device_get_address ${device})" ]; then + log DEBUG "Device '${device}' equals port '${port}'." exit ${EXIT_OK} fi + log DEBUG "Device '${device}' does not equal port '${port}'." exit ${EXIT_ERROR} } diff --git a/udev/network-hotplug b/udev/network-hotplug index d4a76cb9..63fd3795 100755 --- a/udev/network-hotplug +++ b/udev/network-hotplug @@ -19,11 +19,17 @@ # # ############################################################################### -. /lib/network/functions +. /usr/lib/network/functions + +# Setup logging. +LOG_FACILITY="network-hotplug" + +log DEBUG "Called with ACTION='${ACTION}', INTERFACE='${INTERFACE}'." # Do nothing, if the network isn't running. # That happens for example on boot time. if ! network_is_running; then + log DEBUG "network has not been started, yet. Exiting." exit 0 fi @@ -33,23 +39,30 @@ assert isset INTERFACE # Check, if the device is a physical network interface and # if we can handle it. -if ! device_is_real ${INTERFACE}; then - exit ${EXIT_OK} -fi - -# Check, if there is a configuration for that device. -if port_exists ${INTERFACE}; then - port=${INTERFACE} - -else - # If the given device was not configured, - # we create an initial configuration. - port_create ethernet ${INTERFACE} - exit ${EXIT_OK} +if device_exists ${INTERFACE}; then + if ! device_is_real ${INTERFACE}; then + log DEBUG "Called for interface '${INTERFACE}' which is a virtual interface. Exiting." + exit ${EXIT_OK} + fi fi case "${ACTION}" in add|register) + # Check, if there is a configuration for that device. + if port_exists ${INTERFACE}; then + port=${INTERFACE} + + # Create new configuration for _real_ network devices. + elif device_is_real ${INTERFACE}; then + # If the given device was not configured, + # we create an initial configuration. + port_create ethernet ${INTERFACE} + + # Dunno what to do in any other case. + else + exit 0 + fi + zone=$(port_zone ${port}) # Check, if the device is configured in a zone. @@ -63,7 +76,7 @@ case "${ACTION}" in ;; remove|unregister) - port_down ${port} + # Do nothing. ;; esac diff --git a/udev/network-hotplug-rename b/udev/network-hotplug-rename index 3879d029..1678deb6 100755 --- a/udev/network-hotplug-rename +++ b/udev/network-hotplug-rename @@ -19,11 +19,28 @@ # # ############################################################################### -. /lib/network/functions +# Setup logging. +LOG_FACILITY="network-hotplug-rename" +LOG_DISABLE_STDOUT="true" + +. /usr/lib/network/functions + +# Setup the locking. +LOCKFILE="${RUN_DIR}/.rename_lock" +function cleanup() { + lock_release ${LOCKFILE} +} +trap cleanup EXIT TERM KILL # Check if the INTERFACE variable is properly set. assert isset INTERFACE +# Log what we are doing here. +log DEBUG "Called for interface '${INTERFACE}'." + +# Acquiring lock for this operation. +lock_acquire ${LOCKFILE} + # Get the name of that device from the configuration # or return a new one if it is unknown. device_hotplug ${INTERFACE} diff --git a/udev/rules.d/60-net.rules b/udev/rules.d/60-net.rules index 6d7bc0b3..ab1779b3 100644 --- a/udev/rules.d/60-net.rules +++ b/udev/rules.d/60-net.rules @@ -2,7 +2,7 @@ # Call a script that checks for the right name of the new device. # It is either renamed to match an existing configuration or gets # a new name. -ACTION=="add", SUBSYSTEM=="net", PROGRAM="/lib/udev/network-hotplug-rename", RESULT=="?*", ENV{INTERFACE_NAME}="$result" +ACTION=="add", SUBSYSTEM=="net", PROGRAM="/usr/lib/udev/network-hotplug-rename", RESULT=="?*", NAME="$result" # Handle all plugged-in devices. -SUBSYSTEM=="net", RUN+="/lib/udev/network-hotplug" +SUBSYSTEM=="net", RUN+="/usr/lib/udev/network-hotplug"