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;
180 }
186 \f
187 /* process command-line arguments */
188 int
189 process_arguments (int argc, char **argv)
190 {
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 ();
297 }
303 int
304 validate_arguments (void)
305 {
306 return OK;
307 }
314 \f
315 void
316 print_help (void)
317 {
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));
355 }
360 void
361 print_usage (void)
362 {
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);
370 }