diff -ruN nagios-plugins-1.3.1/plugins/check_dns.c nagios-plugins-1.3.1-new/plugins/check_dns.c --- nagios-plugins-1.3.1/plugins/check_dns.c 2003-05-31 15:39:33.000000000 +0100 +++ nagios-plugins-1.3.1-new/plugins/check_dns.c 2003-07-14 19:59:16.000000000 +0100 @@ -11,6 +11,7 @@ * Notes: * - Safe popen added by Karl DeBisschop 9-11-99 * - expected-address parameter added by Alex Chaffee - 7 Oct 2002 + * - extended to use RESOLVER, HOST or NSLOOKUP by Howard Wilkinson - 24 March 2003 * * Command line: (see print_usage) * @@ -46,6 +47,28 @@ #include "common.h" #include "popen.h" + +#ifdef USE_NSLOOKUP +# if !defined(NSLOOKUP_COMMAND) +# error "Need NSLOOKUP to use this option" +# endif +#endif +#ifdef USE_HOST +# if !defined(HOST_COMMAND) +# error "Need HOST to use this option" +# endif +#endif +#if defined(USE_NSLOOKUP) +# undef USE_HOST +# undef USE_RESOLVER +#elif defined(USE_HOST) +# undef USE_RESOLVER +#elif !defined(USE_RESOLVER) +# define USE_NSLOOKUP +#endif +#ifdef USE_RESOLVER +#include "netutils.h" +#endif #include "utils.h" const char *progname = "check_dns"; @@ -58,7 +81,9 @@ void print_help (void); int error_scan (char *); -#define ADDRESS_LENGTH 256 +#define ADDRESS_LENGTH 10240 +#define RRTYPE_LENGTH 32 +char record_type[RRTYPE_LENGTH] = "A"; char query_address[ADDRESS_LENGTH] = ""; char dns_server[ADDRESS_LENGTH] = ""; char ptr_server[ADDRESS_LENGTH] = ""; @@ -69,144 +94,293 @@ int main (int argc, char **argv) { - char *command_line = NULL; - char input_buffer[MAX_INPUT_BUFFER]; - char *output = NULL; - char *address = NULL; - char *temp_buffer = NULL; - int result = STATE_UNKNOWN; - - /* Set signal handling and alarm */ - if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) { - printf ("Cannot catch SIGALRM"); - return STATE_UNKNOWN; + char *command_line = NULL; + char input_buffer[MAX_INPUT_BUFFER]; + char *output = NULL; + char *address = NULL; + char *temp_buffer = NULL; + int result = STATE_UNKNOWN; + int linecnt = 0; + + /* Set signal handling and alarm */ + if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) { + printf ("Cannot catch SIGALRM"); + return STATE_UNKNOWN; + } + if (process_arguments (argc, argv) != OK) { + print_usage (); + return STATE_UNKNOWN; + } + /* get the command to run */ +#ifdef USE_RESOLVER +#error "THIS CODE DOES NOT WORK" + { + int i; + struct hostent *response; + res_init(); + if (strlen(dns_server)) { + if ((response=gethostbyname(dns_server)) == NULL) { + printf ("DNS problem = server %s can not be resolved %s\n", + dns_server, strerror(h_errno)); + return STATE_CRITICAL; + } else { + _res.nscount = response->h_length; + for (i = 0; i < response->h_length && i < MAXNS; i++) { + if (response->h_addr_list[i] == NULL) { + break; + } + _res.nsaddr_list[i].sin_family = AF_INET; + _res.nsaddr_list[i].sin_port = NS_DEFAULTPORT; + _res.nsaddr_list[i].sin_addr.s_addr = ((struct in_addr *)response->h_addr_list[i])->s_addr; } - - if (process_arguments (argc, argv) != OK) { - print_usage (); - return STATE_UNKNOWN; + } + _res.options &= ~(RES_RECURSE|RES_DEFNAMES); + } + if ((response=gethostbyname(query_address)) == NULL) { + asprintf (&output, "lookup failed with %s", strerror(h_errno)); + result = STATE_CRITICAL; + } else { + int len=0; + struct in_addr in; + for (i = 0; i < response->h_length; i++) { + if (response->h_addr_list[i] == NULL) { + break; } - - /* get the command to run */ - asprintf (&command_line, "%s %s %s", NSLOOKUP_COMMAND, query_address, dns_server); - - alarm (timeout_interval); - time (&start_time); - - if (verbose) - printf ("%s\n", command_line); - /* run the command */ - child_process = spopen (command_line); - if (child_process == NULL) { - printf ("Could not open pipe: %s\n", command_line); - return STATE_UNKNOWN; + memcpy(&in, ((struct in_addr *)response->h_addr_list[i]), sizeof(in)); + len+=strlen(inet_ntoa(in))+1; + } + address =(char *)malloc(len); + address[0]='\0'; + for (i = 0; i < response->h_length; i++) { + if (response->h_addr_list[i] == NULL) { + break; } - - child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); - if (child_stderr == NULL) - printf ("Could not open stderr for %s\n", command_line); - - /* scan stdout */ - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { - - if (verbose) - printf ("%s\n", input_buffer); - - if (strstr (input_buffer, ".in-addr.arpa")) { - if ((temp_buffer = strstr (input_buffer, "name = "))) - address = strscpy (address, temp_buffer + 7); - else { - output = strscpy (output, "Unknown error (plugin)"); - result = STATE_WARNING; - } - } - - /* the server is responding, we just got the host name... */ - if (strstr (input_buffer, "Name:")) { - - /* get the host address */ - if (!fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) - break; - - if (verbose) - printf ("%s\n", input_buffer); - - if ((temp_buffer = index (input_buffer, ':'))) { - temp_buffer++; - /* Strip leading spaces */ - for (; *temp_buffer != '\0' && *temp_buffer == ' '; temp_buffer++) - /* NOOP */; - address = strdup (temp_buffer); - strip (address); - if (address==NULL || strlen(address)==0) - terminate (STATE_CRITICAL, - "DNS CRITICAL - '%s' returned empty host name string\n", - NSLOOKUP_COMMAND); - result = STATE_OK; - } - else { - output = strdup ("Unknown error (plugin)"); - result = STATE_WARNING; - } - - break; - } - - result = error_scan (input_buffer); - if (result != STATE_OK) { - output = strscpy (output, 1 + index (input_buffer, ':')); - break; - } - + memcpy(&in, ((struct in_addr*)response->h_addr_list[i]), sizeof(in)); + strcat(address, inet_ntoa(in)); + strcat(address, ","); + } + address[strlen(address)-1]='\0'; + result = STATE_OK; + } + } +#endif +#ifdef USE_NSLOOKUP + asprintf (&command_line, "%s -timeout=%d -query=%s %s %s", + NSLOOKUP_COMMAND, timeout_interval-1, + record_type, query_address, dns_server); +#endif +#ifdef USE_HOST +#error "HOST IS NOT IMPLEMENTED YET" + asprintf (&command_line, "%s -W %d -t %s %s %s", + HOST_COMMAND, timeout_interval-1, + record_type, query_address, dns_server); +#endif + alarm (timeout_interval); + time (&start_time); + if (verbose) + printf ("%s\n", command_line); + /* run the command */ + child_process = spopen (command_line); + if (child_process == NULL) { + printf ("Could not 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); +#ifdef USE_NSLOOKUP + /* scan stdout */ + while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { + if (verbose) + printf ("%s\n", input_buffer); + if (linecnt == 0) { + /* First line should be server name */ + if (strstr (input_buffer, "Server:") != input_buffer) { + output = strscpy (output, "NSLOOKUP error (plugin) - no Server line found"); + result = STATE_WARNING; + } + linecnt++; + } else if (linecnt == 1) { + /* Next line is server address */ + if (strstr (input_buffer, "Address:") != input_buffer) { + output = (output == NULL) + ?strscpy (output, "NSLOOKUP error (plugin) - no Address line found") + :strscat (output, ", no Address line found"); + result = STATE_WARNING; + } + linecnt++; + } else { + linecnt++; + strip(input_buffer); + if (strstr (input_buffer, ".in-addr.arpa")) { + if ((temp_buffer = strstr (input_buffer, "name = "))) + address = strscpy (address, temp_buffer + 7); + else { + output = strscpy (output, "Unknown error (plugin)"); + result = STATE_WARNING; } - - /* scan stderr */ - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { - if (error_scan (input_buffer) != STATE_OK) { - result = max_state (result, error_scan (input_buffer)); - output = strscpy (output, 1 + index (input_buffer, ':')); - } + continue; + } else if ((temp_buffer = strstr (input_buffer, "canonical name ="))) { + address = strscat (address, temp_buffer + strlen("cannonical name =")); + continue; + } else if ((temp_buffer = strstr (input_buffer, "hinfo ="))) { + address = strscat (address, temp_buffer + strlen("hinfo =")); + continue; + } else if ((temp_buffer = strstr (input_buffer, "mail exchanger ="))) { + address = strscat (address, temp_buffer + strlen("mail exchanger =")); + continue; + } else if ((temp_buffer = strstr (input_buffer, "nameserver ="))) { + address = strscat (address, temp_buffer + strlen("nameserver =")); + continue; + } else if ((temp_buffer = strstr (input_buffer, "text ="))) { + address = strscat (address, temp_buffer + strlen("text =")); + continue; + } else if (strcasecmp(record_type, "SOA") == 0) { + if (strncasecmp(input_buffer, query_address, strlen(query_address)) == 0) { + /* Read in SOA */ + while(fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { + if (verbose) + printf ("%s\n", input_buffer); + strip(input_buffer); + address = strscat(address, input_buffer+1); + if (strstr(input_buffer, "minimum =")) + break; + } + continue; } - - /* close stderr */ - (void) fclose (child_stderr); - - /* close stdout */ - if (spclose (child_process)) { - result = max_state (result, STATE_WARNING); - if (!strcmp (output, "")) - output = strscpy (output, "nslookup returned error status"); + } else if (strstr (input_buffer, "Name:")) { + /* the server is responding, we just got the host name... */ + /* get the host address */ + if (!fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) + break; + strip (input_buffer); + if (verbose) + printf ("%s\n", input_buffer); + if ((temp_buffer = index (input_buffer, ':'))) { + address = strscpy (address, temp_buffer + 2); + strip (address); + result = STATE_OK; + } else { + output = strscpy (output, "Unknown error (plugin)"); + result = STATE_WARNING; } - - /* If we got here, we should have an address string, - and we can segfault if we do not */ + continue; + } + } + result = error_scan (input_buffer); + if (result != STATE_OK) { + output = strscpy (output, 1 + index (input_buffer, ':')); + break; + } + } + /* scan stderr */ + while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { + if (error_scan (input_buffer) != STATE_OK) { + result = max_state (result, error_scan (input_buffer)); + output = strscpy (output, 1 + index (input_buffer, ':')); + } + } + /* close stderr */ + (void) fclose (child_stderr); + /* close stdout */ + if (spclose (child_process)) { + result = max_state (result, STATE_WARNING); + if (!strcmp (output, "")) + output = strscpy (output, "nslookup returned error status"); + } +#endif +#ifdef USE_HOST +#error "HOST IS NOT IMPLEMENTED YET" + /* scan stdout */ + while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { + if (verbose) + printf ("%s\n", input_buffer); + if (strstr (input_buffer, ".in-addr.arpa")) { + if ((temp_buffer = strstr (input_buffer, "name = "))) + address = strscpy (address, temp_buffer + 7); + else { + output = strscpy (output, "Unknown error (plugin)"); + result = STATE_WARNING; + } + } + /* the server is responding, we just got the host name... */ + if (strstr (input_buffer, "Name:")) { + /* get the host address */ + if (!fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) + break; + if (verbose) + printf ("%s\n", input_buffer); + if ((temp_buffer = index (input_buffer, ':'))) { + temp_buffer++; + /* Strip leading spaces */ + for (; *temp_buffer != '\0' && *temp_buffer == ' '; temp_buffer++) + /* NOOP */; + address = strdup (temp_buffer); + strip (address); if (address==NULL || strlen(address)==0) - terminate (STATE_CRITICAL, - "DNS CRITICAL - '%s' output parsing exited with no address\n", - NSLOOKUP_COMMAND); - - /* compare to expected address */ - if (result == STATE_OK && match_expected_address && strcmp(address, expected_address)) { - result = STATE_CRITICAL; - asprintf(&output, "expected %s but got %s", expected_address, address); - } - - (void) time (&end_time); - - if (result == STATE_OK) - printf ("DNS ok - %d seconds response time, Address(es) is/are %s\n", - (int) (end_time - start_time), address); - else if (result == STATE_WARNING) - printf ("DNS WARNING - %s\n", - !strcmp (output, "") ? " Probably a non-existent host/domain" : output); - else if (result == STATE_CRITICAL) - printf ("DNS CRITICAL - %s\n", - !strcmp (output, "") ? " Probably a non-existent host/domain" : output); - else - printf ("DNS problem - %s\n", - !strcmp (output, "") ? " Probably a non-existent host/domain" : output); - - return result; + terminate (STATE_CRITICAL, + "DNS CRITICAL - '%s' returned empty host name string\n", + NSLOOKUP_COMMAND); + result = STATE_OK; + } + else { + output = strdup ("Unknown error (plugin)"); + result = STATE_WARNING; + } + break; + } + result = error_scan (input_buffer); + if (result != STATE_OK) { + output = strscpy (output, 1 + index (input_buffer, ':')); + break; + } + } + /* scan stderr */ + while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { + if (error_scan (input_buffer) != STATE_OK) { + result = max (result, error_scan (input_buffer)); + output = strscpy (output, 1 + index (input_buffer, ':')); + } + } + /* close stderr */ + (void) fclose (child_stderr); + /* close stdout */ + if (spclose (child_process)) { + result = max_state (result, STATE_WARNING); /* was "max" check for problems */ + if (!strcmp (output, "")) + output = strscpy (output, "nslookup returned error status"); + } +#endif + (void) time (&end_time); + if (address) { + while (isspace(address[0])) { + address=&address[1]; + } + } + /* If we got here, we should have an address string, + and we can segfault if we do not */ + if (address==NULL || strlen(address)==0) + terminate (STATE_CRITICAL, + "DNS CRITICAL - '%s' output parsing exited with no address\n", + NSLOOKUP_COMMAND); + /* compare to expected address */ + if (result == STATE_OK && match_expected_address && strcmp(address, expected_address)) { + result = STATE_CRITICAL; + asprintf(&output, "expected %s but got %s", expected_address, address); + } + if (result == STATE_OK) + printf ("DNS ok - %d seconds response time, Address(es) is/are %s\n", + (int) (end_time - start_time), address); + else if (result == STATE_WARNING) + printf ("DNS WARNING - %s\n", + !strcmp (output, "") ? " Probably a non-existent host/domain" : output); + else if (result == STATE_CRITICAL) + printf ("DNS CRITICAL - %s\n", + !strcmp (output, "") ? " Probably a non-existent host/domain" : output); + else + printf ("DNS problem - %s\n", + !strcmp (output, "") ? " Probably a non-existent host/domain" : output); + return result; } int @@ -262,6 +436,13 @@ else if (strstr (input_buffer, "Format error")) return STATE_WARNING; + else if (strstr (input_buffer, "No answer")) + return STATE_WARNING; + + /* Server is not authoritative for this question */ + else if (strstr (input_buffer, "Non-authoritative answer")) + return STATE_OK; + else return STATE_OK; @@ -283,7 +464,8 @@ {"hostname", required_argument, 0, 'H'}, {"server", required_argument, 0, 's'}, {"reverse-server", required_argument, 0, 'r'}, - {"expected-address", required_argument, 0, 'a'}, + {"expected-answer", required_argument, 0, 'a'}, + {"resource-record", required_argument, 0, 'T'}, {0, 0, 0, 0} }; #endif @@ -297,9 +479,9 @@ while (1) { #ifdef HAVE_GETOPT_H - c = getopt_long (argc, argv, "hVvt:H:s:r:a:", long_opts, &opt_index); + c = getopt_long (argc, argv, "+?hVvt:H:s:r:a:T:", long_opts, &opt_index); #else - c = getopt (argc, argv, "hVvt:H:s:r:a:"); + c = getopt (argc, argv, "+?hVvt:H:s:r:a:T:"); #endif if (c == -1 || c == EOF) @@ -352,17 +534,17 @@ terminate (STATE_UNKNOWN, "Input buffer overflow\n"); strcpy (ptr_server, optarg); break; - case 'a': /* expected address */ - if (is_dotted_quad (optarg) == FALSE) { - printf ("Invalid expected address\n\n"); - print_usage (); - exit (STATE_UNKNOWN); - } + case 'a': /* expected answer */ if (strlen (optarg) >= ADDRESS_LENGTH) terminate (STATE_UNKNOWN, "Input buffer overflow\n"); strcpy (expected_address, optarg); match_expected_address = TRUE; break; + case 'T': /* Resource record type */ + if (strlen (optarg) >= RRTYPE_LENGTH) + terminate (STATE_UNKNOWN, "INput buffer overflow\n"); + strcpy (record_type, optarg); + break; } } @@ -402,8 +584,10 @@ void print_usage (void) { - printf ("Usage: %s -H host [-s server] [-a expected-address] [-t timeout]\n" " %s --help\n" - " %s --version\n", progname, progname, progname); + printf ("Usage: %s -H host [-s server] [-r reverse-server] [-t timeout] [-T querytype] [-a answer]\n" + " %s --help\n" + " %s --version\n", + progname, progname, progname); } void @@ -418,16 +602,28 @@ " The name or address you want to query\n" "-s, --server=HOST\n" " Optional DNS server you want to use for the lookup\n" - "-a, --expected-address=IP-ADDRESS\n" - " Optional IP address you expect the DNS server to return\n" + "-r, --reverse-server=HOST\n" + " Optional DNS server to do PTR lookup - NOT IMPLEMENTED\n" "-t, --timeout=INTEGER\n" " Seconds before connection times out (default: %d)\n" + "-T, --resource-record=QUERYTYPE\n" + " Type of query to issue - default is A - [A,CNAME,HINFO,MINFO,MX,NS,PTR,SOA,TXT,UINFO,WKS,ANY]\n" + "-a, --expected-answer=STRING\n" + " String to match from server as answer - be very careful how you specify this\n" "-h, --help\n" " Print detailed help\n" "-V, --version\n" " Print version numbers and license information\n" "\n" +#ifdef USE_NSLOOKUP "This plugin uses the nslookup program to obtain the IP address\n" +#endif +#ifdef USE_HOST + "This plugin uses the host program to obtain the IP address\n" +#endif +#ifdef USE_RESOLVER + "This plugin uses the resolver library to obtain the IP address\n" +#endif "for the given host/domain query. A optional DNS server to use may\n" "be specified. If no DNS server is specified, the default server(s)\n" "specified in /etc/resolv.conf will be used.\n", DEFAULT_SOCKET_TIMEOUT); diff -ruN nagios-plugins-1.3.1/plugins/check_tcp.c nagios-plugins-1.3.1-new/plugins/check_tcp.c --- nagios-plugins-1.3.1/plugins/check_tcp.c 2003-06-10 05:56:47.000000000 +0100 +++ nagios-plugins-1.3.1-new/plugins/check_tcp.c 2003-07-14 18:39:57.000000000 +0100 @@ -67,7 +67,7 @@ void print_usage (void); void print_help (void); int my_recv (void); - +int check_expect(char *); char *progname = "check_tcp"; char *SERVICE = NULL; char *SEND = NULL; @@ -259,6 +259,7 @@ while ((i = my_recv ()) > 0) { buffer[i] = '\0'; asprintf (&status, "%s%s", status, buffer); + if (server_expect_count > 0 && check_expect(status)) break; if (buffer[i-2] == '\r' && buffer[i-1] == '\n') break; if (maxbytes>0 && strlen(status)>=maxbytes) @@ -274,16 +275,11 @@ if (status && verbose) printf ("%s\n", status); + /* - does not do anything!! if (server_expect_count > 0) { - for (i = 0;; i++) { - if (verbose) - printf ("%d %d\n", i, server_expect_count); - if (i >= server_expect_count) - terminate (STATE_WARNING, "Invalid response from host\n"); - if (strstr (status, server_expect[i])) - break; - } + check_expect(status); } + */ } if (server_quit != NULL) @@ -608,10 +604,24 @@ } else { #endif - i = read (sd, buffer, MAXBUF - 1); + i = recv (sd, buffer, MAXBUF - 1, 0); #ifdef HAVE_SSL } #endif return i; } + +int check_expect(char * status) { + int i; + + for (i = 0;; i++) { + if (verbose) + printf ("%d %d\n", i, server_expect_count); + if (i >= server_expect_count) + terminate (STATE_WARNING, "Invalid response from host\n"); + if (strstr (status, server_expect[i])) + return TRUE; + } + return FALSE; +}