c048e9f0a0
up; libevent2 complains about this.
232 lines
5.3 KiB
C
232 lines
5.3 KiB
C
--- 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);
|
|
+}
|