summaryrefslogtreecommitdiffstats
path: root/plugins/check_dig.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_dig.c')
-rw-r--r--plugins/check_dig.c663
1 files changed, 321 insertions, 342 deletions
diff --git a/plugins/check_dig.c b/plugins/check_dig.c
index be7a6101..d0903be2 100644
--- a/plugins/check_dig.c
+++ b/plugins/check_dig.c
@@ -1,30 +1,30 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_dig plugin 3 * Monitoring check_dig plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2002-2008 Monitoring Plugins Development Team 6 * Copyright (c) 2002-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_dig plugin 10 * This file contains the check_dig plugin
11* 11 *
12* 12 *
13* This program is free software: you can redistribute it and/or modify 13 * This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
15* the Free Software Foundation, either version 3 of the License, or 15 * the Free Software Foundation, either version 3 of the License, or
16* (at your option) any later version. 16 * (at your option) any later version.
17* 17 *
18* This program is distributed in the hope that it will be useful, 18 * This program is distributed in the hope that it will be useful,
19* but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21* GNU General Public License for more details. 21 * GNU General Public License for more details.
22* 22 *
23* You should have received a copy of the GNU General Public License 23 * You should have received a copy of the GNU General Public License
24* along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25* 25 *
26* 26 *
27*****************************************************************************/ 27 *****************************************************************************/
28 28
29/* Hackers note: 29/* Hackers note:
30 * There are typecasts to (char *) from _("foo bar") in this file. 30 * There are typecasts to (char *) from _("foo bar") in this file.
@@ -33,7 +33,7 @@
33 * because on some architectures those strings are in non-writable memory */ 33 * because on some architectures those strings are in non-writable memory */
34 34
35const char *progname = "check_dig"; 35const char *progname = "check_dig";
36const char *copyright = "2002-2008"; 36const char *copyright = "2002-2024";
37const char *email = "devel@monitoring-plugins.org"; 37const char *email = "devel@monitoring-plugins.org";
38 38
39#include "common.h" 39#include "common.h"
@@ -41,340 +41,319 @@ const char *email = "devel@monitoring-plugins.org";
41#include "utils.h" 41#include "utils.h"
42#include "runcmd.h" 42#include "runcmd.h"
43 43
44int process_arguments (int, char **); 44#include "check_dig.d/config.h"
45int validate_arguments (void); 45#include "states.h"
46void print_help (void); 46
47void print_usage (void); 47typedef struct {
48 48 int errorcode;
49#define UNDEFINED 0 49 check_dig_config config;
50#define DEFAULT_PORT 53 50} check_dig_config_wrapper;
51#define DEFAULT_TRIES 2 51static check_dig_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
52 52static check_dig_config_wrapper validate_arguments(check_dig_config_wrapper /*config_wrapper*/);
53char *query_address = NULL; 53
54char *record_type = "A"; 54static void print_help(void);
55char *expected_address = NULL; 55void print_usage(void);
56char *dns_server = NULL; 56
57char *dig_args = ""; 57static int verbose = 0;
58char *query_transport = ""; 58
59bool verbose = false; 59int main(int argc, char **argv) {
60int server_port = DEFAULT_PORT; 60 setlocale(LC_ALL, "");
61int number_tries = DEFAULT_TRIES; 61 bindtextdomain(PACKAGE, LOCALEDIR);
62double warning_interval = UNDEFINED; 62 textdomain(PACKAGE);
63double critical_interval = UNDEFINED; 63
64struct timeval tv; 64 /* Set signal handling and alarm */
65 65 if (signal(SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) {
66int 66 usage_va(_("Cannot catch SIGALRM"));
67main (int argc, char **argv) 67 }
68{ 68
69 char *command_line; 69 /* Parse extra opts if any */
70 output chld_out, chld_err; 70 argv = np_extra_opts(&argc, argv, progname);
71 char *msg = NULL; 71
72 size_t i; 72 check_dig_config_wrapper tmp_config = process_arguments(argc, argv);
73 char *t; 73 if (tmp_config.errorcode == ERROR) {
74 long microsec; 74 usage_va(_("Could not parse arguments"));
75 double elapsed_time; 75 }
76 int result = STATE_UNKNOWN; 76
77 int timeout_interval_dig; 77 const check_dig_config config = tmp_config.config;
78 78
79 setlocale (LC_ALL, ""); 79 /* dig applies the timeout to each try, so we need to work around this */
80 bindtextdomain (PACKAGE, LOCALEDIR); 80 int timeout_interval_dig = ((int)timeout_interval / config.number_tries) + config.number_tries;
81 textdomain (PACKAGE); 81
82 82 char *command_line;
83 /* Set signal handling and alarm */ 83 /* get the command to run */
84 if (signal (SIGALRM, runcmd_timeout_alarm_handler) == SIG_ERR) 84 xasprintf(&command_line, "%s %s %s -p %d @%s %s %s +retry=%d +time=%d", PATH_TO_DIG, config.dig_args, config.query_transport,
85 usage_va(_("Cannot catch SIGALRM")); 85 config.server_port, config.dns_server, config.query_address, config.record_type, config.number_tries, timeout_interval_dig);
86 86
87 /* Parse extra opts if any */ 87 alarm(timeout_interval);
88 argv=np_extra_opts (&argc, argv, progname); 88 struct timeval start_time;
89 89 gettimeofday(&start_time, NULL);
90 if (process_arguments (argc, argv) == ERROR) 90
91 usage_va(_("Could not parse arguments")); 91 if (verbose) {
92 92 printf("%s\n", command_line);
93 /* dig applies the timeout to each try, so we need to work around this */ 93 if (config.expected_address != NULL) {
94 timeout_interval_dig = timeout_interval / number_tries + number_tries; 94 printf(_("Looking for: '%s'\n"), config.expected_address);
95 95 } else {
96 /* get the command to run */ 96 printf(_("Looking for: '%s'\n"), config.query_address);
97 xasprintf (&command_line, "%s %s %s -p %d @%s %s %s +retry=%d +time=%d", 97 }
98 PATH_TO_DIG, dig_args, query_transport, server_port, dns_server, query_address, record_type, number_tries, timeout_interval_dig); 98 }
99 99
100 alarm (timeout_interval); 100 output chld_out;
101 gettimeofday (&tv, NULL); 101 output chld_err;
102 102 char *msg = NULL;
103 if (verbose) { 103 mp_state_enum result = STATE_UNKNOWN;
104 printf ("%s\n", command_line); 104 /* run the command */
105 if(expected_address != NULL) { 105 if (np_runcmd(command_line, &chld_out, &chld_err, 0) != 0) {
106 printf (_("Looking for: '%s'\n"), expected_address); 106 result = STATE_WARNING;
107 } else { 107 msg = (char *)_("dig returned an error status");
108 printf (_("Looking for: '%s'\n"), query_address); 108 }
109 } 109
110 } 110 for (size_t i = 0; i < chld_out.lines; i++) {
111 111 /* the server is responding, we just got the host name... */
112 /* run the command */ 112 if (strstr(chld_out.line[i], ";; ANSWER SECTION:")) {
113 if(np_runcmd(command_line, &chld_out, &chld_err, 0) != 0) { 113
114 result = STATE_WARNING; 114 /* loop through the whole 'ANSWER SECTION' */
115 msg = (char *)_("dig returned an error status"); 115 for (; i < chld_out.lines; i++) {
116 } 116 /* get the host address */
117 117 if (verbose) {
118 for(i = 0; i < chld_out.lines; i++) { 118 printf("%s\n", chld_out.line[i]);
119 /* the server is responding, we just got the host name... */ 119 }
120 if (strstr (chld_out.line[i], ";; ANSWER SECTION:")) { 120
121 121 if (strcasestr(chld_out.line[i], (config.expected_address == NULL ? config.query_address : config.expected_address)) !=
122 /* loop through the whole 'ANSWER SECTION' */ 122 NULL) {
123 for(; i < chld_out.lines; i++) { 123 msg = chld_out.line[i];
124 /* get the host address */ 124 result = STATE_OK;
125 if (verbose) 125
126 printf ("%s\n", chld_out.line[i]); 126 /* Translate output TAB -> SPACE */
127 127 char *temp = msg;
128 if (strcasestr (chld_out.line[i], (expected_address == NULL ? query_address : expected_address)) != NULL) { 128 while ((temp = strchr(temp, '\t')) != NULL) {
129 msg = chld_out.line[i]; 129 *temp = ' ';
130 result = STATE_OK; 130 }
131 131 break;
132 /* Translate output TAB -> SPACE */ 132 }
133 t = msg; 133 }
134 while ((t = strchr(t, '\t')) != NULL) *t = ' '; 134
135 break; 135 if (result == STATE_UNKNOWN) {
136 } 136 msg = (char *)_("Server not found in ANSWER SECTION");
137 } 137 result = STATE_WARNING;
138 138 }
139 if (result == STATE_UNKNOWN) { 139
140 msg = (char *)_("Server not found in ANSWER SECTION"); 140 /* we found the answer section, so break out of the loop */
141 result = STATE_WARNING; 141 break;
142 } 142 }
143 143 }
144 /* we found the answer section, so break out of the loop */ 144
145 break; 145 if (result == STATE_UNKNOWN) {
146 } 146 msg = (char *)_("No ANSWER SECTION found");
147 } 147 result = STATE_CRITICAL;
148 148 }
149 if (result == STATE_UNKNOWN) { 149
150 msg = (char *)_("No ANSWER SECTION found"); 150 /* If we get anything on STDERR, at least set warning */
151 result = STATE_CRITICAL; 151 if (chld_err.buflen > 0) {
152 } 152 result = max_state(result, STATE_WARNING);
153 153 if (!msg) {
154 /* If we get anything on STDERR, at least set warning */ 154 for (size_t i = 0; i < chld_err.lines; i++) {
155 if(chld_err.buflen > 0) { 155 msg = strchr(chld_err.line[0], ':');
156 result = max_state(result, STATE_WARNING); 156 if (msg) {
157 if(!msg) for(i = 0; i < chld_err.lines; i++) { 157 msg++;
158 msg = strchr(chld_err.line[0], ':'); 158 break;
159 if(msg) { 159 }
160 msg++; 160 }
161 break; 161 }
162 } 162 }
163 } 163
164 } 164 long microsec = deltime(start_time);
165 165 double elapsed_time = (double)microsec / 1.0e6;
166 microsec = deltime (tv); 166
167 elapsed_time = (double)microsec / 1.0e6; 167 if (config.critical_interval > UNDEFINED && elapsed_time > config.critical_interval) {
168 168 result = STATE_CRITICAL;
169 if (critical_interval > UNDEFINED && elapsed_time > critical_interval) 169 }
170 result = STATE_CRITICAL; 170
171 171 else if (config.warning_interval > UNDEFINED && elapsed_time > config.warning_interval) {
172 else if (warning_interval > UNDEFINED && elapsed_time > warning_interval) 172 result = STATE_WARNING;
173 result = STATE_WARNING; 173 }
174 174
175 printf ("DNS %s - %.3f seconds response time (%s)|%s\n", 175 printf("DNS %s - %.3f seconds response time (%s)|%s\n", state_text(result), elapsed_time,
176 state_text (result), elapsed_time, 176 msg ? msg : _("Probably a non-existent host/domain"),
177 msg ? msg : _("Probably a non-existent host/domain"), 177 fperfdata("time", elapsed_time, "s", (config.warning_interval > UNDEFINED), config.warning_interval,
178 fperfdata("time", elapsed_time, "s", 178 (config.critical_interval > UNDEFINED), config.critical_interval, true, 0, false, 0));
179 (warning_interval>UNDEFINED ? true:false), 179 exit(result);
180 warning_interval,
181 (critical_interval>UNDEFINED ? true:false),
182 critical_interval,
183 true, 0, false, 0));
184 return result;
185} 180}
186 181
187
188
189/* process command-line arguments */ 182/* process command-line arguments */
190int 183check_dig_config_wrapper process_arguments(int argc, char **argv) {
191process_arguments (int argc, char **argv) 184 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
192{ 185 {"query_address", required_argument, 0, 'l'},
193 int c; 186 {"warning", required_argument, 0, 'w'},
194 187 {"critical", required_argument, 0, 'c'},
195 int option = 0; 188 {"timeout", required_argument, 0, 't'},
196 static struct option longopts[] = { 189 {"dig-arguments", required_argument, 0, 'A'},
197 {"hostname", required_argument, 0, 'H'}, 190 {"verbose", no_argument, 0, 'v'},
198 {"query_address", required_argument, 0, 'l'}, 191 {"version", no_argument, 0, 'V'},
199 {"warning", required_argument, 0, 'w'}, 192 {"help", no_argument, 0, 'h'},
200 {"critical", required_argument, 0, 'c'}, 193 {"record_type", required_argument, 0, 'T'},
201 {"timeout", required_argument, 0, 't'}, 194 {"expected_address", required_argument, 0, 'a'},
202 {"dig-arguments", required_argument, 0, 'A'}, 195 {"port", required_argument, 0, 'p'},
203 {"verbose", no_argument, 0, 'v'}, 196 {"use-ipv4", no_argument, 0, '4'},
204 {"version", no_argument, 0, 'V'}, 197 {"use-ipv6", no_argument, 0, '6'},
205 {"help", no_argument, 0, 'h'}, 198 {0, 0, 0, 0}};
206 {"record_type", required_argument, 0, 'T'}, 199
207 {"expected_address", required_argument, 0, 'a'}, 200 check_dig_config_wrapper result = {
208 {"port", required_argument, 0, 'p'}, 201 .errorcode = OK,
209 {"use-ipv4", no_argument, 0, '4'}, 202 .config = check_dig_config_init(),
210 {"use-ipv6", no_argument, 0, '6'}, 203 };
211 {0, 0, 0, 0} 204
212 }; 205 if (argc < 2) {
213 206 result.errorcode = ERROR;
214 if (argc < 2) 207 return result;
215 return ERROR; 208 }
216 209
217 while (1) { 210 int option = 0;
218 c = getopt_long (argc, argv, "hVvt:l:H:w:c:T:p:a:A:46", longopts, &option); 211 while (true) {
219 212 int option_index = getopt_long(argc, argv, "hVvt:l:H:w:c:T:p:a:A:46", longopts, &option);
220 if (c == -1 || c == EOF) 213
221 break; 214 if (option_index == -1 || option_index == EOF) {
222 215 break;
223 switch (c) { 216 }
224 case 'h': /* help */ 217
225 print_help (); 218 switch (option_index) {
226 exit (STATE_UNKNOWN); 219 case 'h': /* help */
227 case 'V': /* version */ 220 print_help();
228 print_revision (progname, NP_VERSION); 221 exit(STATE_UNKNOWN);
229 exit (STATE_UNKNOWN); 222 case 'V': /* version */
230 case 'H': /* hostname */ 223 print_revision(progname, NP_VERSION);
231 host_or_die(optarg); 224 exit(STATE_UNKNOWN);
232 dns_server = optarg; 225 case 'H': /* hostname */
233 break; 226 host_or_die(optarg);
234 case 'p': /* server port */ 227 result.config.dns_server = optarg;
235 if (is_intpos (optarg)) { 228 break;
236 server_port = atoi (optarg); 229 case 'p': /* server port */
237 } 230 if (is_intpos(optarg)) {
238 else { 231 result.config.server_port = atoi(optarg);
239 usage_va(_("Port must be a positive integer - %s"), optarg); 232 } else {
240 } 233 usage_va(_("Port must be a positive integer - %s"), optarg);
241 break; 234 }
242 case 'l': /* address to lookup */ 235 break;
243 query_address = optarg; 236 case 'l': /* address to lookup */
244 break; 237 result.config.query_address = optarg;
245 case 'w': /* warning */ 238 break;
246 if (is_nonnegative (optarg)) { 239 case 'w': /* warning */
247 warning_interval = strtod (optarg, NULL); 240 if (is_nonnegative(optarg)) {
248 } 241 result.config.warning_interval = strtod(optarg, NULL);
249 else { 242 } else {
250 usage_va(_("Warning interval must be a positive integer - %s"), optarg); 243 usage_va(_("Warning interval must be a positive integer - %s"), optarg);
251 } 244 }
252 break; 245 break;
253 case 'c': /* critical */ 246 case 'c': /* critical */
254 if (is_nonnegative (optarg)) { 247 if (is_nonnegative(optarg)) {
255 critical_interval = strtod (optarg, NULL); 248 result.config.critical_interval = strtod(optarg, NULL);
256 } 249 } else {
257 else { 250 usage_va(_("Critical interval must be a positive integer - %s"), optarg);
258 usage_va(_("Critical interval must be a positive integer - %s"), optarg); 251 }
259 } 252 break;
260 break; 253 case 't': /* timeout */
261 case 't': /* timeout */ 254 if (is_intnonneg(optarg)) {
262 if (is_intnonneg (optarg)) { 255 timeout_interval = atoi(optarg);
263 timeout_interval = atoi (optarg); 256 } else {
264 } 257 usage_va(_("Timeout interval must be a positive integer - %s"), optarg);
265 else { 258 }
266 usage_va(_("Timeout interval must be a positive integer - %s"), optarg); 259 break;
267 } 260 case 'A': /* dig arguments */
268 break; 261 result.config.dig_args = strdup(optarg);
269 case 'A': /* dig arguments */ 262 break;
270 dig_args = strdup(optarg); 263 case 'v': /* verbose */
271 break; 264 verbose++;
272 case 'v': /* verbose */ 265 break;
273 verbose = true; 266 case 'T':
274 break; 267 result.config.record_type = optarg;
275 case 'T': 268 break;
276 record_type = optarg; 269 case 'a':
277 break; 270 result.config.expected_address = optarg;
278 case 'a': 271 break;
279 expected_address = optarg; 272 case '4':
280 break; 273 result.config.query_transport = "-4";
281 case '4': 274 break;
282 query_transport = "-4"; 275 case '6':
283 break; 276 result.config.query_transport = "-6";
284 case '6': 277 break;
285 query_transport = "-6"; 278 default: /* usage5 */
286 break; 279 usage5();
287 default: /* usage5 */ 280 }
288 usage5(); 281 }
289 } 282
290 } 283 int index = optind;
291 284 if (result.config.dns_server == NULL) {
292 c = optind; 285 if (index < argc) {
293 if (dns_server == NULL) { 286 host_or_die(argv[index]);
294 if (c < argc) { 287 result.config.dns_server = argv[index];
295 host_or_die(argv[c]); 288 } else {
296 dns_server = argv[c]; 289 if (strcmp(result.config.query_transport, "-6") == 0) {
297 } 290 result.config.dns_server = strdup("::1");
298 else { 291 } else {
299 if (strcmp(query_transport,"-6") == 0) 292 result.config.dns_server = strdup("127.0.0.1");
300 dns_server = strdup("::1"); 293 }
301 else 294 }
302 dns_server = strdup ("127.0.0.1"); 295 }
303 } 296
304 } 297 return validate_arguments(result);
305
306 return validate_arguments ();
307} 298}
308 299
309 300check_dig_config_wrapper validate_arguments(check_dig_config_wrapper config_wrapper) {
310 301 if (config_wrapper.config.query_address == NULL) {
311int 302 config_wrapper.errorcode = ERROR;
312validate_arguments (void) 303 }
313{ 304 return config_wrapper;
314 if (query_address != NULL)
315 return OK;
316 else
317 return ERROR;
318} 305}
319 306
307void print_help(void) {
308 char *myport;
320 309
310 xasprintf(&myport, "%d", DEFAULT_PORT);
321 311
322void 312 print_revision(progname, NP_VERSION);
323print_help (void)
324{
325 char *myport;
326 313
327 xasprintf (&myport, "%d", DEFAULT_PORT); 314 printf("Copyright (c) 2000 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n");
315 printf(COPYRIGHT, copyright, email);
328 316
329 print_revision (progname, NP_VERSION); 317 printf(_("This plugin tests the DNS service on the specified host using dig"));
330 318
331 printf ("Copyright (c) 2000 Karl DeBisschop <kdebisschop@users.sourceforge.net>\n"); 319 printf("\n\n");
332 printf (COPYRIGHT, copyright, email);
333 320
334 printf (_("This plugin tests the DNS service on the specified host using dig")); 321 print_usage();
335 322
336 printf ("\n\n"); 323 printf(UT_HELP_VRSN);
337 324
338 print_usage (); 325 printf(UT_EXTRA_OPTS);
339 326
340 printf (UT_HELP_VRSN); 327 printf(UT_HOST_PORT, 'p', myport);
341 328
342 printf (UT_EXTRA_OPTS); 329 printf(" %s\n", "-4, --use-ipv4");
330 printf(" %s\n", _("Force dig to only use IPv4 query transport"));
331 printf(" %s\n", "-6, --use-ipv6");
332 printf(" %s\n", _("Force dig to only use IPv6 query transport"));
333 printf(" %s\n", "-l, --query_address=STRING");
334 printf(" %s\n", _("Machine name to lookup"));
335 printf(" %s\n", "-T, --record_type=STRING");
336 printf(" %s\n", _("Record type to lookup (default: A)"));
337 printf(" %s\n", "-a, --expected_address=STRING");
338 printf(" %s\n", _("An address expected to be in the answer section. If not set, uses whatever"));
339 printf(" %s\n", _("was in -l"));
340 printf(" %s\n", "-A, --dig-arguments=STRING");
341 printf(" %s\n", _("Pass STRING as argument(s) to dig"));
342 printf(UT_WARN_CRIT);
343 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
344 printf(UT_VERBOSE);
343 345
344 printf (UT_HOST_PORT, 'p', myport); 346 printf("\n");
347 printf("%s\n", _("Examples:"));
348 printf(" %s\n", "check_dig -H DNSSERVER -l www.example.com -A \"+tcp\"");
349 printf(" %s\n", "This will send a tcp query to DNSSERVER for www.example.com");
345 350
346 printf (" %s\n","-4, --use-ipv4"); 351 printf(UT_SUPPORT);
347 printf (" %s\n",_("Force dig to only use IPv4 query transport"));
348 printf (" %s\n","-6, --use-ipv6");
349 printf (" %s\n",_("Force dig to only use IPv6 query transport"));
350 printf (" %s\n","-l, --query_address=STRING");
351 printf (" %s\n",_("Machine name to lookup"));
352 printf (" %s\n","-T, --record_type=STRING");
353 printf (" %s\n",_("Record type to lookup (default: A)"));
354 printf (" %s\n","-a, --expected_address=STRING");
355 printf (" %s\n",_("An address expected to be in the answer section. If not set, uses whatever"));
356 printf (" %s\n",_("was in -l"));
357 printf (" %s\n","-A, --dig-arguments=STRING");
358 printf (" %s\n",_("Pass STRING as argument(s) to dig"));
359 printf (UT_WARN_CRIT);
360 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
361 printf (UT_VERBOSE);
362
363 printf ("\n");
364 printf ("%s\n", _("Examples:"));
365 printf (" %s\n", "check_dig -H DNSSERVER -l www.example.com -A \"+tcp\"");
366 printf (" %s\n", "This will send a tcp query to DNSSERVER for www.example.com");
367
368 printf (UT_SUPPORT);
369} 352}
370 353
371 354void print_usage(void) {
372 355 printf("%s\n", _("Usage:"));
373void 356 printf("%s -l <query_address> [-H <host>] [-p <server port>]\n", progname);
374print_usage (void) 357 printf(" [-T <query type>] [-w <warning interval>] [-c <critical interval>]\n");
375{ 358 printf(" [-t <timeout>] [-a <expected answer address>] [-v]\n");
376 printf ("%s\n", _("Usage:"));
377 printf ("%s -l <query_address> [-H <host>] [-p <server port>]\n", progname);
378 printf (" [-T <query type>] [-w <warning interval>] [-c <critical interval>]\n");
379 printf (" [-t <timeout>] [-a <expected answer address>] [-v]\n");
380} 359}