summaryrefslogtreecommitdiffhomepage
path: root/contrib/package/freifunk-watchdog/src/watchdog.c
diff options
context:
space:
mode:
authorSven Roederer <freifunk@it-solutions.geroedel.de>2019-02-03 14:13:35 +0100
committerSven Roederer <freifunk@it-solutions.geroedel.de>2019-02-13 21:23:34 +0100
commit4654ba92c3999d84b08211f05d2ccb5ea9da731b (patch)
tree06cedf8e8badc0ce584d8bd5e97fab7476c81549 /contrib/package/freifunk-watchdog/src/watchdog.c
parenteda8f02dac3caa4d0f52cd1e860d7a392c295df3 (diff)
treewide: move freifunk-related packages to separate repo
Even Freifunk was one of the major factory to create the LuCI-system, it's now only a very small part of LuCI. LuCI has become a much bigger thing and it seems that it's time to move the packages only relating to Freifunk into it's own feed. On the mailinglist it was discussed [1] and a repo below the general Freifunk team on github was created. This commit removes all packages that will be hosted in the new repo [2] 1 - http://lists.freifunk.net/pipermail/wlannews-freifunk.net/2019-February/004818.html 2 - https://github.com/freifunk/openwrt-packages Signed-off-by: Sven Roederer <freifunk@it-solutions.geroedel.de>
Diffstat (limited to 'contrib/package/freifunk-watchdog/src/watchdog.c')
-rw-r--r--contrib/package/freifunk-watchdog/src/watchdog.c527
1 files changed, 0 insertions, 527 deletions
diff --git a/contrib/package/freifunk-watchdog/src/watchdog.c b/contrib/package/freifunk-watchdog/src/watchdog.c
deleted file mode 100644
index 4bc3ab0b6..000000000
--- a/contrib/package/freifunk-watchdog/src/watchdog.c
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
- *
- * Copyright (C) 2009 Jo-Philipp Wich <jow@openwrt.org>
- */
-
-#include "watchdog.h"
-
-/* Global watchdog fd, required by signal handler */
-int wdfd = -1;
-
-/* Handle finished children */
-static void sigchld_handler(int sig)
-{
- pid_t pid;
-
- while( (pid = waitpid(-1, NULL, WNOHANG)) > 0 )
- syslog(LOG_INFO, "Child returned (pid %d)", pid);
-}
-
-/* Watchdog shutdown helper */
-static void shutdown_watchdog(int sig)
-{
- static const char wshutdown = WATCH_SHUTDOWN;
-
- if( wdfd > -1 )
- {
- syslog(LOG_INFO, "Stopping watchdog timer");
- write(wdfd, &wshutdown, 1);
- close(wdfd);
- wdfd = -1;
- }
-
- exit(0);
-}
-
-/* Get BSSID of given interface */
-static int iw_get_bssid(int iwfd, const char *ifname, char *bssid)
-{
- struct iwreq iwrq;
-
- if( iw_ioctl(iwfd, ifname, SIOCGIWAP, &iwrq) >= 0 )
- {
- unsigned char *addr = (unsigned char *)iwrq.u.ap_addr.sa_data;
-
- sprintf(bssid, "%02X:%02X:%02X:%02X:%02X:%02X",
- addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
-
- return 0;
- }
-
- return -1;
-}
-
-/* Get channel of given interface */
-static int iw_get_channel(int iwfd, const char *ifname, int *channel)
-{
- int i;
- char buffer[sizeof(struct iw_range)];
- double cur_freq, cmp_freq;
- struct iwreq iwrq;
- struct iw_range *range;
-
- memset(buffer, 0, sizeof(buffer));
-
- iwrq.u.data.pointer = (char *)buffer;
- iwrq.u.data.length = sizeof(buffer);
- iwrq.u.data.flags = 0;
-
- if( iw_ioctl(iwfd, ifname, SIOCGIWRANGE, &iwrq) < 0)
- {
- *channel = -1;
- return -1;
- }
-
- range = (struct iw_range *)buffer;
-
- if( iw_ioctl(iwfd, ifname, SIOCGIWFREQ, &iwrq) >= 0 )
- {
- cur_freq = ((double)iwrq.u.freq.m) * pow(10, iwrq.u.freq.e);
- if( cur_freq < 1000.00 )
- {
- *channel = (int)cur_freq;
- return 0;
- }
-
- for(i = 0; i < range->num_frequency; i++)
- {
- cmp_freq = ((double)range->freq[i].m) * pow(10, range->freq[i].e);
- if( cmp_freq == cur_freq )
- {
- *channel = (int)range->freq[i].i;
- return 0;
- }
- }
- }
-
- *channel = -1;
- return -1;
-}
-
-/* Get the (first) pid of given process name */
-static int find_process(const char *name)
-{
- int pid = -1;
- int file;
- char buffer[128];
- char cmpname[128];
- DIR *dir;
- struct dirent *entry;
-
- if( (dir = opendir("/proc")) != NULL )
- {
- snprintf(cmpname, sizeof(cmpname), "Name:\t%s\n", name);
-
- while( (entry = readdir(dir)) != NULL )
- {
- if( !strcmp(entry->d_name, "..") || !isdigit(*entry->d_name) )
- continue;
-
- sprintf(buffer, "/proc/%s/status", entry->d_name);
- if( (file = open(buffer, O_RDONLY)) > -1 )
- {
- read(file, buffer, sizeof(buffer));
- close(file);
-
- if( strstr(buffer, cmpname) == buffer )
- {
- pid = atoi(entry->d_name);
-
- /* Skip myself ... */
- if( pid == getpid() )
- pid = -1;
- else
- break;
- }
- }
- }
-
- closedir(dir);
- return pid;
- }
-
- syslog(LOG_CRIT, "Unable to open /proc: %s",
- strerror(errno));
-
- return -1;
-}
-
-/* Get the 5 minute load average */
-static double find_loadavg(void)
-{
- int fd;
- char buffer[10];
- double load = 0.00;
-
- if( (fd = open("/proc/loadavg", O_RDONLY)) > -1 )
- {
- if( read(fd, buffer, sizeof(buffer)) == sizeof(buffer) )
- load = atof(&buffer[5]);
-
- close(fd);
- }
-
- return load;
-}
-
-/* Check if given uci file was updated */
-static int check_uci_update(const char *config, time_t *mtime)
-{
- struct stat s;
- char path[128];
-
- snprintf(path, sizeof(path), "/var/state/%s", config);
- if( stat(path, &s) > -1 )
- {
- if( (*mtime == 0) || (s.st_mtime > *mtime) )
- {
- *mtime = s.st_mtime;
- return 1;
- }
- }
-
- return 0;
-}
-
-/* Add tuple */
-static void load_wifi_uci_add_iface(const char *section, struct uci_wifi_iface_itr_ctx *itr)
-{
- wifi_tuple_t *t;
- const char *ucitmp;
- int val = 0;
-
- ucitmp = ucix_get_option(itr->ctx, "wireless", section, "mode");
- if( ucitmp && !strncmp(ucitmp, "adhoc", 5) )
- {
- if( (t = (wifi_tuple_t *)malloc(sizeof(wifi_tuple_t))) != NULL )
- {
- ucitmp = ucix_get_option(itr->ctx, "wireless", section, "ifname");
- if(ucitmp)
- {
- strncpy(t->ifname, ucitmp, sizeof(t->ifname));
- val++;
- }
-
- ucitmp = ucix_get_option(itr->ctx, "wireless", section, "bssid");
- if(ucitmp)
- {
- strncpy(t->bssid, ucitmp, sizeof(t->bssid));
- val++;
- }
-
- ucitmp = ucix_get_option(itr->ctx, "wireless", section, "device");
- if(ucitmp)
- {
- ucitmp = ucix_get_option(itr->ctx, "wireless", ucitmp, "channel");
- if(ucitmp)
- {
- t->channel = atoi(ucitmp);
- val++;
- }
- }
-
- if( val == 3 )
- {
- syslog(LOG_INFO, "Monitoring %s: bssid=%s channel=%d",
- t->ifname, t->bssid, t->channel);
-
- t->next = itr->list;
- itr->list = t;
- }
- else
- {
- free(t);
- }
- }
- }
-}
-
-/* Load config */
-static wifi_tuple_t * load_wifi_uci(wifi_tuple_t *ifs, time_t *modtime)
-{
- struct uci_context *ctx;
- struct uci_wifi_iface_itr_ctx itr;
- wifi_tuple_t *cur, *next;
-
- if( check_uci_update("wireless", modtime) )
- {
- syslog(LOG_INFO, "Wireless config changed, reloading");
-
- if( (ctx = ucix_init("wireless")) != NULL )
- {
- if( ifs != NULL )
- {
- for(cur = ifs; cur; cur = next)
- {
- next = cur->next;
- free(cur);
- }
- }
-
- itr.list = NULL;
- itr.ctx = ctx;
-
- ucix_for_each_section_type(ctx, "wireless", "wifi-iface",
- (void *)load_wifi_uci_add_iface, &itr);
-
- return itr.list;
- }
- }
-
- 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)
-{
- static int wdtrigger = 1;
- static int wdtimeout = BASE_INTERVAL * 2;
- static const char wdkeepalive = WATCH_KEEPALIVE;
-
- int iwfd;
- int channel;
- char bssid[18];
- struct sigaction sa;
-
- 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 loadavg_panic = 0;
-
- openlog(SYSLOG_IDENT, 0, LOG_DAEMON);
- memset(&sa, 0, sizeof(sa));
-
- if( (iwfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 )
- {
- syslog(LOG_ERR, "Can not open wireless control socket: %s",
- strerror(errno));
-
- return 1;
- }
-
- if( (wdfd = open(WATCH_DEVICE, O_WRONLY)) > -1 )
- {
- syslog(LOG_INFO, "Opened %s - polling every %i seconds",
- WATCH_DEVICE, BASE_INTERVAL);
-
- /* Install signal handler to halt watchdog on shutdown */
- sa.sa_handler = shutdown_watchdog;
- sa.sa_flags = SA_NOCLDWAIT | SA_RESTART;
- sigaction(SIGHUP, &sa, NULL);
- sigaction(SIGINT, &sa, NULL);
- sigaction(SIGPIPE, &sa, NULL);
- sigaction(SIGTERM, &sa, NULL);
- sigaction(SIGUSR1, &sa, NULL);
- sigaction(SIGUSR2, &sa, NULL);
-
- /* Set watchdog timeout to twice the interval */
- ioctl(wdfd, WDIOC_SETTIMEOUT, &wdtimeout);
- }
-
- /* Install signal handler to reap children */
- sa.sa_handler = sigchld_handler;
- sa.sa_flags = 0;
- sigaction(SIGCHLD, &sa, NULL);
-
- /* Load watchdog configuration only once */
- procs = load_watchdog_uci(procs);
-
- while( 1 )
- {
- /* Check/increment action interval */
- if( ++action_intv >= ACTION_INTERVAL )
- {
- /* Reset action interval */
- action_intv = 0;
-
- /* Check average load */
- if( find_loadavg() >= LOAD_TRESHOLD )
- loadavg_panic++;
- else
- loadavg_panic = 0;
-
- /* Check wireless interfaces */
- 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, curr_if->ifname, bssid) == 0) &&
- (iw_get_channel(iwfd, curr_if->ifname, &channel) == 0) )
- {
- /* Check BSSID */
- if( strcasecmp(bssid, curr_if->bssid) != 0 )
- {
- syslog(LOG_WARNING, "BSSID mismatch on %s: current=%s wanted=%s",
- curr_if->ifname, bssid, curr_if->bssid);
-
- restart_wifi++;
- }
-
- /* Check channel */
- else if( channel != curr_if->channel )
- {
- syslog(LOG_WARNING, "Channel mismatch on %s: current=%d wanted=%d",
- curr_if->ifname, channel, curr_if->channel);
-
- restart_wifi++;
- }
- }
- else
- {
- 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);
- }
- }
-
-
- /* Wifi restart required? */
- if( restart_wifi >= HYSTERESIS )
- {
- restart_wifi = 0;
- syslog(LOG_WARNING, "Channel or BSSID mismatch on wireless interface, restarting");
- EXEC(WIFI_ACTION);
- }
-
- /* Is there a load problem? */
- if( loadavg_panic >= HYSTERESIS )
- {
- syslog(LOG_EMERG, "Critical system load level, triggering reset!");
-
- /* Try watchdog, fall back to reboot */
- if( wdfd > -1 )
- ioctl(wdfd, WDIOC_SETTIMEOUT, &wdtrigger);
- else
- EXEC(LOAD_ACTION);
- }
- }
-
-
- /* Reset watchdog timer */
- if( wdfd > -1 )
- write(wdfd, &wdkeepalive, 1);
-
- sleep(BASE_INTERVAL);
- }
-
- shutdown_watchdog(0);
- closelog();
-
- return 0;
-}
-
-
-int main(int argc, char *argv[])
-{
- /* Check if watchdog is running ... */
- if( (argc > 1) && (strcmp(argv[1], "running") == 0) )
- {
- return (find_process(BINARY) == -1);
- }
-
- /* Start daemon */
- return do_daemon();
-}