The following diff adds support for detecting the state change of a departed
interface. ifstated is not a very verbose daemon, so this diff quietly does
the right thing (i.e. there is no exttra warning about a departing interface).
The re-arrival of a departed interface involves re-indexing the interface and
possibly other complexities that require more consideration, but for now at
least this obvious condition is handled in what I believe is a more
appropriate manner.
Updated regression tests pass, and the corresponding regression diff is also
attached.
Ok?
Index: regress/usr.sbin/ifstated/ifstated
===================================================================
RCS file: /cvs/src/regress/usr.sbin/ifstated/ifstated,v
retrieving revision 1.3
diff -u -p -r1.3 ifstated
--- regress/usr.sbin/ifstated/ifstated 31 Jul 2017 18:41:21 -0000 1.3
+++ regress/usr.sbin/ifstated/ifstated 6 Aug 2017 23:29:11 -0000
@@ -124,6 +124,7 @@ changing state to primary
changing state to demoted
changing state to primary
changing state to primary
+changing state to demoted
EOF
(cd working && nohup ifstated -dvf ./ifstated.conf > ifstated.log 2>&1) &
@@ -148,6 +149,8 @@ ifconfig carp${VHIDB} inet ${PREFIX}.${V
${PREFIX}.255 vhid ${VHIDB} carpdev ${NIC}
sleep ${SLEEP}
kill -HUP $(pgrep ifstated) >/dev/null 2>&1
+sleep ${SLEEP}
+ifconfig carp${VHIDA} destroy
sleep ${SLEEP}
grep ^changing working/ifstated.log > working/output.new
Index: usr.sbin/ifstated/ifstated.c
===================================================================
RCS file: /cvs/src/usr.sbin/ifstated/ifstated.c,v
retrieving revision 1.57
diff -u -p -r1.57 ifstated.c
--- usr.sbin/ifstated/ifstated.c 6 Aug 2017 19:27:54 -0000 1.57
+++ usr.sbin/ifstated/ifstated.c 6 Aug 2017 23:29:12 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: ifstated.c,v 1.57 2017/08/06 19:27:54 rob Exp $ */
+/* $OpenBSD: ifstated.c,v 1.56 2017/07/24 12:33:59 jca Exp $ */
/*
* Copyright (c) 2004 Marco Pfatschbacher <[email protected]>
@@ -61,6 +61,7 @@ void rt_msg_handler(int, short, void *)
void external_handler(int, short, void *);
void external_exec(struct ifsd_external *, int);
void check_external_status(struct ifsd_state *);
+void check_for_ifdeparture(void);
void external_evtimer_setup(struct ifsd_state *, int);
void scan_ifstate(int, int, int);
int scan_ifstate_single(int, int, struct ifsd_state *);
@@ -150,7 +151,7 @@ main(int argc, char *argv[])
if ((rt_fd = socket(PF_ROUTE, SOCK_RAW, 0)) < 0)
err(1, "no routing socket");
- rtfilter = ROUTE_FILTER(RTM_IFINFO);
+ rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_IFANNOUNCE);
if (setsockopt(rt_fd, PF_ROUTE, ROUTE_MSGFILTER,
&rtfilter, sizeof(rtfilter)) == -1) /* not fatal */
log_warn("%s: setsockopt msgfilter", __func__);
@@ -234,6 +235,7 @@ rt_msg_handler(int fd, short event, void
char msg[2048];
struct rt_msghdr *rtm = (struct rt_msghdr *)&msg;
struct if_msghdr ifm;
+ struct if_announcemsghdr ifan;
ssize_t len;
if ((len = read(fd, msg, sizeof(msg))) == -1) {
@@ -253,8 +255,19 @@ rt_msg_handler(int fd, short event, void
memcpy(&ifm, rtm, sizeof(ifm));
scan_ifstate(ifm.ifm_index, ifm.ifm_data.ifi_link_state, 1);
break;
+ case RTM_IFANNOUNCE:
+ memcpy(&ifan, rtm, sizeof(ifan));
+ switch (ifan.ifan_what) {
+ case IFAN_DEPARTURE:
+ scan_ifstate(ifan.ifan_index, LINK_STATE_DOWN, 1);
+ break;
+ default:
+ break;
+ }
+ break;
case RTM_DESYNC:
fetch_ifstate(1);
+ check_for_ifdeparture();
break;
default:
break;
@@ -626,6 +639,26 @@ fetch_ifstate(int do_eval)
}
freeifaddrs(ifap);
+}
+
+void
+check_for_ifdeparture(void)
+{
+ struct ifsd_state *state;
+ struct ifsd_ifstate *ifstate;
+ char ifnamebuf[IF_NAMESIZE];
+ char *if_name;
+
+ TAILQ_FOREACH(state, &conf->states, entries) {
+ TAILQ_FOREACH(ifstate, &state->interface_states, entries) {
+ if_name = if_indextoname(ifstate->ifindex, ifnamebuf);
+ if (if_name == NULL) {
+ scan_ifstate(ifstate->ifindex,
+ LINK_STATE_DOWN, 1);
+ }
+ }
+ }
+ return;
}
void