--- ifstated.c.orig	2011-07-04 12:34:14.000000000 +0800
+++ ifstated.c	2014-12-05 15:10:34.000000000 +0800
@@ -26,9 +26,11 @@
 #include <sys/time.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
+#include <sys/sysctl.h>
 #include <sys/wait.h>
 
 #include <net/if.h>
+#include <net/if_mib.h>
 #include <net/route.h>
 #include <netinet/in.h>
 
@@ -47,7 +49,8 @@
 
 int	 opts = 0;
 int	 opt_inhibit = 0;
-char	*configfile = "/etc/ifstated.conf";
+char	*configfile = "/usr/local/etc/ifstated.conf";
+char	*pidfile = NULL;
 struct event	rt_msg_ev, sighup_ev, startup_ev, sigchld_ev;
 
 void	startup_handler(int, short, void *);
@@ -61,6 +64,8 @@
 void	external_evtimer_setup(struct ifsd_state *, int);
 void	scan_ifstate(int, int, int);
 int	scan_ifstate_single(int, int, struct ifsd_state *);
+int	get_ifcount(void);
+int	get_ifmib_general(int row, struct ifmibdata *ifmd);
 void	fetch_state(void);
 void	usage(void);
 void	adjust_expressions(struct ifsd_expression_list *, int);
@@ -70,13 +75,14 @@
 void	do_action(struct ifsd_action *);
 void	remove_action(struct ifsd_action *, struct ifsd_state *);
 void	remove_expression(struct ifsd_expression *, struct ifsd_state *);
+void	remove_pidfile(int);
 
 void
 usage(void)
 {
 	extern char *__progname;
 
-	fprintf(stderr, "usage: %s [-dhinv] [-D macro=value] [-f file]\n",
+	fprintf(stderr, "usage: %s [-dhinv] [-D macro=value] [-f file] [-p pidfile]\n",
 	    __progname);
 	exit(1);
 }
@@ -90,7 +96,7 @@
 
 	log_init(1);
 
-	while ((ch = getopt(argc, argv, "dD:f:hniv")) != -1) {
+	while ((ch = getopt(argc, argv, "dD:f:p:hniv")) != -1) {
 		switch (ch) {
 		case 'd':
 			debug = 1;
@@ -112,6 +118,9 @@
 		case 'i':
 			opt_inhibit = 1;
 			break;
+		case 'p':
+			pidfile = optarg;
+			break;
 		case 'v':
 			if (opts & IFSD_OPT_VERBOSE)
 				opts |= IFSD_OPT_VERBOSE2;
@@ -156,7 +165,6 @@
 startup_handler(int fd, short event, void *arg)
 {
 	int rt_fd;
-	unsigned int rtfilter;
 
 	if ((rt_fd = socket(PF_ROUTE, SOCK_RAW, 0)) < 0)
 		err(1, "no routing socket");
@@ -166,11 +174,24 @@
 		exit(1);
 	}
 
-	rtfilter = ROUTE_FILTER(RTM_IFINFO);
-	if (setsockopt(rt_fd, PF_ROUTE, ROUTE_MSGFILTER,
-	    &rtfilter, sizeof(rtfilter)) == -1)         /* not fatal */
-		log_warn("startup_handler: setsockopt");
-	
+	if (pidfile != NULL) {
+		FILE* file = fopen(pidfile, "w");
+
+		if (file == NULL) {
+			log_warnx("unable to open pidfile");
+		}
+		else {
+			fprintf(file, "%ld\n", (long)getpid());
+			fclose(file);
+			log_debug("wrote pidfile %s", pidfile);
+
+			signal(SIGINT, remove_pidfile);
+			signal(SIGQUIT, remove_pidfile);
+			signal(SIGABRT, remove_pidfile);
+			signal(SIGTERM, remove_pidfile);
+		}
+	}
+
 	event_set(&rt_msg_ev, rt_fd, EV_READ|EV_PERSIST, rt_msg_handler, NULL);
 	event_add(&rt_msg_ev, NULL);
 
@@ -396,13 +417,15 @@
 					waitpid(external->pid, &s, 0);
 					external->pid = 0;
 				}
-				evtimer_del(&external->ev);
+				if (event_initialized(&external->ev))
+					evtimer_del(&external->ev);
 			}
 			break;
 		}
 	}
 }
 
+#define LINK_STATE_IS_UP(_s)		((_s) >= LINK_STATE_UP)
 #define	LINK_STATE_IS_DOWN(_s)		(!LINK_STATE_IS_UP((_s)))
 
 int
@@ -534,7 +557,8 @@
 	if (conf->nextstate != NULL && conf->curstate != conf->nextstate) {
 		log_info("changing state to %s", conf->nextstate->name);
 		if (conf->curstate != NULL) {
-			evtimer_del(&conf->curstate->ev);
+			if (event_initialized (&conf->curstate->ev))
+				evtimer_del(&conf->curstate->ev);
 			external_evtimer_setup(conf->curstate,
 			    IFSD_EVTIMER_DEL);
 		}
@@ -580,6 +604,44 @@
 	}
 }
 
+int
+get_ifcount(void)
+{
+  int name[5], count;
+  size_t len;
+
+  name[0] = CTL_NET;
+  name[1] = PF_LINK;
+  name[2] = NETLINK_GENERIC;
+  name[3] = IFMIB_SYSTEM;
+  name[4] = IFMIB_IFCOUNT;
+
+  len = sizeof(int);
+
+  if (sysctl(name, 5, &count, &len, NULL, 0) != -1)
+    return(count);
+  else
+    return(-1);
+}
+
+int
+get_ifmib_general(int row, struct ifmibdata *ifmd)
+{
+  int name[6];
+  size_t len;
+
+  name[0] = CTL_NET;
+  name[1] = PF_LINK;
+  name[2] = NETLINK_GENERIC;
+  name[3] = IFMIB_IFDATA;
+  name[4] = row;
+  name[5] = IFDATA_GENERAL;
+
+  len = sizeof(*ifmd);
+
+  return sysctl(name, 6, ifmd, &len, (void *)0, 0);
+}
+
 /*
  * Fetch the current link states.
  */
@@ -589,26 +651,31 @@
 	struct ifaddrs *ifap, *ifa;
 	char *oname = NULL;
 	int sock = socket(AF_INET, SOCK_DGRAM, 0);
+        int ifcount = get_ifcount();
+        int i;
 
-	if (getifaddrs(&ifap) != 0)
+	if (getifaddrs(&ifap) != 0 || ifcount == -1)
 		err(1, "getifaddrs");
 
 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
-		struct ifreq ifr;
-		struct if_data  ifrdat;
+		struct ifmibdata ifmd;
+		struct if_data  ifdata;
 
 		if (oname && !strcmp(oname, ifa->ifa_name))
 			continue;
 		oname = ifa->ifa_name;
 
-		strlcpy(ifr.ifr_name, ifa->ifa_name, sizeof(ifr.ifr_name));
-		ifr.ifr_data = (caddr_t)&ifrdat;
+		for (i = 1; i <= ifcount; i++)
+		  {
+		    get_ifmib_general(i, &ifmd);
+		    if (! strcmp(ifmd.ifmd_name, oname))
+		      break;
+		  }
 
-		if (ioctl(sock, SIOCGIFDATA, (caddr_t)&ifr) == -1)
-			continue;
+		ifdata = ifmd.ifmd_data;
 
 		scan_ifstate(if_nametoindex(ifa->ifa_name),
-		    ifrdat.ifi_link_state, 0);
+		    ifdata.ifi_link_state, 0);
 	}
 	freeifaddrs(ifap);
 	close(sock);
@@ -703,3 +770,13 @@
 	}
 	free(expression);
 }
+
+void
+remove_pidfile(int code)
+{
+	if ((pidfile != NULL) && unlink(pidfile)) {
+		log_warnx("could not remove pidfile");
+	}
+
+	exit(code);
+}
