freebsd-ports/net/ifstated/files/patch-ifstated.c
2014-12-24 05:59:32 +00:00

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);
+}