X-Git-Url: http://git.subgeniuskitty.com/icmpmonitor/.git/blobdiff_plain/476ea14deedd4013ab02425e5a1791cbf5e4ba2c..8f7eee8c47253a145a06b143b8c869bb13c2d318:/icmpmonitor.c diff --git a/icmpmonitor.c b/icmpmonitor.c index f2c10a2..7d24d1a 100644 --- a/icmpmonitor.c +++ b/icmpmonitor.c @@ -4,86 +4,34 @@ * © 2019 Aaron Taylor * © 1999 Vadim Zaliva * © 1989 The Regents of the University of California & Mike Muuss - * See LICENSE.txt file for copyright and license details. + * See LICENSE file for copyright and license details. */ #include #include #include -#ifdef HAVE_SYSLOG_H -# include -#endif #include #include #include -#ifdef HAVE_SYS_TIME_H -# include -# include -#endif +#include +#include #include #include -#ifdef HAVE_FCNTL_H -# include -#endif -#ifdef HAVE_SYS_FCNTL_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif - +#include +#include +#include #include - #include #include #include #include #include #include - -/* Workaround for broken ICMP header on Slackware 4.x */ -#ifdef _LINUX_ICMP_H -# warning "Broken Slackware 4.x 'netinet/ip_icmp.h' header detected. Using replacement 'struct icmp' definition." -# define ICMP_MINLEN 8 -struct icmp -{ - u_int8_t icmp_type; - u_int8_t icmp_code; - u_int16_t icmp_cksum; - union - { - struct ih_idseq - { - u_int16_t icd_id; - u_int16_t icd_seq; - } ih_idseq; - } icmp_hun; - -# define icmp_id icmp_hun.ih_idseq.icd_id -# define icmp_seq icmp_hun.ih_idseq.icd_seq - - union { - u_int8_t id_data[1]; - } icmp_dun; - -# define icmp_data icmp_dun.id_data - -}; -#endif /* _LINUX_ICMP_H */ - #include #include #include "cfg.h" -/* defines */ - -/* #define DEBUG */ - -#ifndef nil -# define nil NULL -#endif - /* return codes */ #define RET_OK 0 #define RET_NO_HOSTS 1 @@ -95,7 +43,6 @@ struct icmp #define DEFDATALEN (64 - 8) /* default data length */ #define VERSION "ICMPmonitor v1.2 by lord@crocodile.org" -#define MAX_LOG_MSG_SIZE 4096 # define icmphdr icmp @@ -125,9 +72,6 @@ typedef struct monitor_host } monitor_host_t; /* protos */ -static void logopen(void); -static void logclose(void); -static void log(int type, char *format, ...); static int gethostaddr(const char *name); static void read_hosts(const char *cfg_file_name); static void init_hosts(void); @@ -136,38 +80,41 @@ static void pinger(int); static int in_cksum(u_short *addr, int len); static void read_icmp_data(monitor_host_t *p); static void tvsub(struct timeval *out, struct timeval *in); -static void done(int code); -static void start_daemon(void); static int gcd(int x, int y); /* globals */ -static monitor_host_t **hosts = nil; -static int isDaemon = 0; +static monitor_host_t **hosts = NULL; static int isVerbose = 0; static int keepBanging = 0; static unsigned short ident; static int send_delay = 1; + + + + + + + + + + + + int main(int ac, char **av) { extern char* optarg; extern int optind; - char *cfgfile=nil; + char *cfgfile=NULL; int param; - - logopen(); - log(LOG_INFO, VERSION " is starting."); - while((param = getopt(ac, av, "rvdf:")) != -1) + while((param = getopt(ac, av, "rvf:")) != -1) switch(param) { case 'v': isVerbose = 1; break; - case 'd': - isDaemon = 1; - break; case 'r': keepBanging = 1; break; @@ -175,21 +122,16 @@ int main(int ac, char **av) cfgfile=strdup(optarg); break; default: - fprintf(stderr,"Usage: icmpmonitor [-d] [-v] [-r] [-f cfgfile]\n"); - done(RET_BAD_OPT); + fprintf(stderr,"Usage: icmpmonitor [-v] [-r] [-f cfgfile]\n"); + exit(EXIT_FAILURE); } - if(!cfgfile) - { - log(LOG_WARNING,"No cfg file specified. Assuming 'icmpmonitor.cfg'"); - cfgfile="icmpmonitor.cfg"; + if (!cfgfile) { + fprintf(stderr, "ERROR: No config file specified.\n"); + exit(EXIT_FAILURE); } - read_hosts(cfgfile); /* we do this before becoming daemon, - to be able process relative path */ - - if(isDaemon) - start_daemon(); + read_hosts(cfgfile); init_hosts(); @@ -199,8 +141,8 @@ int main(int ac, char **av) alarm(send_delay); get_response(); - - done(RET_OK); + + exit(EXIT_SUCCESS); } @@ -272,15 +214,14 @@ static void pinger(int ignore) { p->down = 1; - if(isVerbose) - log(LOG_INFO,"Host %s in down. Executing DOWN command",p->name); + if (isVerbose) printf("INFO: Host %s is down. Executing DOWN command.\n", p->name); if(!fork()) { system(p->downcmd); exit(0); } else { - wait(nil); + wait(NULL); } } } @@ -299,8 +240,7 @@ static void pinger(int ignore) icp->icmp_seq = p->socket; icp->icmp_id = ident; - if(isVerbose) - log(LOG_INFO,"Sending ICMP packet to %s.",p->name); + if (isVerbose) printf("INFO: Sending ICMP packet to %s.\n", p->name); (void)gettimeofday((struct timeval *)&outpack[8], (struct timezone *)NULL); @@ -318,8 +258,7 @@ static void pinger(int ignore) if(i<0 || i!=cc) { - if(i<0) - log(LOG_WARNING,"Sending ICMP packet to %s failed.",p->name); + if (i<0) fprintf(stderr, "WARN: Failed sending ICMP packet to %s.\n", p->name); } p->sentpackets++; } @@ -354,7 +293,7 @@ static void get_response(void) p=p->next; } - retval = select(maxd+1, &rfds, nil, nil, nil); + retval = select(maxd+1, &rfds, NULL, NULL, NULL); if(retval<0) { /* we get her in case we are interrupted by signal. @@ -364,7 +303,6 @@ static void get_response(void) { if(retval>0) { - /* log(LOG_DEBUG,"ICMP data is available now."); */ p=hosts[0]; while(p) { @@ -375,9 +313,8 @@ static void get_response(void) } p=p->next; } - } else - { - log(LOG_DEBUG,"select returns 0."); /* TODO */ + } else { + /* TODO: How to handle this error? */ } } } @@ -398,24 +335,18 @@ static void read_icmp_data(monitor_host_t *p) (void)gettimeofday(&tv, (struct timezone *)NULL); fromlen = sizeof(from); - if((cc = recvfrom(p->socket, buf, sizeof(buf), 0, - (struct sockaddr *)&from, &fromlen)) < 0) - { - if(errno != EINTR) - log(LOG_WARNING,"Error reading ICMP data from %s.",p->name); + if ((cc = recvfrom(p->socket, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen)) < 0) { + if (errno != EINTR) fprintf(stderr, "WARN: Error reading ICMP data from %s.\n", p->name); return; } - /* log(LOG_DEBUG,"Got %d bytes of ICMP data from %s.",cc, p->name); */ - /* check IP header actual len */ ip = (struct ip *)buf ; iphdrlen = ip->ip_hl<<2 ; icmp = (struct icmp *) (buf+iphdrlen) ; - if(cc < iphdrlen+ICMP_MINLEN) - { - log(LOG_WARNING,"Received short packet from %s.",p->name); + if (cc < iphdrlen + ICMP_MINLEN) { + fprintf(stderr, "WARN: Received short packet from %s.\n", p->name); return; } @@ -430,31 +361,23 @@ static void read_icmp_data(monitor_host_t *p) tvsub(&tv, (struct timeval *) &icmp->icmp_data[0]); delay=tv.tv_sec*1000+(tv.tv_usec/1000); - if(isVerbose) - log(LOG_INFO,"Got ICMP reply from %s in %d ms.",p->name,delay); + if(isVerbose) printf("INFO: Got ICMP reply from %s in %d ms.\n", p->name, delay); p->down=0; if(!p->up) { p->up=1; - if(isVerbose) - log(LOG_INFO,"Host %s in now up. Executing UP command",p->name); + if (isVerbose) printf("INFO: Host %s is up. Executing UP command.\n", p->name); if(!fork()) { system(p->upcmd); exit(0); } else { - wait(nil); + wait(NULL); } } - } else - { - /* - log(LOG_DEBUG,"ICMP packet of type %d from %s. Ident=%d",icmp->icmp_type, - p->name, - icmp->icmp_id - ); - */ + } else { + /* TODO: Do anything here? */ } } @@ -463,28 +386,23 @@ static void read_hosts(const char *cfg_file_name) int i,n=0; struct Cfg *cfg; - if((cfg=readcfg(cfg_file_name))==NULL) - { - log(LOG_ERR,"Error reading cfg. Exiting."); - done(RET_BAD_CFG); + if ((cfg = readcfg(cfg_file_name)) == NULL) { + fprintf(stderr, "ERROR: Failed to read config.\n"); + exit(EXIT_FAILURE); } - if(cfg->nelements) - { - hosts=malloc(sizeof(monitor_host_t *)*cfg->nelements); - for(i=0;inelements;i++) - { - if(cfg->dict[i]->nvalues<4) - { - log(LOG_ERR,"Not enough fields in record %d of cfg file. Got %d.",n, cfg->dict[i]->nvalues+1); - done(RET_BAD_CFG); - } else if(cfg->dict[i]->nvalues>5) - { - log(LOG_ERR,"Too many fields in record %d of cfg file. Got %d.",n, cfg->dict[i]->nvalues+1); - done(RET_BAD_CFG); + if (cfg->nelements) { + hosts = malloc(sizeof(monitor_host_t *) * cfg->nelements); + for (i=0; inelements; i++) { + if (cfg->dict[i]->nvalues < 4) { + fprintf(stderr, "ERROR: Not enough fields in record %d of cfg file. Got %d.\n", n, cfg->dict[i]->nvalues+1); + exit(EXIT_FAILURE); + } else if (cfg->dict[i]->nvalues>5) { + fprintf(stderr, "ERROR: Too many fields in record %d of cfg file. Got %d.\n", n, cfg->dict[i]->nvalues+1); + exit(EXIT_FAILURE); } - hosts[n]=malloc(sizeof(monitor_host_t)); + hosts[n] = malloc(sizeof(monitor_host_t)); hosts[n]->name = strdup(cfg->dict[i]->name); hosts[n]->ping_interval = atoi (cfg->dict[i]->value[0]); hosts[n]->max_delay = atoi (cfg->dict[i]->value[1]); @@ -511,19 +429,17 @@ static void read_hosts(const char *cfg_file_name) { hosts[n]->down = 0; hosts[n]->up = 0; - } else - { - log(LOG_ERR,"Illegal value %s in record %n for startup condition.", cfg->dict[i]->value[4], n); - done(RET_BAD_CFG); + } else { + fprintf(stderr, "ERROR: Illegal value %s in record %n for startup condition.\n", cfg->dict[i]->value[4], n); + exit(EXIT_FAILURE); } hosts[n]->sentpackets = 0; hosts[n]->recvdpackets = 0; hosts[n]->socket = -1; - hosts[n]->next = nil; - if(n>0) - hosts[n-1]->next=hosts[n]; - (void)gettimeofday(&(hosts[n]->last_ping_received), (struct timezone *)NULL); + hosts[n]->next = NULL; + if (n > 0) hosts[n-1]->next=hosts[n]; + gettimeofday(&(hosts[n]->last_ping_received), (struct timezone *)NULL); n++; } @@ -531,14 +447,10 @@ static void read_hosts(const char *cfg_file_name) freecfg(cfg); - if(n<=0) - { - log(LOG_ERR,"No hosts defined in cfg file, exiting."); - done(RET_NO_HOSTS); + if (n <= 0) { + fprintf(stderr, "ERROR: No hosts defined in cfg file, exiting.\n"); + exit(EXIT_FAILURE); } - else - log(LOG_DEBUG,"%d host(s) found in cfg file,", n); - } static int gethostaddr(const char *name) @@ -562,27 +474,23 @@ static void init_hosts(void) struct protoent *proto; int ok=0; - if((proto=getprotobyname("icmp"))==nil) - { - log(LOG_ERR,"Unknown protocol: icmp. Exiting."); - done(RET_INIT_ERROR); + if ((proto = getprotobyname("icmp")) == NULL) { + fprintf(stderr, "ERROR: Unknown protocol: icmp.\n"); + exit(EXIT_FAILURE); } - while(p) - { - log(LOG_DEBUG,"resolving host %s", p->name); - + while(p) { bzero(&p->dest,sizeof(p->dest)); p->dest.sin_family=AF_INET; if((p->dest.sin_addr.s_addr=gethostaddr(p->name))<=0) { - log(LOG_ERR,"Can't resolve host. Skipping client %s.",p->name); + fprintf(stderr, "WARN: Can't resolve host. Skipping client %s.\n", p->name); p->socket=-1; } else { if((p->socket=socket(AF_INET,SOCK_RAW,proto->p_proto))<0) { - log(LOG_ERR,"Can't create socket. Skipping client %s.",p->name); + fprintf(stderr, "WARN: Can't create socket. Skipping client %s.\n", p->name); p->socket=-1; } else { @@ -598,8 +506,8 @@ static void init_hosts(void) if(!ok) { - log(LOG_ERR,"No hosts left to process, exiting."); - done(RET_NO_HOSTS); + fprintf(stderr, "ERROR: No hosts left to process.\n"); + exit(EXIT_FAILURE); } } @@ -618,104 +526,9 @@ tvsub(register struct timeval *out, register struct timeval *in) out->tv_sec -= in->tv_sec; } -void done(int code) -{ - logclose(); - exit(code); -} - -void start_daemon(void) -{ - if(fork()) - exit(0); - - chdir("/"); - umask(0); - (void) close(0); - (void) close(1); - (void) close(2); - (void) open("/", O_RDONLY); - (void) dup2(0, 1); - (void) dup2(0, 2); - setsid(); -} - -static void logopen(void) -{ -#if HAVE_OPENLOG - if(isDaemon) - openlog("icmpmonitor", LOG_PID| LOG_CONS|LOG_NOWAIT, LOG_USER); -#else - log(LOG_WARNING,"Compiled without syslog. Syslog can't be used."); -#endif -} - -static void logclose(void) -{ -#if HAVE_CLOSELOG - if(isDaemon) - closelog(); -#endif -} - -/** - * This function should be used as central logging facility. - * 'type' argument should be one of following: - * - * LOG_EMERG system is unusable - * LOG_ALERT action must be taken immediately - * LOG_CRIT critical conditions - * LOG_ERR error conditions - * LOG_WARNING warning conditions - * LOG_NOTICE normal but significant condition - * LOG_INFO informational - * LOG_DEBUG debug-level messages - */ -static void log(int type, char *format, ...) -{ - va_list ap; - -#ifndef DEBUG - if(type==LOG_DEBUG) - return; -#endif - - va_start(ap, format); - - if(isDaemon) - { - char buffer[MAX_LOG_MSG_SIZE]; - -#if HAVE_VSNPRINTF - (void)vsnprintf(buffer, MAX_LOG_MSG_SIZE, format, ap); -#else -# if HAVE_VSPRINTF -# warning "Using VSPRINTF. Buffer overflow could happen!" - (void)vsprintf(buffer, format, ap); -# else -# error "Your standard libabry have neither vsnprintf nor vsprintf defined. One of them is reqired!" -# endif -#endif -#if HAVE_SYSLOG - syslog(type,buffer); -#endif - } else - { - (void) fprintf(stderr, "icmpmonitor[%d]:", (int)getpid()); - (void) vfprintf(stderr, format, ap); - (void) fprintf(stderr, "\n"); - } - va_end(ap); -} - static int gcd(int x, int y) { - while(x!=y) - { - if(x