diff options
author | Ethan Galstad <egalstad@users.sourceforge.net> | 2002-02-28 06:42:51 (GMT) |
---|---|---|
committer | Ethan Galstad <egalstad@users.sourceforge.net> | 2002-02-28 06:42:51 (GMT) |
commit | 44a321cb8a42d6c0ea2d96a1086a17f2134c89cc (patch) | |
tree | a1a4d9f7b92412a17ab08f34f04eec45433048b7 /contrib/check_fping_in.c | |
parent | 54fd5d7022ff2d6a59bc52b8869182f3fc77a058 (diff) | |
download | monitoring-plugins-44a321cb8a42d6c0ea2d96a1086a17f2134c89cc.tar.gz |
Initial revision
git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@2 f882894a-f735-0410-b71e-b25c423dba1c
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 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 | |||
48 | int textscan(char *buf); | ||
49 | int process_arguments(int, char **); | ||
50 | int get_threshold (char *arg, char *rv[2]); | ||
51 | void print_usage(void); | ||
52 | void print_help(void); | ||
53 | |||
54 | char *server_names=NULL; | ||
55 | char *name="INTERNET"; | ||
56 | int cthresh=CRITICAL_COUNT; | ||
57 | int wthresh=WARNING_COUNT; | ||
58 | int nnames=0; | ||
59 | int tpl=UNKNOWN_PACKET_LOSS; | ||
60 | double trta=UNKNOWN_TRIP_TIME; | ||
61 | int packet_size=PACKET_SIZE; | ||
62 | int packet_count=PACKET_COUNT; | ||
63 | int verbose=FALSE; | ||
64 | int fail = 0; | ||
65 | int not_found = 0; | ||
66 | int rta_fail = 0; | ||
67 | int pl_fail = 0; | ||
68 | int unreachable = 0; | ||
69 | |||
70 | int 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 | */ | ||
166 | int 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 */ | ||
234 | int 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 | |||
380 | void print_usage(void) | ||
381 | { | ||
382 | printf("Usage: %s <host_address> <host_address> [<host_address>] ...\n",PROGNAME); | ||
383 | } | ||
384 | |||
385 | |||
386 | |||
387 | |||
388 | |||
389 | void 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 | } | ||