The ifstated daemon on OpenBSD runs commands in response to network state changes, which it determines by monitoring interface link state or running external tests. For example, it can be used with carp(4) to change running services or to ensure that carp(4) interfaces stay in sync, or with pf(4) to test server or link availability and modify translation or routing rules.
Think of ifstated as a daemon which looks for a pre-defined string in ifconfig or any other logic and executes a command depending on a set of if-then conditions. This makes the ifstated daemon quite powerful as you can design any logic you want into the config file. Lets take a look at some examples.
To use ifstated to monitor your interfaces you need to edit the file "/etc/ifstated.conf". You can use one of our examples below or make one your self. Once the file is in place execute the binary, /sbin/ifstated. To make ifstated start on reboot edit your /etc/rc.conf.local and add the line, ifstated_flags="" including the empty double quotes. Thats about it. Now, lets take a look at some fully working examples.
This configuration file can be used on your CARP enabled interface to see which machine is the master. It will watch the Carp1 device and see what state it is in. If the state changes, for example if the master becomes the slave, an email will be sent to root@localhost with the result. This is excellent for monitoring the machines and for an audit trail. Put this script on all CARP enabled machines.
# ## moneyslow.com -- /etc/ifstated.conf # init-state auto fw_carp_up = "carp1.link.up" fw_carp_init = "carp1.link.unknown" state auto { if ($fw_carp_init) run "sleep 10" if ($fw_carp_up) set-state fw_master if (! $fw_carp_up) set-state fw_slave } state fw_master { init { run "echo MASTER firewall is now `hostname` | mail -s 'Firewall State Change: MASTER' root@localhost" } if ($fw_carp_init) run "sleep 2" if (! $fw_carp_up) set-state fw_slave } state fw_slave { init { run "echo SLAVE firewall is now `hostname` | mail -s 'Firewall State Change: SLAVE' root@localhost" } if ($fw_carp_init) run "sleep 2" if ($fw_carp_up) set-state fw_master }
This ifstated.conf will check to see if the interface of your network card is up. This is accomplished by checking if the egress network card is plugged into a powered switch, router or cable modem by looking for the string "status: active" in the ifconfig results. Next, our script in the "net_check" variable will make sure the external interface has a non-private IPv4 ip address and, if it does, will ping google three(3) times with a two(2) second delay between icmp packets. If any of these tests fail the external NIC will be considered suspect and tagged as offline. The lines in "net_check" are run every 120 seconds as specified in the "every 120" directive no matter if the interface is up or not.
If the interface is down ifstated will execute the 'run' commands in the init section of if_offline. This tries to get the interface up (ifconfig em0 up) as well as stop and restart dhclient in case the daemon is stuck in a loop. Hopefully this will get us back online.
When the external interface comes back up an email will be sent to root@localhost. Emails are only sent in a state change from extif_online to extif_offline and vise versa.
This script was originally constructed to compensate for the OpenBSD / FreeBSD version of dhclient connecting to Comcast's flaky and overloaded DHCP servers. Sometimes we would see errors on the local system like, "Corrupt lease file - possible data loss!" in the dhclient leases file. Other times Comcast would randomly serve the private ip, "192.168.100.10". This ip is in Comcast's "walled garden"; an internal cable modem network use for diagnostics and for unregistered cable modems. To get back online we need to force dhclient to get an ip which is public and valid.
# ## moneyslow.com -- /etc/ifstated.conf # # init-state auto net_check = '( "ifconfig egress | grep \"status: active\" && \ ifconfig egress | grep \"inet *.*.*.* netmask\" | grep -v \"inet 192\" && \ ping -q -c 3 -i 2 -w 1 www.google.com > /dev/null" every 120)' state auto { if $net_check { set-state if_online } if ! $net_check { set-state if_offline } } state if_online { init { run "ifconfig egress | mail -s 'External Interface ON-line' root@localhost" } if ! $net_check { set-state if_offline } } state if_offline { init { run "ifconfig egress | mail -s 'External Interface OFF-line' root@localhost" run "pkill dhclient;sleep 2;ifconfig em0 up && sleep 2 && \ ifconfig egress | grep \"status: active\" && /sbin/dhclient em0" } if $net_check { set-state if_online } }
Run the command, "ifstated -dvv". In this mode the daemon will printout everything the daemon is doing while running in the foreground. This is a good way to see exactly what ifstated will do when running. You may want to set the "every 120" timing lower to something like 30 seconds to speed up testing.
Do you have any other "how to's" ? Indeed. Check on the moneyslow.com Home Page for more links and examples.