Code

Checks different record types and checks against an expected address (Bill Kunkel)
[nagiosplug.git] / plugins / check_dig.c
1 /*****************************************************************************
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; either version 2 of the License, or
6  (at your option) any later version.
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  GNU General Public License for more details.
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 *****************************************************************************/
19 #include "common.h"
20 #include "netutils.h"
21 #include "utils.h"
22 #include "popen.h"
24 int process_arguments (int, char **);
25 int validate_arguments (void);
26 void print_help (void);
27 void print_usage (void);
29 const char *progname = "check_dig";
30 const char *revision = "$Revision$";
31 const char *copyright = "2002-2003";
32 const char *email = "nagiosplug-devel@lists.sourceforge.net";
34 enum {
35         UNDEFINED = 0,
36         DEFAULT_PORT = 53
37 };
39 char *query_address = NULL;
40 char *record_type = "A";
41 char *expected_address = NULL;
42 char *dns_server = NULL;
43 int verbose = FALSE;
44 int server_port = DEFAULT_PORT;
45 double warning_interval = UNDEFINED;
46 double critical_interval = UNDEFINED;
47 struct timeval tv;
49 int
50 main (int argc, char **argv)
51 {
52         char input_buffer[MAX_INPUT_BUFFER];
53         char *command_line;
54         char *output;
55         long microsec;
56         double elapsed_time;
57         int result = STATE_UNKNOWN;
59         output = strdup ("");
61         setlocale (LC_ALL, "");
62         bindtextdomain (PACKAGE, LOCALEDIR);
63         textdomain (PACKAGE);
65         /* Set signal handling and alarm */
66         if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR)
67                 usage (_("Cannot catch SIGALRM\n"));
69         if (process_arguments (argc, argv) != OK)
70                 usage (_("Could not parse arguments\n"));
72         /* get the command to run */
73         asprintf (&command_line, "%s @%s -p %d %s -t %s",
74                   PATH_TO_DIG, dns_server, server_port, query_address, record_type);
76         alarm (timeout_interval);
77         gettimeofday (&tv, NULL);
79         if (verbose) {
80                 printf ("%s\n", command_line);
81                 if(expected_address != NULL) {
82                         printf ("Looking for: '%s'\n", expected_address);
83                 } else {
84                         printf ("Looking for: '%s'\n", query_address);
85                 }
86         }
88         /* run the command */
89         child_process = spopen (command_line);
90         if (child_process == NULL) {
91                 printf (_("Could not open pipe: %s\n"), command_line);
92                 return STATE_UNKNOWN;
93         }
95         child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
96         if (child_stderr == NULL)
97                 printf (_("Could not open stderr for %s\n"), command_line);
99         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
101                 /* the server is responding, we just got the host name... */
102                 if (strstr (input_buffer, ";; ANSWER SECTION:")) {
104                         /* loop through the whole 'ANSWER SECTION' */
105                         do {
106                                 /* get the host address */
107                                 if (!fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process))
108                                         break;
110                                 if (strpbrk (input_buffer, "\r\n"))
111                                         input_buffer[strcspn (input_buffer, "\r\n")] = '\0';
113                                 if (verbose && !strstr (input_buffer, ";; ")) 
114                                         printf ("%s\n", input_buffer); 
116                                 if (expected_address==NULL && strstr (input_buffer, query_address) != NULL) {
117                                         output = strdup(input_buffer);
118                                         result = STATE_OK;
119                                 }
120                                 else if (expected_address != NULL && strstr (input_buffer, expected_address) != NULL) {
121                                         output = strdup(input_buffer);
122                                         result = STATE_OK;
123                                 }
125                         } while (!strstr (input_buffer, ";; "));
127                         if (result == STATE_UNKNOWN) {
128                                 asprintf (&output, _("Server not found in ANSWER SECTION"));
129                                 result = STATE_WARNING;
130                         }
132                 }
134         }
136         if (result == STATE_UNKNOWN) {
137                 asprintf (&output, _("No ANSWER SECTION found"));
138         }
140         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
141                 /* If we get anything on STDERR, at least set warning */
142                 result = max_state (result, STATE_WARNING);
143                 printf ("%s", input_buffer);
144                 if (strlen (output) == 0)
145                         output = strdup (1 + index (input_buffer, ':'));
146         }
148         (void) fclose (child_stderr);
150         /* close the pipe */
151         if (spclose (child_process)) {
152                 result = max_state (result, STATE_WARNING);
153                 if (strlen (output) == 0)
154                         asprintf (&output, _("dig returned error status"));
155         }
157         microsec = deltime (tv);
158         elapsed_time = (double)microsec / 1.0e6;
160         if (output == NULL || strlen (output) == 0)
161                 asprintf (&output, _(" Probably a non-existent host/domain"));
163         if (critical_interval > UNDEFINED && elapsed_time > critical_interval)
164                 result = STATE_CRITICAL;
166         else if (warning_interval > UNDEFINED && elapsed_time > warning_interval)
167                 result = STATE_WARNING;
169         asprintf (&output, _("%.3f seconds response time (%s)"), elapsed_time, output);
171         printf ("DNS %s - %s|%s\n",
172                 state_text (result), output,
173                 fperfdata("time", elapsed_time, "s",
174                          (warning_interval>UNDEFINED?TRUE:FALSE),
175                          warning_interval,
176                          (critical_interval>UNDEFINED?TRUE:FALSE),
177                          critical_interval,
178                                                                          TRUE, 0, FALSE, 0));
179         return result;
186 \f
187 /* process command-line arguments */
188 int
189 process_arguments (int argc, char **argv)
191         int c;
193         int option = 0;
194         static struct option longopts[] = {
195                 {"hostname", required_argument, 0, 'H'},
196                 {"query_address", required_argument, 0, 'l'},
197                 {"warning", required_argument, 0, 'w'},
198                 {"critical", required_argument, 0, 'c'},
199                 {"timeout", required_argument, 0, 't'},
200                 {"verbose", no_argument, 0, 'v'},
201                 {"version", no_argument, 0, 'V'},
202                 {"help", no_argument, 0, 'h'},
203                 {"record_type", required_argument, 0, 'T'},
204                 {"expected_address", required_argument, 0, 'a'},
205                 {0, 0, 0, 0}
206         };
208         if (argc < 2)
209                 return ERROR;
211         while (1) {
212                 c = getopt_long (argc, argv, "hVvt:l:H:w:c:T:a:", longopts, &option);
214                 if (c == -1 || c == EOF)
215                         break;
217                 switch (c) {
218                 case '?':                                                                       /* help */
219                         usage3 (_("Unknown argument"), optopt);
220                 case 'h':                                                                       /* help */
221                         print_help ();
222                         exit (STATE_OK);
223                 case 'V':                                                                       /* version */
224                         print_revision (progname, "$Revision$");
225                         exit (STATE_OK);
226                 case 'H':                                                                       /* hostname */
227                         if (is_host (optarg)) {
228                                 dns_server = optarg;
229                         }
230                         else {
231                                 usage2 (_("Invalid host name"), optarg);
232                         }
233                         break;
234                 case 'p':                 /* server port */
235                         if (is_intpos (optarg)) {
236                                 server_port = atoi (optarg);
237                         }
238                         else {
239                                 usage2 (_("Server port must be a nonnegative integer"), optarg);
240                         }
241                         break;
242                 case 'l':                                                                       /* address to lookup */
243                         query_address = optarg;
244                         break;
245                 case 'w':                                                                       /* warning */
246                         if (is_nonnegative (optarg)) {
247                                 warning_interval = strtod (optarg, NULL);
248                         }
249                         else {
250                                 usage2 (_("Warning interval must be a nonnegative integer"), optarg);
251                         }
252                         break;
253                 case 'c':                                                                       /* critical */
254                         if (is_nonnegative (optarg)) {
255                                 critical_interval = strtod (optarg, NULL);
256                         }
257                         else {
258                                 usage2 (_("Critical interval must be a nonnegative integer"), optarg);
259                         }
260                         break;
261                 case 't':                                                                       /* timeout */
262                         if (is_intnonneg (optarg)) {
263                                 timeout_interval = atoi (optarg);
264                         }
265                         else {
266                                 usage2 (_("Time interval must be a nonnegative integer"), optarg);
267                         }
268                         break;
269                 case 'v':                                                                       /* verbose */
270                         verbose = TRUE;
271                         break;
272                 case 'T':
273                         record_type = optarg;
274                         break;
275                 case 'a':
276                         expected_address = optarg;
277                         break;
278                 }
279         }
281         c = optind;
282         if (dns_server == NULL) {
283                 if (c < argc) {
284                         if (is_host (argv[c])) {
285                                 dns_server = argv[c];
286                         }
287                         else {
288                                 usage2 (_("Invalid host name"), argv[c]);
289                         }
290                 }
291                 else {
292                         dns_server = strdup ("127.0.0.1");
293                 }
294         }
296         return validate_arguments ();
303 int
304 validate_arguments (void)
306         return OK;
314 \f
315 void
316 print_help (void)
318         char *myport;
320         asprintf (&myport, "%d", DEFAULT_PORT);
322         print_revision (progname, revision);
324         printf (_("Copyright (c) 2000 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n"));
325         printf (_(COPYRIGHT), copyright, email);
327         printf (_("Test the DNS service on the specified host using dig\n\n"));
329         print_usage ();
331         printf (_(UT_HELP_VRSN));
333         printf (_(UT_HOST_PORT), 'P', myport);
335         printf (_("\
336  -l, --lookup=STRING\n\
337    machine name to lookup\n"));
339         printf (_("\
340  -T, --record_type=STRING\n\
341    record type to lookup (default: A)\n"));
343         printf (_("\
344  -a, --expected_address=STRING\n\
345    an address expected to be in the asnwer section.\n\
346    if not set, uses whatever was in -l\n"));
348         printf (_(UT_WARN_CRIT));
350         printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
352         printf (_(UT_VERBOSE));
354         printf (_(UT_SUPPORT));
360 void
361 print_usage (void)
363         printf (_("\
364 Usage: %s -H host -l lookup [-p <server port>] [-T <query type>]\n\
365          [-w <warning interval>] [-c <critical interval>] [-t <timeout>]\n\
366          [-a <expected answer address>] [-v]\n"),
367                 progname);
368         printf ("       %s (-h|--help)\n", progname);
369         printf ("       %s (-V|--version)\n", progname);