diff --git a/debian/ifup@.service b/debian/ifup@.service index da1891b3..8f065193 100644 --- a/debian/ifup@.service +++ b/debian/ifup@.service @@ -11,7 +11,27 @@ IgnoreOnIsolate=yes [Service] # avoid stopping on shutdown via stopping system-ifup.slice Slice=system.slice -ExecStart=/sbin/ifup --allow=hotplug %I -ExecStop=/sbin/ifdown %I +Environment=HOTPLUG_ARGS= +Environment=LOCKFILE=/run/network/.lock +EnvironmentFile=-/etc/default/networking +ExecStart=/bin/sh -ec "( \ + /bin/test \"$VERBOSE\" = \"yes\" && EXTRA_ARGS=-v; \ + /bin/test \"$DEBUG\" = \"yes\" && EXTRA_ARGS=\"$EXTRA_ARGS -d\"; \ + flock 9; \ + if $(/sbin/ifquery -L 9 -l --allow=hotplug 2>/dev/null | grep -w -q \"^%I$\"); then \ + exec /sbin/ifup $EXTRA_ARGS $HOTPLUG_ARGS %I -L 9 --systemd; \ + fi; \ + exit 1; \ +) 9>$LOCKFILE" +ExecStop=/bin/sh -ec "( \ + /bin/test \"$VERBOSE\" = \"yes\" && EXTRA_ARGS=-v; \ + /bin/test \"$DEBUG\" = \"yes\" && EXTRA_ARGS=\"$EXTRA_ARGS -d\"; \ + flock 9; \ + exec /sbin/ifdown $EXTRA_ARGS %I -L 9 --systemd; \ +) 9>$LOCKFILE" RemainAfterExit=true TimeoutStartSec=2min + +# remove log duplications +StandardOutput=null +StandardError=null diff --git a/debian/ifupdown2-hotplug b/debian/ifupdown2-hotplug new file mode 100755 index 00000000..2b6b869b --- /dev/null +++ b/debian/ifupdown2-hotplug @@ -0,0 +1,161 @@ +#!/bin/sh -e +# +# run /sbin/{ifup,ifdown} with the --allow=hotplug option. +# + +PATH='/sbin:/bin:/usr/sbin:/usr/bin' + +if [ -x /usr/bin/logger ]; then + LOGGER=/usr/bin/logger +elif [ -x /bin/logger ]; then + LOGGER=/bin/logger +else + unset LOGGER +fi + +LOCKFILE=/run/network/.lock + +# for diagnostics +if [ -t 1 -a -z "$LOGGER" ] || [ ! -e '/dev/log' ]; then + mesg() { + echo "$@" >&2 + } +elif [ -t 1 ]; then + mesg() { + echo "$@" + $LOGGER -t "${0##*/}[$$]" "$@" + } +else + mesg() { + $LOGGER -t "${0##*/}[$$]" "$@" + } +fi + +if [ -z "$INTERFACE" ]; then + mesg "Bad ifupdown udev helper invocation: \$INTERFACE is not set" + exit 1 +fi + +wait_for_interface() { + local interface=$1 + local state + + while :; do + read state /sys/class/net/$interface/operstate 2>/dev/null || true + if [ "$state" != down ]; then + return 0 + fi + sleep 1 + done +} + +process_exclusions() { + set -- $EXCLUDE_INTERFACES + exclusions="" + for d; do + exclusions="-X $d $exclusions" + done + echo $exclusions +} + +net_ifup() { + . /etc/default/networking 2>/dev/null || true + + exclusions=$(process_exclusions) + + # exit if the interface is not configured as allow-hotplug or excluded (querying does not require a lock) + if ! $(/sbin/ifquery --allow=hotplug -l $exclusions 2>/dev/null | grep -w -q "^$INTERFACE$"); then + exit 0 + fi + + if [ -d /run/systemd/system ]; then + exec systemctl --no-block start $(systemd-escape --template ifup@.service $INTERFACE) + fi + + EXTRA_ARGS= + [ "$VERBOSE" = yes ] && EXTRA_ARGS=-v + [ "$DEBUG" = yes ] && EXTRA_ARGS="$EXTRA_ARGS -d" + [ "$SYSLOG" = yes ] && EXTRA_ARGS="$EXTRA_ARGS --syslog" + + # Take the lock and wait for lo before exec ifup. + ( + flock 9 + wait_for_interface lo + exec ifup $EXTRA_ARGS $HOTPLUG_ARGS -L 9 $INTERFACE + ) 9>$LOCKFILE +} + +net_ifdown() { + + # systemd will automatically ifdown the interface on device + # removal by binding the instanced service to the network device + if [ -d /run/systemd/system ]; then + exit 0 + fi + + . /etc/default/networking 2>/dev/null || true + + exclusions=$(process_exclusions) + + # exit if the interface is not configured as allow-hotplug or excluded (querying does not require a lock) + if ! $(/sbin/ifquery --allow=hotplug -l $exclusions 2>/dev/null | grep -w -q "^$INTERFACE$"); then + exit 0 + fi + + EXTRA_ARGS= + [ "$VERBOSE" = yes ] && EXTRA_ARGS=-v + [ "$DEBUG" = yes ] && EXTRA_ARGS="$EXTRA_ARGS -d" + [ "$SYSLOG" = yes ] && EXTRA_ARGS="$EXTRA_ARGS --syslog" + + # Take the lock and exec ifdown. + ( + flock 9 + exec ifdown $EXTRA_ARGS $INTERFACE -L 9 + ) 9>$LOCKFILE +} + +do_everything() { + +case "$ACTION" in + add) + # these interfaces generate hotplug events *after* they are brought up + case $INTERFACE in + ppp*|ippp*|isdn*|plip*|lo|irda*|ipsec*) + exit 0 ;; + esac + + net_ifup + ;; + + remove) + # the pppd persist option may have been used, so it should not be killed + case $INTERFACE in + ppp*) + exit 0 ;; + esac + + net_ifdown + ;; + + *) + mesg "NET $ACTION event not supported" + exit 1 + ;; +esac + +} + +# under systemd we don't do synchronous operations, so we can run in the +# foreground; we also need to, as forked children get killed right away under +# systemd +if [ -d /run/systemd/system ]; then + do_everything +else + # under sysvinit we need to fork as we start the long-running + # "ifup". but there, forked processes won't get killed. + # When udev_log="debug" stdout and stderr are pipes connected to udevd. + # They need to be closed or udevd will wait for this process which will + # deadlock with udevsettle until the timeout. + exec > /dev/null 2> /dev/null + do_everything & +fi diff --git a/debian/ifupdown2.install b/debian/ifupdown2.install index 0ecf4b98..a2967114 100644 --- a/debian/ifupdown2.install +++ b/debian/ifupdown2.install @@ -1,2 +1,3 @@ etc/network/ifupdown2/addons.conf /etc/network/ifupdown2/ etc/network/ifupdown2/ifupdown2.conf /etc/network/ifupdown2/ +debian/ifupdown2-hotplug lib/udev diff --git a/debian/ifupdown2.udev b/debian/ifupdown2.udev new file mode 100644 index 00000000..e07f0808 --- /dev/null +++ b/debian/ifupdown2.udev @@ -0,0 +1,5 @@ +# Allow rfkill for users in the netdev group +KERNEL=="rfkill", MODE="0664", GROUP="netdev" + +# Handle allow-hotplug interfaces +SUBSYSTEM=="net", ACTION=="add|remove", RUN+="ifupdown2-hotplug" diff --git a/debian/rules b/debian/rules index ea6f4342..92bb0803 100755 --- a/debian/rules +++ b/debian/rules @@ -16,6 +16,8 @@ override_dh_install: mkdir -p debian/ifupdown2/lib/systemd/system/ install --mode=644 debian/ifup@.service debian/ifupdown2/lib/systemd/system/ +override_dh_installudev: + dh_installudev --priority=80 override_dh_systemd_start: dh_systemd_start --name=networking --no-start diff --git a/ifupdown2/ifupdown/argv.py b/ifupdown2/ifupdown/argv.py index f8fbb885..ab4d38b9 100644 --- a/ifupdown2/ifupdown/argv.py +++ b/ifupdown2/ifupdown/argv.py @@ -7,6 +7,7 @@ # import sys +import os import argparse try: @@ -239,11 +240,18 @@ def update_ifreload_argparser(self, argparser): def update_common_argparser(self, argparser): ''' general parsing rules ''' + def file_or_fd(value): + try: + fp = os.fdopen(int(value)) + except ValueError: + fp = os.open(value, os.O_CREAT | os.O_TRUNC | os.O_WRONLY) + return fp argparser.add_argument('-V', '--version', action=VersionAction, nargs=0) argparser.add_argument( '-L', '--lock', default='/run/network/.lock', dest='lockfile', - help='use lock file instead of default /run/network/.lock' + help='use lock file instead of default /run/network/.lock (can be fd integer)', + type=file_or_fd ) argparser.add_argument( "--nldebug", diff --git a/ifupdown2/ifupdown/utils.py b/ifupdown2/ifupdown/utils.py index 05c7e48e..72591ca0 100644 --- a/ifupdown2/ifupdown/utils.py +++ b/ifupdown2/ifupdown/utils.py @@ -224,9 +224,8 @@ def importName(cls, modulename, name): @classmethod def lockFile(cls, lockfile): try: - fp = os.open(lockfile, os.O_CREAT | os.O_TRUNC | os.O_WRONLY) - fcntl.flock(fp, fcntl.LOCK_EX | fcntl.LOCK_NB) - fcntl.fcntl(fp, fcntl.F_SETFD, fcntl.FD_CLOEXEC) + fcntl.flock(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB) + fcntl.fcntl(lockfile, fcntl.F_SETFD, fcntl.FD_CLOEXEC) except IOError: return False return True diff --git a/ifupdown2/sbin/start-networking b/ifupdown2/sbin/start-networking index 8f790a09..82f0f0f5 100755 --- a/ifupdown2/sbin/start-networking +++ b/ifupdown2/sbin/start-networking @@ -78,25 +78,6 @@ check_network_swap() { done < /proc/swaps } -ifup_hotplug () { - if [ -d /sys/class/net ] - then - ifaces=$(for iface in $(ifquery --list --allow=hotplug 2>/dev/null) - do - link=${iface##:*} - link=${link##.*} - if [ -e "/sys/class/net/$link" ] - then - echo "$iface" - fi - done) - if [ -n "$ifaces" ] - then - ifup $ifaces "$@" --systemd || true - fi - fi -} - ifup_mgmt () { ifaces=$(ifquery --list --allow=mgmt 2>/dev/null) if [ -n "$ifaces" ]; then @@ -128,7 +109,6 @@ start) echo ${NAME}':' "Configuring network interfaces" ifup_mgmt ifup -a $EXTRA_ARGS $exclusions $perfoptions --systemd - ifup_hotplug $HOTPLUG_ARGS $EXTRA_ARGS $exclusions ;; stop) if [ "$SKIP_DOWN_AT_SYSRESET" = "yes" ]; then