Using ifstated(8) for OpenBSD Laptop Network Management

⊕ 2020-05-20

I’ve been using OpenBSD as a daily driver for almost 2 years now and one of the few annoyances I had with my setup was roaming between my wireless access points and my Ethernet at my work space. To make things somewhat easier I had been using a set of sh scripts with doas(1) to quickly swap between the two workflows. This worked fine but was a little clunky and with all the fun COVID-19 fun and being stuck at home I had been wanting to move around more and have a bit more of a seamless experience.

After chatting with some friends over at 2f30 it was suggested that ifstated(8) might be the solution. I had never bumped into this tool before so I figured I’d jump into the man pages, and for the first time on OpenBSD I found myself with the right tool but not enough documentation on actually setting up a realistic laptop configuration. ifstated(8) simply manages a state machine and runs commands based on the state, which is ideal for a poor mans network management tool.

I needed the following configuration:

So I dove into the source and did some ifstated -d debugging. After a bit of testing the following ifstated.conf(5) solves these configuration requirements (iwm0 is my wireless interface and em0 is my Ethernet interface):

/etc/ifstated.conf

init-state auto

net_check = '( "ifconfig em0 | grep -q \"status: no carrier\"" every 10)'

state auto {
        if $net_check {
                set-state if_offline
        }
        if ! $net_check {
                set-state if_online
        }
}

state if_offline {
        init {
                run "( ifconfig iwm0 | grep -q \"inet \" ) || ( sh /etc/netstart iwm0 && ifconfig iwm0 up && dhclient iwm0 )"
                run "( ifconfig em0 -inet && ifconfig em0 down )"
        }
        if ! $net_check {
                set-state if_online
        }
}

state if_online {
        init {
                run "ifconfig iwm0 -nwid && ifconfig iwm0 -inet && dhclient -r iwm0 && ifconfig iwm0 down"
                run "( ifconfig em0 | grep -q \"inet \") || dhclient em0"
        }
        if $net_check {
                set-state if_offline
        }
}

Then you can test the configuration with a ifstated -n:

# ifstated -n
configuration OK

Finally test the configuration by firing it up in foreground mode and do some periodic plugging and unplugging to watch what the state checks look like:

# ifstated -d
initial state: auto
changing state to auto
changing state to if_offline
started
changing state to if_online
em0: no link....
em0: 10.0.1.7 lease accepted from 10.0.0.1 (00:31:33:37:fa:34)
changing state to if_offline
iwm0: 10.0.0.6 lease accepted from 10.0.0.1 (00:31:33:37:fa:34)
changing state to if_online
em0: no link....
em0: 10.0.1.7 lease accepted from 10.0.0.1 (00:31:33:37:fa:34)

Then set the host to enable and start ifstated(8) and everything should be configured:

rcctl enable ifstated
rcctl start ifstated