Code

Fixed reading too many argv parameters and changed to asprintf
[nagiosplug.git] / plugins / check_ping.c
index b61b41b503cc4ff6fd032293cd57504e2b49c91e..2526a74f451aa8037fae927d5fb0093e856890a6 100644 (file)
@@ -10,7 +10,7 @@
 *
 *****************************************************************************/
 
-#define PROGNAME "check_pgsql"
+const char *progname = "check_ping";
 #define REVISION "$Revision$"
 #define COPYRIGHT "1999-2001"
 #define AUTHOR "Ethan Galstad/Karl DeBisschop"
@@ -56,10 +56,9 @@ the contrib area of the downloads section at http://www.nagios.org\n\n"
 #define WARN_DUPLICATES "DUPLICATES FOUND! "
 
 int process_arguments (int, char **);
-int call_getopt (int, char **);
 int get_threshold (char *, float *, int *);
 int validate_arguments (void);
-int run_ping (char *);
+int run_ping (char *, char *);
 void print_usage (void);
 void print_help (void);
 
@@ -68,7 +67,9 @@ int wpl = UNKNOWN_PACKET_LOSS;
 int cpl = UNKNOWN_PACKET_LOSS;
 float wrta = UNKNOWN_TRIP_TIME;
 float crta = UNKNOWN_TRIP_TIME;
-char *server_address = NULL;
+char **addresses = NULL;
+int n_addresses;
+int max_addr = 1;
 int max_packets = -1;
 int verbose = FALSE;
 
@@ -82,18 +83,14 @@ main (int argc, char **argv)
 {
        char *command_line = NULL;
        int result = STATE_UNKNOWN;
+       int this_result = STATE_UNKNOWN;
+       int i;
+
+       addresses = malloc (max_addr);
 
        if (process_arguments (argc, argv) == ERROR)
                usage ("Could not parse arguments");
-
-       /* does the host address of number of packets argument come first? */
-#ifdef PING_PACKETS_FIRST
-       command_line =
-               ssprintf (command_line, PING_COMMAND, max_packets, server_address);
-#else
-       command_line =
-               ssprintf (command_line, PING_COMMAND, server_address, max_packets);
-#endif
+       exit;
 
        /* Set signal handling and alarm */
        if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
@@ -104,39 +101,55 @@ main (int argc, char **argv)
        /* handle timeouts gracefully */
        alarm (timeout_interval);
 
-       if (verbose)
-               printf ("%s ==> ", command_line);
+       for (i = 0 ; i < n_addresses ; i++) {
 
-       /* run the command */
-       run_ping (command_line);
+               /* does the host address of number of packets argument come first? */
+#ifdef PING_PACKETS_FIRST
+               asprintf (&command_line, PING_COMMAND, max_packets, addresses[i]);
+#else
+               asprintf (&command_line, PING_COMMAND, addresses[i], max_packets);
+#endif
 
-       if (pl == UNKNOWN_PACKET_LOSS || rta == UNKNOWN_TRIP_TIME) {
-               printf ("%s\n", command_line);
-               terminate (STATE_UNKNOWN,
-                                                        "Error: Could not interpret output from ping command\n");
-       }
+               if (verbose)
+                       printf ("%s ==> ", command_line);
 
-       if (pl >= cpl || rta >= crta || rta < 0)
-               result = STATE_CRITICAL;
-       else if (pl >= wpl || rta >= wrta)
-               result = STATE_WARNING;
-       else if (pl < wpl && rta < wrta && pl >= 0 && rta >= 0)
-               result = max (result, STATE_OK);
+               /* run the command */
+               this_result = run_ping (command_line, addresses[i]);
 
-       if (display_html == TRUE)
-               printf ("<A HREF='%s/traceroute.cgi?%s'>", CGIURL, server_address);
-       if (pl == 100)
-               printf ("PING %s - %sPacket loss = %d%%", state_text (result), warn_text,
-                                               pl);
-       else
-               printf ("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms",
-                                               state_text (result), warn_text, pl, rta);
-       if (display_html == TRUE)
-               printf ("</A>");
-       printf ("\n");
+               if (pl == UNKNOWN_PACKET_LOSS || rta == UNKNOWN_TRIP_TIME) {
+                       printf ("%s\n", command_line);
+                       terminate (STATE_UNKNOWN,
+                                                                "Error: Could not interpret output from ping command\n");
+               }
+
+               if (pl >= cpl || rta >= crta || rta < 0)
+                       this_result = STATE_CRITICAL;
+               else if (pl >= wpl || rta >= wrta)
+                       this_result = STATE_WARNING;
+               else if (pl >= 0 && rta >= 0)
+                       this_result = max_state (STATE_OK, this_result);        
+       
+               if (n_addresses > 1 && this_result != STATE_UNKNOWN)
+                       terminate (STATE_OK, "%s is alive\n", addresses[i]);
+
+               if (display_html == TRUE)
+                       printf ("<A HREF='%s/traceroute.cgi?%s'>", CGIURL, addresses[i]);
+               if (pl == 100)
+                       printf ("PING %s - %sPacket loss = %d%%", state_text (this_result), warn_text,
+                                                       pl);
+               else
+                       printf ("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms",
+                                                       state_text (this_result), warn_text, pl, rta);
+               if (display_html == TRUE)
+                       printf ("</A>");
+               printf ("\n");
+
+               if (verbose)
+                       printf ("%f:%d%% %f:%d%%\n", wrta, wpl, crta, cpl);
 
-       if (verbose)
-               printf ("%f:%d%% %f:%d%%\n", wrta, wpl, crta, cpl);
+               result = max_state (result, this_result);
+
+       }
 
        return result;
 }
@@ -146,7 +159,17 @@ main (int argc, char **argv)
 int
 process_arguments (int argc, char **argv)
 {
-       int c;
+       int c = 1;
+       char *ptr;
+
+       int option_index = 0;
+       static struct option long_options[] = {
+               STD_LONG_OPTS,
+               {"packets", required_argument, 0, 'p'},
+               {"nohtml", no_argument, 0, 'n'},
+               {"link", no_argument, 0, 'L'},
+               {0, 0, 0, 0}
+       };
 
        if (argc < 2)
                return ERROR;
@@ -158,138 +181,56 @@ process_arguments (int argc, char **argv)
                        strcpy (argv[c], "-n");
        }
 
-       c = 0;
-       while ((c += call_getopt (argc - c, &argv[c])) < argc) {
-
-               if (is_option (argv[c]))
-                       continue;
-
-               if (server_address == NULL) {
-                       if (is_host (argv[c]) == FALSE) {
-                               printf ("Invalid host name/address: %s\n\n", argv[c]);
-                               return ERROR;
-                       }
-                       server_address = argv[c];
-               }
-               else if (wpl == UNKNOWN_PACKET_LOSS) {
-                       if (is_intpercent (argv[c]) == FALSE) {
-                               printf ("<wpl> (%s) must be an integer percentage\n", argv[c]);
-                               return ERROR;
-                       }
-                       wpl = atoi (argv[c]);
-               }
-               else if (cpl == UNKNOWN_PACKET_LOSS) {
-                       if (is_intpercent (argv[c]) == FALSE) {
-                               printf ("<cpl> (%s) must be an integer percentage\n", argv[c]);
-                               return ERROR;
-                       }
-                       cpl = atoi (argv[c]);
-               }
-               else if (wrta == UNKNOWN_TRIP_TIME) {
-                       if (is_negative (argv[c])) {
-                               printf ("<wrta> (%s) must be a non-negative number\n", argv[c]);
-                               return ERROR;
-                       }
-                       wrta = atof (argv[c]);
-               }
-               else if (crta == UNKNOWN_TRIP_TIME) {
-                       if (is_negative (argv[c])) {
-                               printf ("<crta> (%s) must be a non-negative number\n", argv[c]);
-                               return ERROR;
-                       }
-                       crta = atof (argv[c]);
-               }
-               else if (max_packets == -1) {
-                       if (is_intnonneg (argv[c])) {
-                               max_packets = atoi (argv[c]);
-                       }
-                       else {
-                               printf ("<max_packets> (%s) must be a non-negative number\n",
-                                                               argv[c]);
-                               return ERROR;
-                       }
-               }
-
-       }
-
-       return validate_arguments ();
-}
-
-int
-call_getopt (int argc, char **argv)
-{
-       int c, i = 0;
-
-#ifdef HAVE_GETOPT_H
-       int option_index = 0;
-       static struct option long_options[] = {
-               {"help", no_argument, 0, 'h'},
-               {"version", no_argument, 0, 'V'},
-               {"verbose", no_argument, 0, 'v'},
-               {"nohtml", no_argument, 0, 'n'},
-               {"link", no_argument, 0, 'L'},
-               {"timeout", required_argument, 0, 't'},
-               {"critical", required_argument, 0, 'c'},
-               {"warning", required_argument, 0, 'w'},
-               {"hostname", required_argument, 0, 'H'},
-               {"packets", required_argument, 0, 'p'},
-               {0, 0, 0, 0}
-       };
-#endif
-
        while (1) {
-#ifdef HAVE_GETOPT_H
-               c =
-                       getopt_long (argc, argv, "+hVvt:c:w:H:p:nL", long_options,
-                                                                        &option_index);
-#else
-               c = getopt (argc, argv, "+hVvt:c:w:H:p:nL");
-#endif
+               c = getopt_long (argc, argv, "VvhnLt:c:w:H:p:", long_options, &option_index);
 
-               i++;
-
-               if (c == -1 || c == EOF || c == 1)
+               if (c == -1 || c == EOF)
                        break;
 
                switch (c) {
-               case 't':
-               case 'c':
-               case 'w':
-               case 'H':
-               case 'p':
-                       i++;
-               }
-
-               switch (c) {
-               case '?':                                                                       /* print short usage statement if args not parsable */
-                       usage2 ("Unknown argument", optarg);
-               case 'h':                                                                       /* help */
+               case '?':       /* usage */
+                       usage3 ("Unknown argument", optopt);
+               case 'h':       /* help */
                        print_help ();
                        exit (STATE_OK);
-               case 'V':                                                                       /* version */
-                       print_revision (PROGNAME, REVISION);
+               case 'V':       /* version */
+                       print_revision (progname, REVISION);
                        exit (STATE_OK);
-               case 't':                                                                       /* timeout period */
+               case 't':       /* timeout period */
                        timeout_interval = atoi (optarg);
                        break;
-               case 'v':                                                                       /* verbose mode */
+               case 'v':       /* verbose mode */
                        verbose = TRUE;
                        break;
-               case 'H':                                                                       /* hostname */
-                       if (is_host (optarg) == FALSE)
-                               usage2 ("Invalid host name/address", optarg);
-                       server_address = optarg;
+               case 'H':       /* hostname */
+                       ptr=optarg;
+                       while (1) {
+                               n_addresses++;
+                               if (n_addresses > max_addr) {
+                                       max_addr *= 2;
+                                       addresses = realloc (addresses, max_addr);
+                                       if (addresses == NULL)
+                                               terminate (STATE_UNKNOWN, "Could not realloc() addresses\n");
+                               }
+                               addresses[n_addresses-1] = ptr;
+                               if (ptr = index (ptr, ',')) {
+                                       strcpy (ptr, "");
+                                       ptr += sizeof(char);
+                               } else {
+                                       break;
+                               }
+                       }
                        break;
-               case 'p':                                                                       /* number of packets to send */
+               case 'p':       /* number of packets to send */
                        if (is_intnonneg (optarg))
                                max_packets = atoi (optarg);
                        else
                                usage2 ("<max_packets> (%s) must be a non-negative number\n", optarg);
                        break;
-               case 'n':                                                                       /* no HTML */
+               case 'n':       /* no HTML */
                        display_html = FALSE;
                        break;
-               case 'L':                                                                       /* show HTML */
+               case 'L':       /* show HTML */
                        display_html = TRUE;
                        break;
                case 'c':
@@ -301,7 +242,75 @@ call_getopt (int argc, char **argv)
                }
        }
 
-       return i;
+       c = optind;
+       if (c == argc)
+               return validate_arguments ();
+
+       if (addresses[0] == NULL) {
+               if (is_host (argv[c]) == FALSE) {
+                       printf ("Invalid host name/address: %s\n\n", argv[c]);
+                       return ERROR;
+               } else {
+                       addresses[0] = argv[c++];
+                       if (c == argc)
+                               return validate_arguments ();
+               }
+       }
+
+       if (wpl == UNKNOWN_PACKET_LOSS) {
+               if (is_intpercent (argv[c]) == FALSE) {
+                       printf ("<wpl> (%s) must be an integer percentage\n", argv[c]);
+                       return ERROR;
+               } else {
+                       wpl = atoi (argv[c++]);
+                       if (c == argc)
+                               return validate_arguments ();
+               }
+       }
+
+       if (cpl == UNKNOWN_PACKET_LOSS) {
+               if (is_intpercent (argv[c]) == FALSE) {
+                       printf ("<cpl> (%s) must be an integer percentage\n", argv[c]);
+                       return ERROR;
+               } else {
+                       cpl = atoi (argv[c++]);
+                       if (c == argc)
+                               return validate_arguments ();
+               }
+       }
+
+       if (wrta == UNKNOWN_TRIP_TIME) {
+               if (is_negative (argv[c])) {
+                       printf ("<wrta> (%s) must be a non-negative number\n", argv[c]);
+                       return ERROR;
+               } else {
+                       wrta = atof (argv[c++]);
+                       if (c == argc)
+                               return validate_arguments ();
+               }
+       }
+
+       if (crta == UNKNOWN_TRIP_TIME) {
+               if (is_negative (argv[c])) {
+                       printf ("<crta> (%s) must be a non-negative number\n", argv[c]);
+                       return ERROR;
+               } else {
+                       crta = atof (argv[c++]);
+                       if (c == argc)
+                               return validate_arguments ();
+               }
+       }
+
+       if (max_packets == -1) {
+               if (is_intnonneg (argv[c])) {
+                       max_packets = atoi (argv[c++]);
+               }       else {
+                       printf ("<max_packets> (%s) must be a non-negative number\n", argv[c]);
+                       return ERROR;
+               }
+       }
+
+       return validate_arguments ();
 }
 
 int
@@ -315,13 +324,13 @@ get_threshold (char *arg, float *trta, int *tpl)
                return OK;
        else
                usage2 ("%s: Warning threshold must be integer or percentage!\n\n", arg);
-
 }
 
 int
 validate_arguments ()
 {
        float max_seconds;
+       int i;
 
        if (wrta == UNKNOWN_TRIP_TIME) {
                printf ("<wrta> was not set\n");
@@ -355,12 +364,17 @@ validate_arguments ()
        if (max_seconds > timeout_interval)
                timeout_interval = (int)max_seconds;
 
+       for (i=0; i<n_addresses; i++) {
+               if (is_host(addresses[i]) == FALSE)
+                       usage2 ("Invalid host name/address", addresses[i]);
+       }
+
        return OK;
 }
 \f
 
 int
-run_ping (char *command_line)
+run_ping (char *command_line, char *server_address)
 {
        char input_buffer[MAX_INPUT_BUFFER];
        int result = STATE_UNKNOWN;
@@ -381,7 +395,12 @@ run_ping (char *command_line)
        while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
 
                if (strstr (input_buffer, "(DUP!)")) {
-                       result = max (result, STATE_WARNING);
+                       /* cannot use the max function since STATE_UNKNOWN is max
+                       result = max (result, STATE_WARNING); */
+                       if( !(result == STATE_CRITICAL) ){
+                               result = STATE_WARNING;
+                       }
+                       
                        warn_text = realloc (warn_text, strlen (WARN_DUPLICATES) + 1);
                        if (warn_text == NULL)
                                terminate (STATE_UNKNOWN, "unable to realloc warn_text");
@@ -390,12 +409,17 @@ run_ping (char *command_line)
 
                /* get the percent loss statistics */
                if (sscanf
-                               (input_buffer,
-                                "%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss",
-                                &pl) == 1
-                               || sscanf (input_buffer,
-                                                                        "%*d packets transmitted, %*d packets received, %d%% packet loss",
-                                                                        &pl) == 1)
+                                       (input_buffer, "%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss",
+                                                &pl) == 1
+                               || sscanf 
+                                       (input_buffer, "%*d packets transmitted, %*d packets received, %d%% packet loss",
+                                               &pl) == 1
+                               || sscanf 
+                                       (input_buffer, "%*d packets transmitted, %*d packets received, %d%% loss, time", &pl) == 1
+                               || sscanf
+                                       (input_buffer, "%*d packets transmitted, %*d received, %d%% loss, time", &pl) == 1
+                                       /* Suse 8.0 as reported by Richard * Brodie */
+                               )
                        continue;
 
                /* get the round trip average */
@@ -415,7 +439,10 @@ run_ping (char *command_line)
                                                                                 "round-trip min/avg/max/std-dev = %*f/%f/%*f/%*f",
                                                                                 &rta) == 1
                                        || sscanf (input_buffer, "round-trip (ms) min/avg/max = %*f/%f/%*f",
-                                                                                &rta) == 1)
+                                                                                &rta) == 1
+                                       || sscanf (input_buffer, "rtt min/avg/max/mdev = %*f/%f/%*f/%*f ms",
+                                                                                &rta) == 1
+                                                                               )
                        continue;
        }
 
@@ -437,6 +464,9 @@ run_ping (char *command_line)
                else if (strstr (input_buffer, "Destination Host Unreachable"))
                        terminate (STATE_CRITICAL, "PING CRITICAL - Host Unreachable (%s)",
                                                                 server_address);
+               else if (strstr (input_buffer, "unknown host" ) )
+                       terminate (STATE_CRITICAL, "PING CRITICAL - Host not found (%s)",
+                                                               server_address);
 
                warn_text =
                        realloc (warn_text, strlen (warn_text) + strlen (input_buffer) + 2);
@@ -447,40 +477,38 @@ run_ping (char *command_line)
                else
                        sprintf (warn_text, "%s %s", warn_text, input_buffer);
 
-               if (strstr (input_buffer, "DUPLICATES FOUND"))
-                       result = max (result, STATE_WARNING);
+               if (strstr (input_buffer, "DUPLICATES FOUND")) {
+                       if( !(result == STATE_CRITICAL) ){
+                               result = STATE_WARNING;
+                       }
+               }
                else
-                       result = max (result, STATE_CRITICAL);
+                       result = STATE_CRITICAL ;
        }
        (void) fclose (child_stderr);
 
 
        /* close the pipe - WARNING if status is set */
        if (spclose (child_process))
-               result = max (result, STATE_WARNING);
+               result = max_state (result, STATE_WARNING);
 
        return result;
 }
-\f
+
 
 void
 print_usage (void)
 {
        printf ("Usage:\n" " %s %s\n"
-#ifdef HAVE_GETOPT_H
                                        " %s (-h | --help) for detailed help\n"
                                        " %s (-V | --version) for version information\n",
-#else
-                                       " %s -h for detailed help\n"
-                                       " %s -V for version information\n",
-#endif
-                                       PROGNAME, OPTIONS, PROGNAME, PROGNAME);
+                                       progname, OPTIONS, progname, progname);
 }
 
 void
 print_help (void)
 {
-       print_revision (PROGNAME, REVISION);
+       print_revision (progname, REVISION);
        printf
                ("Copyright (c) %s %s <%s>\n\n%s\n",
                 COPYRIGHT, AUTHOR, EMAIL, SUMMARY);