Autoswitching network interfaces

Since I’m a lazy git, I want my laptop to automatically switch back & forth between my wired and wireless interfaces. Seems that stuff like Network Manager can do that for you, but it’s not really my thing. I don’t like stuff where you need a GUI to configure it, a duplicaton of network configuration, and it also tends to hang my machine. No idea why, though.

After an afternoon of fiddling around with several things, I came up with the recipe:
1 portion ifplugd, a good mix of ifupdown configuration with guessnet mappings, and some home-grown scripts. Mix well, and let simmer over a hot stove for half an hour. ;)

The details (tailored to Debian Sid):

  1. Install ifplugd and guessnet: apt-get install ifplugd guessnet
  2. Configure the interface you want ifplugd to monitor. For me, this is eth0 (wired ethernet). You can do this by editing /etc/default/ifplugd and adding eth0 in the INTERFACES field.
    Restart ifplugd (/etc/init.d/ifplugd restart)
  3. Edit your /etc/network/interfaces file the way you like it. I’m using multiple wireless entries with guessnet:
    mapping ath0
            script guessnet-ifupdown
            map verbose: false
            map debug: false
            map autofilter: true
    
    iface ath0-work inet dhcp
            test wireless essid WORK
            wpa-ssid WORK
            wpa-key-mgmt WPA-PSK
            wpa-proto WPA
            wpa-psk "***"
            wpa-driver wext
    
    iface ath0-home inet dhcp
            test wireless essid HOME
            wpa-ssid HOME
            wpa-key-mgmt WPA-PSK
            wpa-proto WPA
            wpa-psk "***"
            wpa-driver wext
    

    For syntax info, see man guessnet

  4. Replace the script in /etc/ifplugd/action.d with something more usable. The installed script only calls ifup or ifdown depending on what’s happening. What we want is to ifdown the interface, and ifup the other.

    Something like this:

    #!/bin/sh
    set -e
    
    WIRED_INTERFACE="eth0"
    WIFI_INTERFACE="ath0"
    WIFI_MODULE="ath_pci"
    IFUPDOWN_STATE="/etc/network/run/ifstate"
    
    if [ $# -ne 2 ]; then
            echo "Incorrect usage!"
            echo "$0:  "
            exit 1
    fi
    
    case "$2" in
    up)
            if [ "$1" = $WIRED_INTERFACE ]; then
                    # Wired interface is going up, bring wireless down
                    # if it is active.
                    WIFI_MODULE_LOADED=$(lsmod | grep ^$WIFI_MODULE | wc -l)
                    if [ $WIFI_MODULE_LOADED -eq 1 ]; then
                            /sbin/ifdown $WIFI_INTERFACE
                            /sbin/rmmod $WIFI_MODULE
                    fi
                    /sbin/ifup $WIRED_INTERFACE
            else
                    /sbin/ifup $1
            fi
            ;;
    down)
            if [ "$1" = $WIRED_INTERFACE ]; then
                    # Wired interface is going down, bring up the
                    # wireless one.
                    /sbin/ifdown $WIRED_INTERFACE
    
                    /sbin/modprobe $WIFI_MODULE
                    /sbin/ifconfig $WIFI_INTERFACE up
                    sleep 5
                    /sbin/ifup $WIFI_INTERFACE
    
                    WIFI_CONFIGURED=$(grep ^$WIFI_INTERFACE $IFUPDOWN_STATE | wc -l)
                    if [ $WIFI_CONFIGURED -eq 0 ]; then
                            # Interface was not configured, bring it back down
                            # to save power
                            /sbin/rmmod $WIFI_MODULE
                    fi
            else
                    /sbin/ifdown $1
            fi
            ;;
    esac
    

Now, every time ifplugd configures up eth0, ath0 is automatically deconfigured, and vice versa.
The actual configuration of the interfaces is still in /etc/network/interfaces, so you can still handle it by hand if you want to.

As always, it works fine for me, but YMMV, and TIMTOWTDI!