summaryrefslogtreecommitdiffstats
path: root/plugins/check_dns.c
diff options
context:
space:
mode:
authorRincewindsHat <12514511+RincewindsHat@users.noreply.github.com>2021-12-02 16:42:05 +0100
committerGitHub <noreply@github.com>2021-12-02 16:42:05 +0100
commit911e44045d7291f5ede22739fd176ef55dd3de4a (patch)
treecf36b95a4a964b03d6ecf75770ced2cb3a2ac3a9 /plugins/check_dns.c
parent8294af907bd8482a86df749f562b7ec09e3faeed (diff)
parented7cdf82a42f16532801ea4f118870ce9a130fcf (diff)
downloadmonitoring-plugins-911e44045d7291f5ede22739fd176ef55dd3de4a.tar.gz
Merge branch 'master' into fix/shellcheck
Diffstat (limited to 'plugins/check_dns.c')
-rw-r--r--plugins/check_dns.c119
1 files changed, 93 insertions, 26 deletions
diff --git a/plugins/check_dns.c b/plugins/check_dns.c
index 5feafc80..9de6caf5 100644
--- a/plugins/check_dns.c
+++ b/plugins/check_dns.c
@@ -41,7 +41,7 @@ const char *email = "devel@monitoring-plugins.org";
41 41
42int process_arguments (int, char **); 42int process_arguments (int, char **);
43int validate_arguments (void); 43int validate_arguments (void);
44int error_scan (char *); 44int error_scan (char *, int *);
45int ip_match_cidr(const char *, const char *); 45int ip_match_cidr(const char *, const char *);
46unsigned long ip2long(const char *); 46unsigned long ip2long(const char *);
47void print_help (void); 47void print_help (void);
@@ -54,8 +54,10 @@ char ptr_server[ADDRESS_LENGTH] = "";
54int verbose = FALSE; 54int verbose = FALSE;
55char **expected_address = NULL; 55char **expected_address = NULL;
56int expected_address_cnt = 0; 56int expected_address_cnt = 0;
57int expect_nxdomain = FALSE;
57 58
58int expect_authority = FALSE; 59int expect_authority = FALSE;
60int all_match = FALSE;
59thresholds *time_thresholds = NULL; 61thresholds *time_thresholds = NULL;
60 62
61static int 63static int
@@ -86,6 +88,7 @@ main (int argc, char **argv)
86 int parse_address = FALSE; /* This flag scans for Address: but only after Name: */ 88 int parse_address = FALSE; /* This flag scans for Address: but only after Name: */
87 output chld_out, chld_err; 89 output chld_out, chld_err;
88 size_t i; 90 size_t i;
91 int is_nxdomain = FALSE;
89 92
90 setlocale (LC_ALL, ""); 93 setlocale (LC_ALL, "");
91 bindtextdomain (PACKAGE, LOCALEDIR); 94 bindtextdomain (PACKAGE, LOCALEDIR);
@@ -168,8 +171,8 @@ main (int argc, char **argv)
168 temp_buffer++; 171 temp_buffer++;
169 172
170 /* Strip leading spaces */ 173 /* Strip leading spaces */
171 for (; *temp_buffer != '\0' && *temp_buffer == ' '; temp_buffer++) 174 while (*temp_buffer == ' ')
172 /* NOOP */; 175 temp_buffer++;
173 176
174 strip(temp_buffer); 177 strip(temp_buffer);
175 if (temp_buffer==NULL || strlen(temp_buffer)==0) { 178 if (temp_buffer==NULL || strlen(temp_buffer)==0) {
@@ -185,7 +188,7 @@ main (int argc, char **argv)
185 } 188 }
186 189
187 190
188 result = error_scan (chld_out.line[i]); 191 result = error_scan (chld_out.line[i], &is_nxdomain);
189 if (result != STATE_OK) { 192 if (result != STATE_OK) {
190 msg = strchr (chld_out.line[i], ':'); 193 msg = strchr (chld_out.line[i], ':');
191 if(msg) msg++; 194 if(msg) msg++;
@@ -198,13 +201,20 @@ main (int argc, char **argv)
198 if (verbose) 201 if (verbose)
199 puts(chld_err.line[i]); 202 puts(chld_err.line[i]);
200 203
201 if (error_scan (chld_err.line[i]) != STATE_OK) { 204 if (error_scan (chld_err.line[i], &is_nxdomain) != STATE_OK) {
202 result = max_state (result, error_scan (chld_err.line[i])); 205 result = max_state (result, error_scan (chld_err.line[i], &is_nxdomain));
203 msg = strchr(input_buffer, ':'); 206 msg = strchr(input_buffer, ':');
204 if(msg) msg++; 207 if(msg)
208 msg++;
209 else
210 msg = input_buffer;
205 } 211 }
206 } 212 }
207 213
214 if (is_nxdomain && !expect_nxdomain) {
215 die (STATE_CRITICAL, _("Domain '%s' was not found by the server\n"), query_address);
216 }
217
208 if (addresses) { 218 if (addresses) {
209 int i,slen; 219 int i,slen;
210 char *adrp; 220 char *adrp;
@@ -228,16 +238,27 @@ main (int argc, char **argv)
228 if (result == STATE_OK && expected_address_cnt > 0) { 238 if (result == STATE_OK && expected_address_cnt > 0) {
229 result = STATE_CRITICAL; 239 result = STATE_CRITICAL;
230 temp_buffer = ""; 240 temp_buffer = "";
241 unsigned long expect_match = (1 << expected_address_cnt) - 1;
242 unsigned long addr_match = (1 << n_addresses) - 1;
231 243
232 for (i=0; i<expected_address_cnt; i++) { 244 for (i=0; i<expected_address_cnt; i++) {
245 int j;
233 /* check if we get a match on 'raw' ip or cidr */ 246 /* check if we get a match on 'raw' ip or cidr */
234 if ( strcmp(address, expected_address[i]) == 0 247 for (j=0; j<n_addresses; j++) {
235 || ip_match_cidr(address, expected_address[i]) ) 248 if ( strcmp(addresses[j], expected_address[i]) == 0
236 result = STATE_OK; 249 || ip_match_cidr(addresses[j], expected_address[i]) ) {
250 result = STATE_OK;
251 addr_match &= ~(1 << j);
252 expect_match &= ~(1 << i);
253 }
254 }
237 255
238 /* prepare an error string */ 256 /* prepare an error string */
239 xasprintf(&temp_buffer, "%s%s; ", temp_buffer, expected_address[i]); 257 xasprintf(&temp_buffer, "%s%s; ", temp_buffer, expected_address[i]);
240 } 258 }
259 /* check if expected_address must cover all in addresses and none may be missing */
260 if (all_match && (expect_match != 0 || addr_match != 0))
261 result = STATE_CRITICAL;
241 if (result == STATE_CRITICAL) { 262 if (result == STATE_CRITICAL) {
242 /* Strip off last semicolon... */ 263 /* Strip off last semicolon... */
243 temp_buffer[strlen(temp_buffer)-2] = '\0'; 264 temp_buffer[strlen(temp_buffer)-2] = '\0';
@@ -245,6 +266,16 @@ main (int argc, char **argv)
245 } 266 }
246 } 267 }
247 268
269 if (expect_nxdomain) {
270 if (!is_nxdomain) {
271 result = STATE_CRITICAL;
272 xasprintf(&msg, _("Domain '%s' was found by the server: '%s'\n"), query_address, address);
273 } else {
274 if (address != NULL) free(address);
275 address = "NXDOMAIN";
276 }
277 }
278
248 /* check if authoritative */ 279 /* check if authoritative */
249 if (result == STATE_OK && expect_authority && non_authoritative) { 280 if (result == STATE_OK && expect_authority && non_authoritative) {
250 result = STATE_CRITICAL; 281 result = STATE_CRITICAL;
@@ -324,9 +355,15 @@ ip2long(const char* src) {
324} 355}
325 356
326int 357int
327error_scan (char *input_buffer) 358error_scan (char *input_buffer, int *is_nxdomain)
328{ 359{
329 360
361 const int nxdomain = strstr (input_buffer, "Non-existent") ||
362 strstr (input_buffer, "** server can't find") ||
363 strstr (input_buffer, "** Can't find") ||
364 strstr (input_buffer, "NXDOMAIN");
365 if (nxdomain) *is_nxdomain = TRUE;
366
330 /* the DNS lookup timed out */ 367 /* the DNS lookup timed out */
331 if (strstr (input_buffer, _("Note: nslookup is deprecated and may be removed from future releases.")) || 368 if (strstr (input_buffer, _("Note: nslookup is deprecated and may be removed from future releases.")) ||
332 strstr (input_buffer, _("Consider using the `dig' or `host' programs instead. Run nslookup with")) || 369 strstr (input_buffer, _("Consider using the `dig' or `host' programs instead. Run nslookup with")) ||
@@ -336,6 +373,8 @@ error_scan (char *input_buffer)
336 /* DNS server is not running... */ 373 /* DNS server is not running... */
337 else if (strstr (input_buffer, "No response from server")) 374 else if (strstr (input_buffer, "No response from server"))
338 die (STATE_CRITICAL, _("No response from DNS %s\n"), dns_server); 375 die (STATE_CRITICAL, _("No response from DNS %s\n"), dns_server);
376 else if (strstr (input_buffer, "no servers could be reached"))
377 die (STATE_CRITICAL, _("No response from DNS %s\n"), dns_server);
339 378
340 /* Host name is valid, but server doesn't have records... */ 379 /* Host name is valid, but server doesn't have records... */
341 else if (strstr (input_buffer, "No records")) 380 else if (strstr (input_buffer, "No records"))
@@ -343,7 +382,7 @@ error_scan (char *input_buffer)
343 382
344 /* Connection was refused */ 383 /* Connection was refused */
345 else if (strstr (input_buffer, "Connection refused") || 384 else if (strstr (input_buffer, "Connection refused") ||
346 strstr (input_buffer, "Couldn't find server") || 385 strstr (input_buffer, "Couldn't find server") ||
347 strstr (input_buffer, "Refused") || 386 strstr (input_buffer, "Refused") ||
348 (strstr (input_buffer, "** server can't find") && 387 (strstr (input_buffer, "** server can't find") &&
349 strstr (input_buffer, ": REFUSED"))) 388 strstr (input_buffer, ": REFUSED")))
@@ -357,12 +396,6 @@ error_scan (char *input_buffer)
357 else if (strstr (input_buffer, "No information")) 396 else if (strstr (input_buffer, "No information"))
358 die (STATE_CRITICAL, _("No information returned by DNS server at %s\n"), dns_server); 397 die (STATE_CRITICAL, _("No information returned by DNS server at %s\n"), dns_server);
359 398
360 /* Host or domain name does not exist */
361 else if (strstr (input_buffer, "Non-existent") ||
362 strstr (input_buffer, "** server can't find") ||
363 strstr (input_buffer,"NXDOMAIN"))
364 die (STATE_CRITICAL, _("Domain %s was not found by the server\n"), query_address);
365
366 /* Network is unreachable */ 399 /* Network is unreachable */
367 else if (strstr (input_buffer, "Network is unreachable")) 400 else if (strstr (input_buffer, "Network is unreachable"))
368 die (STATE_CRITICAL, _("Network is unreachable\n")); 401 die (STATE_CRITICAL, _("Network is unreachable\n"));
@@ -399,7 +432,9 @@ process_arguments (int argc, char **argv)
399 {"server", required_argument, 0, 's'}, 432 {"server", required_argument, 0, 's'},
400 {"reverse-server", required_argument, 0, 'r'}, 433 {"reverse-server", required_argument, 0, 'r'},
401 {"expected-address", required_argument, 0, 'a'}, 434 {"expected-address", required_argument, 0, 'a'},
435 {"expect-nxdomain", no_argument, 0, 'n'},
402 {"expect-authority", no_argument, 0, 'A'}, 436 {"expect-authority", no_argument, 0, 'A'},
437 {"all", no_argument, 0, 'L'},
403 {"warning", required_argument, 0, 'w'}, 438 {"warning", required_argument, 0, 'w'},
404 {"critical", required_argument, 0, 'c'}, 439 {"critical", required_argument, 0, 'c'},
405 {0, 0, 0, 0} 440 {0, 0, 0, 0}
@@ -413,7 +448,7 @@ process_arguments (int argc, char **argv)
413 strcpy (argv[c], "-t"); 448 strcpy (argv[c], "-t");
414 449
415 while (1) { 450 while (1) {
416 c = getopt_long (argc, argv, "hVvAt:H:s:r:a:w:c:", long_opts, &opt_index); 451 c = getopt_long (argc, argv, "hVvALnt:H:s:r:a:w:c:", long_opts, &opt_index);
417 452
418 if (c == -1 || c == EOF) 453 if (c == -1 || c == EOF)
419 break; 454 break;
@@ -454,13 +489,33 @@ process_arguments (int argc, char **argv)
454 case 'a': /* expected address */ 489 case 'a': /* expected address */
455 if (strlen (optarg) >= ADDRESS_LENGTH) 490 if (strlen (optarg) >= ADDRESS_LENGTH)
456 die (STATE_UNKNOWN, _("Input buffer overflow\n")); 491 die (STATE_UNKNOWN, _("Input buffer overflow\n"));
457 expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**)); 492 if (strchr(optarg, ',') != NULL) {
458 expected_address[expected_address_cnt] = strdup(optarg); 493 char *comma = strchr(optarg, ',');
459 expected_address_cnt++; 494 while (comma != NULL) {
495 expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**));
496 expected_address[expected_address_cnt] = strndup(optarg, comma - optarg);
497 expected_address_cnt++;
498 optarg = comma + 1;
499 comma = strchr(optarg, ',');
500 }
501 expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**));
502 expected_address[expected_address_cnt] = strdup(optarg);
503 expected_address_cnt++;
504 } else {
505 expected_address = (char **)realloc(expected_address, (expected_address_cnt+1) * sizeof(char**));
506 expected_address[expected_address_cnt] = strdup(optarg);
507 expected_address_cnt++;
508 }
509 break;
510 case 'n': /* expect NXDOMAIN */
511 expect_nxdomain = TRUE;
460 break; 512 break;
461 case 'A': /* expect authority */ 513 case 'A': /* expect authority */
462 expect_authority = TRUE; 514 expect_authority = TRUE;
463 break; 515 break;
516 case 'L': /* all must match */
517 all_match = TRUE;
518 break;
464 case 'w': 519 case 'w':
465 warning = optarg; 520 warning = optarg;
466 break; 521 break;
@@ -496,8 +551,15 @@ process_arguments (int argc, char **argv)
496int 551int
497validate_arguments () 552validate_arguments ()
498{ 553{
499 if (query_address[0] == 0) 554 if (query_address[0] == 0) {
555 printf ("missing --host argument\n");
500 return ERROR; 556 return ERROR;
557 }
558
559 if (expected_address_cnt > 0 && expect_nxdomain) {
560 printf ("--expected-address and --expect-nxdomain cannot be combined\n");
561 return ERROR;
562 }
501 563
502 return OK; 564 return OK;
503} 565}
@@ -529,14 +591,19 @@ print_help (void)
529 printf (" -a, --expected-address=IP-ADDRESS|CIDR|HOST\n"); 591 printf (" -a, --expected-address=IP-ADDRESS|CIDR|HOST\n");
530 printf (" %s\n", _("Optional IP-ADDRESS/CIDR you expect the DNS server to return. HOST must end")); 592 printf (" %s\n", _("Optional IP-ADDRESS/CIDR you expect the DNS server to return. HOST must end"));
531 printf (" %s\n", _("with a dot (.). This option can be repeated multiple times (Returns OK if any")); 593 printf (" %s\n", _("with a dot (.). This option can be repeated multiple times (Returns OK if any"));
532 printf (" %s\n", _("value match). If multiple addresses are returned at once, you have to match")); 594 printf (" %s\n", _("value matches)."));
533 printf (" %s\n", _("the whole string of addresses separated with commas (sorted alphabetically).")); 595 printf (" -n, --expect-nxdomain\n");
596 printf (" %s\n", _("Expect the DNS server to return NXDOMAIN (i.e. the domain was not found)"));
597 printf (" %s\n", _("Cannot be used together with -a"));
534 printf (" -A, --expect-authority\n"); 598 printf (" -A, --expect-authority\n");
535 printf (" %s\n", _("Optionally expect the DNS server to be authoritative for the lookup")); 599 printf (" %s\n", _("Optionally expect the DNS server to be authoritative for the lookup"));
536 printf (" -w, --warning=seconds\n"); 600 printf (" -w, --warning=seconds\n");
537 printf (" %s\n", _("Return warning if elapsed time exceeds value. Default off")); 601 printf (" %s\n", _("Return warning if elapsed time exceeds value. Default off"));
538 printf (" -c, --critical=seconds\n"); 602 printf (" -c, --critical=seconds\n");
539 printf (" %s\n", _("Return critical if elapsed time exceeds value. Default off")); 603 printf (" %s\n", _("Return critical if elapsed time exceeds value. Default off"));
604 printf (" -L, --all\n");
605 printf (" %s\n", _("Return critical if the list of expected addresses does not match all addresses"));
606 printf (" %s\n", _("returned. Default off"));
540 607
541 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 608 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
542 609
@@ -548,5 +615,5 @@ void
548print_usage (void) 615print_usage (void)
549{ 616{
550 printf ("%s\n", _("Usage:")); 617 printf ("%s\n", _("Usage:"));
551 printf ("%s -H host [-s server] [-a expected-address] [-A] [-t timeout] [-w warn] [-c crit]\n", progname); 618 printf ("%s -H host [-s server] [-a expected-address] [-n] [-A] [-t timeout] [-w warn] [-c crit] [-L]\n", progname);
552} 619}