NetworkManager: automatically switch between Ethernet and Wi-Fi

When I’m at home, I mostly use my laptop at my desk, connected to a dock, which has Ethernet to it.

But when I move to my taxi, I don’t have Ethernet there, so I need Wi-Fi.

So I would like to have Wi-Fi turn off when I connect to Ethernet, and Wi-Fi enabled when I disconnect from Ethernet.

I couldn’t find a GUI option in NetworkManager or Advanced Network Settings for this, so turned to nmcli instead.

Dispatcher scripts

In the NetworkManager man page, there is a tantalising suggestion:

Note that NetworkManager can also execute scripts, called “dispatcher scripts”, in response to network events.

There’s a whole page about dispatcher scripts.

There are some key things to note:

NetworkManager will execute scripts in the /etc/NetworkManager/dispatcher.d directory or subdirectories in alphabetical order in response to network events.

So, alphabetical order.

And put the script in /etc/NetworkManager/dispatcher.d

Each script should be a regular executable file owned by root.

Should? Or must. Let’s assume “must”.

Furthermore, it must not be writable by group or other, and not setuid.

Okay!

The man page explains what actions are available, and I should dig back through it some point.

The nmcli script

As luck would have it, there are some nmcli examples, and one of them is:

nmcli usage in a NetworkManager dispatcher script to make Ethernet and Wi-Fi mutually exclusive

#!/bin/bash
export LC_ALL=C

enable_disable_wifi ()
{
    result=$(nmcli dev | grep "ethernet" | grep -w "connected")
    if [ -n "$result" ]; then
        nmcli radio wifi off
    else
        nmcli radio wifi on
    fi
}

if [ "$2" = "up" ]; then
    enable_disable_wifi
fi

if [ "$2" = "down" ]; then
    enable_disable_wifi
fi

It also says:

Name this script e.g. 70-wifi-wired-exclusive.sh and put it into /etc/NetworkManager/dispatcher.d/

So I tried that.

Making it do what I want

This script doesn’t do exactly what I want: I want Wi-Fi to be enabled when I disconnect from Ethernet (an action), not when I am disconnected from Ethernet (a state). In other words, I want to be able to turn off Wi-Fi, and this script does not do that, as nmcli shows state rather than action.

But I can adapt the script to do that. I have:

#!/bin/bash
export LC_ALL=C

# Add the name of your specific ethernet device here, as shown in `nmcli dev`
ETHERNET="enx806d9728435c"

disable_wifi_if_ethernet_is_up ()
{
    result=$(nmcli dev | grep "ethernet" | grep -w "connected")
    if [ -n "$result" ]; then
        nmcli radio wifi off
    fi
}

enable_wifi ()
{
    nmcli radio wifi on

}

if [ "$1" = "$ETHERNET" ] && [ "$2" = "up" ]; then
    disable_wifi_if_ethernet_is_up
fi

if [ "$1" = "$ETHERNET" ] && [ "$2" = "down" ]; then
    enable_wifi
fi

Pop that into /etc/NetworkManager/dispatcher.d/70-wifi-wired-exclusive.sh, then:

sudo chown root:root /etc/NetworkManager/dispatcher.d/70-wifi-wired-exclusive.sh

sudo chmod 744 /etc/NetworkManager/dispatcher.d/70-wifi-wired-exclusive.sh

sudo systemctl restart NetworkManager

Additional bits

I need to test what happens if the computer is suspended when I disconnect it from the dock. This might not work in that situation.