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 2f301 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

 1init-state auto
 2
 3net_check = '( "ifconfig em0 | grep -q \"status: no carrier\"" every 10)'
 4
 5state auto {
 6        if $net_check {
 7                set-state if_offline
 8        }
 9        if ! $net_check {
10                set-state if_online
11        }
12}
13
14state if_offline {
15        init {
16                run "( ifconfig iwm0 | grep -q \"inet \" ) || ( sh /etc/netstart iwm0 && ifconfig iwm0 up && dhclient iwm0 )"
17                run "( ifconfig em0 -inet && ifconfig em0 down )"
18        }
19        if ! $net_check {
20                set-state if_online
21        }
22}
23
24state if_online {
25        init {
26                run "ifconfig iwm0 -nwid && ifconfig iwm0 -inet && dhclient -r iwm0 && ifconfig iwm0 down"
27                run "( ifconfig em0 | grep -q \"inet \") || dhclient em0"
28        }
29        if $net_check {
30                set-state if_offline
31        }
32}

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

1# ifstated -n
2configuration 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:

 1# ifstated -d
 2initial state: auto
 3changing state to auto
 4changing state to if_offline
 5started
 6changing state to if_online
 7em0: no link....
 8em0: 10.0.1.7 lease accepted from 10.0.0.1 (00:31:33:37:fa:34)
 9changing state to if_offline
10iwm0: 10.0.0.6 lease accepted from 10.0.0.1 (00:31:33:37:fa:34)
11changing state to if_online
12em0: no link....
13em0: 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:

1rcctl enable ifstated
2rcctl start ifstated

  1. 2f30 ↩︎