summaryrefslogtreecommitdiffstats
path: root/web/attachments/454482-check_ping.c
diff options
context:
space:
mode:
Diffstat (limited to 'web/attachments/454482-check_ping.c')
-rw-r--r--web/attachments/454482-check_ping.c622
1 files changed, 622 insertions, 0 deletions
diff --git a/web/attachments/454482-check_ping.c b/web/attachments/454482-check_ping.c
new file mode 100644
index 0000000..6e0d2ed
--- /dev/null
+++ b/web/attachments/454482-check_ping.c
@@ -0,0 +1,622 @@
1/*****************************************************************************
2*
3* Nagios check_ping plugin
4*
5* License: GPL
6* Copyright (c) 2000-2007 Nagios Plugins Development Team
7*
8* Description:
9*
10* This file contains the check_ping plugin
11*
12* Use the ping program to check connection statistics for a remote host.
13*
14*
15* This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version.
19*
20* This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details.
24*
25* You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>.
27*
28* Olli = additions from Oliver to specify the used Interface
29*
30*****************************************************************************/
31
32const char *progname = "check_ping";
33const char *copyright = "2000-2007";
34const char *email = "nagiosplug-devel@lists.sourceforge.net";
35
36#include "common.h"
37#include "netutils.h"
38#include "popen.h"
39#include "utils.h"
40
41#define WARN_DUPLICATES "DUPLICATES FOUND! "
42#define UNKNOWN_TRIP_TIME -1.0 /* -1 seconds */
43
44enum {
45 UNKNOWN_PACKET_LOSS = 200, /* 200% */
46 DEFAULT_MAX_PACKETS = 5 /* default no. of ICMP ECHO packets */
47};
48
49int process_arguments (int, char **);
50int get_threshold (char *, float *, int *);
51int validate_arguments (void);
52int run_ping (const char *cmd, const char *addr);
53int error_scan (char buf[MAX_INPUT_BUFFER], const char *addr);
54void print_usage (void);
55void print_help (void);
56
57int display_html = FALSE;
58int wpl = UNKNOWN_PACKET_LOSS;
59int cpl = UNKNOWN_PACKET_LOSS;
60float wrta = UNKNOWN_TRIP_TIME;
61float crta = UNKNOWN_TRIP_TIME;
62char **addresses = NULL;
63int n_addresses = 0;
64int max_addr = 1;
65int max_packets = -1;
66int verbose = 0;
67
68float rta = UNKNOWN_TRIP_TIME;
69int pl = UNKNOWN_PACKET_LOSS;
70
71char *warn_text;
72
73char *interface = "\0"; /*Olli*/
74char *r_command = NULL; /*Olli*/
75
76int
77main (int argc, char **argv)
78{
79 char *cmd = NULL;
80 char *rawcmd = NULL;
81 int result = STATE_UNKNOWN;
82 int this_result = STATE_UNKNOWN;
83 int i;
84
85 setlocale (LC_ALL, "");
86 setlocale (LC_NUMERIC, "C");
87 bindtextdomain (PACKAGE, LOCALEDIR);
88 textdomain (PACKAGE);
89
90 addresses = malloc (sizeof(char*) * max_addr);
91 addresses[0] = NULL;
92
93 /* Parse extra opts if any */
94 argv=np_extra_opts (&argc, argv, progname);
95
96 if (process_arguments (argc, argv) == ERROR)
97 usage4 (_("Could not parse arguments"));
98
99 /* Set signal handling and alarm */
100 if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
101 usage4 (_("Cannot catch SIGALRM"));
102 }
103
104 /* If ./configure finds ping has timeout values, set plugin alarm slightly
105 * higher so that we can use response from command line ping */
106#if defined(PING_PACKETS_FIRST) && defined(PING_HAS_TIMEOUT)
107 alarm (timeout_interval + 1);
108#else
109 alarm (timeout_interval);
110#endif
111
112 for (i = 0 ; i < n_addresses ; i++) {
113
114#ifdef PING6_COMMAND
115 if (address_family != AF_INET && is_inet6_addr(addresses[i]))
116 rawcmd = strdup(PING6_COMMAND);
117 else
118 rawcmd = strdup(PING_COMMAND);
119#else
120 rawcmd = strdup(PING_COMMAND);
121#endif
122
123 /* does the host address of number of packets argument come first? */
124#ifdef PING_PACKETS_FIRST
125# ifdef PING_HAS_TIMEOUT
126 asprintf (&cmd, rawcmd, timeout_interval, max_packets, addresses[i]);
127# else
128 asprintf (&cmd, rawcmd, max_packets, addresses[i]);
129# endif
130#else
131 asprintf (&cmd, rawcmd, addresses[i], max_packets);
132#endif
133
134 if (verbose >= 2)
135 printf ("CMD: %s\n", cmd);
136
137 /* run the command */
138
139 if ( strlen (interface) != 0) {
140 /*Olli*/
141 asprintf (&r_command,"%s -I %s", cmd, interface);
142 /*Olli*/
143 cmd = r_command;
144 /*Olli*/
145 }
146 /*Olli*/
147
148 this_result = run_ping (cmd, addresses[i]);
149
150 if (pl == UNKNOWN_PACKET_LOSS || rta < 0.0) {
151 printf ("%s\n", cmd);
152 die (STATE_UNKNOWN,
153 _("CRITICAL - Could not interpret output from ping command\n"));
154 }
155
156 if (pl >= cpl || rta >= crta || rta < 0)
157 this_result = STATE_CRITICAL;
158 else if (pl >= wpl || rta >= wrta)
159 this_result = STATE_WARNING;
160 else if (pl >= 0 && rta >= 0)
161 this_result = max_state (STATE_OK, this_result);
162
163 if (n_addresses > 1 && this_result != STATE_UNKNOWN)
164 die (STATE_OK, "%s is alive\n", addresses[i]);
165
166 if (display_html == TRUE)
167 printf ("<A HREF='%s/traceroute.cgi?%s'>", CGIURL, addresses[i]);
168 if (pl == 100)
169 printf (_("PING %s - %sPacket loss = %d%%"), state_text (this_result), warn_text,
170 pl);
171 else
172 printf (_("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms"),
173 state_text (this_result), warn_text, pl, rta);
174 if (display_html == TRUE)
175 printf ("</A>");
176
177 /* Print performance data */
178 printf("|%s", fperfdata ("rta", (double) rta, "ms",
179 wrta>0?TRUE:FALSE, wrta,
180 crta>0?TRUE:FALSE, crta,
181 TRUE, 0, FALSE, 0));
182 printf(" %s\n", perfdata ("pl", (long) pl, "%",
183 wpl>0?TRUE:FALSE, wpl,
184 cpl>0?TRUE:FALSE, cpl,
185 TRUE, 0, FALSE, 0));
186
187 if (verbose >= 2)
188 printf ("%f:%d%% %f:%d%%\n", wrta, wpl, crta, cpl);
189
190 result = max_state (result, this_result);
191 free (rawcmd);
192 free (cmd);
193 }
194
195 return result;
196}
197
198
199
200/* process command-line arguments */
201int
202process_arguments (int argc, char **argv)
203{
204 int c = 1;
205 char *ptr;
206
207 int option = 0;
208 static struct option longopts[] = {
209 STD_LONG_OPTS,
210 {"packets", required_argument, 0, 'p'},
211 {"nohtml", no_argument, 0, 'n'},
212 {"link", no_argument, 0, 'L'},
213 {"use-ipv4", no_argument, 0, '4'},
214 {"use-ipv6", no_argument, 0, '6'},
215 {"interface", required_argument, 0 ,'I'}, /*Olli*/
216 {0, 0, 0, 0}
217 };
218
219 if (argc < 2)
220 return ERROR;
221
222 for (c = 1; c < argc; c++) {
223 if (strcmp ("-to", argv[c]) == 0)
224 strcpy (argv[c], "-t");
225 if (strcmp ("-nohtml", argv[c]) == 0)
226 strcpy (argv[c], "-n");
227 }
228
229 while (1) {
230 c = getopt_long (argc, argv, "VvhnL46t:c:w:H:p:I:", longopts, &option); /*Olli*/
231
232 if (c == -1 || c == EOF)
233 break;
234
235 switch (c) {
236 case '?': /* usage */
237 usage5 ();
238 case 'h': /* help */
239 print_help ();
240 exit (STATE_OK);
241 break;
242 case 'V': /* version */
243 print_revision (progname, NP_VERSION);
244 exit (STATE_OK);
245 break;
246 case 't': /* timeout period */
247 timeout_interval = atoi (optarg);
248 break;
249 case 'v': /* verbose mode */
250 verbose++;
251 break;
252 case '4': /* IPv4 only */
253 address_family = AF_INET;
254 break;
255 case '6': /* IPv6 only */
256#ifdef USE_IPV6
257 address_family = AF_INET6;
258#else
259 usage (_("IPv6 support not available\n"));
260#endif
261 break;
262 case 'H': /* hostname */
263 ptr=optarg;
264 while (1) {
265 n_addresses++;
266 if (n_addresses > max_addr) {
267 max_addr *= 2;
268 addresses = realloc (addresses, sizeof(char*) * max_addr);
269 if (addresses == NULL)
270 die (STATE_UNKNOWN, _("Could not realloc() addresses\n"));
271 }
272 addresses[n_addresses-1] = ptr;
273 if ((ptr = index (ptr, ','))) {
274 strcpy (ptr, "");
275 ptr += sizeof(char);
276 } else {
277 break;
278 }
279 }
280 break;
281 case 'p': /* number of packets to send */
282 if (is_intnonneg (optarg))
283 max_packets = atoi (optarg);
284 else
285 usage2 (_("<max_packets> (%s) must be a non-negative number\n"), optarg);
286 break;
287 case 'n': /* no HTML */
288 display_html = FALSE;
289 break;
290 case 'L': /* show HTML */
291 display_html = TRUE;
292 break;
293 case 'c':
294 get_threshold (optarg, &crta, &cpl);
295 break;
296 case 'w':
297 get_threshold (optarg, &wrta, &wpl);
298 break;
299 case 'I': /* Interface used for Ping*/ /*Olli*/
300 interface = optarg; /*Olli*/
301 break; /*Olli*/
302 }
303 }
304
305 c = optind;
306 if (c == argc)
307 return validate_arguments ();
308
309 if (addresses[0] == NULL) {
310 if (is_host (argv[c]) == FALSE) {
311 usage2 (_("Invalid hostname/address"), argv[c]);
312 } else {
313 addresses[0] = argv[c++];
314 n_addresses++;
315 if (c == argc)
316 return validate_arguments ();
317 }
318 }
319
320 if (wpl == UNKNOWN_PACKET_LOSS) {
321 if (is_intpercent (argv[c]) == FALSE) {
322 printf (_("<wpl> (%s) must be an integer percentage\n"), argv[c]);
323 return ERROR;
324 } else {
325 wpl = atoi (argv[c++]);
326 if (c == argc)
327 return validate_arguments ();
328 }
329 }
330
331 if (cpl == UNKNOWN_PACKET_LOSS) {
332 if (is_intpercent (argv[c]) == FALSE) {
333 printf (_("<cpl> (%s) must be an integer percentage\n"), argv[c]);
334 return ERROR;
335 } else {
336 cpl = atoi (argv[c++]);
337 if (c == argc)
338 return validate_arguments ();
339 }
340 }
341
342 if (wrta < 0.0) {
343 if (is_negative (argv[c])) {
344 printf (_("<wrta> (%s) must be a non-negative number\n"), argv[c]);
345 return ERROR;
346 } else {
347 wrta = atof (argv[c++]);
348 if (c == argc)
349 return validate_arguments ();
350 }
351 }
352
353 if (crta < 0.0) {
354 if (is_negative (argv[c])) {
355 printf (_("<crta> (%s) must be a non-negative number\n"), argv[c]);
356 return ERROR;
357 } else {
358 crta = atof (argv[c++]);
359 if (c == argc)
360 return validate_arguments ();
361 }
362 }
363
364 if (max_packets == -1) {
365 if (is_intnonneg (argv[c])) {
366 max_packets = atoi (argv[c++]);
367 } else {
368 printf (_("<max_packets> (%s) must be a non-negative number\n"), argv[c]);
369 return ERROR;
370 }
371 }
372
373 return validate_arguments ();
374}
375
376
377
378int
379get_threshold (char *arg, float *trta, int *tpl)
380{
381 if (is_intnonneg (arg) && sscanf (arg, "%f", trta) == 1)
382 return OK;
383 else if (strpbrk (arg, ",:") && strstr (arg, "%") && sscanf (arg, "%f%*[:,]%d%%", trta, tpl) == 2)
384 return OK;
385 else if (strstr (arg, "%") && sscanf (arg, "%d%%", tpl) == 1)
386 return OK;
387
388 usage2 (_("%s: Warning threshold must be integer or percentage!\n\n"), arg);
389 return STATE_UNKNOWN;
390}
391
392int
393validate_arguments ()
394{
395 float max_seconds;
396 int i;
397
398 if (wrta < 0.0) {
399 printf (_("<wrta> was not set\n"));
400 return ERROR;
401 }
402 else if (crta < 0.0) {
403 printf (_("<crta> was not set\n"));
404 return ERROR;
405 }
406 else if (wpl == UNKNOWN_PACKET_LOSS) {
407 printf (_("<wpl> was not set\n"));
408 return ERROR;
409 }
410 else if (cpl == UNKNOWN_PACKET_LOSS) {
411 printf (_("<cpl> was not set\n"));
412 return ERROR;
413 }
414 else if (wrta > crta) {
415 printf (_("<wrta> (%f) cannot be larger than <crta> (%f)\n"), wrta, crta);
416 return ERROR;
417 }
418 else if (wpl > cpl) {
419 printf (_("<wpl> (%d) cannot be larger than <cpl> (%d)\n"), wpl, cpl);
420 return ERROR;
421 }
422
423 if (max_packets == -1)
424 max_packets = DEFAULT_MAX_PACKETS;
425
426 max_seconds = crta / 1000.0 * max_packets + max_packets;
427 if (max_seconds > timeout_interval)
428 timeout_interval = (int)max_seconds;
429
430 for (i=0; i<n_addresses; i++) {
431 if (is_host(addresses[i]) == FALSE)
432 usage2 (_("Invalid hostname/address"), addresses[i]);
433 }
434
435 if (n_addresses == 0) {
436 usage (_("You must specify a server address or host name"));
437 }
438
439 return OK;
440}
441
442
443
444int
445run_ping (const char *cmd, const char *addr)
446{
447 char buf[MAX_INPUT_BUFFER];
448 int result = STATE_UNKNOWN;
449 int match;
450
451 if ((child_process = spopen (cmd)) == NULL)
452 die (STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd);
453
454 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
455 if (child_stderr == NULL)
456 printf (_("Cannot open stderr for %s\n"), cmd);
457
458 while (fgets (buf, MAX_INPUT_BUFFER - 1, child_process)) {
459
460 if (verbose >= 3)
461 printf("Output: %s", buf);
462
463 result = max_state (result, error_scan (buf, addr));
464
465 /* get the percent loss statistics */
466 match = 0;
467 if((sscanf(buf,"%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) ||
468 (sscanf(buf,"%*d packets transmitted, %*d packets received, +%*d duplicates, %d%% packet loss%n",&pl,&match) && match) ||
469 (sscanf(buf,"%*d packets transmitted, %*d received, +%*d duplicates, %d%% packet loss%n",&pl,&match) && match) ||
470 (sscanf(buf,"%*d packets transmitted, %*d packets received, %d%% packet loss%n",&pl,&match) && match) ||
471 (sscanf(buf,"%*d packets transmitted, %*d packets received, %d%% loss, time%n",&pl,&match) && match) ||
472 (sscanf(buf,"%*d packets transmitted, %*d received, %d%% loss, time%n",&pl,&match) && match) ||
473 (sscanf(buf,"%*d packets transmitted, %*d received, %d%% packet loss, time%n",&pl,&match) && match) ||
474 (sscanf(buf,"%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss%n",&pl,&match) && match) ||
475 (sscanf(buf,"%*d packets transmitted %*d received, +%*d errors, %d%% packet loss%n",&pl,&match) && match)
476 )
477 continue;
478
479 /* get the round trip average */
480 else
481 if((sscanf(buf,"round-trip min/avg/max = %*f/%f/%*f%n",&rta,&match) && match) ||
482 (sscanf(buf,"round-trip min/avg/max/mdev = %*f/%f/%*f/%*f%n",&rta,&match) && match) ||
483 (sscanf(buf,"round-trip min/avg/max/sdev = %*f/%f/%*f/%*f%n",&rta,&match) && match) ||
484 (sscanf(buf,"round-trip min/avg/max/stddev = %*f/%f/%*f/%*f%n",&rta,&match) && match) ||
485 (sscanf(buf,"round-trip min/avg/max/std-dev = %*f/%f/%*f/%*f%n",&rta,&match) && match) ||
486 (sscanf(buf,"round-trip (ms) min/avg/max = %*f/%f/%*f%n",&rta,&match) && match) ||
487 (sscanf(buf,"round-trip (ms) min/avg/max/stddev = %*f/%f/%*f/%*f%n",&rta,&match) && match) ||
488 (sscanf(buf,"rtt min/avg/max/mdev = %*f/%f/%*f/%*f ms%n",&rta,&match) && match))
489 continue;
490 }
491
492 /* this is needed because there is no rta if all packets are lost */
493 if (pl == 100)
494 rta = crta;
495
496 /* check stderr, setting at least WARNING if there is output here */
497 /* Add warning into warn_text */
498 while (fgets (buf, MAX_INPUT_BUFFER - 1, child_stderr)) {
499 if (! strstr(buf,"WARNING - no SO_TIMESTAMP support, falling back to SIOCGSTAMP")) {
500 if (verbose >= 3) {
501 printf("Got stderr: %s", buf);
502 }
503 if ((result=error_scan(buf, addr)) == STATE_OK) {
504 result = STATE_WARNING;
505 if (warn_text == NULL) {
506 warn_text = strdup(_("System call sent warnings to stderr "));
507 } else {
508 asprintf(&warn_text, "%s %s", warn_text, _("System call sent warnings to stderr "));
509 }
510 }
511 }
512 }
513
514 (void) fclose (child_stderr);
515
516
517 spclose (child_process);
518
519 if (warn_text == NULL)
520 warn_text = strdup("");
521
522 return result;
523}
524
525
526
527int
528error_scan (char buf[MAX_INPUT_BUFFER], const char *addr)
529{
530 if (strstr (buf, "Network is unreachable") ||
531 strstr (buf, "Destination Net Unreachable")
532 )
533 die (STATE_CRITICAL, _("CRITICAL - Network Unreachable (%s)\n"), addr);
534 else if (strstr (buf, "Destination Host Unreachable"))
535 die (STATE_CRITICAL, _("CRITICAL - Host Unreachable (%s)\n"), addr);
536 else if (strstr (buf, "Destination Port Unreachable"))
537 die (STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Port Unreachable (%s)\n"), addr);
538 else if (strstr (buf, "Destination Protocol Unreachable"))
539 die (STATE_CRITICAL, _("CRITICAL - Bogus ICMP: Protocol Unreachable (%s)\n"), addr);
540 else if (strstr (buf, "Destination Net Prohibited"))
541 die (STATE_CRITICAL, _("CRITICAL - Network Prohibited (%s)\n"), addr);
542 else if (strstr (buf, "Destination Host Prohibited"))
543 die (STATE_CRITICAL, _("CRITICAL - Host Prohibited (%s)\n"), addr);
544 else if (strstr (buf, "Packet filtered"))
545 die (STATE_CRITICAL, _("CRITICAL - Packet Filtered (%s)\n"), addr);
546 else if (strstr (buf, "unknown host" ))
547 die (STATE_CRITICAL, _("CRITICAL - Host not found (%s)\n"), addr);
548 else if (strstr (buf, "Time to live exceeded"))
549 die (STATE_CRITICAL, _("CRITICAL - Time to live exceeded (%s)\n"), addr);
550 else if (strstr (buf, "Destination unreachable: "))
551 die (STATE_CRITICAL, _("CRITICAL - Destination Unreachable (%s)\n"), addr);
552
553 if (strstr (buf, "(DUP!)") || strstr (buf, "DUPLICATES FOUND")) {
554 if (warn_text == NULL)
555 warn_text = strdup (_(WARN_DUPLICATES));
556 else if (! strstr (warn_text, _(WARN_DUPLICATES)) &&
557 asprintf (&warn_text, "%s %s", warn_text, _(WARN_DUPLICATES)) == -1)
558 die (STATE_UNKNOWN, _("Unable to realloc warn_text\n"));
559 return (STATE_WARNING);
560 }
561
562 return (STATE_OK);
563}
564
565
566
567void
568print_help (void)
569{
570 print_revision (progname, NP_VERSION);
571
572 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
573 printf (COPYRIGHT, copyright, email);
574
575 printf (_("Use ping to check connection statistics for a remote host."));
576
577 printf ("\n\n");
578
579 print_usage ();
580
581 printf (UT_HELP_VRSN);
582 printf (UT_EXTRA_OPTS);
583
584 printf (UT_IPv46);
585
586 printf (" %s\n", "-H, --hostname=HOST");
587 printf (" %s\n", _("host to ping"));
588 printf (" %s\n", "-w, --warning=THRESHOLD");
589 printf (" %s\n", _("warning threshold pair"));
590 printf (" %s\n", "-c, --critical=THRESHOLD");
591 printf (" %s\n", _("critical threshold pair"));
592 printf (" %s\n", "-p, --packets=INTEGER");
593 printf (" %s ", _("number of ICMP ECHO packets to send"));
594 printf (_("(Default: %d)\n"), DEFAULT_MAX_PACKETS);
595 printf (" %s\n", "-I, --interface=INTERFACE"); /*Olli*/
596 printf (" %s ", _("Specify the interface which is used for pinging (Requires iputils-ping)")); /*Olli*/
597 printf (" %s\n", "-L, --link");
598 printf (" %s\n", _("show HTML in the plugin output (obsoleted by urlize)"));
599
600 printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
601
602 printf ("\n");
603 printf ("%s\n", _("THRESHOLD is <rta>,<pl>% where <rta> is the round trip average travel"));
604 printf ("%s\n", _("time (ms) which triggers a WARNING or CRITICAL state, and <pl> is the"));
605 printf ("%s\n", _("percentage of packet loss to trigger an alarm state."));
606
607 printf ("\n");
608 printf ("%s\n", _("This plugin uses the ping command to probe the specified host for packet loss"));
609 printf ("%s\n", _("(percentage) and round trip average (milliseconds). It can produce HTML output"));
610 printf ("%s\n", _("linking to a traceroute CGI contributed by Ian Cass. The CGI can be found in"));
611 printf ("%s\n", _("the contrib area of the downloads section at http://www.nagios.org/"));
612
613 printf (UT_SUPPORT);
614}
615
616void
617print_usage (void)
618{
619 printf ("%s\n", _("Usage:"));
620 printf ("%s -H <host_address> -w <wrta>,<wpl>%% -c <crta>,<cpl>%%\n", progname);
621 printf (" [-p packets] [-t timeout] [-4|-6] [-I interface] \n"); /*Olli*/
622}