2

On networking I often need to know when a connection is complete established with an ip address or if it gets down. In the past this was done with the classic daemon ifplugd. The Debian package for it uses old style ifupdown managed with /etc/network/interfaces. But since Raspbian Wheezy 2015-05-05 dhcpcd is used for networking instead of ifupdown.

How can I make ifplugd available again for Raspbian without using ifupdown?

Ingo
  • 40,606
  • 15
  • 76
  • 189
  • @Milliways I have corrected the version in the answer. Thanks. And yes you are right, `ifplugd` is still in the Buster repository. I haven't said that it isn't. Otherwise I wouldn't be able to download it. Have you realized my question? – Ingo Dec 21 '19 at 03:16

1 Answers1

4

ifplugd is running as daemon so we have to use a systemd service to manage it. I will only use the daemon program /usr/sbin/ifplugd without the management scripts from Debian.

Tested with
Raspberry Pi OS 2020-12-02 based on Buster on a Raspberry Pi 4B updated at 2020-05-12.
Raspbian Stretch Lite 2019-04-08 updated at 2019-04-16.
Updates done with sudo apt update && sudo apt full-upgrade && sudo reboot.

Install ifplugd program

First we download the ifplugd package but don't install it, only extract the daemon program:

rpi ~$ apt download ifplugd
rpi ~$ ar -p ifplugd_*_armhf.deb data.tar.xz | sudo tar -xJ -C / ./usr/sbin/ifplugd
rpi ~$ rm ifplugd_*_armhf.deb
rpi ~$ ifplugd --version   # at the time testing this
ifplugd 0.28 (SVN: 124)

Create new service for the ifplugd program

We will not run ifplugd as classic daemon. Instead we run it as service and do not have to "daemonize" it. Look at the man page (1) that we have to use option --no-daemon. Other options are used to disable functions that are managed by systemd now. Create the new service with:

rpi ~$ sudo -Es
rpi ~# systemctl --full --force edit ifplug@.service

In the empty editor insert these statements, save them and quit the editor:

[Unit]
Description=Interface plug monitor (interface-specific version)
Documentation=https://raspberrypi.stackexchange.com/a/96605/79866
After=sys-subsystem-net-devices-%i.device

[Service]
ExecStart=/usr/sbin/ifplugd --iface=%i --no-daemon --no-auto --no-syslog --no-beep --no-shutdown --run=/etc/ifplugs/ifplugs.action

[Install]
WantedBy=sys-subsystem-net-devices-%i.device

Create Action Script

As described in the man page (1) the service calls a script on every event up and down on an interface. Here I will use a template. Create this action script with your editor:

rpi ~# mkdir /etc/ifplugs
rpi ~# editor /etc/ifplugs/ifplugs.action

In the empty editor insert these statements, save them and quit the editor:

#!/bin/bash
# redirect all output into a logfile for debug
#exec 1>> /tmp/ifplugs-debug.log 2>&1

INTERFACE="$1"
EVENT="$2"
IPADDR=''

get_ipaddr () {
    if [ "$EVENT" = "down" ]; then
        IPADDR=$(/sbin/ip -4 -br addr show $INTERFACE | /bin/grep -Po "\d+\.\d+\.\d+\.\d+")
        return 0
    fi
    # check 10 times with 1 sec delay if ip address is available
    for ((i=10; i>0; i--)); do
        IPADDR=$(/sbin/ip -4 -br addr show $INTERFACE | /bin/grep -Po "\d+\.\d+\.\d+\.\d+")
        [ $? -eq 0 ] && break
        /bin/sleep 1
    done
}

case "$INTERFACE" in
eth0)
    case "$EVENT" in
    up)
        # do stuff on connect with interface
        get_ipaddr
        echo "$INTERFACE" up with ip address \""$IPADDR"\"
        ;;
    down)
        # do stuff on disconnect with interface
        get_ipaddr
        echo "$INTERFACE" down with ip address \""$IPADDR"\"
        ;;
    *)
        >&2 echo empty or undefined event for "$INTERFACE": \""$EVENT"\"
        exit 1
        ;;
    esac
    ;;

wlan0)
    case "$EVENT" in
    up)
        # do stuff on connect with interface
        get_ipaddr
        echo "$INTERFACE" up with ip address \""$IPADDR"\"
        ;;
    down)
        # do stuff on disconnect with interface
        get_ipaddr
        echo "$INTERFACE" down with ip address \""$IPADDR"\"
        ;;
    *)
        >&2 echo empty or undefined event for "$INTERFACE": \""$EVENT"\"
        exit 1
        ;;
    esac
    ;;

*)
    >&2 echo empty or unknown interface: \""$INTERFACE"\"
    exit 1
    ;;
esac

Make it executable:

rpi ~# chmod +x /etc/ifplugs/ifplugs.action

/usr/sbin/ifplugd needs an own instance for every interface. So we start them with the interface-specific version:

rpi ~# systemctl start ifplug@eth0.service
rpi ~# systemctl start ifplug@wlan0.service
rpi ~# exit
rpi ~$

If you want to start the ifplug.service on boot up, just enable it:

rpi ~$ sudo systemctl enable ifplug@eth0.service
rpi ~$ sudo systemctl enable ifplug@wlan0.service

Now the actions up and down for each monitored interface are logged to the journal. Follow it with

rpi ~$ journalctl --follow

# You may filter it with:
rpi ~$ journalctl --follow | grep ifplugd

You are free to modify /etc/ifplugs/ifplugs.action or create your own. If you want to monitor other interfaces then just use its interface names for the interface-specific services and in the action script instead of eth0 and wlan0 in this example.

References:
(1): man page ifplugd

Ingo
  • 40,606
  • 15
  • 76
  • 189
  • I just tried this protocol, and while everything looks like it deploys, I'm getting log messages about missing shared library libdaemon on service start. This is on Buster 2020-12-02, with latest updates applied. What's best? Install from sources? Or is there a better way? – Stuart Watt Jan 06 '21 at 21:49
  • @StuartWatt Is`libdaemon` the exact name of the missing library? Do you see the log message in the journal with `journalctl -b`? – Ingo Jan 07 '21 at 20:28
  • Thanks for the crystal-clear instructions. @Ingo This works really well and helps to plaster over what was previously what /etc/network/interfaces. Learnt something new with the %i arguments in the unit files too. I would buy you a beer if you were nearby! – lackdaz Jul 22 '21 at 06:25
  • 1
    @lackdaz drinking a beer would be a good idea but its a bit complicated with corona restrictions ;-) – Ingo Aug 07 '21 at 18:34