~ubuntu-branches/ubuntu/precise/nagios-plugins/precise-proposed

« back to all changes in this revision

Viewing changes to plugins/check_dns.c

  • Committer: Bazaar Package Importer
  • Author(s): Guido Trotter
  • Date: 2004-06-15 15:37:48 UTC
  • Revision ID: james.westby@ubuntu.com-20040615153748-pq7702qdzghqfcns
Tags: upstream-1.3.1.0
ImportĀ upstreamĀ versionĀ 1.3.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************************************
 
2
 *
 
3
 * CHECK_DNS.C
 
4
 *
 
5
 * Program: DNS plugin for Nagios
 
6
 * License: GPL
 
7
 * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
 
8
 *
 
9
 * Last Modified: $Date: 2003/05/31 14:39:33 $
 
10
 *
 
11
 * Notes:
 
12
 *  - Safe popen added by Karl DeBisschop 9-11-99
 
13
 *  - expected-address parameter added by Alex Chaffee - 7 Oct 2002
 
14
 *
 
15
 * Command line: (see print_usage)
 
16
 *
 
17
 * Description:
 
18
 *
 
19
 * This program will use the nslookup program to obtain the IP address
 
20
 * for a given host name.  A optional DNS server may be specified.  If
 
21
 * no DNS server is specified, the default server(s) for the system
 
22
 * are used.
 
23
 *
 
24
 * Return Values:
 
25
 *  OK           The DNS query was successful (host IP address was returned).
 
26
 *  WARNING      The DNS server responded, but could not fulfill the request.
 
27
 *  CRITICAL     The DNS server is not responding or encountered an error.
 
28
 *
 
29
 * License Information:
 
30
 *
 
31
 * This program is free software; you can redistribute it and/or modify
 
32
 * it under the terms of the GNU General Public License as published by
 
33
 * the Free Software Foundation; either version 2 of the License, or
 
34
 * (at your option) any later version.
 
35
 *
 
36
 * This program is distributed in the hope that it will be useful,
 
37
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
38
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
39
 * GNU General Public License for more details.
 
40
 *
 
41
 * You should have received a copy of the GNU General Public License
 
42
 * along with this program; if not, write to the Free Software
 
43
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
44
 *
 
45
 *****************************************************************************/
 
46
 
 
47
#include "common.h"
 
48
#include "popen.h"
 
49
#include "utils.h"
 
50
 
 
51
const char *progname = "check_dns";
 
52
#define REVISION "$Revision: 1.8.2.3 $"
 
53
#define COPYRIGHT "2000-2002"
 
54
 
 
55
int process_arguments (int, char **);
 
56
int validate_arguments (void);
 
57
void print_usage (void);
 
58
void print_help (void);
 
59
int error_scan (char *);
 
60
 
 
61
#define ADDRESS_LENGTH 256
 
62
char query_address[ADDRESS_LENGTH] = "";
 
63
char dns_server[ADDRESS_LENGTH] = "";
 
64
char ptr_server[ADDRESS_LENGTH] = "";
 
65
int verbose = FALSE;
 
66
char expected_address[ADDRESS_LENGTH] = "";
 
67
int match_expected_address = FALSE;
 
68
 
 
69
int
 
70
main (int argc, char **argv)
 
71
{
 
72
        char *command_line = NULL;
 
73
        char input_buffer[MAX_INPUT_BUFFER];
 
74
        char *output = NULL;
 
75
        char *address = NULL;
 
76
        char *temp_buffer = NULL;
 
77
        int result = STATE_UNKNOWN;
 
78
 
 
79
        /* Set signal handling and alarm */
 
80
        if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
 
81
                printf ("Cannot catch SIGALRM");
 
82
                return STATE_UNKNOWN;
 
83
        }
 
84
 
 
85
        if (process_arguments (argc, argv) != OK) {
 
86
                print_usage ();
 
87
                return STATE_UNKNOWN;
 
88
        }
 
89
 
 
90
        /* get the command to run */
 
91
        asprintf (&command_line, "%s %s %s", NSLOOKUP_COMMAND,  query_address, dns_server);
 
92
 
 
93
        alarm (timeout_interval);
 
94
        time (&start_time);
 
95
 
 
96
        if (verbose)
 
97
                printf ("%s\n", command_line);
 
98
        /* run the command */
 
99
        child_process = spopen (command_line);
 
100
        if (child_process == NULL) {
 
101
                printf ("Could not open pipe: %s\n", command_line);
 
102
                return STATE_UNKNOWN;
 
103
        }
 
104
 
 
105
        child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
 
106
        if (child_stderr == NULL)
 
107
                printf ("Could not open stderr for %s\n", command_line);
 
108
 
 
109
        /* scan stdout */
 
110
        while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
 
111
 
 
112
                if (verbose)
 
113
                        printf ("%s\n", input_buffer);
 
114
 
 
115
                if (strstr (input_buffer, ".in-addr.arpa")) {
 
116
                        if ((temp_buffer = strstr (input_buffer, "name = ")))
 
117
                                address = strscpy (address, temp_buffer + 7);
 
118
                        else {
 
119
                                output = strscpy (output, "Unknown error (plugin)");
 
120
                                result = STATE_WARNING;
 
121
                        }
 
122
                }
 
123
 
 
124
                /* the server is responding, we just got the host name... */
 
125
                if (strstr (input_buffer, "Name:")) {
 
126
 
 
127
                        /* get the host address */
 
128
                        if (!fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process))
 
129
                                break;
 
130
 
 
131
                        if (verbose)
 
132
                                printf ("%s\n", input_buffer);
 
133
 
 
134
                        if ((temp_buffer = index (input_buffer, ':'))) {
 
135
                                temp_buffer++;
 
136
                                /* Strip leading spaces */
 
137
                                for (; *temp_buffer != '\0' && *temp_buffer == ' '; temp_buffer++)
 
138
                                        /* NOOP */;
 
139
                                address = strdup (temp_buffer);
 
140
                                strip (address);
 
141
                                if (address==NULL || strlen(address)==0)
 
142
                                        terminate (STATE_CRITICAL,
 
143
                                                   "DNS CRITICAL - '%s' returned empty host name string\n",
 
144
                                                   NSLOOKUP_COMMAND);
 
145
                                result = STATE_OK;
 
146
                        }
 
147
                        else {
 
148
                                output = strdup ("Unknown error (plugin)");
 
149
                                result = STATE_WARNING;
 
150
                        }
 
151
 
 
152
                        break;
 
153
                }
 
154
 
 
155
                result = error_scan (input_buffer);
 
156
                if (result != STATE_OK) {
 
157
                        output = strscpy (output, 1 + index (input_buffer, ':'));
 
158
                        break;
 
159
                }
 
160
 
 
161
        }
 
162
 
 
163
        /* scan stderr */
 
164
        while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
 
165
                if (error_scan (input_buffer) != STATE_OK) {
 
166
                        result = max_state (result, error_scan (input_buffer));
 
167
                        output = strscpy (output, 1 + index (input_buffer, ':'));
 
168
                }
 
169
        }
 
170
 
 
171
        /* close stderr */
 
172
        (void) fclose (child_stderr);
 
173
 
 
174
        /* close stdout */
 
175
        if (spclose (child_process)) {
 
176
                result = max_state (result, STATE_WARNING);
 
177
                if (!strcmp (output, ""))
 
178
                        output = strscpy (output, "nslookup returned error status");
 
179
        }
 
180
 
 
181
        /* If we got here, we should have an address string, 
 
182
           and we can segfault if we do not */
 
183
        if (address==NULL || strlen(address)==0)
 
184
                terminate (STATE_CRITICAL,
 
185
                           "DNS CRITICAL - '%s' output parsing exited with no address\n",
 
186
                           NSLOOKUP_COMMAND);
 
187
 
 
188
        /* compare to expected address */
 
189
        if (result == STATE_OK && match_expected_address && strcmp(address, expected_address)) {
 
190
                result = STATE_CRITICAL;
 
191
                asprintf(&output, "expected %s but got %s", expected_address, address);
 
192
        }
 
193
        
 
194
        (void) time (&end_time);
 
195
 
 
196
        if (result == STATE_OK)
 
197
                printf ("DNS ok - %d seconds response time, Address(es) is/are %s\n",
 
198
                                                (int) (end_time - start_time), address);
 
199
        else if (result == STATE_WARNING)
 
200
                printf ("DNS WARNING - %s\n",
 
201
                        !strcmp (output, "") ? " Probably a non-existent host/domain" : output);
 
202
        else if (result == STATE_CRITICAL)
 
203
                printf ("DNS CRITICAL - %s\n",
 
204
                        !strcmp (output, "") ? " Probably a non-existent host/domain" : output);
 
205
        else
 
206
                printf ("DNS problem - %s\n",
 
207
                        !strcmp (output, "") ? " Probably a non-existent host/domain" : output);
 
208
 
 
209
        return result;
 
210
}
 
211
 
 
212
int
 
213
error_scan (char *input_buffer)
 
214
{
 
215
 
 
216
        /* the DNS lookup timed out */
 
217
        if (strstr (input_buffer,
 
218
             "Note:  nslookup is deprecated and may be removed from future releases.")
 
219
            || strstr (input_buffer,
 
220
             "Consider using the `dig' or `host' programs instead.  Run nslookup with")
 
221
            || strstr (input_buffer,
 
222
             "the `-sil[ent]' option to prevent this message from appearing."))
 
223
                return STATE_OK;
 
224
 
 
225
        /* the DNS lookup timed out */
 
226
        else if (strstr (input_buffer, "Timed out"))
 
227
                return STATE_WARNING;
 
228
 
 
229
        /* DNS server is not running... */
 
230
        else if (strstr (input_buffer, "No response from server"))
 
231
                return STATE_CRITICAL;
 
232
 
 
233
        /* Host name is valid, but server doesn't have records... */
 
234
        else if (strstr (input_buffer, "No records"))
 
235
                return STATE_WARNING;
 
236
 
 
237
        /* Host or domain name does not exist */
 
238
        else if (strstr (input_buffer, "Non-existent"))
 
239
                return STATE_CRITICAL;
 
240
        else if (strstr (input_buffer, "** server can't find"))
 
241
                return STATE_CRITICAL;
 
242
        else if(strstr(input_buffer,"NXDOMAIN")) /* 9.x */
 
243
                return STATE_CRITICAL;
 
244
 
 
245
        /* Connection was refused */
 
246
        else if (strstr (input_buffer, "Connection refused"))
 
247
                return STATE_CRITICAL;
 
248
 
 
249
        /* Network is unreachable */
 
250
        else if (strstr (input_buffer, "Network is unreachable"))
 
251
                return STATE_CRITICAL;
 
252
 
 
253
        /* Internal server failure */
 
254
        else if (strstr (input_buffer, "Server failure"))
 
255
                return STATE_CRITICAL;
 
256
 
 
257
        /* DNS server refused to service request */
 
258
        else if (strstr (input_buffer, "Refused"))
 
259
                return STATE_CRITICAL;
 
260
 
 
261
        /* Request error */
 
262
        else if (strstr (input_buffer, "Format error"))
 
263
                return STATE_WARNING;
 
264
 
 
265
        else
 
266
                return STATE_OK;
 
267
 
 
268
}
 
269
 
 
270
/* process command-line arguments */
 
271
int
 
272
process_arguments (int argc, char **argv)
 
273
{
 
274
        int c;
 
275
 
 
276
#ifdef HAVE_GETOPT_H
 
277
        int opt_index = 0;
 
278
        static struct option long_opts[] = {
 
279
                {"help", no_argument, 0, 'h'},
 
280
                {"version", no_argument, 0, 'V'},
 
281
                {"verbose", no_argument, 0, 'v'},
 
282
                {"timeout", required_argument, 0, 't'},
 
283
                {"hostname", required_argument, 0, 'H'},
 
284
                {"server", required_argument, 0, 's'},
 
285
                {"reverse-server", required_argument, 0, 'r'},
 
286
                {"expected-address", required_argument, 0, 'a'},
 
287
                {0, 0, 0, 0}
 
288
        };
 
289
#endif
 
290
 
 
291
        if (argc < 2)
 
292
                return ERROR;
 
293
 
 
294
        for (c = 1; c < argc; c++)
 
295
                if (strcmp ("-to", argv[c]) == 0)
 
296
                        strcpy (argv[c], "-t");
 
297
 
 
298
        while (1) {
 
299
#ifdef HAVE_GETOPT_H
 
300
                c = getopt_long (argc, argv, "hVvt:H:s:r:a:", long_opts, &opt_index);
 
301
#else
 
302
                c = getopt (argc, argv, "hVvt:H:s:r:a:");
 
303
#endif
 
304
 
 
305
                if (c == -1 || c == EOF)
 
306
                        break;
 
307
 
 
308
                switch (c) {
 
309
                case '?': /* args not parsable */
 
310
                        printf ("%s: Unknown argument: %s\n\n", progname, optarg);
 
311
                        print_usage ();
 
312
                        exit (STATE_UNKNOWN);
 
313
                case 'h': /* help */
 
314
                        print_help ();
 
315
                        exit (STATE_OK);
 
316
                case 'V': /* version */
 
317
                        print_revision (progname, REVISION);
 
318
                        exit (STATE_OK);
 
319
                case 'v': /* version */
 
320
                        verbose = TRUE;
 
321
                        break;
 
322
                case 't': /* timeout period */
 
323
                        timeout_interval = atoi (optarg);
 
324
                        break;
 
325
                case 'H': /* hostname */
 
326
                        if (is_host (optarg) == FALSE) {
 
327
                                printf ("Invalid host name/address\n\n");
 
328
                                print_usage ();
 
329
                                exit (STATE_UNKNOWN);
 
330
                        }
 
331
                        if (strlen (optarg) >= ADDRESS_LENGTH)
 
332
                                terminate (STATE_UNKNOWN, "Input buffer overflow\n");
 
333
                        strcpy (query_address, optarg);
 
334
                        break;
 
335
                case 's': /* server name */
 
336
                        if (is_host (optarg) == FALSE) {
 
337
                                printf ("Invalid server name/address\n\n");
 
338
                                print_usage ();
 
339
                                exit (STATE_UNKNOWN);
 
340
                        }
 
341
                        if (strlen (optarg) >= ADDRESS_LENGTH)
 
342
                                terminate (STATE_UNKNOWN, "Input buffer overflow\n");
 
343
                        strcpy (dns_server, optarg);
 
344
                        break;
 
345
                case 'r': /* reverse server name */
 
346
                        if (is_host (optarg) == FALSE) {
 
347
                                printf ("Invalid host name/address\n\n");
 
348
                                print_usage ();
 
349
                                exit (STATE_UNKNOWN);
 
350
                        }
 
351
                        if (strlen (optarg) >= ADDRESS_LENGTH)
 
352
                                terminate (STATE_UNKNOWN, "Input buffer overflow\n");
 
353
                        strcpy (ptr_server, optarg);
 
354
                        break;
 
355
                case 'a': /* expected address */
 
356
                        if (is_dotted_quad (optarg) == FALSE) {
 
357
                                printf ("Invalid expected address\n\n");
 
358
                                print_usage ();
 
359
                                exit (STATE_UNKNOWN);
 
360
                        }
 
361
                        if (strlen (optarg) >= ADDRESS_LENGTH)
 
362
                                terminate (STATE_UNKNOWN, "Input buffer overflow\n");
 
363
                        strcpy (expected_address, optarg);
 
364
                        match_expected_address = TRUE;
 
365
                        break;
 
366
                }
 
367
        }
 
368
 
 
369
        c = optind;
 
370
        if (strlen(query_address)==0 && c<argc) {
 
371
                if (is_host(argv[c])==FALSE) {
 
372
                        printf ("Invalid name/address: %s\n\n", argv[c]);
 
373
                        return ERROR;
 
374
                }
 
375
                if (strlen(argv[c])>=ADDRESS_LENGTH)
 
376
                        terminate (STATE_UNKNOWN, "Input buffer overflow\n");
 
377
                strcpy (query_address, argv[c++]);
 
378
        }
 
379
 
 
380
        if (strlen(dns_server)==0 && c<argc) {
 
381
                if (is_host(argv[c]) == FALSE) {
 
382
                        printf ("Invalid name/address: %s\n\n", argv[c]);
 
383
                        return ERROR;
 
384
                }
 
385
                if (strlen(argv[c]) >= ADDRESS_LENGTH)
 
386
                        terminate (STATE_UNKNOWN, "Input buffer overflow\n");
 
387
                strcpy (dns_server, argv[c++]);
 
388
        }
 
389
 
 
390
        return validate_arguments ();
 
391
}
 
392
 
 
393
int
 
394
validate_arguments ()
 
395
{
 
396
        if (query_address[0] == 0)
 
397
                return ERROR;
 
398
        else
 
399
                return OK;
 
400
}
 
401
 
 
402
void
 
403
print_usage (void)
 
404
{
 
405
        printf ("Usage: %s -H host [-s server] [-a expected-address] [-t timeout]\n" "       %s --help\n"
 
406
                                        "       %s --version\n", progname, progname, progname);
 
407
}
 
408
 
 
409
void
 
410
print_help (void)
 
411
{
 
412
        print_revision (progname, REVISION);
 
413
        printf ("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n\n");
 
414
        print_usage ();
 
415
        printf
 
416
                ("\nOptions:\n"
 
417
                 "-H, --hostname=HOST\n"
 
418
                 "   The name or address you want to query\n"
 
419
                 "-s, --server=HOST\n"
 
420
                 "   Optional DNS server you want to use for the lookup\n"
 
421
                 "-a, --expected-address=IP-ADDRESS\n"
 
422
                 "   Optional IP address you expect the DNS server to return\n"
 
423
                 "-t, --timeout=INTEGER\n"
 
424
                 "   Seconds before connection times out (default: %d)\n"
 
425
                 "-h, --help\n"
 
426
                 "   Print detailed help\n"
 
427
                 "-V, --version\n"
 
428
                 "   Print version numbers and license information\n"
 
429
                 "\n"
 
430
                 "This plugin uses the nslookup program to obtain the IP address\n"
 
431
                 "for the given host/domain query.  A optional DNS server to use may\n"
 
432
                 "be specified.  If no DNS server is specified, the default server(s)\n"
 
433
                 "specified in /etc/resolv.conf will be used.\n", DEFAULT_SOCKET_TIMEOUT);
 
434
}