diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/config.c | 28 | ||||
-rw-r--r-- | src/defs.h | 13 | ||||
-rw-r--r-- | src/ping903.h | 3 | ||||
-rw-r--r-- | src/pinger.c | 111 |
4 files changed, 141 insertions, 14 deletions
diff --git a/src/config.c b/src/config.c index f2376a5..8a5028a 100644 --- a/src/config.c +++ b/src/config.c @@ -47,12 +47,8 @@ static int cf_ip_list_parse(union cf_callback_arg *arg, void *data) { FILE *fp; - char buf[1024]; - unsigned ln = 0; - int skip_to_eol = 0; - int ret = CF_RET_OK; - struct addrinfo hints; - + int rc; + fp = fopen(arg->input.val, "r"); if (!fp) { error("%s:%d: can't open file %s: %s", @@ -60,7 +56,20 @@ cf_ip_list_parse(union cf_callback_arg *arg, void *data) arg->input.val, strerror(errno)); exit(1); } - + rc = file_read_ip_list(fp, arg->input.val); + fclose(fp); + return rc; +} + +int +file_read_ip_list(FILE *fp, char const *fname) +{ + char buf[1024]; + unsigned ln = 0; + int skip_to_eol = 0; + int ret = CF_RET_OK; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_protocol = IPPROTO_TCP; @@ -84,7 +93,7 @@ cf_ip_list_parse(union cf_callback_arg *arg, void *data) if (buf[len-1] == '\n') buf[--len] = 0; else if (!feof(fp)) { - error("%s:%d: line too long", arg->input.val, ln); + error("%s:%d: line too long", fname, ln); skip_to_eol = 1; ret = CF_RET_FAIL; continue; @@ -102,14 +111,13 @@ cf_ip_list_parse(union cf_callback_arg *arg, void *data) rc = getaddrinfo(p, NULL, &hints, &res); if (rc) { - error("%s:%d: invalid IP address", arg->input.val, ln); + error("%s:%d: invalid IP address", fname, ln); ret = CF_RET_FAIL; continue; } hostping_add(p, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); } - fclose(fp); return ret; } @@ -6,9 +6,18 @@ #ifndef DEFAULT_SERVICE # define DEFAULT_SERVICE "8080" #endif -#ifndef DEFAULT_CONFIG_FILE -# define DEFAULT_CONFIG_FILE "/etc/ping903.conf" +#ifndef SYSCONFDIR +# define SYSCONFDIR "/etc" #endif +#ifndef LOCALSTATEDIR +# define LOCALSTATEDIR "/var/lib" +#endif +#ifndef PACKAGESTATEDIR +# define PACKAGESTATEDIR LOCALSTATEDIR "/" PACKAGE +#endif +#define DEFAULT_CONFIG_FILE SYSCONFDIR "/" PACKAGE ".conf" +#define LOCAL_IP_LIST_FILE PACKAGESTATEDIR "/ip-list" + #define COPYLEFT "\ Copyright (C) 2020 Sergey Poznyakoff\n\ License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\ diff --git a/src/ping903.h b/src/ping903.h index 2f2d7ef..e24e356 100644 --- a/src/ping903.h +++ b/src/ping903.h @@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with Ping903. If not, see <http://www.gnu.org/licenses/>. */ +#include <stdio.h> #include <pthread.h> #include <stdarg.h> #include <microhttpd.h> @@ -132,6 +133,8 @@ int get_all_host_stat(struct json_value **); struct addrinfo; int get_host_matches(struct addrinfo **aip, struct json_value **retval); +int file_read_ip_list(FILE *fp, char const *fname); + void p903_init(void); void *p903_sender(void *p); void *p903_receiver(void *p); diff --git a/src/pinger.c b/src/pinger.c index 19572d5..2517781 100644 --- a/src/pinger.c +++ b/src/pinger.c @@ -18,6 +18,7 @@ #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> +#include <sys/stat.h> #include <netinet/in_systm.h> #include <netinet/in.h> @@ -28,6 +29,7 @@ #include <string.h> #include <stddef.h> #include <stdlib.h> +#include <stdio.h> #include <errno.h> #include <pthread.h> #include <limits.h> @@ -100,6 +102,8 @@ timespec_incr(struct timespec *a, struct timespec const *b) static HOSTPING *hostping_head, *hostping_tail; static size_t hostping_count; static pthread_rwlock_t hostping_rwlock = PTHREAD_RWLOCK_INITIALIZER; +static size_t conf_hostping_count; +static int hostping_updated; void hostping_add(char const *name, struct sockaddr *addr, socklen_t addrlen) @@ -122,6 +126,7 @@ hostping_add(char const *name, struct sockaddr *addr, socklen_t addrlen) hostping_tail = hp; hostping_count++; + hostping_updated = 1; } void @@ -136,7 +141,8 @@ hostping_delete(HOSTPING *hp) else hostping_tail = hp->prev; hostping_count--; - + hostping_updated = 1; + free(hp->name); free(hp->addr); pthread_mutex_destroy(&hp->mutex); @@ -611,11 +617,26 @@ p903_init(void) { struct protoent *proto; int i; + FILE *fp; + + conf_hostping_count = hostping_count; + fp = fopen(LOCAL_IP_LIST_FILE, "r"); + if (fp) { + int rc = file_read_ip_list(fp, LOCAL_IP_LIST_FILE); + if (rc == CF_RET_FAIL) + exit(1); + fclose(fp); + } else if (errno != ENOENT) { + fatal("can't open %s: %s", LOCAL_IP_LIST_FILE, + strerror(errno)); + exit(1); + } if (hostping_count == 0) { info("no IP addresses configured, starting anyway"); } - + hostping_updated = 0; + proto = getprotobyname("icmp"); if (!proto) { fatal("no entry for icmp in the system protocol database"); @@ -943,6 +964,91 @@ p903_receiver(void *p) } } +static int +create_dirs(char const *filename) +{ + char *namebuf; + char *p; + char *endp; + struct stat st; + size_t len; + + p = strrchr(filename, '/'); + if (!p) + return -1; + len = p - filename; + namebuf = malloc(len + 1); + if (!namebuf) + return -1; + memcpy(namebuf, filename, len); + namebuf[len] = 0; + endp = namebuf + len; + + while ((p = strrchr(namebuf, '/')) != NULL && p > namebuf) { + *p = 0; + if (stat(namebuf, &st)) { + if (errno == ENOENT) + continue; + error("can't stat %s: %s", namebuf, strerror(errno)); + goto err; + } + if (S_ISDIR(st.st_mode)) { + break; + } else { + error("file name component %s is not a directory", + namebuf); + goto err; + } + } + + while (p < endp) { + *p = '/'; + if (mkdir(namebuf, 0755)) { + error("can't create directory %s: %s", + namebuf, strerror(errno)); + goto err; + } + p = p + strlen(p); + } + return 0; +err: + free(namebuf); + return -1; +} + +static void +save_local_ip_list(void) +{ + FILE *fp; + HOSTPING *hp; + size_t i; + + if (!hostping_updated) + return; + fp = fopen(LOCAL_IP_LIST_FILE, "w"); + if (!fp) { + if (errno == ENOENT) { + create_dirs(LOCAL_IP_LIST_FILE); + fp = fopen(LOCAL_IP_LIST_FILE, "w"); + } + if (!fp) { + fatal("can't open %s for writing: %s", + LOCAL_IP_LIST_FILE, + strerror(errno)); + return; + } + } + i = 0; + FOR_EACH_HOSTPING(hp) { + if (i >= conf_hostping_count) + fprintf(fp, "%s\n", hp->name); + i++; + } + fclose(fp); + + hostping_updated = 0; +} + void * p903_scheduler(void *p) { @@ -954,6 +1060,7 @@ p903_scheduler(void *p) FOR_EACH_HOSTPING(hp) { hostping_reset(hp); } + save_local_ip_list(); pthread_rwlock_unlock(&hostping_rwlock); start_probe(); |