Revert "check_disk - show all disks if state is ok and option error only is used"
[monitoring-plugins.git] / plugins / check_tcp.c
blob61333bd706964d5b63bc2723c3d7081c7af0cc62
1 /*****************************************************************************
3 * Monitoring check_tcp plugin
5 * License: GPL
6 * Copyright (c) 1999-2013 Monitoring Plugins Development Team
8 * Description:
10 * This file contains the check_tcp plugin
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
15 * the Free Software Foundation, either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
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/>.
26 * $Id$
28 *****************************************************************************/
30 /* progname "check_tcp" changes depending on symlink called */
31 char *progname;
32 const char *copyright = "1999-2008";
33 const char *email = "devel@monitoring-plugins.org";
35 #include "common.h"
36 #include "netutils.h"
37 #include "utils.h"
38 #include "utils_tcp.h"
40 #include <ctype.h>
41 #include <sys/select.h>
43 #ifdef HAVE_SSL
44 static int check_cert = FALSE;
45 static int days_till_exp_warn, days_till_exp_crit;
46 # define my_recv(buf, len) ((flags & FLAG_SSL) ? np_net_ssl_read(buf, len) : read(sd, buf, len))
47 # define my_send(buf, len) ((flags & FLAG_SSL) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0))
48 #else
49 # define my_recv(buf, len) read(sd, buf, len)
50 # define my_send(buf, len) send(sd, buf, len, 0)
51 #endif
53 /* int my_recv(char *, size_t); */
54 static int process_arguments (int, char **);
55 void print_help (void);
56 void print_usage (void);
58 #define EXPECT server_expect[0]
59 static char *SERVICE = "TCP";
60 static char *SEND = NULL;
61 static char *QUIT = NULL;
62 static int PROTOCOL = IPPROTO_TCP; /* most common is default */
63 static int PORT = 0;
64 static int READ_TIMEOUT = 2;
66 static int server_port = 0;
67 static char *server_address = NULL;
68 static int host_specified = FALSE;
69 static char *server_send = NULL;
70 static char *server_quit = NULL;
71 static char **server_expect;
72 static size_t server_expect_count = 0;
73 static size_t maxbytes = 0;
74 static char **warn_codes = NULL;
75 static size_t warn_codes_count = 0;
76 static char **crit_codes = NULL;
77 static size_t crit_codes_count = 0;
78 static unsigned int delay = 0;
79 static double warning_time = 0;
80 static double critical_time = 0;
81 static double elapsed_time = 0;
82 static long microsec;
83 static int sd = 0;
84 #define MAXBUF 1024
85 static char buffer[MAXBUF];
86 static int expect_mismatch_state = STATE_WARNING;
87 static int match_flags = NP_MATCH_EXACT;
89 #define FLAG_SSL 0x01
90 #define FLAG_VERBOSE 0x02
91 #define FLAG_TIME_WARN 0x04
92 #define FLAG_TIME_CRIT 0x08
93 #define FLAG_HIDE_OUTPUT 0x10
94 static size_t flags;
96 int
97 main (int argc, char **argv)
99 int result = STATE_UNKNOWN;
100 int i;
101 char *status = NULL;
102 struct timeval tv;
103 struct timeval timeout;
104 size_t len;
105 int match = -1;
106 fd_set rfds;
108 FD_ZERO(&rfds);
110 setlocale (LC_ALL, "");
111 bindtextdomain (PACKAGE, LOCALEDIR);
112 textdomain (PACKAGE);
114 /* determine program- and service-name quickly */
115 progname = strrchr(argv[0], '/');
116 if(progname != NULL) progname++;
117 else progname = argv[0];
119 len = strlen(progname);
120 if(len > 6 && !memcmp(progname, "check_", 6)) {
121 SERVICE = strdup(progname + 6);
122 for(i = 0; i < len - 6; i++)
123 SERVICE[i] = toupper(SERVICE[i]);
126 /* set up a resonable buffer at first (will be realloc()'ed if
127 * user specifies other options) */
128 server_expect = calloc(sizeof(char *), 2);
130 /* determine defaults for this service's protocol */
131 if (!strncmp(SERVICE, "UDP", 3)) {
132 PROTOCOL = IPPROTO_UDP;
134 else if (!strncmp(SERVICE, "FTP", 3)) {
135 EXPECT = "220";
136 QUIT = "QUIT\r\n";
137 PORT = 21;
139 else if (!strncmp(SERVICE, "POP", 3) || !strncmp(SERVICE, "POP3", 4)) {
140 EXPECT = "+OK";
141 QUIT = "QUIT\r\n";
142 PORT = 110;
144 else if (!strncmp(SERVICE, "SMTP", 4)) {
145 EXPECT = "220";
146 QUIT = "QUIT\r\n";
147 PORT = 25;
149 else if (!strncmp(SERVICE, "IMAP", 4)) {
150 EXPECT = "* OK";
151 QUIT = "a1 LOGOUT\r\n";
152 PORT = 143;
154 #ifdef HAVE_SSL
155 else if (!strncmp(SERVICE, "SIMAP", 5)) {
156 EXPECT = "* OK";
157 QUIT = "a1 LOGOUT\r\n";
158 flags |= FLAG_SSL;
159 PORT = 993;
161 else if (!strncmp(SERVICE, "SPOP", 4)) {
162 EXPECT = "+OK";
163 QUIT = "QUIT\r\n";
164 flags |= FLAG_SSL;
165 PORT = 995;
167 else if (!strncmp(SERVICE, "SSMTP", 5)) {
168 EXPECT = "220";
169 QUIT = "QUIT\r\n";
170 flags |= FLAG_SSL;
171 PORT = 465;
173 else if (!strncmp(SERVICE, "JABBER", 6)) {
174 SEND = "<stream:stream to=\'host\' xmlns=\'jabber:client\' xmlns:stream=\'http://etherx.jabber.org/streams\'>\n";
175 EXPECT = "<?xml version=\'1.0\'";
176 QUIT = "</stream:stream>\n";
177 flags |= FLAG_HIDE_OUTPUT;
178 PORT = 5222;
180 else if (!strncmp (SERVICE, "NNTPS", 5)) {
181 server_expect_count = 2;
182 server_expect[0] = "200";
183 server_expect[1] = "201";
184 QUIT = "QUIT\r\n";
185 flags |= FLAG_SSL;
186 PORT = 563;
188 #endif
189 else if (!strncmp (SERVICE, "NNTP", 4)) {
190 server_expect_count = 2;
191 server_expect = malloc(sizeof(char *) * server_expect_count);
192 server_expect[0] = strdup("200");
193 server_expect[1] = strdup("201");
194 QUIT = "QUIT\r\n";
195 PORT = 119;
197 else if (!strncmp(SERVICE, "CLAMD", 5)) {
198 SEND = "PING";
199 EXPECT = "PONG";
200 QUIT = NULL;
201 PORT = 3310;
203 /* fallthrough check, so it's supposed to use reverse matching */
204 else if (strcmp (SERVICE, "TCP"))
205 usage (_("CRITICAL - Generic check_tcp called with unknown service\n"));
207 server_address = "127.0.0.1";
208 server_port = PORT;
209 server_send = SEND;
210 server_quit = QUIT;
211 status = NULL;
213 /* Parse extra opts if any */
214 argv=np_extra_opts (&argc, argv, progname);
216 if (process_arguments (argc, argv) == ERROR)
217 usage4 (_("Could not parse arguments"));
219 if(flags & FLAG_VERBOSE) {
220 printf("Using service %s\n", SERVICE);
221 printf("Port: %d\n", server_port);
222 printf("flags: 0x%x\n", (int)flags);
225 if(EXPECT && !server_expect_count)
226 server_expect_count++;
228 if(PROTOCOL==IPPROTO_UDP && !(server_expect_count && server_send)){
229 usage(_("With UDP checks, a send/expect string must be specified."));
232 /* set up the timer */
233 signal (SIGALRM, socket_timeout_alarm_handler);
234 alarm (socket_timeout);
236 /* try to connect to the host at the given port number */
237 gettimeofday (&tv, NULL);
239 result = np_net_connect (server_address, server_port, &sd, PROTOCOL);
240 if (result == STATE_CRITICAL) return econn_refuse_state;
242 #ifdef HAVE_SSL
243 if (flags & FLAG_SSL){
244 result = np_net_ssl_init(sd);
245 if (result == STATE_OK && check_cert == TRUE) {
246 result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit);
249 if(result != STATE_OK){
250 if(sd) close(sd);
251 np_net_ssl_cleanup();
252 return result;
254 #endif /* HAVE_SSL */
256 if (server_send != NULL) { /* Something to send? */
257 my_send(server_send, strlen(server_send));
260 if (delay > 0) {
261 tv.tv_sec += delay;
262 sleep (delay);
265 if(flags & FLAG_VERBOSE) {
266 if (server_send) {
267 printf("Send string: %s\n", server_send);
269 if (server_quit) {
270 printf("Quit string: %s\n", server_quit);
272 printf("server_expect_count: %d\n", (int)server_expect_count);
273 for(i = 0; i < server_expect_count; i++)
274 printf("\t%d: %s\n", i, server_expect[i]);
277 /* if(len) later on, we know we have a non-NULL response */
278 len = 0;
279 if (server_expect_count) {
281 /* watch for the expect string */
282 while ((i = my_recv(buffer, sizeof(buffer))) > 0) {
283 status = realloc(status, len + i + 1);
284 memcpy(&status[len], buffer, i);
285 len += i;
286 status[len] = '\0';
288 /* stop reading if user-forced */
289 if (maxbytes && len >= maxbytes)
290 break;
292 if ((match = np_expect_match(status,
293 server_expect,
294 server_expect_count,
295 match_flags)) != NP_MATCH_RETRY)
296 break;
298 /* some protocols wait for further input, so make sure we don't wait forever */
299 FD_SET(sd, &rfds);
300 timeout.tv_sec = READ_TIMEOUT;
301 timeout.tv_usec = 0;
302 if(select(sd + 1, &rfds, NULL, NULL, &timeout) <= 0)
303 break;
305 if (match == NP_MATCH_RETRY)
306 match = NP_MATCH_FAILURE;
308 /* no data when expected, so return critical */
309 if (len == 0)
310 die (STATE_CRITICAL, _("No data received from host\n"));
312 /* print raw output if we're debugging */
313 if(flags & FLAG_VERBOSE)
314 printf("received %d bytes from host\n#-raw-recv-------#\n%s\n#-raw-recv-------#\n",
315 (int)len + 1, status);
316 /* strip whitespace from end of output */
317 while(--len > 0 && isspace(status[len]))
318 status[len] = '\0';
321 if (server_quit != NULL) {
322 my_send(server_quit, strlen(server_quit));
324 if (sd) close (sd);
325 #ifdef HAVE_SSL
326 np_net_ssl_cleanup();
327 #endif
329 microsec = deltime (tv);
330 elapsed_time = (double)microsec / 1.0e6;
332 if (flags & FLAG_TIME_CRIT && elapsed_time > critical_time)
333 result = STATE_CRITICAL;
334 else if (flags & FLAG_TIME_WARN && elapsed_time > warning_time)
335 result = STATE_WARNING;
337 /* did we get the response we hoped? */
338 if(match == NP_MATCH_FAILURE && result != STATE_CRITICAL)
339 result = expect_mismatch_state;
341 /* reset the alarm */
342 alarm (0);
344 /* this is a bit stupid, because we don't want to print the
345 * response time (which can look ok to the user) if we didn't get
346 * the response we were looking for. if-else */
347 printf("%s %s - ", SERVICE, state_text(result));
349 if(match == NP_MATCH_FAILURE && len && !(flags & FLAG_HIDE_OUTPUT))
350 printf("Unexpected response from host/socket: %s", status);
351 else {
352 if(match == NP_MATCH_FAILURE)
353 printf("Unexpected response from host/socket on ");
354 else
355 printf("%.3f second response time on ", elapsed_time);
356 if(server_address[0] != '/') {
357 if (host_specified)
358 printf("%s port %d",
359 server_address, server_port);
360 else
361 printf("port %d", server_port);
363 else
364 printf("socket %s", server_address);
367 if (match != NP_MATCH_FAILURE && !(flags & FLAG_HIDE_OUTPUT) && len)
368 printf (" [%s]", status);
370 /* perf-data doesn't apply when server doesn't talk properly,
371 * so print all zeroes on warn and crit. Use fperfdata since
372 * localisation settings can make different outputs */
373 if(match == NP_MATCH_FAILURE)
374 printf ("|%s",
375 fperfdata ("time", elapsed_time, "s",
376 (flags & FLAG_TIME_WARN ? TRUE : FALSE), 0,
377 (flags & FLAG_TIME_CRIT ? TRUE : FALSE), 0,
378 TRUE, 0,
379 TRUE, socket_timeout)
381 else
382 printf("|%s",
383 fperfdata ("time", elapsed_time, "s",
384 (flags & FLAG_TIME_WARN ? TRUE : FALSE), warning_time,
385 (flags & FLAG_TIME_CRIT ? TRUE : FALSE), critical_time,
386 TRUE, 0,
387 TRUE, socket_timeout)
390 putchar('\n');
391 return result;
396 /* process command-line arguments */
397 static int
398 process_arguments (int argc, char **argv)
400 int c;
401 int escape = 0;
402 char *temp;
404 int option = 0;
405 static struct option longopts[] = {
406 {"hostname", required_argument, 0, 'H'},
407 {"critical", required_argument, 0, 'c'},
408 {"warning", required_argument, 0, 'w'},
409 {"critical-codes", required_argument, 0, 'C'},
410 {"warning-codes", required_argument, 0, 'W'},
411 {"timeout", required_argument, 0, 't'},
412 {"protocol", required_argument, 0, 'P'}, /* FIXME: Unhandled */
413 {"port", required_argument, 0, 'p'},
414 {"escape", no_argument, 0, 'E'},
415 {"all", no_argument, 0, 'A'},
416 {"send", required_argument, 0, 's'},
417 {"expect", required_argument, 0, 'e'},
418 {"maxbytes", required_argument, 0, 'm'},
419 {"quit", required_argument, 0, 'q'},
420 {"jail", no_argument, 0, 'j'},
421 {"delay", required_argument, 0, 'd'},
422 {"refuse", required_argument, 0, 'r'},
423 {"mismatch", required_argument, 0, 'M'},
424 {"use-ipv4", no_argument, 0, '4'},
425 {"use-ipv6", no_argument, 0, '6'},
426 {"verbose", no_argument, 0, 'v'},
427 {"version", no_argument, 0, 'V'},
428 {"help", no_argument, 0, 'h'},
429 {"ssl", no_argument, 0, 'S'},
430 {"certificate", required_argument, 0, 'D'},
431 {0, 0, 0, 0}
434 if (argc < 2)
435 usage4 (_("No arguments found"));
437 /* backwards compatibility */
438 for (c = 1; c < argc; c++) {
439 if (strcmp ("-to", argv[c]) == 0)
440 strcpy (argv[c], "-t");
441 else if (strcmp ("-wt", argv[c]) == 0)
442 strcpy (argv[c], "-w");
443 else if (strcmp ("-ct", argv[c]) == 0)
444 strcpy (argv[c], "-c");
447 if (!is_option (argv[1])) {
448 server_address = argv[1];
449 argv[1] = argv[0];
450 argv = &argv[1];
451 argc--;
454 while (1) {
455 c = getopt_long (argc, argv, "+hVv46EAH:s:e:q:m:c:w:t:p:C:W:d:Sr:jD:M:",
456 longopts, &option);
458 if (c == -1 || c == EOF || c == 1)
459 break;
461 switch (c) {
462 case '?': /* print short usage statement if args not parsable */
463 usage5 ();
464 case 'h': /* help */
465 print_help ();
466 exit (STATE_UNKNOWN);
467 case 'V': /* version */
468 print_revision (progname, NP_VERSION);
469 exit (STATE_UNKNOWN);
470 case 'v': /* verbose mode */
471 flags |= FLAG_VERBOSE;
472 match_flags |= NP_MATCH_VERBOSE;
473 break;
474 case '4':
475 address_family = AF_INET;
476 break;
477 case '6':
478 #ifdef USE_IPV6
479 address_family = AF_INET6;
480 #else
481 usage4 (_("IPv6 support not available"));
482 #endif
483 break;
484 case 'H': /* hostname */
485 host_specified = TRUE;
486 server_address = optarg;
487 break;
488 case 'c': /* critical */
489 critical_time = strtod (optarg, NULL);
490 flags |= FLAG_TIME_CRIT;
491 break;
492 case 'j': /* hide output */
493 flags |= FLAG_HIDE_OUTPUT;
494 break;
495 case 'w': /* warning */
496 warning_time = strtod (optarg, NULL);
497 flags |= FLAG_TIME_WARN;
498 break;
499 case 'C':
500 crit_codes = realloc (crit_codes, ++crit_codes_count);
501 crit_codes[crit_codes_count - 1] = optarg;
502 break;
503 case 'W':
504 warn_codes = realloc (warn_codes, ++warn_codes_count);
505 warn_codes[warn_codes_count - 1] = optarg;
506 break;
507 case 't': /* timeout */
508 if (!is_intpos (optarg))
509 usage4 (_("Timeout interval must be a positive integer"));
510 else
511 socket_timeout = atoi (optarg);
512 break;
513 case 'p': /* port */
514 if (!is_intpos (optarg))
515 usage4 (_("Port must be a positive integer"));
516 else
517 server_port = atoi (optarg);
518 break;
519 case 'E':
520 escape = 1;
521 break;
522 case 's':
523 if (escape)
524 server_send = np_escaped_string(optarg);
525 else
526 xasprintf(&server_send, "%s", optarg);
527 break;
528 case 'e': /* expect string (may be repeated) */
529 match_flags &= ~NP_MATCH_EXACT;
530 if (server_expect_count == 0)
531 server_expect = malloc (sizeof (char *) * (++server_expect_count));
532 else
533 server_expect = realloc (server_expect, sizeof (char *) * (++server_expect_count));
534 server_expect[server_expect_count - 1] = optarg;
535 break;
536 case 'm':
537 if (!is_intpos (optarg))
538 usage4 (_("Maxbytes must be a positive integer"));
539 else
540 maxbytes = strtol (optarg, NULL, 0);
541 break;
542 case 'q':
543 if (escape)
544 server_quit = np_escaped_string(optarg);
545 else
546 xasprintf(&server_quit, "%s\r\n", optarg);
547 break;
548 case 'r':
549 if (!strncmp(optarg,"ok",2))
550 econn_refuse_state = STATE_OK;
551 else if (!strncmp(optarg,"warn",4))
552 econn_refuse_state = STATE_WARNING;
553 else if (!strncmp(optarg,"crit",4))
554 econn_refuse_state = STATE_CRITICAL;
555 else
556 usage4 (_("Refuse must be one of ok, warn, crit"));
557 break;
558 case 'M':
559 if (!strncmp(optarg,"ok",2))
560 expect_mismatch_state = STATE_OK;
561 else if (!strncmp(optarg,"warn",4))
562 expect_mismatch_state = STATE_WARNING;
563 else if (!strncmp(optarg,"crit",4))
564 expect_mismatch_state = STATE_CRITICAL;
565 else
566 usage4 (_("Mismatch must be one of ok, warn, crit"));
567 break;
568 case 'd':
569 if (is_intpos (optarg))
570 delay = atoi (optarg);
571 else
572 usage4 (_("Delay must be a positive integer"));
573 break;
574 case 'D': /* Check SSL cert validity - days 'til certificate expiration */
575 #ifdef HAVE_SSL
576 # ifdef USE_OPENSSL /* XXX */
577 if ((temp=strchr(optarg,','))!=NULL) {
578 *temp='\0';
579 if (!is_intnonneg (optarg))
580 usage2 (_("Invalid certificate expiration period"), optarg);
581 days_till_exp_warn = atoi (optarg);
582 *temp=',';
583 temp++;
584 if (!is_intnonneg (temp))
585 usage2 (_("Invalid certificate expiration period"), temp);
586 days_till_exp_crit = atoi (temp);
588 else {
589 days_till_exp_crit=0;
590 if (!is_intnonneg (optarg))
591 usage2 (_("Invalid certificate expiration period"), optarg);
592 days_till_exp_warn = atoi (optarg);
594 check_cert = TRUE;
595 flags |= FLAG_SSL;
596 break;
597 # endif /* USE_OPENSSL */
598 #endif
599 /* fallthrough if we don't have ssl */
600 case 'S':
601 #ifdef HAVE_SSL
602 flags |= FLAG_SSL;
603 #else
604 die (STATE_UNKNOWN, _("Invalid option - SSL is not available"));
605 #endif
606 break;
607 case 'A':
608 match_flags |= NP_MATCH_ALL;
609 break;
613 c = optind;
614 if(host_specified == FALSE && c < argc)
615 server_address = strdup (argv[c++]);
617 if (server_address == NULL)
618 usage4 (_("You must provide a server address"));
619 else if (server_address[0] != '/' && is_host (server_address) == FALSE)
620 die (STATE_CRITICAL, "%s %s - %s: %s\n", SERVICE, state_text(STATE_CRITICAL), _("Invalid hostname, address or socket"), server_address);
622 return TRUE;
626 void
627 print_help (void)
629 print_revision (progname, NP_VERSION);
631 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
632 printf (COPYRIGHT, copyright, email);
634 printf (_("This plugin tests %s connections with the specified host (or unix socket).\n\n"),
635 SERVICE);
637 print_usage ();
639 printf (UT_HELP_VRSN);
640 printf (UT_EXTRA_OPTS);
642 printf (UT_HOST_PORT, 'p', "none");
644 printf (UT_IPv46);
646 printf (" %s\n", "-E, --escape");
647 printf (" %s\n", _("Can use \\n, \\r, \\t or \\\\ in send or quit string. Must come before send or quit option"));
648 printf (" %s\n", _("Default: nothing added to send, \\r\\n added to end of quit"));
649 printf (" %s\n", "-s, --send=STRING");
650 printf (" %s\n", _("String to send to the server"));
651 printf (" %s\n", "-e, --expect=STRING");
652 printf (" %s %s\n", _("String to expect in server response"), _("(may be repeated)"));
653 printf (" %s\n", "-A, --all");
654 printf (" %s\n", _("All expect strings need to occur in server response. Default is any"));
655 printf (" %s\n", "-q, --quit=STRING");
656 printf (" %s\n", _("String to send server to initiate a clean close of the connection"));
657 printf (" %s\n", "-r, --refuse=ok|warn|crit");
658 printf (" %s\n", _("Accept TCP refusals with states ok, warn, crit (default: crit)"));
659 printf (" %s\n", "-M, --mismatch=ok|warn|crit");
660 printf (" %s\n", _("Accept expected string mismatches with states ok, warn, crit (default: warn)"));
661 printf (" %s\n", "-j, --jail");
662 printf (" %s\n", _("Hide output from TCP socket"));
663 printf (" %s\n", "-m, --maxbytes=INTEGER");
664 printf (" %s\n", _("Close connection once more than this number of bytes are received"));
665 printf (" %s\n", "-d, --delay=INTEGER");
666 printf (" %s\n", _("Seconds to wait between sending string and polling for response"));
668 #ifdef HAVE_SSL
669 printf (" %s\n", "-D, --certificate=INTEGER[,INTEGER]");
670 printf (" %s\n", _("Minimum number of days a certificate has to be valid."));
671 printf (" %s\n", _("1st is #days for warning, 2nd is critical (if not specified - 0)."));
672 printf (" %s\n", "-S, --ssl");
673 printf (" %s\n", _("Use SSL for the connection."));
674 #endif
676 printf (UT_WARN_CRIT);
678 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
680 printf (UT_VERBOSE);
682 printf (UT_SUPPORT);
686 void
687 print_usage (void)
689 printf ("%s\n", _("Usage:"));
690 printf ("%s -H host -p port [-w <warning time>] [-c <critical time>] [-s <send string>]\n",progname);
691 printf ("[-e <expect string>] [-q <quit string>][-m <maximum bytes>] [-d <delay>]\n");
692 printf ("[-t <timeout seconds>] [-r <refuse state>] [-M <mismatch state>] [-v] [-4|-6] [-j]\n");
693 printf ("[-D <warn days cert expire>[,<crit days cert expire>]] [-S <use SSL>] [-E]\n");