summaryrefslogtreecommitdiffstats
path: root/contrib/check_fping_in.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/check_fping_in.c')
-rw-r--r--contrib/check_fping_in.c430
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 0000000..50fd5ee
--- /dev/null
+++ b/contrib/check_fping_in.c
@@ -0,0 +1,430 @@
1/******************************************************************************
2*
3* CHECK_INET_FPING.C
4*
5* Program: Fping plugin for Nagios
6* License: GPL
7* Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)
8* $Id$
9*
10* Modifications:
11*
12* 08-24-1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)
13* Intial Coding
14* 09-11-1999 Karl DeBisschop (kdebiss@alum.mit.edu)
15* Change to spopen
16* Fix so that state unknown is returned by default
17* (formerly would give state ok if no fping specified)
18* Add server_name to output
19* Reformat to 80-character standard screen
20* 11-18-1999 Karl DeBisschop (kdebiss@alum.mit.edu)
21* set STATE_WARNING of stderr written or nonzero status returned
22* 09-29-2000 Matthew Grant (matthewg@plain.co.nz)
23* changes for monitoring multiple hosts for checking Internet
24* reachibility
25*
26* Description:
27*
28* This plugin will use the /bin/fping command (from nagios) to ping
29* the specified host for a fast check if the host is alive. Note that
30* it is necessary to set the suid flag on fping.
31******************************************************************************/
32
33#include "config.h"
34#include "common.h"
35#include "popen.h"
36#include "utils.h"
37
38#define PROGNAME "check_fping"
39#define PACKET_COUNT 15
40#define PACKET_SIZE 56
41#define CRITICAL_COUNT 2
42#define WARNING_COUNT 1
43#define UNKNOWN_PACKET_LOSS 200 /* 200% */
44#define UNKNOWN_TRIP_TIME -1.0 /* -1 seconds */
45
46#define STRSZ 100
47
48int textscan(char *buf);
49int process_arguments(int, char **);
50int get_threshold (char *arg, char *rv[2]);
51void print_usage(void);
52void print_help(void);
53
54char *server_names=NULL;
55char *name="INTERNET";
56int cthresh=CRITICAL_COUNT;
57int wthresh=WARNING_COUNT;
58int nnames=0;
59int tpl=UNKNOWN_PACKET_LOSS;
60double trta=UNKNOWN_TRIP_TIME;
61int packet_size=PACKET_SIZE;
62int packet_count=PACKET_COUNT;
63int verbose=FALSE;
64int fail = 0;
65int not_found = 0;
66int rta_fail = 0;
67int pl_fail = 0;
68int unreachable = 0;
69
70int main(int argc, char **argv){
71 int result;
72 int status=STATE_UNKNOWN;
73 char *servers=NULL;
74 char *command_line=NULL;
75 char *input_buffer=NULL;
76 char *pl_buffer=NULL;
77 char *rta_buffer=NULL;
78 input_buffer=malloc(MAX_INPUT_BUFFER);
79 rta_buffer = malloc(80);
80 pl_buffer = malloc(80);
81 memset(rta_buffer, 0, 80);
82 memset(pl_buffer, 0, 80);
83
84 if(process_arguments(argc,argv)==ERROR)
85 usage("Could not parse arguments\n");
86
87 servers=strscpy(servers,server_names);
88
89 /* compose the command */
90 command_line=ssprintf
91 (command_line,"%s -b %d -c %d %s",
92 PATH_TO_FPING,
93 packet_size,
94 packet_count,
95 servers);
96
97 if (verbose) printf("%s\n",command_line);
98
99 /* run the command */
100 child_process=spopen(command_line);
101 if(child_process==NULL){
102 printf("Unable to open pipe: %s\n",command_line);
103 return STATE_UNKNOWN;
104 }
105
106 child_stderr=fdopen(child_stderr_array[fileno(child_process)],"r");
107 if(child_stderr==NULL){
108 printf("Could not open stderr for %s\n",command_line);
109 }
110
111 while (fgets(input_buffer,MAX_INPUT_BUFFER-1,child_process)) {
112 if (verbose) printf("%s",input_buffer);
113 result = textscan(input_buffer);
114 status = max(status,result);
115 }
116
117 while(fgets(input_buffer,MAX_INPUT_BUFFER-1,child_stderr)) {
118 if (verbose) printf("%s",input_buffer);
119 result = textscan(input_buffer);
120 status = max(status,result);
121 }
122
123 (void)fclose(child_stderr);
124
125 /* close the pipe */
126 if(spclose(child_process))
127 status=max(status,STATE_WARNING);
128
129 /* Analyse fail count and produce results */
130 if (fail >= wthresh) {
131 status = max(status, STATE_WARNING);
132 }
133
134 if (fail >= cthresh) {
135 status = max(status, STATE_CRITICAL);
136 }
137
138 if( tpl != UNKNOWN_PACKET_LOSS ) {
139 snprintf(pl_buffer, 80, ", %d PL", pl_fail);
140 }
141
142 if( trta != UNKNOWN_TRIP_TIME ) {
143 snprintf(rta_buffer, 80, ", %d RTA", rta_fail);
144
145 }
146
147 printf("FPING %s - %s, %d of %d fail, %d NF, %d UR%s%s\n",
148 state_text(status),
149 (name != NULL ? name : server_names),
150 fail,
151 nnames,
152 not_found,
153 unreachable,
154 pl_buffer,
155 rta_buffer);
156
157 return status;
158}
159
160
161
162/* analyse fping output - each event resulting in an increment of fail
163 * must be mutually exclusive. packet loss and round trip time analysed
164 * together, both at once just results in one increment of fail
165 */
166int textscan(char *buf)
167{
168 char *rtastr=NULL;
169 char *losstr=NULL;
170 double loss;
171 double rta;
172 int status=STATE_OK;
173
174 if (strstr(buf,"not found")) {
175 fail++;
176 not_found++;
177 } else if(strstr(buf,"xmt/rcv/%loss")
178 && strstr(buf,"min/avg/max")) {
179 losstr = strstr(buf,"=");
180 losstr = 1+strstr(losstr,"/");
181 losstr = 1+strstr(losstr,"/");
182 rtastr = strstr(buf,"min/avg/max");
183 rtastr = strstr(rtastr,"=");
184 rtastr = 1+index(rtastr,'/');
185 loss = strtod(losstr,NULL);
186 rta = strtod(rtastr,NULL);
187 /* Increment fail counter
188 */
189 if (tpl!=UNKNOWN_PACKET_LOSS && loss>tpl) {
190 fail++;
191 }
192 else if (trta!=UNKNOWN_TRIP_TIME && rta>trta) {
193 fail++;
194 }
195 else if (loss >= 100) {
196 fail++;
197 }
198 /* Increment other counters
199 */
200 if (trta!=UNKNOWN_TRIP_TIME && rta>trta)
201 rta_fail++;
202 if (tpl!=UNKNOWN_PACKET_LOSS && loss>tpl)
203 pl_fail++;
204 if (loss >= 100)
205 unreachable++;
206 } else if(strstr(buf,"xmt/rcv/%loss") ) {
207 losstr = strstr(buf,"=");
208 losstr = 1+strstr(losstr,"/");
209 losstr = 1+strstr(losstr,"/");
210 loss = strtod(losstr,NULL);
211 /* Increment fail counter
212 */
213 if (tpl!=UNKNOWN_PACKET_LOSS && loss>tpl) {
214 fail++;
215 }
216 else if (loss >= 100) {
217 fail++;
218 }
219 /* Increment other counters
220 */
221 if (tpl!=UNKNOWN_PACKET_LOSS && loss>tpl)
222 pl_fail++;
223 if (loss >= 100)
224 unreachable++;
225 }
226
227 return status;
228}
229
230
231
232
233/* process command-line arguments */
234int process_arguments(int argc, char **argv)
235{
236 int c;
237
238#ifdef HAVE_GETOPT_H
239 int option_index = 0;
240 static struct option long_options[] =
241 {
242 {"hostname" ,required_argument,0,'H'},
243 {"critical" ,required_argument,0,'c'},
244 {"warning" ,required_argument,0,'w'},
245 {"bytes" ,required_argument,0,'b'},
246 {"number" ,required_argument,0,'n'},
247 {"pl-threshold" ,required_argument,0,'p'},
248 {"rta-threshold" ,required_argument,0,'r'},
249 {"name" ,required_argument,0,'N'},
250 {"verbose" ,no_argument, 0,'v'},
251 {"version" ,no_argument, 0,'V'},
252 {"help" ,no_argument, 0,'h'},
253 {0,0,0,0}
254 };
255#else
256
257 if(argc<2) return ERROR;
258
259 if (!is_option(argv[1])){
260 server_names=argv[1];
261 argv[1]=argv[0];
262 argv=&argv[1];
263 argc--;
264 }
265#endif
266
267 while (1){
268#ifdef HAVE_GETOPT_H
269 c = getopt_long(argc,argv,"+hVvH:c:w:b:n:N:p:r:",long_options,&option_index);
270#else
271 c = getopt(argc,argv,"+hVvH:c:w:b:n:N:p:r:");
272#endif
273
274 if (c==-1||c==EOF||c==1)
275 break;
276
277 switch (c)
278 {
279 case '?': /* print short usage statement if args not parsable */
280 printf("%s: Unknown argument: %s\n\n",my_basename(argv[0]),optarg);
281 print_usage();
282 exit(STATE_UNKNOWN);
283 case 'h': /* help */
284 print_help();
285 exit(STATE_OK);
286 case 'V': /* version */
287 print_revision(my_basename(argv[0]),"$Revision$");
288 exit(STATE_OK);
289 case 'v': /* verbose mode */
290 verbose=TRUE;
291 break;
292 case 'H': /* hostname */
293 if(is_host(optarg)==FALSE){
294 printf("Invalid host name/address\n\n");
295 print_usage();
296 exit(STATE_UNKNOWN);
297 }
298 if (server_names != NULL)
299 server_names=strscat(server_names," ");
300 server_names=strscat(server_names,optarg);
301 nnames++;
302 break;
303 case 'c':
304 if (is_intpos(optarg))
305 cthresh = atoi(optarg);
306 else
307 usage("Critical threshold must be a positive integer");
308 break;
309 case 'w':
310 if (is_intpos(optarg))
311 wthresh = atoi(optarg);
312 else
313 usage("Warning threshold must be a postive integer");
314 break;
315 case 'r':
316 if (is_intpos(optarg)) {
317 trta=strtod(optarg,NULL);
318 }
319 else {
320 usage("RTA threshold must be a positive integer");
321 }
322 break;
323 case 'p':
324 if (is_intpos(optarg)) {
325 tpl=strtod(optarg,NULL);
326 }
327 else {
328 usage("RTA threshold must be a positive integer");
329 }
330 break;
331 case 'b': /* bytes per packet */
332 if (is_intpos(optarg))
333 packet_size=atoi(optarg);
334 else
335 usage("Packet size must be a positive integer");
336 break;
337 case 'N': /* Name of service */
338 name = optarg;
339 break;
340 case 'n': /* number of packets */
341 if (is_intpos(optarg))
342 packet_count=atoi(optarg);
343 else
344 usage("Packet count must be a positive integer");
345 break;
346 }
347 }
348
349 while (optind < argc) {
350 if(is_host(argv[optind])==FALSE) {
351 printf("Invalid host name/address\n\n");
352 print_usage();
353 exit(STATE_UNKNOWN);
354 }
355 if (server_names != NULL)
356 server_names=strscat(server_names," ");
357 server_names=strscat(server_names,argv[optind]);
358 nnames++;
359 optind++;
360 }
361
362 if (server_names==NULL || nnames < 2)
363 usage("At least 2 hostnames must be supplied\n\n");
364
365 if (cthresh < 2)
366 usage("Critical threshold must be at least 2");
367 if (cthresh > nnames)
368 usage("Critical threshold cannot be greater than number of hosts tested");
369 if (wthresh < 1)
370 usage("Warning threshold must be at least 1");
371 if (wthresh > nnames)
372 usage("Warning threshold cannot be greater than number of hosts tested");
373 if(wthresh >= cthresh)
374 usage("Warning threshold must be less than the critical threshold");
375
376 return OK;
377}
378
379
380void print_usage(void)
381{
382 printf("Usage: %s <host_address> <host_address> [<host_address>] ...\n",PROGNAME);
383}
384
385
386
387
388
389void print_help(void)
390{
391
392 print_revision(PROGNAME,"$Revision$");
393
394 printf
395 ("Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)\n"
396 " (c) 2000 Matthew Grant (matthewg@plain.co.nz)\n"
397 "This plugin will use the /bin/fping command (from saint) to ping the\n"
398 "specified hosts for a fast check to see if the Internet is still \n"
399 "reachable, and the results of the testing aggregated. Note that it\n"
400 "is necessary to set the suid flag on fping.\n\n");
401
402 print_usage();
403
404 printf
405 ("\nOptions:\n"
406 "-b, --bytes=INTEGER\n"
407 " Size of ICMP packet (default: %d)\n"
408 "-c, --critical=INTEGER (default: %d)\n"
409 " critical threshold failure count\n"
410 "-n, --number=INTEGER\n"
411 " Number of ICMP packets to send (default: %d)\n"
412 "-H, --hostname=HOST\n"
413 " Name or IP Address of host to ping (IP Address bypasses name lookup,\n"
414 " reducing system load)\n"
415 "-h, --help\n"
416 " Print this help screen\n"
417 "-N, --name\n"
418 " Service name to print in results, defaults to INTERNET\n"
419 "-p, --pl-threshold\n"
420 " Packet loss threshold - specify to turn on packet loss testing\n"
421 "-r, --rta-threshold\n"
422 " Round trip average threshold - specify to turn on RTA testing\n"
423 "-V, --version\n"
424 " Print version information\n"
425 "-v, --verbose\n"
426 " Show details for command-line debugging (do not use with nagios server)\n"
427 "-w, --warning=INTEGER (default: %d)\n"
428 " warning threshold failure count\n",
429 PACKET_SIZE, CRITICAL_COUNT, PACKET_COUNT, WARNING_COUNT);
430}