diff options
4 files changed, 139 insertions, 53 deletions
diff --git a/contrib/package/freifunk-watchdog/Makefile b/contrib/package/freifunk-watchdog/Makefile index dcc3ac4b7..33ba33da3 100644 --- a/contrib/package/freifunk-watchdog/Makefile +++ b/contrib/package/freifunk-watchdog/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org> +# Copyright (C) 2009-2012 Jo-Philipp Wich <xm@subsignal.org> # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=freifunk-watchdog -PKG_RELEASE:=7 +PKG_RELEASE:=8 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) PKG_BUILD_DEPENDS := uci @@ -46,6 +46,8 @@ endef define Package/freifunk-watchdog/install $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_BIN) ./files/freifunk-watchdog.init $(1)/etc/init.d/freifunk-watchdog + $(INSTALL_DIR) $(1)/etc/config + $(INSTALL_CONF) ./files/freifunk-watchdog.config $(1)/etc/config/freifunk-watchdog $(INSTALL_DIR) $(1)/usr/sbin $(INSTALL_BIN) $(PKG_BUILD_DIR)/ffwatchd $(1)/usr/sbin/ endef diff --git a/contrib/package/freifunk-watchdog/files/freifunk-watchdog.config b/contrib/package/freifunk-watchdog/files/freifunk-watchdog.config new file mode 100644 index 000000000..b6e65433d --- /dev/null +++ b/contrib/package/freifunk-watchdog/files/freifunk-watchdog.config @@ -0,0 +1,7 @@ +config process + option process 'dropbear' + option initscript '/etc/init.d/dropbear' + +config process + option process 'crond' + option initscript '/etc/init.d/cron' diff --git a/contrib/package/freifunk-watchdog/src/watchdog.c b/contrib/package/freifunk-watchdog/src/watchdog.c index 2d6e4a6f7..ce66adadb 100644 --- a/contrib/package/freifunk-watchdog/src/watchdog.c +++ b/contrib/package/freifunk-watchdog/src/watchdog.c @@ -197,7 +197,7 @@ static int check_uci_update(const char *config, time_t *mtime) } /* Add tuple */ -static void load_wifi_uci_add_iface(const char *section, struct uci_itr_ctx *itr) +static void load_wifi_uci_add_iface(const char *section, struct uci_wifi_iface_itr_ctx *itr) { wifi_tuple_t *t; const char *ucitmp; @@ -253,12 +253,12 @@ static void load_wifi_uci_add_iface(const char *section, struct uci_itr_ctx *itr static wifi_tuple_t * load_wifi_uci(wifi_tuple_t *ifs, time_t *modtime) { struct uci_context *ctx; - struct uci_itr_ctx itr; + struct uci_wifi_iface_itr_ctx itr; wifi_tuple_t *cur, *next; if( check_uci_update("wireless", modtime) ) { - syslog(LOG_INFO, "Config changed, reloading"); + syslog(LOG_INFO, "Wireless config changed, reloading"); if( (ctx = ucix_init("wireless")) != NULL ) { @@ -284,6 +284,78 @@ static wifi_tuple_t * load_wifi_uci(wifi_tuple_t *ifs, time_t *modtime) return ifs; } +/* Add tuple */ +static void load_watchdog_uci_add_process(const char *section, struct uci_process_itr_ctx *itr) +{ + process_tuple_t *t; + const char *ucitmp; + int val = 0; + + if( (t = (process_tuple_t *)malloc(sizeof(process_tuple_t))) != NULL ) + { + t->restart = 0; + + ucitmp = ucix_get_option(itr->ctx, "freifunk-watchdog", section, "process"); + if(ucitmp) + { + strncpy(t->process, ucitmp, sizeof(t->process)); + val++; + } + + ucitmp = ucix_get_option(itr->ctx, "freifunk-watchdog", section, "initscript"); + if(ucitmp) + { + strncpy(t->initscript, ucitmp, sizeof(t->initscript)); + val++; + } + + if( val == 2 ) + { + syslog(LOG_INFO, "Monitoring %s: initscript=%s", + t->process, t->initscript); + + t->next = itr->list; + itr->list = t; + } + else + { + free(t); + } + } +} + +/* Load config */ +static process_tuple_t * load_watchdog_uci(process_tuple_t *procs) +{ + struct uci_context *ctx; + struct uci_process_itr_ctx itr; + process_tuple_t *cur, *next; + + syslog(LOG_INFO, "Loading watchdog config"); + + if( (ctx = ucix_init("freifunk-watchdog")) != NULL ) + { + if( procs != NULL ) + { + for(cur = procs; cur; cur = next) + { + next = cur->next; + free(cur); + } + } + + itr.list = NULL; + itr.ctx = ctx; + + ucix_for_each_section_type(ctx, "freifunk-watchdog", "process", + (void *)load_watchdog_uci_add_process, &itr); + + return itr.list; + } + + return procs; +} + /* Daemon implementation */ static int do_daemon(void) { @@ -296,13 +368,12 @@ static int do_daemon(void) char bssid[18]; struct sigaction sa; - wifi_tuple_t *ifs = NULL, *curif; - time_t modtime = 0; + wifi_tuple_t *ifs = NULL, *curr_if; + process_tuple_t *procs = NULL, *curr_proc; + time_t wireless_modtime = 0; int action_intv = 0; int restart_wifi = 0; - int restart_cron = 0; - int restart_sshd = 0; int loadavg_panic = 0; openlog(SYSLOG_IDENT, 0, LOG_DAEMON); @@ -340,6 +411,9 @@ static int do_daemon(void) sa.sa_flags = 0; sigaction(SIGCHLD, &sa, NULL); + /* Load watchdog configuration only once */ + procs = load_watchdog_uci(procs); + while( 1 ) { /* Check/increment action interval */ @@ -354,47 +428,52 @@ static int do_daemon(void) else loadavg_panic = 0; - /* Check crond */ - if( find_process("crond") < 0 ) - restart_cron++; - else - restart_cron = 0; - - /* Check SSHd */ - if( find_process("dropbear") < 0 ) - restart_sshd++; - else - restart_sshd = 0; - /* Check wireless interfaces */ - ifs = load_wifi_uci(ifs, &modtime); - for( curif = ifs; curif; curif = curif->next ) + ifs = load_wifi_uci(ifs, &wireless_modtime); + for( curr_if = ifs; curr_if; curr_if = curr_if->next ) { /* Get current channel and bssid */ - if( (iw_get_bssid(iwfd, curif->ifname, bssid) == 0) && - (iw_get_channel(iwfd, curif->ifname, &channel) == 0) ) + if( (iw_get_bssid(iwfd, curr_if->ifname, bssid) == 0) && + (iw_get_channel(iwfd, curr_if->ifname, &channel) == 0) ) { /* Check BSSID */ - if( strcasecmp(bssid, curif->bssid) != 0 ) + if( strcasecmp(bssid, curr_if->bssid) != 0 ) { syslog(LOG_WARNING, "BSSID mismatch on %s: current=%s wanted=%s", - curif->ifname, bssid, curif->bssid); + curr_if->ifname, bssid, curr_if->bssid); restart_wifi++; } /* Check channel */ - else if( channel != curif->channel ) + else if( channel != curr_if->channel ) { syslog(LOG_WARNING, "Channel mismatch on %s: current=%d wanted=%d", - curif->ifname, channel, curif->channel); + curr_if->ifname, channel, curr_if->channel); restart_wifi++; } } else { - syslog(LOG_WARNING, "Requested interface %s not present", curif->ifname); + syslog(LOG_WARNING, "Requested interface %s not present", curr_if->ifname); + } + } + + /* Check processes */ + for( curr_proc = procs; curr_proc; curr_proc = curr_proc->next ) + { + if( find_process(curr_proc->process) < 0 ) + curr_proc->restart++; + else + curr_proc->restart = 0; + + /* Process restart required? */ + if( curr_proc->restart >= HYSTERESIS ) + { + curr_proc->restart = 0; + syslog(LOG_WARNING, "The %s process died, restarting", curr_proc->process); + EXEC(PROC_ACTION); } } @@ -407,22 +486,6 @@ static int do_daemon(void) EXEC(WIFI_ACTION); } - /* Cron restart required? */ - if( restart_cron >= HYSTERESIS ) - { - restart_cron = 0; - syslog(LOG_WARNING, "The cron process died, restarting"); - EXEC(CRON_ACTION); - } - - /* SSHd restart required? */ - if( restart_sshd >= HYSTERESIS ) - { - restart_sshd = 0; - syslog(LOG_WARNING, "The ssh process died, restarting"); - EXEC(SSHD_ACTION); - } - /* Is there a load problem? */ if( loadavg_panic >= HYSTERESIS ) { diff --git a/contrib/package/freifunk-watchdog/src/watchdog.h b/contrib/package/freifunk-watchdog/src/watchdog.h index 71c10e9c1..34d616c3a 100644 --- a/contrib/package/freifunk-watchdog/src/watchdog.h +++ b/contrib/package/freifunk-watchdog/src/watchdog.h @@ -52,15 +52,12 @@ /* How to call myself in the logs */ #define SYSLOG_IDENT "Freifunk Watchdog" +/* Process error action */ +#define PROC_ACTION curr_proc->initscript, curr_proc->initscript, "restart" + /* Wifi error action */ #define WIFI_ACTION "/sbin/wifi", "/sbin/wifi" -/* Crond error action */ -#define CRON_ACTION "/etc/init.d/cron", "/etc/init.d/cron", "restart" - -/* SSHd error action */ -#define SSHD_ACTION "/etc/init.d/dropbear", "/etc/init.d/dropbear", "restart" - /* Watchdog device */ #define WATCH_DEVICE "/dev/watchdog" #define WATCH_SHUTDOWN 'V' @@ -85,7 +82,7 @@ struct wifi_tuple { }; /* structure to hold tuple-list and uci context during iteration */ -struct uci_itr_ctx { +struct uci_wifi_iface_itr_ctx { struct wifi_tuple *list; struct uci_context *ctx; }; @@ -93,6 +90,23 @@ struct uci_itr_ctx { typedef struct wifi_tuple wifi_tuple_t; +/* process name/exec tuples */ +struct process_tuple { + char process[PATH_MAX + 1]; + char initscript[PATH_MAX + 1]; + int restart; + struct process_tuple *next; +}; + +/* structure to hold tuple-list and uci context during iteration */ +struct uci_process_itr_ctx { + struct process_tuple *list; + struct uci_context *ctx; +}; + +typedef struct process_tuple process_tuple_t; + + /* ioctl() helper (stolen from iwlib) */ static inline int iw_ioctl(int skfd, /* Socket to the kernel */ |