Improve error checking during processing of routing messages. Handling of
RTM_DESYNC encouraged by deraadt. Regression tests pass.
I have another diff ready to go that handles interface depature, but I thought
it best to separate them.
Ok?
Index: ifstated.c
===================================================================
RCS file: /cvs/src/usr.sbin/ifstated/ifstated.c,v
retrieving revision 1.56
diff -u -p -r1.56 ifstated.c
--- ifstated.c 24 Jul 2017 12:33:59 -0000 1.56
+++ ifstated.c 6 Aug 2017 03:49:54 -0000
@@ -38,6 +38,7 @@
#include <stdint.h>
#include <syslog.h>
#include <err.h>
+#include <errno.h>
#include <event.h>
#include <unistd.h>
#include <ifaddrs.h>
@@ -63,7 +64,7 @@ void check_external_status(struct ifsd_
void external_evtimer_setup(struct ifsd_state *, int);
void scan_ifstate(int, int, int);
int scan_ifstate_single(int, int, struct ifsd_state *);
-void fetch_ifstate(void);
+void fetch_ifstate(int);
__dead void usage(void);
void adjust_expressions(struct ifsd_expression_list *, int);
void adjust_external_expressions(struct ifsd_state *);
@@ -210,7 +211,7 @@ load_config(void)
clear_config(conf);
conf = newconf;
conf->initstate.entered = time(NULL);
- fetch_ifstate();
+ fetch_ifstate(0);
external_evtimer_setup(&conf->initstate, IFSD_EVTIMER_ADD);
adjust_external_expressions(&conf->initstate);
eval_state(&conf->initstate);
@@ -235,20 +236,30 @@ rt_msg_handler(int fd, short event, void
struct if_msghdr ifm;
ssize_t len;
- len = read(fd, msg, sizeof(msg));
+ if ((len = read(fd, msg, sizeof(msg))) == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ return;
+ fatal("%s: routing socket read error", __func__);
+ }
- /* XXX ignore errors? */
- if (len < sizeof(struct rt_msghdr))
- return;
+ if (len == 0)
+ fatal("%s: routing socket closed", __func__);
if (rtm->rtm_version != RTM_VERSION)
return;
- if (rtm->rtm_type != RTM_IFINFO)
- return;
-
- memcpy(&ifm, rtm, sizeof(ifm));
- scan_ifstate(ifm.ifm_index, ifm.ifm_data.ifi_link_state, 1);
+ switch (rtm->rtm_type) {
+ case RTM_IFINFO:
+ memcpy(&ifm, rtm, sizeof(ifm));
+ scan_ifstate(ifm.ifm_index, ifm.ifm_data.ifi_link_state, 1);
+ break;
+ case RTM_DESYNC:
+ fetch_ifstate(1);
+ break;
+ default:
+ break;
+ }
+ return;
}
void
@@ -599,7 +610,7 @@ do_action(struct ifsd_action *action)
* Fetch the current link states.
*/
void
-fetch_ifstate(void)
+fetch_ifstate(int do_eval)
{
struct ifaddrs *ifap, *ifa;
@@ -610,7 +621,7 @@ fetch_ifstate(void)
if (ifa->ifa_addr->sa_family == AF_LINK) {
struct if_data *ifdata = ifa->ifa_data;
scan_ifstate(if_nametoindex(ifa->ifa_name),
- ifdata->ifi_link_state, 0);
+ ifdata->ifi_link_state, do_eval);
}
}