Code

Convert tabs to spaces from dig's answer section (Randy O'Meara - 1107651)
[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  $Id$
18  
19 *****************************************************************************/
21 const char *progname = "check_dig";
22 const char *revision = "$Revision$";
23 const char *copyright = "2002-2004";
24 const char *email = "nagiosplug-devel@lists.sourceforge.net";
26 #include "common.h"
27 #include "netutils.h"
28 #include "utils.h"
29 #include "popen.h"
31 int process_arguments (int, char **);
32 int validate_arguments (void);
33 void print_help (void);
34 void print_usage (void);
36 enum {
37         UNDEFINED = 0,
38         DEFAULT_PORT = 53
39 };
41 char *query_address = NULL;
42 char *record_type = "A";
43 char *expected_address = NULL;
44 char *dns_server = NULL;
45 int verbose = FALSE;
46 int server_port = DEFAULT_PORT;
47 double warning_interval = UNDEFINED;
48 double critical_interval = UNDEFINED;
49 struct timeval tv;
51 int
52 main (int argc, char **argv)
53 {
54         char input_buffer[MAX_INPUT_BUFFER];
55         char *command_line;
56         char *output;
57         char *t;
58         long microsec;
59         double elapsed_time;
60         int result = STATE_UNKNOWN;
62         output = strdup ("");
64         setlocale (LC_ALL, "");
65         bindtextdomain (PACKAGE, LOCALEDIR);
66         textdomain (PACKAGE);
68         /* Set signal handling and alarm */
69         if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR)
70                 usage4 (_("Cannot catch SIGALRM"));
72         if (process_arguments (argc, argv) == ERROR)
73                 usage4 (_("Could not parse arguments"));
75         /* get the command to run */
76         asprintf (&command_line, "%s @%s -p %d %s -t %s",
77                   PATH_TO_DIG, dns_server, server_port, query_address, record_type);
79         alarm (timeout_interval);
80         gettimeofday (&tv, NULL);
82         if (verbose) {
83                 printf ("%s\n", command_line);
84                 if(expected_address != NULL) {
85                         printf (_("Looking for: '%s'\n"), expected_address);
86                 } else {
87                         printf (_("Looking for: '%s'\n"), query_address);
88                 }
89         }
91         /* run the command */
92         child_process = spopen (command_line);
93         if (child_process == NULL) {
94                 printf (_("Could not open pipe: %s\n"), command_line);
95                 return STATE_UNKNOWN;
96         }
98         child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
99         if (child_stderr == NULL)
100                 printf (_("Could not open stderr for %s\n"), command_line);
102         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
104                 /* the server is responding, we just got the host name... */
105                 if (strstr (input_buffer, ";; ANSWER SECTION:")) {
107                         /* loop through the whole 'ANSWER SECTION' */
108                         do {
109                                 /* get the host address */
110                                 if (!fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process))
111                                         break;
113                                 if (strpbrk (input_buffer, "\r\n"))
114                                         input_buffer[strcspn (input_buffer, "\r\n")] = '\0';
116                                 if (verbose && !strstr (input_buffer, ";; ")) 
117                                         printf ("%s\n", input_buffer); 
119                                 if (expected_address==NULL && strstr (input_buffer, query_address) != NULL) {
120                                         output = strdup(input_buffer);
121                                         result = STATE_OK;
122                                 }
123                                 else if (expected_address != NULL && strstr (input_buffer, expected_address) != NULL) {
124                                         output = strdup(input_buffer);
125                                         result = STATE_OK;
126                                 }
128                                 /* Translate output TAB -> SPACE */
129                                 t = output;
130                                 while ((t = index(t, '\t')) != NULL) 
131                                         *t = ' ';
133                         } while (!strstr (input_buffer, ";; "));
135                         if (result == STATE_UNKNOWN) {
136                                 asprintf (&output, _("Server not found in ANSWER SECTION"));
137                                 result = STATE_WARNING;
138                         }
139                 }
141         }
143         if (result == STATE_UNKNOWN) {
144                 asprintf (&output, _("No ANSWER SECTION found"));
145         }
147         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
148                 /* If we get anything on STDERR, at least set warning */
149                 result = max_state (result, STATE_WARNING);
150                 printf ("%s", input_buffer);
151                 if (strlen (output) == 0)
152                         output = strdup (1 + index (input_buffer, ':'));
153         }
155         (void) fclose (child_stderr);
157         /* close the pipe */
158         if (spclose (child_process)) {
159                 result = max_state (result, STATE_WARNING);
160                 if (strlen (output) == 0)
161                         asprintf (&output, _("dig returned an error status"));
162         }
164         microsec = deltime (tv);
165         elapsed_time = (double)microsec / 1.0e6;
167         if (output == NULL || strlen (output) == 0)
168                 asprintf (&output, _(" Probably a non-existent host/domain"));
170         if (critical_interval > UNDEFINED && elapsed_time > critical_interval)
171                 result = STATE_CRITICAL;
173         else if (warning_interval > UNDEFINED && elapsed_time > warning_interval)
174                 result = STATE_WARNING;
176         asprintf (&output, _("%.3f seconds response time (%s)"), elapsed_time, output);
178         printf ("DNS %s - %s|%s\n",
179                 state_text (result), output,
180                 fperfdata("time", elapsed_time, "s",
181                          (warning_interval>UNDEFINED?TRUE:FALSE),
182                          warning_interval,
183                          (critical_interval>UNDEFINED?TRUE:FALSE),
184                          critical_interval,
185                                                                          TRUE, 0, FALSE, 0));
186         return result;
191 /* process command-line arguments */
192 int
193 process_arguments (int argc, char **argv)
195         int c;
197         int option = 0;
198         static struct option longopts[] = {
199                 {"hostname", required_argument, 0, 'H'},
200                 {"query_address", required_argument, 0, 'l'},
201                 {"warning", required_argument, 0, 'w'},
202                 {"critical", required_argument, 0, 'c'},
203                 {"timeout", required_argument, 0, 't'},
204                 {"verbose", no_argument, 0, 'v'},
205                 {"version", no_argument, 0, 'V'},
206                 {"help", no_argument, 0, 'h'},
207                 {"record_type", required_argument, 0, 'T'},
208                 {"expected_address", required_argument, 0, 'a'},
209                 {0, 0, 0, 0}
210         };
212         if (argc < 2)
213                 return ERROR;
215         while (1) {
216                 c = getopt_long (argc, argv, "hVvt:l:H:w:c:T:a:", longopts, &option);
218                 if (c == -1 || c == EOF)
219                         break;
221                 switch (c) {
222                 case '?':                                                                       /* help */
223                         usage2 (_("Unknown argument"), optarg);
224                 case 'h':                                                                       /* help */
225                         print_help ();
226                         exit (STATE_OK);
227                 case 'V':                                                                       /* version */
228                         print_revision (progname, revision);
229                         exit (STATE_OK);
230                 case 'H':                                                                       /* hostname */
231                         if (is_host (optarg)) {
232                                 dns_server = optarg;
233                         }
234                         else {
235                                 usage2 (_("Invalid hostname/address"), optarg);
236                         }
237                         break;
238                 case 'p':                 /* server port */
239                         if (is_intpos (optarg)) {
240                                 server_port = atoi (optarg);
241                         }
242                         else {
243                                 usage2 (_("Port must be a positive integer"), optarg);
244                         }
245                         break;
246                 case 'l':                                                                       /* address to lookup */
247                         query_address = optarg;
248                         break;
249                 case 'w':                                                                       /* warning */
250                         if (is_nonnegative (optarg)) {
251                                 warning_interval = strtod (optarg, NULL);
252                         }
253                         else {
254                                 usage2 (_("Warning interval must be a positive integer"), optarg);
255                         }
256                         break;
257                 case 'c':                                                                       /* critical */
258                         if (is_nonnegative (optarg)) {
259                                 critical_interval = strtod (optarg, NULL);
260                         }
261                         else {
262                                 usage2 (_("Critical interval must be a positive integer"), optarg);
263                         }
264                         break;
265                 case 't':                                                                       /* timeout */
266                         if (is_intnonneg (optarg)) {
267                                 timeout_interval = atoi (optarg);
268                         }
269                         else {
270                                 usage2 (_("Timeout interval must be a positive integer"), optarg);
271                         }
272                         break;
273                 case 'v':                                                                       /* verbose */
274                         verbose = TRUE;
275                         break;
276                 case 'T':
277                         record_type = optarg;
278                         break;
279                 case 'a':
280                         expected_address = optarg;
281                         break;
282                 }
283         }
285         c = optind;
286         if (dns_server == NULL) {
287                 if (c < argc) {
288                         if (is_host (argv[c])) {
289                                 dns_server = argv[c];
290                         }
291                         else {
292                                 usage2 (_("Invalid hostname/address"), argv[c]);
293                         }
294                 }
295                 else {
296                         dns_server = strdup ("127.0.0.1");
297                 }
298         }
300         return validate_arguments ();
305 int
306 validate_arguments (void)
308         return OK;
313 void
314 print_help (void)
316         char *myport;
318         asprintf (&myport, "%d", DEFAULT_PORT);
320         print_revision (progname, revision);
322         printf ("Copyright (c) 2000 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n");
323         printf (COPYRIGHT, copyright, email);
325         printf (_("Test the DNS service on the specified host using dig\n\n"));
327         print_usage ();
329         printf (_(UT_HELP_VRSN));
331         printf (_(UT_HOST_PORT), 'P', myport);
333         printf (_("\
334  -l, --lookup=STRING\n\
335    machine name to lookup\n"));
337         printf (_("\
338  -T, --record_type=STRING\n\
339    record type to lookup (default: A)\n"));
341         printf (_("\
342  -a, --expected_address=STRING\n\
343    an address expected to be in the answer section.\n\
344    if not set, uses whatever was in -l\n"));
346         printf (_(UT_WARN_CRIT));
348         printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
350         printf (_(UT_VERBOSE));
352         printf (_(UT_SUPPORT));
357 void
358 print_usage (void)
360         printf ("\
361 Usage: %s -H host -l lookup [-p <server port>] [-T <query type>]\n\
362                   [-w <warning interval>] [-c <critical interval>] [-t <timeout>]\n\
363                   [-a <expected answer address>] [-v]\n", progname);