diff options
Diffstat (limited to 'contrib/check_fping_in.c')
-rw-r--r-- | contrib/check_fping_in.c | 430 |
1 files changed, 430 insertions, 0 deletions
diff --git a/contrib/check_fping_in.c b/contrib/check_fping_in.c new file mode 100644 index 00000000..50fd5eea --- /dev/null +++ b/contrib/check_fping_in.c @@ -0,0 +1,430 @@ +/****************************************************************************** +* +* CHECK_INET_FPING.C +* +* Program: Fping plugin for Nagios +* License: GPL +* Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at) +* $Id$ +* +* Modifications: +* +* 08-24-1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at) +* Intial Coding +* 09-11-1999 Karl DeBisschop (kdebiss@alum.mit.edu) +* Change to spopen +* Fix so that state unknown is returned by default +* (formerly would give state ok if no fping specified) +* Add server_name to output +* Reformat to 80-character standard screen +* 11-18-1999 Karl DeBisschop (kdebiss@alum.mit.edu) +* set STATE_WARNING of stderr written or nonzero status returned +* 09-29-2000 Matthew Grant (matthewg@plain.co.nz) +* changes for monitoring multiple hosts for checking Internet +* reachibility +* +* Description: +* +* This plugin will use the /bin/fping command (from nagios) to ping +* the specified host for a fast check if the host is alive. Note that +* it is necessary to set the suid flag on fping. +******************************************************************************/ + +#include "config.h" +#include "common.h" +#include "popen.h" +#include "utils.h" + +#define PROGNAME "check_fping" +#define PACKET_COUNT 15 +#define PACKET_SIZE 56 +#define CRITICAL_COUNT 2 +#define WARNING_COUNT 1 +#define UNKNOWN_PACKET_LOSS 200 /* 200% */ +#define UNKNOWN_TRIP_TIME -1.0 /* -1 seconds */ + +#define STRSZ 100 + +int textscan(char *buf); +int process_arguments(int, char **); +int get_threshold (char *arg, char *rv[2]); +void print_usage(void); +void print_help(void); + +char *server_names=NULL; +char *name="INTERNET"; +int cthresh=CRITICAL_COUNT; +int wthresh=WARNING_COUNT; +int nnames=0; +int tpl=UNKNOWN_PACKET_LOSS; +double trta=UNKNOWN_TRIP_TIME; +int packet_size=PACKET_SIZE; +int packet_count=PACKET_COUNT; +int verbose=FALSE; +int fail = 0; +int not_found = 0; +int rta_fail = 0; +int pl_fail = 0; +int unreachable = 0; + +int main(int argc, char **argv){ + int result; + int status=STATE_UNKNOWN; + char *servers=NULL; + char *command_line=NULL; + char *input_buffer=NULL; + char *pl_buffer=NULL; + char *rta_buffer=NULL; + input_buffer=malloc(MAX_INPUT_BUFFER); + rta_buffer = malloc(80); + pl_buffer = malloc(80); + memset(rta_buffer, 0, 80); + memset(pl_buffer, 0, 80); + + if(process_arguments(argc,argv)==ERROR) + usage("Could not parse arguments\n"); + + servers=strscpy(servers,server_names); + + /* compose the command */ + command_line=ssprintf + (command_line,"%s -b %d -c %d %s", + PATH_TO_FPING, + packet_size, + packet_count, + servers); + + if (verbose) printf("%s\n",command_line); + + /* run the command */ + child_process=spopen(command_line); + if(child_process==NULL){ + printf("Unable to open pipe: %s\n",command_line); + return STATE_UNKNOWN; + } + + child_stderr=fdopen(child_stderr_array[fileno(child_process)],"r"); + if(child_stderr==NULL){ + printf("Could not open stderr for %s\n",command_line); + } + + while (fgets(input_buffer,MAX_INPUT_BUFFER-1,child_process)) { + if (verbose) printf("%s",input_buffer); + result = textscan(input_buffer); + status = max(status,result); + } + + while(fgets(input_buffer,MAX_INPUT_BUFFER-1,child_stderr)) { + if (verbose) printf("%s",input_buffer); + result = textscan(input_buffer); + status = max(status,result); + } + + (void)fclose(child_stderr); + + /* close the pipe */ + if(spclose(child_process)) + status=max(status,STATE_WARNING); + + /* Analyse fail count and produce results */ + if (fail >= wthresh) { + status = max(status, STATE_WARNING); + } + + if (fail >= cthresh) { + status = max(status, STATE_CRITICAL); + } + + if( tpl != UNKNOWN_PACKET_LOSS ) { + snprintf(pl_buffer, 80, ", %d PL", pl_fail); + } + + if( trta != UNKNOWN_TRIP_TIME ) { + snprintf(rta_buffer, 80, ", %d RTA", rta_fail); + + } + + printf("FPING %s - %s, %d of %d fail, %d NF, %d UR%s%s\n", + state_text(status), + (name != NULL ? name : server_names), + fail, + nnames, + not_found, + unreachable, + pl_buffer, + rta_buffer); + + return status; +} + + + +/* analyse fping output - each event resulting in an increment of fail + * must be mutually exclusive. packet loss and round trip time analysed + * together, both at once just results in one increment of fail + */ +int textscan(char *buf) +{ + char *rtastr=NULL; + char *losstr=NULL; + double loss; + double rta; + int status=STATE_OK; + + if (strstr(buf,"not found")) { + fail++; + not_found++; + } else if(strstr(buf,"xmt/rcv/%loss") + && strstr(buf,"min/avg/max")) { + losstr = strstr(buf,"="); + losstr = 1+strstr(losstr,"/"); + losstr = 1+strstr(losstr,"/"); + rtastr = strstr(buf,"min/avg/max"); + rtastr = strstr(rtastr,"="); + rtastr = 1+index(rtastr,'/'); + loss = strtod(losstr,NULL); + rta = strtod(rtastr,NULL); + /* Increment fail counter + */ + if (tpl!=UNKNOWN_PACKET_LOSS && loss>tpl) { + fail++; + } + else if (trta!=UNKNOWN_TRIP_TIME && rta>trta) { + fail++; + } + else if (loss >= 100) { + fail++; + } + /* Increment other counters + */ + if (trta!=UNKNOWN_TRIP_TIME && rta>trta) + rta_fail++; + if (tpl!=UNKNOWN_PACKET_LOSS && loss>tpl) + pl_fail++; + if (loss >= 100) + unreachable++; + } else if(strstr(buf,"xmt/rcv/%loss") ) { + losstr = strstr(buf,"="); + losstr = 1+strstr(losstr,"/"); + losstr = 1+strstr(losstr,"/"); + loss = strtod(losstr,NULL); + /* Increment fail counter + */ + if (tpl!=UNKNOWN_PACKET_LOSS && loss>tpl) { + fail++; + } + else if (loss >= 100) { + fail++; + } + /* Increment other counters + */ + if (tpl!=UNKNOWN_PACKET_LOSS && loss>tpl) + pl_fail++; + if (loss >= 100) + unreachable++; + } + + return status; +} + + + + +/* process command-line arguments */ +int process_arguments(int argc, char **argv) +{ + int c; + +#ifdef HAVE_GETOPT_H + int option_index = 0; + static struct option long_options[] = + { + {"hostname" ,required_argument,0,'H'}, + {"critical" ,required_argument,0,'c'}, + {"warning" ,required_argument,0,'w'}, + {"bytes" ,required_argument,0,'b'}, + {"number" ,required_argument,0,'n'}, + {"pl-threshold" ,required_argument,0,'p'}, + {"rta-threshold" ,required_argument,0,'r'}, + {"name" ,required_argument,0,'N'}, + {"verbose" ,no_argument, 0,'v'}, + {"version" ,no_argument, 0,'V'}, + {"help" ,no_argument, 0,'h'}, + {0,0,0,0} + }; +#else + + if(argc<2) return ERROR; + + if (!is_option(argv[1])){ + server_names=argv[1]; + argv[1]=argv[0]; + argv=&argv[1]; + argc--; + } +#endif + + while (1){ +#ifdef HAVE_GETOPT_H + c = getopt_long(argc,argv,"+hVvH:c:w:b:n:N:p:r:",long_options,&option_index); +#else + c = getopt(argc,argv,"+hVvH:c:w:b:n:N:p:r:"); +#endif + + if (c==-1||c==EOF||c==1) + break; + + switch (c) + { + case '?': /* print short usage statement if args not parsable */ + printf("%s: Unknown argument: %s\n\n",my_basename(argv[0]),optarg); + print_usage(); + exit(STATE_UNKNOWN); + case 'h': /* help */ + print_help(); + exit(STATE_OK); + case 'V': /* version */ + print_revision(my_basename(argv[0]),"$Revision$"); + exit(STATE_OK); + case 'v': /* verbose mode */ + verbose=TRUE; + break; + case 'H': /* hostname */ + if(is_host(optarg)==FALSE){ + printf("Invalid host name/address\n\n"); + print_usage(); + exit(STATE_UNKNOWN); + } + if (server_names != NULL) + server_names=strscat(server_names," "); + server_names=strscat(server_names,optarg); + nnames++; + break; + case 'c': + if (is_intpos(optarg)) + cthresh = atoi(optarg); + else + usage("Critical threshold must be a positive integer"); + break; + case 'w': + if (is_intpos(optarg)) + wthresh = atoi(optarg); + else + usage("Warning threshold must be a postive integer"); + break; + case 'r': + if (is_intpos(optarg)) { + trta=strtod(optarg,NULL); + } + else { + usage("RTA threshold must be a positive integer"); + } + break; + case 'p': + if (is_intpos(optarg)) { + tpl=strtod(optarg,NULL); + } + else { + usage("RTA threshold must be a positive integer"); + } + break; + case 'b': /* bytes per packet */ + if (is_intpos(optarg)) + packet_size=atoi(optarg); + else + usage("Packet size must be a positive integer"); + break; + case 'N': /* Name of service */ + name = optarg; + break; + case 'n': /* number of packets */ + if (is_intpos(optarg)) + packet_count=atoi(optarg); + else + usage("Packet count must be a positive integer"); + break; + } + } + + while (optind < argc) { + if(is_host(argv[optind])==FALSE) { + printf("Invalid host name/address\n\n"); + print_usage(); + exit(STATE_UNKNOWN); + } + if (server_names != NULL) + server_names=strscat(server_names," "); + server_names=strscat(server_names,argv[optind]); + nnames++; + optind++; + } + + if (server_names==NULL || nnames < 2) + usage("At least 2 hostnames must be supplied\n\n"); + + if (cthresh < 2) + usage("Critical threshold must be at least 2"); + if (cthresh > nnames) + usage("Critical threshold cannot be greater than number of hosts tested"); + if (wthresh < 1) + usage("Warning threshold must be at least 1"); + if (wthresh > nnames) + usage("Warning threshold cannot be greater than number of hosts tested"); + if(wthresh >= cthresh) + usage("Warning threshold must be less than the critical threshold"); + + return OK; +} + + +void print_usage(void) +{ + printf("Usage: %s <host_address> <host_address> [<host_address>] ...\n",PROGNAME); +} + + + + + +void print_help(void) +{ + + print_revision(PROGNAME,"$Revision$"); + + printf + ("Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)\n" + " (c) 2000 Matthew Grant (matthewg@plain.co.nz)\n" + "This plugin will use the /bin/fping command (from saint) to ping the\n" + "specified hosts for a fast check to see if the Internet is still \n" + "reachable, and the results of the testing aggregated. Note that it\n" + "is necessary to set the suid flag on fping.\n\n"); + + print_usage(); + + printf + ("\nOptions:\n" + "-b, --bytes=INTEGER\n" + " Size of ICMP packet (default: %d)\n" + "-c, --critical=INTEGER (default: %d)\n" + " critical threshold failure count\n" + "-n, --number=INTEGER\n" + " Number of ICMP packets to send (default: %d)\n" + "-H, --hostname=HOST\n" + " Name or IP Address of host to ping (IP Address bypasses name lookup,\n" + " reducing system load)\n" + "-h, --help\n" + " Print this help screen\n" + "-N, --name\n" + " Service name to print in results, defaults to INTERNET\n" + "-p, --pl-threshold\n" + " Packet loss threshold - specify to turn on packet loss testing\n" + "-r, --rta-threshold\n" + " Round trip average threshold - specify to turn on RTA testing\n" + "-V, --version\n" + " Print version information\n" + "-v, --verbose\n" + " Show details for command-line debugging (do not use with nagios server)\n" + "-w, --warning=INTEGER (default: %d)\n" + " warning threshold failure count\n", + PACKET_SIZE, CRITICAL_COUNT, PACKET_COUNT, WARNING_COUNT); +} |