contrib/package: make freifunk-watchdog more generic
authorJo-Philipp Wich <jow@openwrt.org>
Sun, 15 Jul 2012 17:25:24 +0000 (17:25 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Sun, 15 Jul 2012 17:25:24 +0000 (17:25 +0000)
This change is based on a patch by "flyn" from https://dev.openwrt.org/ticket/11868 .

contrib/package/freifunk-watchdog/Makefile
contrib/package/freifunk-watchdog/files/freifunk-watchdog.config [new file with mode: 0644]
contrib/package/freifunk-watchdog/src/watchdog.c
contrib/package/freifunk-watchdog/src/watchdog.h

index dcc3ac4b730e7d24acefb8bf79f9c16000f238cf..33ba33da3ec049f666540218eef73344dbe6deb4 100644 (file)
@@ -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 (file)
index 0000000..b6e6543
--- /dev/null
@@ -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'
index 2d6e4a6f7d0d6928a54b0561760b0bf21962758a..ce66adadb4eedd5e322ea56d630c5041b21a1ec8 100644 (file)
@@ -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 )
                        {
index 71c10e9c1fcbbffb33950417fac8de0b5a315a73..34d616c3a02b65af8ee43503f84e2a66448acca4 100644 (file)
 /* 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 */