diff options
Diffstat (limited to 'web/attachments/36739-check_dns.diff')
| -rw-r--r-- | web/attachments/36739-check_dns.diff | 913 |
1 files changed, 913 insertions, 0 deletions
diff --git a/web/attachments/36739-check_dns.diff b/web/attachments/36739-check_dns.diff new file mode 100644 index 0000000..c0eb4c6 --- /dev/null +++ b/web/attachments/36739-check_dns.diff | |||
| @@ -0,0 +1,913 @@ | |||
| 1 | --- check_dns_resolver/check_dns_resolver.c Mon Nov 25 18:01:26 2002 | ||
| 2 | +++ TarZip/nagiosplug-1.3-beta1/plugins/check_dns.c Thu Feb 28 01:42:57 2002 | ||
| 3 | @@ -1,508 +1,415 @@ | ||
| 4 | -/* | ||
| 5 | - * check_dns_resolver is a version of check_dns (for nagios) that | ||
| 6 | - * talks to the nameservers without using nslookup | ||
| 7 | - * | ||
| 8 | - * Author: Roy Marantz (marantz@nbcs.rutgers.edu) | ||
| 9 | - * no copyrite - do what you want with this. | ||
| 10 | - * | ||
| 11 | - * $Id: check_dns_resolver.c,v 1.1.1.1 2002/11/25 23:01:26 marantz Exp $ | ||
| 12 | - * | ||
| 13 | - * solaris build instructions | ||
| 14 | - * cc -o check_dns_resolver check_dns_resolver.c -lresolv -lsocket -lnsl | ||
| 15 | - * | ||
| 16 | - */ | ||
| 17 | - | ||
| 18 | -#include <stdio.h> | ||
| 19 | -#include <signal.h> | ||
| 20 | -#include <sys/types.h> | ||
| 21 | -#include <netinet/in.h> | ||
| 22 | -#include <arpa/nameser.h> | ||
| 23 | -#include <resolv.h> | ||
| 24 | -#include <netdb.h> | ||
| 25 | -#include <arpa/inet.h> | ||
| 26 | -#include <time.h> | ||
| 27 | -#include <sys/socket.h> | ||
| 28 | -#include <strings.h> | ||
| 29 | -#include <stdlib.h> | ||
| 30 | - | ||
| 31 | -#define MAXPACKET 8192 /* BIND maximum packet size */ | ||
| 32 | - | ||
| 33 | -void catch_alarm(int ignored) { | ||
| 34 | - printf("query timed out\n"); | ||
| 35 | - exit(2); | ||
| 36 | +/****************************************************************************** | ||
| 37 | + * | ||
| 38 | + * CHECK_DNS.C | ||
| 39 | + * | ||
| 40 | + * Program: DNS plugin for Nagios | ||
| 41 | + * License: GPL | ||
| 42 | + * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org) | ||
| 43 | + * | ||
| 44 | + * Last Modified: $Date: 2002/02/28 06:42:57 $ | ||
| 45 | + * | ||
| 46 | + * Notes: | ||
| 47 | + * - Safe popen added by Karl DeBisschop 9-11-99 | ||
| 48 | + * | ||
| 49 | + * Command line: CHECK_DNS <query_address> [dns_server] | ||
| 50 | + * | ||
| 51 | + * Description: | ||
| 52 | + * | ||
| 53 | + * This program will use the nslookup program to obtain the IP address | ||
| 54 | + * for a given host name. A optional DNS server may be specified. If | ||
| 55 | + * no DNS server is specified, the default server(s) for the system | ||
| 56 | + * are used. | ||
| 57 | + * | ||
| 58 | + * Return Values: | ||
| 59 | + * OK The DNS query was successful (host IP address was returned). | ||
| 60 | + * WARNING The DNS server responded, but could not fulfill the request. | ||
| 61 | + * CRITICAL The DNS server is not responding or encountered an error. | ||
| 62 | + * | ||
| 63 | + * License Information: | ||
| 64 | + * | ||
| 65 | + * This program is free software; you can redistribute it and/or modify | ||
| 66 | + * it under the terms of the GNU General Public License as published by | ||
| 67 | + * the Free Software Foundation; either version 2 of the License, or | ||
| 68 | + * (at your option) any later version. | ||
| 69 | + * | ||
| 70 | + * This program is distributed in the hope that it will be useful, | ||
| 71 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 72 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 73 | + * GNU General Public License for more details. | ||
| 74 | + * | ||
| 75 | + * You should have received a copy of the GNU General Public License | ||
| 76 | + * along with this program; if not, write to the Free Software | ||
| 77 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 78 | + * | ||
| 79 | + *****************************************************************************/ | ||
| 80 | + | ||
| 81 | +#include "common.h" | ||
| 82 | +#include "popen.h" | ||
| 83 | +#include "utils.h" | ||
| 84 | + | ||
| 85 | +int process_arguments (int, char **); | ||
| 86 | +int call_getopt (int, char **); | ||
| 87 | +int validate_arguments (void); | ||
| 88 | +void print_usage (char *); | ||
| 89 | +void print_help (char *); | ||
| 90 | +int error_scan (char *); | ||
| 91 | + | ||
| 92 | +#define ADDRESS_LENGTH 256 | ||
| 93 | +char query_address[ADDRESS_LENGTH] = ""; | ||
| 94 | +char dns_server[ADDRESS_LENGTH] = ""; | ||
| 95 | +char ptr_server[ADDRESS_LENGTH] = ""; | ||
| 96 | +int verbose = FALSE; | ||
| 97 | + | ||
| 98 | +int | ||
| 99 | +main (int argc, char **argv) | ||
| 100 | +{ | ||
| 101 | + char *command_line = NULL; | ||
| 102 | + char input_buffer[MAX_INPUT_BUFFER]; | ||
| 103 | + char *output = NULL; | ||
| 104 | + char *address = NULL; | ||
| 105 | + char *temp_buffer = NULL; | ||
| 106 | + int result = STATE_UNKNOWN; | ||
| 107 | + | ||
| 108 | + /* Set signal handling and alarm */ | ||
| 109 | + if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) { | ||
| 110 | + printf ("Cannot catch SIGALRM"); | ||
| 111 | + return STATE_UNKNOWN; | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + if (process_arguments (argc, argv) != OK) { | ||
| 115 | + print_usage (my_basename (argv[0])); | ||
| 116 | + return STATE_UNKNOWN; | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + /* get the command to run */ | ||
| 120 | + command_line = ssprintf (command_line, "%s %s %s", NSLOOKUP_COMMAND, | ||
| 121 | + query_address, dns_server); | ||
| 122 | + | ||
| 123 | + alarm (timeout_interval); | ||
| 124 | + time (&start_time); | ||
| 125 | + | ||
| 126 | + if (verbose) | ||
| 127 | + printf ("%s\n", command_line); | ||
| 128 | + /* run the command */ | ||
| 129 | + child_process = spopen (command_line); | ||
| 130 | + if (child_process == NULL) { | ||
| 131 | + printf ("Could not open pipe: %s\n", command_line); | ||
| 132 | + return STATE_UNKNOWN; | ||
| 133 | + } | ||
| 134 | + | ||
| 135 | + child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); | ||
| 136 | + if (child_stderr == NULL) | ||
| 137 | + printf ("Could not open stderr for %s\n", command_line); | ||
| 138 | + | ||
| 139 | + /* scan stdout */ | ||
| 140 | + while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { | ||
| 141 | + | ||
| 142 | + if (verbose) | ||
| 143 | + printf ("%s\n", input_buffer); | ||
| 144 | + | ||
| 145 | + if (strstr (input_buffer, ".in-addr.arpa")) { | ||
| 146 | + if ((temp_buffer = strstr (input_buffer, "name = "))) | ||
| 147 | + address = strscpy (address, temp_buffer + 7); | ||
| 148 | + else { | ||
| 149 | + output = strscpy (output, "Unknown error (plugin)"); | ||
| 150 | + result = STATE_WARNING; | ||
| 151 | + } | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | + /* the server is responding, we just got the host name... */ | ||
| 155 | + if (strstr (input_buffer, "Name:")) { | ||
| 156 | + | ||
| 157 | + /* get the host address */ | ||
| 158 | + if (!fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) | ||
| 159 | + break; | ||
| 160 | + | ||
| 161 | + if (verbose) | ||
| 162 | + printf ("%s\n", input_buffer); | ||
| 163 | + | ||
| 164 | + if ((temp_buffer = index (input_buffer, ':'))) { | ||
| 165 | + address = strscpy (address, temp_buffer + 2); | ||
| 166 | + strip (address); | ||
| 167 | + result = STATE_OK; | ||
| 168 | + } | ||
| 169 | + else { | ||
| 170 | + output = strscpy (output, "Unknown error (plugin)"); | ||
| 171 | + result = STATE_WARNING; | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | + break; | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | + result = error_scan (input_buffer); | ||
| 178 | + if (result != STATE_OK) { | ||
| 179 | + output = strscpy (output, 1 + index (input_buffer, ':')); | ||
| 180 | + break; | ||
| 181 | + } | ||
| 182 | + | ||
| 183 | + } | ||
| 184 | + | ||
| 185 | + /* scan stderr */ | ||
| 186 | + while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { | ||
| 187 | + if (error_scan (input_buffer) != STATE_OK) { | ||
| 188 | + result = max (result, error_scan (input_buffer)); | ||
| 189 | + output = strscpy (output, 1 + index (input_buffer, ':')); | ||
| 190 | + } | ||
| 191 | + } | ||
| 192 | + | ||
| 193 | + /* close stderr */ | ||
| 194 | + (void) fclose (child_stderr); | ||
| 195 | + | ||
| 196 | + /* close stdout */ | ||
| 197 | + if (spclose (child_process)) { | ||
| 198 | + result = max (result, STATE_WARNING); | ||
| 199 | + if (!strcmp (output, "")) | ||
| 200 | + output = strscpy (output, "nslookup returned error status"); | ||
| 201 | + } | ||
| 202 | + | ||
| 203 | + (void) time (&end_time); | ||
| 204 | + | ||
| 205 | + if (result == STATE_OK) | ||
| 206 | + printf ("DNS ok - %d seconds response time, Address(es) is/are %s\n", | ||
| 207 | + (int) (end_time - start_time), address); | ||
| 208 | + else if (result == STATE_WARNING) | ||
| 209 | + printf ("DNS WARNING - %s\n", | ||
| 210 | + !strcmp (output, "") ? " Probably a non-existent host/domain" : output); | ||
| 211 | + else if (result == STATE_CRITICAL) | ||
| 212 | + printf ("DNS CRITICAL - %s\n", | ||
| 213 | + !strcmp (output, "") ? " Probably a non-existent host/domain" : output); | ||
| 214 | + else | ||
| 215 | + printf ("DNS problem - %s\n", | ||
| 216 | + !strcmp (output, "") ? " Probably a non-existent host/domain" : output); | ||
| 217 | + | ||
| 218 | + return result; | ||
| 219 | } | ||
| 220 | |||
| 221 | -typedef union { | ||
| 222 | - HEADER hdr; | ||
| 223 | - u_char buf[MAXPACKET]; | ||
| 224 | -} querybuf; | ||
| 225 | - | ||
| 226 | -static struct hostent * | ||
| 227 | -getanswer(const querybuf *answer, | ||
| 228 | - int anslen, | ||
| 229 | - const char *qname, | ||
| 230 | - int qtype); | ||
| 231 | - | ||
| 232 | -int debugging = 0; | ||
| 233 | - | ||
| 234 | -int main (int argc, char **argv) { | ||
| 235 | - int n; | ||
| 236 | - time_t start_time, end_time; | ||
| 237 | - querybuf answer; | ||
| 238 | - struct hostent *hentry; | ||
| 239 | - register char **h; | ||
| 240 | - | ||
| 241 | - int norecurse = 0; | ||
| 242 | - int timeout = 30; | ||
| 243 | - char *host = NULL; | ||
| 244 | - char *server = NULL; | ||
| 245 | - | ||
| 246 | -/* if (process_arguments (argc, argv) != OK) { | ||
| 247 | - print_usage (my_basename (argv[0])); | ||
| 248 | - exit(1); | ||
| 249 | - } | ||
| 250 | -*/ | ||
| 251 | - | ||
| 252 | - { | ||
| 253 | - int c; | ||
| 254 | - int errflg = 0; | ||
| 255 | - int showversion = 0; | ||
| 256 | - char *pgm = argv[0]; | ||
| 257 | - extern char *optarg; | ||
| 258 | - extern int optind; | ||
| 259 | - | ||
| 260 | - while ((c = getopt(argc, argv, "dhrt:s:H:V")) != EOF) | ||
| 261 | - switch (c) { | ||
| 262 | - case 't': timeout = atoi(optarg); break; | ||
| 263 | - case 's': server = optarg; break; | ||
| 264 | - case 'H': host = optarg; break; | ||
| 265 | - case 'r': norecurse = 1; break; | ||
| 266 | - case 'd': debugging++; break; | ||
| 267 | - case 'V': showversion++; break; | ||
| 268 | - case 'h': | ||
| 269 | - case '?': errflg++; | ||
| 270 | - } | ||
| 271 | - if (host == NULL || errflg || optind != argc) { | ||
| 272 | - fprintf(stderr, "usage: %s %s\n%s %d\n%s\n%s\n%s\n%s\n%s\n", | ||
| 273 | - pgm, | ||
| 274 | - "[-d] [-V] [-r] [-t timeout] [-s server] -H host", | ||
| 275 | - "where: timeout is time (in seconds) to wait for dns server, default", | ||
| 276 | - timeout, | ||
| 277 | - " host is the fully qualified hostname to ask address of", | ||
| 278 | - " server is the IP address or hostname of the nameserver to ask, default from /etc/resolv.conf", | ||
| 279 | - " -r turns off recursive resolver lookups", | ||
| 280 | - " -d turns on resolver debugging", | ||
| 281 | - " -V prints program version" | ||
| 282 | - ); | ||
| 283 | - exit (2); | ||
| 284 | - } | ||
| 285 | - if (showversion) { | ||
| 286 | - printf("%s version $Revision: 1.1.1.1 $\n", pgm); | ||
| 287 | - exit(0); | ||
| 288 | - } | ||
| 289 | - } | ||
| 290 | - | ||
| 291 | - | ||
| 292 | - /* Set signal handling and alarm */ | ||
| 293 | - if (signal (SIGALRM, catch_alarm) == SIG_ERR) { | ||
| 294 | - printf("DNS problem - Cannot set ALRM handler"); | ||
| 295 | - exit(33); | ||
| 296 | - } | ||
| 297 | - | ||
| 298 | - /* process /etc/resolv.conf */ | ||
| 299 | - if (res_init() == -1) { | ||
| 300 | - printf("DNS problem - Cannot call res_init \n"); | ||
| 301 | - exit(33); | ||
| 302 | - } | ||
| 303 | - | ||
| 304 | - if (debugging) { | ||
| 305 | - _res.options |= RES_DEBUG; /* turn on resolver debugging */ | ||
| 306 | - } | ||
| 307 | - | ||
| 308 | - if (norecurse) { | ||
| 309 | - _res.options &= ~RES_RECURSE; /* turn off recursive lookup */ | ||
| 310 | - } | ||
| 311 | - | ||
| 312 | - if (server) { | ||
| 313 | - struct hostent *hp; | ||
| 314 | - static struct sockaddr_in *a; | ||
| 315 | - in_addr_t s; | ||
| 316 | - | ||
| 317 | - /* override the nameservers from resolv.conf */ | ||
| 318 | - _res.nscount = 1; | ||
| 319 | - a = &_res.nsaddr_list[0]; | ||
| 320 | - /* a->sin_port = ... leave the port alone */ | ||
| 321 | - | ||
| 322 | - hp = gethostbyname(server); | ||
| 323 | - if (hp && hp->h_addr_list[0] != NULL) { | ||
| 324 | - a->sin_family = hp->h_addrtype; | ||
| 325 | - bcopy(hp->h_addr_list[0], &a->sin_addr, hp->h_length); | ||
| 326 | - } else { | ||
| 327 | - /* assume a dotted quad address */ | ||
| 328 | - s = inet_addr(server); | ||
| 329 | - if (s == -1) { | ||
| 330 | - printf("DNS problem - Cannot resolve server %s\n", server); | ||
| 331 | - exit(33); | ||
| 332 | - } | ||
| 333 | - a->sin_family = AF_INET; | ||
| 334 | - bcopy(&s, &a->sin_addr, sizeof(in_addr_t)); | ||
| 335 | - } | ||
| 336 | - } | ||
| 337 | - | ||
| 338 | - time (&start_time); | ||
| 339 | - alarm (timeout); | ||
| 340 | - | ||
| 341 | - n = res_query(host, C_IN, T_A, answer.buf, sizeof(answer)); | ||
| 342 | - | ||
| 343 | - alarm(0); /* cancel pending alarm */ | ||
| 344 | - (void) time (&end_time); | ||
| 345 | - | ||
| 346 | - if (n < 0) { | ||
| 347 | - printf("DNS CRITICAL - query failed: %d\n", n); | ||
| 348 | - exit(n); | ||
| 349 | - } | ||
| 350 | - | ||
| 351 | - hentry = getanswer(&answer, n, host, T_A); | ||
| 352 | - if (hentry == NULL) { | ||
| 353 | - printf("DNS WARNING - no answer\n"); | ||
| 354 | - exit(2); | ||
| 355 | - } | ||
| 356 | - printf("DNS ok - %d seconds response time, Address(es) is/are", | ||
| 357 | - (int) (end_time - start_time)); | ||
| 358 | - for(h=hentry->h_addr_list; *h; h++) { | ||
| 359 | - struct in_addr a; | ||
| 360 | - bcopy(*h, &a, hentry->h_length); | ||
| 361 | - printf(" %s", inet_ntoa(a)); | ||
| 362 | - } | ||
| 363 | - printf("\n"); | ||
| 364 | +int | ||
| 365 | +error_scan (char *input_buffer) | ||
| 366 | +{ | ||
| 367 | + | ||
| 368 | + /* the DNS lookup timed out */ | ||
| 369 | + if (strstr (input_buffer, | ||
| 370 | + "Note: nslookup is deprecated and may be removed from future releases.") | ||
| 371 | + || strstr (input_buffer, | ||
| 372 | + "Consider using the `dig' or `host' programs instead. Run nslookup with") | ||
| 373 | + || strstr (input_buffer, | ||
| 374 | + "the `-sil[ent]' option to prevent this message from appearing.")) | ||
| 375 | + return STATE_OK; | ||
| 376 | + | ||
| 377 | + /* the DNS lookup timed out */ | ||
| 378 | + else if (strstr (input_buffer, "Timed out")) | ||
| 379 | + return STATE_WARNING; | ||
| 380 | + | ||
| 381 | + /* DNS server is not running... */ | ||
| 382 | + else if (strstr (input_buffer, "No response from server")) | ||
| 383 | + return STATE_CRITICAL; | ||
| 384 | + | ||
| 385 | + /* Host name is valid, but server doesn't have records... */ | ||
| 386 | + else if (strstr (input_buffer, "No records")) | ||
| 387 | + return STATE_WARNING; | ||
| 388 | + | ||
| 389 | + /* Host or domain name does not exist */ | ||
| 390 | + else if (strstr (input_buffer, "Non-existent")) | ||
| 391 | + return STATE_CRITICAL; | ||
| 392 | + else if (strstr (input_buffer, "** server can't find")) | ||
| 393 | + return STATE_CRITICAL; | ||
| 394 | + else if(strstr(input_buffer,"NXDOMAIN")) /* 9.x */ | ||
| 395 | + return STATE_CRITICAL; | ||
| 396 | + | ||
| 397 | + /* Connection was refused */ | ||
| 398 | + else if (strstr (input_buffer, "Connection refused")) | ||
| 399 | + return STATE_CRITICAL; | ||
| 400 | + | ||
| 401 | + /* Network is unreachable */ | ||
| 402 | + else if (strstr (input_buffer, "Network is unreachable")) | ||
| 403 | + return STATE_CRITICAL; | ||
| 404 | + | ||
| 405 | + /* Internal server failure */ | ||
| 406 | + else if (strstr (input_buffer, "Server failure")) | ||
| 407 | + return STATE_CRITICAL; | ||
| 408 | + | ||
| 409 | + /* DNS server refused to service request */ | ||
| 410 | + else if (strstr (input_buffer, "Refused")) | ||
| 411 | + return STATE_CRITICAL; | ||
| 412 | + | ||
| 413 | + /* Request error */ | ||
| 414 | + else if (strstr (input_buffer, "Format error")) | ||
| 415 | + return STATE_WARNING; | ||
| 416 | + | ||
| 417 | + else | ||
| 418 | + return STATE_OK; | ||
| 419 | |||
| 420 | - exit(0); | ||
| 421 | } | ||
| 422 | |||
| 423 | +/* process command-line arguments */ | ||
| 424 | +int | ||
| 425 | +process_arguments (int argc, char **argv) | ||
| 426 | +{ | ||
| 427 | + int c; | ||
| 428 | + | ||
| 429 | + if (argc < 2) | ||
| 430 | + return ERROR; | ||
| 431 | |||
| 432 | + for (c = 1; c < argc; c++) | ||
| 433 | + if (strcmp ("-to", argv[c]) == 0) | ||
| 434 | + strcpy (argv[c], "-t"); | ||
| 435 | + | ||
| 436 | + c = 0; | ||
| 437 | + while (c += (call_getopt (argc - c, &argv[c]))) { | ||
| 438 | + if (argc <= c) | ||
| 439 | + break; | ||
| 440 | + if (query_address[0] == 0) { | ||
| 441 | + if (is_host (argv[c]) == FALSE) { | ||
| 442 | + printf ("Invalid name/address: %s\n\n", argv[c]); | ||
| 443 | + return ERROR; | ||
| 444 | + } | ||
| 445 | + if (strlen (argv[c]) >= ADDRESS_LENGTH) | ||
| 446 | + terminate (STATE_UNKNOWN, "Input buffer overflow\n"); | ||
| 447 | + strcpy (query_address, argv[c]); | ||
| 448 | + } | ||
| 449 | + else if (dns_server[0] == 0) { | ||
| 450 | + if (is_host (argv[c]) == FALSE) { | ||
| 451 | + printf ("Invalid name/address: %s\n\n", argv[c]); | ||
| 452 | + return ERROR; | ||
| 453 | + } | ||
| 454 | + if (strlen (argv[c]) >= ADDRESS_LENGTH) | ||
| 455 | + terminate (STATE_UNKNOWN, "Input buffer overflow\n"); | ||
| 456 | + strcpy (dns_server, argv[c]); | ||
| 457 | + } | ||
| 458 | + } | ||
| 459 | |||
| 460 | -/* stripped down getanswer */ | ||
| 461 | + return validate_arguments (); | ||
| 462 | + | ||
| 463 | +} | ||
| 464 | |||
| 465 | -/* | ||
| 466 | - * Copyright (c) 1985, 1988, 1993 | ||
| 467 | - * The Regents of the University of California. All rights reserved. | ||
| 468 | - * | ||
| 469 | - * Redistribution and use in source and binary forms, with or without | ||
| 470 | - * modification, are permitted provided that the following conditions | ||
| 471 | - * are met: | ||
| 472 | - * 1. Redistributions of source code must retain the above copyright | ||
| 473 | - * notice, this list of conditions and the following disclaimer. | ||
| 474 | - * 2. Redistributions in binary form must reproduce the above copyright | ||
| 475 | - * notice, this list of conditions and the following disclaimer in the | ||
| 476 | - * documentation and/or other materials provided with the distribution. | ||
| 477 | - * 3. All advertising materials mentioning features or use of this software | ||
| 478 | - * must display the following acknowledgement: | ||
| 479 | - * This product includes software developed by the University of | ||
| 480 | - * California, Berkeley and its contributors. | ||
| 481 | - * 4. Neither the name of the University nor the names of its contributors | ||
| 482 | - * may be used to endorse or promote products derived from this software | ||
| 483 | - * without specific prior written permission. | ||
| 484 | - * | ||
| 485 | - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
| 486 | - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 487 | - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 488 | - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
| 489 | - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 490 | - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 491 | - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 492 | - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 493 | - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 494 | - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 495 | - * SUCH DAMAGE. | ||
| 496 | - * - | ||
| 497 | - * Portions Copyright (c) 1993 by Digital Equipment Corporation. | ||
| 498 | - * | ||
| 499 | - * Permission to use, copy, modify, and distribute this software for any | ||
| 500 | - * purpose with or without fee is hereby granted, provided that the above | ||
| 501 | - * copyright notice and this permission notice appear in all copies, and that | ||
| 502 | - * the name of Digital Equipment Corporation not be used in advertising or | ||
| 503 | - * publicity pertaining to distribution of the document or software without | ||
| 504 | - * specific, written prior permission. | ||
| 505 | - * | ||
| 506 | - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL | ||
| 507 | - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES | ||
| 508 | - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT | ||
| 509 | - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | ||
| 510 | - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR | ||
| 511 | - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS | ||
| 512 | - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | ||
| 513 | - * SOFTWARE. | ||
| 514 | - * - | ||
| 515 | - * --Copyright-- | ||
| 516 | - */ | ||
| 517 | - | ||
| 518 | -static const char AskedForGot[] = | ||
| 519 | - "gethostby*.getanswer: asked for \"%s\", got \"%s\""; | ||
| 520 | -static char *h_addr_ptrs[MAXADDRS + 1]; | ||
| 521 | - | ||
| 522 | -static struct hostent host; | ||
| 523 | -static char *host_aliases[MAXALIASES]; | ||
| 524 | -static char hostbuf[8*1024]; | ||
| 525 | -static u_char host_addr[16]; /* IPv4 or IPv6 */ | ||
| 526 | -static FILE *hostf = NULL; | ||
| 527 | -static int stayopen = 0; | ||
| 528 | - | ||
| 529 | - | ||
| 530 | -typedef union { | ||
| 531 | - int32_t al; | ||
| 532 | - char ac; | ||
| 533 | -} align; | ||
| 534 | - | ||
| 535 | -#define dprintf printf | ||
| 536 | - | ||
| 537 | -static struct hostent * | ||
| 538 | -getanswer(const querybuf *answer, | ||
| 539 | - int anslen, | ||
| 540 | - const char *qname, | ||
| 541 | - int qtype) | ||
| 542 | +int | ||
| 543 | +call_getopt (int argc, char **argv) | ||
| 544 | { | ||
| 545 | - register const HEADER *hp; | ||
| 546 | - register const u_char *cp; | ||
| 547 | - register int n; | ||
| 548 | - const u_char *eom; | ||
| 549 | - char *bp, **ap, **hap; | ||
| 550 | - int type, class, buflen, ancount, qdcount; | ||
| 551 | - int haveanswer, had_error; | ||
| 552 | - int toobig = 0; | ||
| 553 | - char tbuf[MAXDNAME]; | ||
| 554 | - const char *tname; | ||
| 555 | - int (*name_ok) __P((const char *)); | ||
| 556 | - | ||
| 557 | - tname = qname; | ||
| 558 | - host.h_name = NULL; | ||
| 559 | - host.h_length = INADDRSZ; | ||
| 560 | - host.h_addrtype = AF_INET; | ||
| 561 | - | ||
| 562 | - eom = answer->buf + anslen; | ||
| 563 | - switch (qtype) { | ||
| 564 | - case T_A: | ||
| 565 | - case T_AAAA: | ||
| 566 | - name_ok = res_hnok; | ||
| 567 | - break; | ||
| 568 | - case T_PTR: | ||
| 569 | - name_ok = res_dnok; | ||
| 570 | - break; | ||
| 571 | - default: | ||
| 572 | - return (NULL); /* XXX should be abort(); */ | ||
| 573 | - } | ||
| 574 | - /* | ||
| 575 | - * find first satisfactory answer | ||
| 576 | - */ | ||
| 577 | - hp = &answer->hdr; | ||
| 578 | - ancount = ntohs(hp->ancount); | ||
| 579 | - qdcount = ntohs(hp->qdcount); | ||
| 580 | - bp = hostbuf; | ||
| 581 | - buflen = sizeof hostbuf; | ||
| 582 | - cp = answer->buf + HFIXEDSZ; | ||
| 583 | - if (qdcount != 1) { | ||
| 584 | - h_errno = NO_RECOVERY; | ||
| 585 | - return (NULL); | ||
| 586 | - } | ||
| 587 | - n = dn_expand(answer->buf, eom, cp, bp, buflen); | ||
| 588 | - if ((n < 0) || !(*name_ok)(bp)) { | ||
| 589 | - h_errno = NO_RECOVERY; | ||
| 590 | - return (NULL); | ||
| 591 | - } | ||
| 592 | - cp += n + QFIXEDSZ; | ||
| 593 | - if (qtype == T_A || qtype == T_AAAA) { | ||
| 594 | - /* res_send() has already verified that the query name is the | ||
| 595 | - * same as the one we sent; this just gets the expanded name | ||
| 596 | - * (i.e., with the succeeding search-domain tacked on). | ||
| 597 | - */ | ||
| 598 | - n = strlen(bp) + 1; /* for the \0 */ | ||
| 599 | - host.h_name = bp; | ||
| 600 | - bp += n; | ||
| 601 | - buflen -= n; | ||
| 602 | - /* The qname can be abbreviated, but h_name is now absolute. */ | ||
| 603 | - qname = host.h_name; | ||
| 604 | - } | ||
| 605 | - ap = host_aliases; | ||
| 606 | - *ap = NULL; | ||
| 607 | - host.h_aliases = host_aliases; | ||
| 608 | - hap = h_addr_ptrs; | ||
| 609 | - *hap = NULL; | ||
| 610 | - host.h_addr_list = h_addr_ptrs; | ||
| 611 | - haveanswer = 0; | ||
| 612 | - had_error = 0; | ||
| 613 | - while (ancount-- > 0 && cp < eom && !had_error) { | ||
| 614 | - n = dn_expand(answer->buf, eom, cp, bp, buflen); | ||
| 615 | - if ((n < 0) || !(*name_ok)(bp)) { | ||
| 616 | - had_error++; | ||
| 617 | - continue; | ||
| 618 | - } | ||
| 619 | - | ||
| 620 | - cp += n; /* name */ | ||
| 621 | - type = _getshort(cp); | ||
| 622 | - cp += INT16SZ; /* type */ | ||
| 623 | - class = _getshort(cp); | ||
| 624 | - cp += INT16SZ + INT32SZ; /* class, TTL */ | ||
| 625 | - n = _getshort(cp); | ||
| 626 | - cp += INT16SZ; /* len */ | ||
| 627 | - if (class != C_IN) { | ||
| 628 | - /* XXX - debug? syslog? */ | ||
| 629 | - cp += n; | ||
| 630 | - continue; /* XXX - had_error++ ? */ | ||
| 631 | - } | ||
| 632 | - if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { | ||
| 633 | - if (ap >= &host_aliases[MAXALIASES-1]) | ||
| 634 | - continue; | ||
| 635 | - n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); | ||
| 636 | - if ((n < 0) || !(*name_ok)(tbuf)) { | ||
| 637 | - had_error++; | ||
| 638 | - continue; | ||
| 639 | - } | ||
| 640 | - cp += n; | ||
| 641 | - /* Store alias. */ | ||
| 642 | - *ap++ = bp; | ||
| 643 | - n = strlen(bp) + 1; /* for the \0 */ | ||
| 644 | - bp += n; | ||
| 645 | - buflen -= n; | ||
| 646 | - /* Get canonical name. */ | ||
| 647 | - n = strlen(tbuf) + 1; /* for the \0 */ | ||
| 648 | - if (n > buflen) { | ||
| 649 | - had_error++; | ||
| 650 | - continue; | ||
| 651 | - } | ||
| 652 | - strcpy(bp, tbuf); | ||
| 653 | - host.h_name = bp; | ||
| 654 | - bp += n; | ||
| 655 | - buflen -= n; | ||
| 656 | - continue; | ||
| 657 | - } | ||
| 658 | - | ||
| 659 | - if (qtype == T_PTR && type == T_CNAME) { | ||
| 660 | - n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); | ||
| 661 | - if ((n < 0) || !res_hnok(tbuf)) { | ||
| 662 | - had_error++; | ||
| 663 | - continue; | ||
| 664 | - } | ||
| 665 | - cp += n; | ||
| 666 | - /* Get canonical name. */ | ||
| 667 | - n = strlen(tbuf) + 1; /* for the \0 */ | ||
| 668 | - if (n > buflen) { | ||
| 669 | - had_error++; | ||
| 670 | - continue; | ||
| 671 | - } | ||
| 672 | - strcpy(bp, tbuf); | ||
| 673 | - tname = bp; | ||
| 674 | - bp += n; | ||
| 675 | - buflen -= n; | ||
| 676 | - continue; | ||
| 677 | - } | ||
| 678 | - if (type != qtype) { | ||
| 679 | - dprintf("gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", | ||
| 680 | - qname, p_class(C_IN), p_type(qtype), | ||
| 681 | - p_type(type)); | ||
| 682 | - cp += n; | ||
| 683 | - continue; /* XXX - had_error++ ? */ | ||
| 684 | - } | ||
| 685 | - switch (type) { | ||
| 686 | - case T_PTR: | ||
| 687 | - if (strcasecmp(tname, bp) != 0) { | ||
| 688 | - dprintf(AskedForGot, qname, bp); | ||
| 689 | - cp += n; | ||
| 690 | - continue; /* XXX - had_error++ ? */ | ||
| 691 | - } | ||
| 692 | - n = dn_expand(answer->buf, eom, cp, bp, buflen); | ||
| 693 | - if ((n < 0) || !res_hnok(bp)) { | ||
| 694 | - had_error++; | ||
| 695 | - break; | ||
| 696 | - } | ||
| 697 | -#if MULTI_PTRS_ARE_ALIASES | ||
| 698 | - cp += n; | ||
| 699 | - if (!haveanswer) | ||
| 700 | - host.h_name = bp; | ||
| 701 | - else if (ap < &host_aliases[MAXALIASES-1]) | ||
| 702 | - *ap++ = bp; | ||
| 703 | - else | ||
| 704 | - n = -1; | ||
| 705 | - if (n != -1) { | ||
| 706 | - n = strlen(bp) + 1; /* for the \0 */ | ||
| 707 | - bp += n; | ||
| 708 | - buflen -= n; | ||
| 709 | - } | ||
| 710 | - break; | ||
| 711 | + int c, i = 1; | ||
| 712 | |||
| 713 | +#ifdef HAVE_GETOPT_H | ||
| 714 | + int opt_index = 0; | ||
| 715 | + static struct option long_opts[] = { | ||
| 716 | + {"help", no_argument, 0, 'h'}, | ||
| 717 | + {"version", no_argument, 0, 'V'}, | ||
| 718 | + {"verbose", no_argument, 0, 'v'}, | ||
| 719 | + {"timeout", required_argument, 0, 't'}, | ||
| 720 | + {"hostname", required_argument, 0, 'H'}, | ||
| 721 | + {"server", required_argument, 0, 's'}, | ||
| 722 | + {"reverse-server", required_argument, 0, 'r'}, | ||
| 723 | + {0, 0, 0, 0} | ||
| 724 | + }; | ||
| 725 | +#endif | ||
| 726 | + | ||
| 727 | + | ||
| 728 | + while (1) { | ||
| 729 | +#ifdef HAVE_GETOPT_H | ||
| 730 | + c = getopt_long (argc, argv, "+?hVvt:H:s:r:", long_opts, &opt_index); | ||
| 731 | #else | ||
| 732 | - host.h_name = bp; | ||
| 733 | - h_errno = NETDB_SUCCESS; | ||
| 734 | - return (&host); | ||
| 735 | + c = getopt (argc, argv, "+?hVvt:H:s:r:"); | ||
| 736 | #endif | ||
| 737 | - case T_A: | ||
| 738 | - case T_AAAA: | ||
| 739 | - if (strcasecmp(host.h_name, bp) != 0) { | ||
| 740 | - dprintf(AskedForGot, host.h_name, bp); | ||
| 741 | - cp += n; | ||
| 742 | - continue; /* XXX - had_error++ ? */ | ||
| 743 | - } | ||
| 744 | - if (n != host.h_length) { | ||
| 745 | - cp += n; | ||
| 746 | - continue; | ||
| 747 | - } | ||
| 748 | - if (!haveanswer) { | ||
| 749 | - register int nn; | ||
| 750 | - | ||
| 751 | - host.h_name = bp; | ||
| 752 | - nn = strlen(bp) + 1; /* for the \0 */ | ||
| 753 | - bp += nn; | ||
| 754 | - buflen -= nn; | ||
| 755 | - } | ||
| 756 | - | ||
| 757 | - bp += sizeof(align) - ((u_long)bp % sizeof(align)); | ||
| 758 | - | ||
| 759 | - if (bp + n >= &hostbuf[sizeof hostbuf]) { | ||
| 760 | - dprintf("size (%d) too big\n", n); | ||
| 761 | - had_error++; | ||
| 762 | - continue; | ||
| 763 | - } | ||
| 764 | - if (hap >= &h_addr_ptrs[MAXADDRS-1]) { | ||
| 765 | - if (!toobig++) | ||
| 766 | - dprintf("Too many addresses (%d)\n", | ||
| 767 | - MAXADDRS); | ||
| 768 | - cp += n; | ||
| 769 | - continue; | ||
| 770 | - } | ||
| 771 | - bcopy(cp, *hap++ = bp, n); | ||
| 772 | - bp += n; | ||
| 773 | - buflen -= n; | ||
| 774 | - cp += n; | ||
| 775 | - break; | ||
| 776 | - default: | ||
| 777 | - abort(); | ||
| 778 | - } | ||
| 779 | - if (!had_error) | ||
| 780 | - haveanswer++; | ||
| 781 | - } | ||
| 782 | - if (haveanswer) { | ||
| 783 | - *ap = NULL; | ||
| 784 | - *hap = NULL; | ||
| 785 | -# if defined(RESOLVSORT) | ||
| 786 | - /* | ||
| 787 | - * Note: we sort even if host can take only one address | ||
| 788 | - * in its return structures - should give it the "best" | ||
| 789 | - * address in that case, not some random one | ||
| 790 | - */ | ||
| 791 | - if (_res.nsort && haveanswer > 1 && qtype == T_A) | ||
| 792 | - addrsort(h_addr_ptrs, haveanswer); | ||
| 793 | -# endif /*RESOLVSORT*/ | ||
| 794 | - if (!host.h_name) { | ||
| 795 | - n = strlen(qname) + 1; /* for the \0 */ | ||
| 796 | - if (n > buflen) | ||
| 797 | - goto try_again; | ||
| 798 | - strcpy(bp, qname); | ||
| 799 | - host.h_name = bp; | ||
| 800 | - bp += n; | ||
| 801 | - buflen -= n; | ||
| 802 | - } | ||
| 803 | - h_errno = NETDB_SUCCESS; | ||
| 804 | - return (&host); | ||
| 805 | - } | ||
| 806 | - try_again: | ||
| 807 | - h_errno = TRY_AGAIN; | ||
| 808 | - return (NULL); | ||
| 809 | + | ||
| 810 | + if (c == -1 || c == EOF) | ||
| 811 | + break; | ||
| 812 | + | ||
| 813 | + i++; | ||
| 814 | + switch (c) { | ||
| 815 | + case 't': | ||
| 816 | + case 'H': | ||
| 817 | + case 's': | ||
| 818 | + case 'r': | ||
| 819 | + i++; | ||
| 820 | + } | ||
| 821 | + | ||
| 822 | + switch (c) { | ||
| 823 | + case '?': /* args not parsable */ | ||
| 824 | + printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg); | ||
| 825 | + print_usage (my_basename (argv[0])); | ||
| 826 | + exit (STATE_UNKNOWN); | ||
| 827 | + case 'h': /* help */ | ||
| 828 | + print_help (my_basename (argv[0])); | ||
| 829 | + exit (STATE_OK); | ||
| 830 | + case 'V': /* version */ | ||
| 831 | + print_revision (my_basename (argv[0]), "$Revision: 1.1.1.1 $"); | ||
| 832 | + exit (STATE_OK); | ||
| 833 | + case 'v': /* version */ | ||
| 834 | + verbose = TRUE; | ||
| 835 | + break; | ||
| 836 | + case 't': /* timeout period */ | ||
| 837 | + timeout_interval = atoi (optarg); | ||
| 838 | + break; | ||
| 839 | + case 'H': /* hostname */ | ||
| 840 | + if (is_host (optarg) == FALSE) { | ||
| 841 | + printf ("Invalid host name/address\n\n"); | ||
| 842 | + print_usage (my_basename (argv[0])); | ||
| 843 | + exit (STATE_UNKNOWN); | ||
| 844 | + } | ||
| 845 | + if (strlen (optarg) >= ADDRESS_LENGTH) | ||
| 846 | + terminate (STATE_UNKNOWN, "Input buffer overflow\n"); | ||
| 847 | + strcpy (query_address, optarg); | ||
| 848 | + break; | ||
| 849 | + case 's': /* server name */ | ||
| 850 | + if (is_host (optarg) == FALSE) { | ||
| 851 | + printf ("Invalid server name/address\n\n"); | ||
| 852 | + print_usage (my_basename (argv[0])); | ||
| 853 | + exit (STATE_UNKNOWN); | ||
| 854 | + } | ||
| 855 | + if (strlen (optarg) >= ADDRESS_LENGTH) | ||
| 856 | + terminate (STATE_UNKNOWN, "Input buffer overflow\n"); | ||
| 857 | + strcpy (dns_server, optarg); | ||
| 858 | + break; | ||
| 859 | + case 'r': /* reverse server name */ | ||
| 860 | + if (is_host (optarg) == FALSE) { | ||
| 861 | + printf ("Invalid host name/address\n\n"); | ||
| 862 | + print_usage (my_basename (argv[0])); | ||
| 863 | + exit (STATE_UNKNOWN); | ||
| 864 | + } | ||
| 865 | + if (strlen (optarg) >= ADDRESS_LENGTH) | ||
| 866 | + terminate (STATE_UNKNOWN, "Input buffer overflow\n"); | ||
| 867 | + strcpy (ptr_server, optarg); | ||
| 868 | + break; | ||
| 869 | + } | ||
| 870 | + } | ||
| 871 | + return i; | ||
| 872 | +} | ||
| 873 | + | ||
| 874 | +int | ||
| 875 | +validate_arguments () | ||
| 876 | +{ | ||
| 877 | + if (query_address[0] == 0) | ||
| 878 | + return ERROR; | ||
| 879 | + else | ||
| 880 | + return OK; | ||
| 881 | +} | ||
| 882 | + | ||
| 883 | +void | ||
| 884 | +print_usage (char *cmd) | ||
| 885 | +{ | ||
| 886 | + printf ("Usage: %s -H host [-s server] [-t timeout]\n" " %s --help\n" | ||
| 887 | + " %s --version\n", cmd, cmd, cmd); | ||
| 888 | +} | ||
| 889 | + | ||
| 890 | +void | ||
| 891 | +print_help (char *cmd) | ||
| 892 | +{ | ||
| 893 | + print_revision (cmd, "$Revision: 1.1.1.1 $"); | ||
| 894 | + printf ("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n\n"); | ||
| 895 | + print_usage (cmd); | ||
| 896 | + printf ("\n"); | ||
| 897 | + printf | ||
| 898 | + ("-H, --hostname=HOST\n" | ||
| 899 | + " The name or address you want to query\n" | ||
| 900 | + "-s, --server=HOST\n" | ||
| 901 | + " Optional DNS server you want to use for the lookup\n" | ||
| 902 | + "-t, --timeout=INTEGER\n" | ||
| 903 | + " Seconds before connection times out (default: %d)\n" | ||
| 904 | + "-h, --help\n" | ||
| 905 | + " Print detailed help\n" | ||
| 906 | + "-V, --version\n" | ||
| 907 | + " Print version numbers and license information\n" | ||
| 908 | + "\n" | ||
| 909 | + "This plugin uses the nslookup program to obtain the IP address\n" | ||
| 910 | + "for the given host/domain query. A optional DNS server to use may\n" | ||
| 911 | + "be specified. If no DNS server is specified, the default server(s)\n" | ||
| 912 | + "specified in /etc/resolv.conf will be used.\n", DEFAULT_SOCKET_TIMEOUT); | ||
| 913 | } | ||
