1 /******************************************************************************
2 *
3 * Nagios check_http plugin
4 *
5 * License: GPL
6 * Copyright (c) 1999-2006 nagios-plugins team
7 *
8 * Last Modified: $Date$
9 *
10 * Description:
11 *
12 * This file contains the check_http plugin
13 *
14 * This plugin tests the HTTP service on the specified host. It can test
15 * normal (http) and secure (https) servers, follow redirects, search for
16 * strings and regular expressions, check connection times, and report on
17 * certificate expiration times.
18 *
19 *
20 * License Information:
21 *
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
36 $Id$
38 ******************************************************************************/
39 /* splint -I. -I../../plugins -I../../lib/ -I/usr/kerberos/include/ ../../plugins/check_http.c */
41 const char *progname = "check_http";
42 const char *revision = "$Revision$";
43 const char *copyright = "1999-2006";
44 const char *email = "nagiosplug-devel@lists.sourceforge.net";
46 #include <ctype.h>
48 #include "common.h"
49 #include "netutils.h"
50 #include "utils.h"
51 #include "base64.h"
53 #define INPUT_DELIMITER ";"
55 #define HTTP_EXPECT "HTTP/1."
56 enum {
57 MAX_IPV4_HOSTLENGTH = 255,
58 HTTP_PORT = 80,
59 HTTPS_PORT = 443,
60 MAX_PORT = 65535
61 };
63 #ifdef HAVE_SSL
64 int check_cert = FALSE;
65 int days_till_exp;
66 char *randbuff;
67 X509 *server_cert;
68 # define my_recv(buf, len) ((use_ssl) ? np_net_ssl_read(buf, len) : read(sd, buf, len))
69 # define my_send(buf, len) ((use_ssl) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0))
70 #else /* ifndef HAVE_SSL */
71 # define my_recv(buf, len) read(sd, buf, len)
72 # define my_send(buf, len) send(sd, buf, len, 0)
73 #endif /* HAVE_SSL */
74 int no_body = FALSE;
75 int maximum_age = -1;
77 enum {
78 REGS = 2,
79 MAX_RE_SIZE = 256
80 };
81 #include "regex.h"
82 regex_t preg;
83 regmatch_t pmatch[REGS];
84 char regexp[MAX_RE_SIZE];
85 char errbuf[MAX_INPUT_BUFFER];
86 int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE;
87 int errcode;
88 int invert_regex = 0;
90 struct timeval tv;
92 #define HTTP_URL "/"
93 #define CRLF "\r\n"
95 int specify_port = FALSE;
96 int server_port = HTTP_PORT;
97 char server_port_text[6] = "";
98 char server_type[6] = "http";
99 char *server_address;
100 char *host_name;
101 char *server_url;
102 char *user_agent;
103 int server_url_length;
104 int server_expect_yn = 0;
105 char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT;
106 char string_expect[MAX_INPUT_BUFFER] = "";
107 double warning_time = 0;
108 int check_warning_time = FALSE;
109 double critical_time = 0;
110 int check_critical_time = FALSE;
111 char user_auth[MAX_INPUT_BUFFER] = "";
112 int display_html = FALSE;
113 char **http_opt_headers;
114 int http_opt_headers_count = 0;
115 int onredirect = STATE_OK;
116 int use_ssl = FALSE;
117 int verbose = FALSE;
118 int sd;
119 int min_page_len = 0;
120 int max_page_len = 0;
121 int redir_depth = 0;
122 int max_depth = 15;
123 char *http_method;
124 char *http_post_data;
125 char *http_content_type;
126 char buffer[MAX_INPUT_BUFFER];
128 int process_arguments (int, char **);
129 int check_http (void);
130 void redir (char *pos, char *status_line);
131 int server_type_check(const char *type);
132 int server_port_check(int ssl_flag);
133 char *perfd_time (double microsec);
134 char *perfd_size (int page_len);
135 void print_help (void);
136 void print_usage (void);
138 int
139 main (int argc, char **argv)
140 {
141 int result = STATE_UNKNOWN;
143 setlocale (LC_ALL, "");
144 bindtextdomain (PACKAGE, LOCALEDIR);
145 textdomain (PACKAGE);
147 /* Set default URL. Must be malloced for subsequent realloc if --onredirect=follow */
148 server_url = strdup(HTTP_URL);
149 server_url_length = strlen(server_url);
150 asprintf (&user_agent, "User-Agent: check_http/%s (nagios-plugins %s)",
151 clean_revstring (revision), VERSION);
153 if (process_arguments (argc, argv) == ERROR)
154 usage4 (_("Could not parse arguments"));
156 if (display_html == TRUE)
157 printf ("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">",
158 use_ssl ? "https" : "http", host_name ? host_name : server_address,
159 server_port, server_url);
161 /* initialize alarm signal handling, set socket timeout, start timer */
162 (void) signal (SIGALRM, socket_timeout_alarm_handler);
163 (void) alarm (socket_timeout);
164 gettimeofday (&tv, NULL);
166 result = check_http ();
167 return result;
168 }
172 /* process command-line arguments */
173 int
174 process_arguments (int argc, char **argv)
175 {
176 int c = 1;
178 enum {
179 INVERT_REGEX = CHAR_MAX + 1
180 };
182 int option = 0;
183 static struct option longopts[] = {
184 STD_LONG_OPTS,
185 {"link", no_argument, 0, 'L'},
186 {"nohtml", no_argument, 0, 'n'},
187 {"ssl", no_argument, 0, 'S'},
188 {"post", required_argument, 0, 'P'},
189 {"IP-address", required_argument, 0, 'I'},
190 {"url", required_argument, 0, 'u'},
191 {"port", required_argument, 0, 'p'},
192 {"authorization", required_argument, 0, 'a'},
193 {"string", required_argument, 0, 's'},
194 {"expect", required_argument, 0, 'e'},
195 {"regex", required_argument, 0, 'r'},
196 {"ereg", required_argument, 0, 'r'},
197 {"eregi", required_argument, 0, 'R'},
198 {"linespan", no_argument, 0, 'l'},
199 {"onredirect", required_argument, 0, 'f'},
200 {"certificate", required_argument, 0, 'C'},
201 {"useragent", required_argument, 0, 'A'},
202 {"header", required_argument, 0, 'k'},
203 {"no-body", no_argument, 0, 'N'},
204 {"max-age", required_argument, 0, 'M'},
205 {"content-type", required_argument, 0, 'T'},
206 {"pagesize", required_argument, 0, 'm'},
207 {"invert-regex", no_argument, NULL, INVERT_REGEX},
208 {"use-ipv4", no_argument, 0, '4'},
209 {"use-ipv6", no_argument, 0, '6'},
210 {0, 0, 0, 0}
211 };
213 if (argc < 2)
214 return ERROR;
216 for (c = 1; c < argc; c++) {
217 if (strcmp ("-to", argv[c]) == 0)
218 strcpy (argv[c], "-t");
219 if (strcmp ("-hn", argv[c]) == 0)
220 strcpy (argv[c], "-H");
221 if (strcmp ("-wt", argv[c]) == 0)
222 strcpy (argv[c], "-w");
223 if (strcmp ("-ct", argv[c]) == 0)
224 strcpy (argv[c], "-c");
225 if (strcmp ("-nohtml", argv[c]) == 0)
226 strcpy (argv[c], "-n");
227 }
229 while (1) {
230 c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:T:I:a:e:p:s:R:r:u:f:C:nlLSm:M:N", longopts, &option);
231 if (c == -1 || c == EOF)
232 break;
234 switch (c) {
235 case '?': /* usage */
236 usage5 ();
237 break;
238 case 'h': /* help */
239 print_help ();
240 exit (STATE_OK);
241 break;
242 case 'V': /* version */
243 print_revision (progname, revision);
244 exit (STATE_OK);
245 break;
246 case 't': /* timeout period */
247 if (!is_intnonneg (optarg))
248 usage2 (_("Timeout interval must be a positive integer"), optarg);
249 else
250 socket_timeout = atoi (optarg);
251 break;
252 case 'c': /* critical time threshold */
253 if (!is_nonnegative (optarg))
254 usage2 (_("Critical threshold must be integer"), optarg);
255 else {
256 critical_time = strtod (optarg, NULL);
257 check_critical_time = TRUE;
258 }
259 break;
260 case 'w': /* warning time threshold */
261 if (!is_nonnegative (optarg))
262 usage2 (_("Warning threshold must be integer"), optarg);
263 else {
264 warning_time = strtod (optarg, NULL);
265 check_warning_time = TRUE;
266 }
267 break;
268 case 'A': /* User Agent String */
269 asprintf (&user_agent, "User-Agent: %s", optarg);
270 break;
271 case 'k': /* Additional headers */
272 if (http_opt_headers_count == 0)
273 http_opt_headers = malloc (sizeof (char *) * (++http_opt_headers_count));
274 else
275 http_opt_headers = realloc (http_opt_headers, sizeof (char *) * (++http_opt_headers_count));
276 http_opt_headers[http_opt_headers_count - 1] = optarg;
277 /* asprintf (&http_opt_headers, "%s", optarg); */
278 break;
279 case 'L': /* show html link */
280 display_html = TRUE;
281 break;
282 case 'n': /* do not show html link */
283 display_html = FALSE;
284 break;
285 case 'C': /* Check SSL cert validity */
286 #ifdef HAVE_SSL
287 if (!is_intnonneg (optarg))
288 usage2 (_("Invalid certificate expiration period"), optarg);
289 else {
290 days_till_exp = atoi (optarg);
291 check_cert = TRUE;
292 }
293 /* Fall through to -S option */
294 #endif
295 case 'S': /* use SSL */
296 #ifndef HAVE_SSL
297 usage4 (_("Invalid option - SSL is not available"));
298 #endif
299 use_ssl = TRUE;
300 if (specify_port == FALSE)
301 server_port = HTTPS_PORT;
302 break;
303 case 'f': /* onredirect */
304 if (!strcmp (optarg, "follow"))
305 onredirect = STATE_DEPENDENT;
306 if (!strcmp (optarg, "unknown"))
307 onredirect = STATE_UNKNOWN;
308 if (!strcmp (optarg, "ok"))
309 onredirect = STATE_OK;
310 if (!strcmp (optarg, "warning"))
311 onredirect = STATE_WARNING;
312 if (!strcmp (optarg, "critical"))
313 onredirect = STATE_CRITICAL;
314 if (verbose)
315 printf(_("option f:%d \n"), onredirect);
316 break;
317 /* Note: H, I, and u must be malloc'd or will fail on redirects */
318 case 'H': /* Host Name (virtual host) */
319 host_name = strdup (optarg);
320 break;
321 case 'I': /* Server IP-address */
322 server_address = strdup (optarg);
323 break;
324 case 'u': /* URL path */
325 server_url = strdup (optarg);
326 server_url_length = strlen (server_url);
327 break;
328 case 'p': /* Server port */
329 if (!is_intnonneg (optarg))
330 usage2 (_("Invalid port number"), optarg);
331 else {
332 server_port = atoi (optarg);
333 specify_port = TRUE;
334 }
335 break;
336 case 'a': /* authorization info */
337 strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1);
338 user_auth[MAX_INPUT_BUFFER - 1] = 0;
339 break;
340 case 'P': /* HTTP POST data in URL encoded format */
341 if (http_method || http_post_data) break;
342 http_method = strdup("POST");
343 http_post_data = strdup (optarg);
344 break;
345 case 's': /* string or substring */
346 strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1);
347 string_expect[MAX_INPUT_BUFFER - 1] = 0;
348 break;
349 case 'e': /* string or substring */
350 strncpy (server_expect, optarg, MAX_INPUT_BUFFER - 1);
351 server_expect[MAX_INPUT_BUFFER - 1] = 0;
352 server_expect_yn = 1;
353 break;
354 case 'T': /* Content-type */
355 asprintf (&http_content_type, "%s", optarg);
356 break;
357 case 'l': /* linespan */
358 cflags &= ~REG_NEWLINE;
359 break;
360 case 'R': /* regex */
361 cflags |= REG_ICASE;
362 case 'r': /* regex */
363 strncpy (regexp, optarg, MAX_RE_SIZE - 1);
364 regexp[MAX_RE_SIZE - 1] = 0;
365 errcode = regcomp (&preg, regexp, cflags);
366 if (errcode != 0) {
367 (void) regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
368 printf (_("Could Not Compile Regular Expression: %s"), errbuf);
369 return ERROR;
370 }
371 break;
372 case INVERT_REGEX:
373 invert_regex = 1;
374 break;
375 case '4':
376 address_family = AF_INET;
377 break;
378 case '6':
379 #ifdef USE_IPV6
380 address_family = AF_INET6;
381 #else
382 usage4 (_("IPv6 support not available"));
383 #endif
384 break;
385 case 'v': /* verbose */
386 verbose = TRUE;
387 break;
388 case 'm': /* min_page_length */
389 {
390 char *tmp;
391 if (strchr(optarg, ':') != (char *)NULL) {
392 /* range, so get two values, min:max */
393 tmp = strtok(optarg, ":");
394 if (tmp == NULL) {
395 printf("Bad format: try \"-m min:max\"\n");
396 exit (STATE_WARNING);
397 } else
398 min_page_len = atoi(tmp);
400 tmp = strtok(NULL, ":");
401 if (tmp == NULL) {
402 printf("Bad format: try \"-m min:max\"\n");
403 exit (STATE_WARNING);
404 } else
405 max_page_len = atoi(tmp);
406 } else
407 min_page_len = atoi (optarg);
408 break;
409 }
410 case 'N': /* no-body */
411 no_body = TRUE;
412 break;
413 case 'M': /* max-age */
414 {
415 int L = strlen(optarg);
416 if (L && optarg[L-1] == 'm')
417 maximum_age = atoi (optarg) * 60;
418 else if (L && optarg[L-1] == 'h')
419 maximum_age = atoi (optarg) * 60 * 60;
420 else if (L && optarg[L-1] == 'd')
421 maximum_age = atoi (optarg) * 60 * 60 * 24;
422 else if (L && (optarg[L-1] == 's' ||
423 isdigit (optarg[L-1])))
424 maximum_age = atoi (optarg);
425 else {
426 fprintf (stderr, "unparsable max-age: %s\n", optarg);
427 exit (STATE_WARNING);
428 }
429 }
430 break;
431 }
432 }
434 c = optind;
436 if (server_address == NULL && c < argc)
437 server_address = strdup (argv[c++]);
439 if (host_name == NULL && c < argc)
440 host_name = strdup (argv[c++]);
442 if (server_address == NULL) {
443 if (host_name == NULL)
444 usage4 (_("You must specify a server address or host name"));
445 else
446 server_address = strdup (host_name);
447 }
449 if (check_critical_time && critical_time>(double)socket_timeout)
450 socket_timeout = (int)critical_time + 1;
452 if (http_method == NULL)
453 http_method = strdup ("GET");
455 return TRUE;
456 }
460 /* Returns 1 if we're done processing the document body; 0 to keep going */
461 static int
462 document_headers_done (char *full_page)
463 {
464 const char *body;
466 for (body = full_page; *body; body++) {
467 if (!strncmp (body, "\n\n", 2) || !strncmp (body, "\n\r\n", 3))
468 break;
469 }
471 if (!*body)
472 return 0; /* haven't read end of headers yet */
474 full_page[body - full_page] = 0;
475 return 1;
476 }
478 static time_t
479 parse_time_string (const char *string)
480 {
481 struct tm tm;
482 time_t t;
483 memset (&tm, 0, sizeof(tm));
485 /* Like this: Tue, 25 Dec 2001 02:59:03 GMT */
487 if (isupper (string[0]) && /* Tue */
488 islower (string[1]) &&
489 islower (string[2]) &&
490 ',' == string[3] &&
491 ' ' == string[4] &&
492 (isdigit(string[5]) || string[5] == ' ') && /* 25 */
493 isdigit (string[6]) &&
494 ' ' == string[7] &&
495 isupper (string[8]) && /* Dec */
496 islower (string[9]) &&
497 islower (string[10]) &&
498 ' ' == string[11] &&
499 isdigit (string[12]) && /* 2001 */
500 isdigit (string[13]) &&
501 isdigit (string[14]) &&
502 isdigit (string[15]) &&
503 ' ' == string[16] &&
504 isdigit (string[17]) && /* 02: */
505 isdigit (string[18]) &&
506 ':' == string[19] &&
507 isdigit (string[20]) && /* 59: */
508 isdigit (string[21]) &&
509 ':' == string[22] &&
510 isdigit (string[23]) && /* 03 */
511 isdigit (string[24]) &&
512 ' ' == string[25] &&
513 'G' == string[26] && /* GMT */
514 'M' == string[27] && /* GMT */
515 'T' == string[28]) {
517 tm.tm_sec = 10 * (string[23]-'0') + (string[24]-'0');
518 tm.tm_min = 10 * (string[20]-'0') + (string[21]-'0');
519 tm.tm_hour = 10 * (string[17]-'0') + (string[18]-'0');
520 tm.tm_mday = 10 * (string[5] == ' ' ? 0 : string[5]-'0') + (string[6]-'0');
521 tm.tm_mon = (!strncmp (string+8, "Jan", 3) ? 0 :
522 !strncmp (string+8, "Feb", 3) ? 1 :
523 !strncmp (string+8, "Mar", 3) ? 2 :
524 !strncmp (string+8, "Apr", 3) ? 3 :
525 !strncmp (string+8, "May", 3) ? 4 :
526 !strncmp (string+8, "Jun", 3) ? 5 :
527 !strncmp (string+8, "Jul", 3) ? 6 :
528 !strncmp (string+8, "Aug", 3) ? 7 :
529 !strncmp (string+8, "Sep", 3) ? 8 :
530 !strncmp (string+8, "Oct", 3) ? 9 :
531 !strncmp (string+8, "Nov", 3) ? 10 :
532 !strncmp (string+8, "Dec", 3) ? 11 :
533 -1);
534 tm.tm_year = ((1000 * (string[12]-'0') +
535 100 * (string[13]-'0') +
536 10 * (string[14]-'0') +
537 (string[15]-'0'))
538 - 1900);
540 tm.tm_isdst = 0; /* GMT is never in DST, right? */
542 if (tm.tm_mon < 0 || tm.tm_mday < 1 || tm.tm_mday > 31)
543 return 0;
545 /*
546 This is actually wrong: we need to subtract the local timezone
547 offset from GMT from this value. But, that's ok in this usage,
548 because we only comparing these two GMT dates against each other,
549 so it doesn't matter what time zone we parse them in.
550 */
552 t = mktime (&tm);
553 if (t == (time_t) -1) t = 0;
555 if (verbose) {
556 const char *s = string;
557 while (*s && *s != '\r' && *s != '\n')
558 fputc (*s++, stdout);
559 printf (" ==> %lu\n", (unsigned long) t);
560 }
562 return t;
564 } else {
565 return 0;
566 }
567 }
571 static void
572 check_document_dates (const char *headers)
573 {
574 const char *s;
575 char *server_date = 0;
576 char *document_date = 0;
578 s = headers;
579 while (*s) {
580 const char *field = s;
581 const char *value = 0;
583 /* Find the end of the header field */
584 while (*s && !isspace(*s) && *s != ':')
585 s++;
587 /* Remember the header value, if any. */
588 if (*s == ':')
589 value = ++s;
591 /* Skip to the end of the header, including continuation lines. */
592 while (*s && !(*s == '\n' && (s[1] != ' ' && s[1] != '\t')))
593 s++;
594 s++;
596 /* Process this header. */
597 if (value && value > field+2) {
598 char *ff = (char *) malloc (value-field);
599 char *ss = ff;
600 while (field < value-1)
601 *ss++ = tolower(*field++);
602 *ss++ = 0;
604 if (!strcmp (ff, "date") || !strcmp (ff, "last-modified")) {
605 const char *e;
606 while (*value && isspace (*value))
607 value++;
608 for (e = value; *e && *e != '\r' && *e != '\n'; e++)
609 ;
610 ss = (char *) malloc (e - value + 1);
611 strncpy (ss, value, e - value);
612 ss[e - value] = 0;
613 if (!strcmp (ff, "date")) {
614 if (server_date) free (server_date);
615 server_date = ss;
616 } else {
617 if (document_date) free (document_date);
618 document_date = ss;
619 }
620 }
621 free (ff);
622 }
623 }
625 /* Done parsing the body. Now check the dates we (hopefully) parsed. */
626 if (!server_date || !*server_date) {
627 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Server date unknown\n"));
628 } else if (!document_date || !*document_date) {
629 die (STATE_CRITICAL, _("HTTP CRITICAL - Document modification date unknown\n"));
630 } else {
631 time_t srv_data = parse_time_string (server_date);
632 time_t doc_data = parse_time_string (document_date);
634 if (srv_data <= 0) {
635 die (STATE_CRITICAL, _("HTTP CRITICAL - Server date \"%100s\" unparsable"), server_date);
636 } else if (doc_data <= 0) {
637 die (STATE_CRITICAL, _("HTTP CRITICAL - Document date \"%100s\" unparsable"), document_date);
638 } else if (doc_data > srv_data + 30) {
639 die (STATE_CRITICAL, _("HTTP CRITICAL - Document is %d seconds in the future\n"), (int)doc_data - (int)srv_data);
640 } else if (doc_data < srv_data - maximum_age) {
641 int n = (srv_data - doc_data);
642 if (n > (60 * 60 * 24 * 2))
643 die (STATE_CRITICAL,
644 _("HTTP CRITICAL - Last modified %.1f days ago\n"),
645 ((float) n) / (60 * 60 * 24));
646 else
647 die (STATE_CRITICAL,
648 _("HTTP CRITICAL - Last modified %d:%02d:%02d ago\n"),
649 n / (60 * 60), (n / 60) % 60, n % 60);
650 }
652 free (server_date);
653 free (document_date);
654 }
655 }
657 int
658 get_content_length (const char *headers)
659 {
660 const char *s;
661 int content_length = 0;
663 s = headers;
664 while (*s) {
665 const char *field = s;
666 const char *value = 0;
668 /* Find the end of the header field */
669 while (*s && !isspace(*s) && *s != ':')
670 s++;
672 /* Remember the header value, if any. */
673 if (*s == ':')
674 value = ++s;
676 /* Skip to the end of the header, including continuation lines. */
677 while (*s && !(*s == '\n' && (s[1] != ' ' && s[1] != '\t')))
678 s++;
679 s++;
681 /* Process this header. */
682 if (value && value > field+2) {
683 char *ff = (char *) malloc (value-field);
684 char *ss = ff;
685 while (field < value-1)
686 *ss++ = tolower(*field++);
687 *ss++ = 0;
689 if (!strcmp (ff, "content-length")) {
690 const char *e;
691 while (*value && isspace (*value))
692 value++;
693 for (e = value; *e && *e != '\r' && *e != '\n'; e++)
694 ;
695 ss = (char *) malloc (e - value + 1);
696 strncpy (ss, value, e - value);
697 ss[e - value] = 0;
698 content_length = atoi(ss);
699 free (ss);
700 }
701 free (ff);
702 }
703 }
704 return (content_length);
705 }
707 int
708 check_http (void)
709 {
710 char *msg;
711 char *status_line;
712 char *status_code;
713 char *header;
714 char *page;
715 char *auth;
716 int http_status;
717 int i = 0;
718 size_t pagesize = 0;
719 char *full_page;
720 char *buf;
721 char *pos;
722 long microsec;
723 double elapsed_time;
724 int page_len = 0;
725 int result = STATE_UNKNOWN;
727 /* try to connect to the host at the given port number */
728 if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK)
729 die (STATE_CRITICAL, _("HTTP CRITICAL - Unable to open TCP socket\n"));
730 #ifdef HAVE_SSL
731 if (use_ssl == TRUE) {
732 np_net_ssl_init(sd);
733 if (check_cert == TRUE) {
734 result = np_net_ssl_check_cert(days_till_exp);
735 np_net_ssl_cleanup();
736 if(sd) close(sd);
737 return result;
738 }
739 }
740 #endif /* HAVE_SSL */
742 asprintf (&buf, "%s %s HTTP/1.0\r\n%s\r\n", http_method, server_url, user_agent);
744 /* tell HTTP/1.1 servers not to keep the connection alive */
745 asprintf (&buf, "%sConnection: close\r\n", buf);
747 /* optionally send the host header info */
748 if (host_name)
749 asprintf (&buf, "%sHost: %s\r\n", buf, host_name);
751 /* optionally send any other header tag */
752 if (http_opt_headers_count) {
753 for (i = 0; i < http_opt_headers_count ; i++) {
754 for ((pos = strtok(http_opt_headers[i], INPUT_DELIMITER)); pos; (pos = strtok(NULL, INPUT_DELIMITER)))
755 asprintf (&buf, "%s%s\r\n", buf, pos);
756 }
757 free(http_opt_headers);
758 }
760 /* optionally send the authentication info */
761 if (strlen(user_auth)) {
762 auth = base64 (user_auth, strlen (user_auth));
763 asprintf (&buf, "%sAuthorization: Basic %s\r\n", buf, auth);
764 }
766 /* either send http POST data */
767 if (http_post_data) {
768 if (http_content_type) {
769 asprintf (&buf, "%sContent-Type: %s\r\n", buf, http_content_type);
770 } else {
771 asprintf (&buf, "%sContent-Type: application/x-www-form-urlencoded\r\n", buf);
772 }
774 asprintf (&buf, "%sContent-Length: %i\r\n\r\n", buf, (int)strlen (http_post_data));
775 asprintf (&buf, "%s%s%s", buf, http_post_data, CRLF);
776 }
777 else {
778 /* or just a newline so the server knows we're done with the request */
779 asprintf (&buf, "%s%s", buf, CRLF);
780 }
782 if (verbose) printf ("%s\n", buf);
783 my_send (buf, strlen (buf));
785 /* fetch the page */
786 full_page = strdup("");
787 while ((i = my_recv (buffer, MAX_INPUT_BUFFER-1)) > 0) {
788 buffer[i] = '\0';
789 asprintf (&full_page, "%s%s", full_page, buffer);
790 pagesize += i;
792 if (no_body && document_headers_done (full_page)) {
793 i = 0;
794 break;
795 }
796 }
798 if (i < 0 && errno != ECONNRESET) {
799 #ifdef HAVE_SSL
800 /*
801 if (use_ssl) {
802 sslerr=SSL_get_error(ssl, i);
803 if ( sslerr == SSL_ERROR_SSL ) {
804 die (STATE_WARNING, _("HTTP WARNING - Client Certificate Required\n"));
805 } else {
806 die (STATE_CRITICAL, _("HTTP CRITICAL - Error on receive\n"));
807 }
808 }
809 else {
810 */
811 #endif
812 die (STATE_CRITICAL, _("HTTP CRITICAL - Error on receive\n"));
813 #ifdef HAVE_SSL
814 /* XXX
815 }
816 */
817 #endif
818 }
820 /* return a CRITICAL status if we couldn't read any data */
821 if (pagesize == (size_t) 0)
822 die (STATE_CRITICAL, _("HTTP CRITICAL - No data received from host\n"));
824 /* close the connection */
825 #ifdef HAVE_SSL
826 np_net_ssl_cleanup();
827 #endif
828 if(sd) close(sd);
830 /* reset the alarm */
831 alarm (0);
833 /* leave full_page untouched so we can free it later */
834 page = full_page;
836 if (verbose)
837 printf ("%s://%s:%d%s is %d characters\n",
838 use_ssl ? "https" : "http", server_address,
839 server_port, server_url, (int)pagesize);
841 /* find status line and null-terminate it */
842 status_line = page;
843 page += (size_t) strcspn (page, "\r\n");
844 pos = page;
845 page += (size_t) strspn (page, "\r\n");
846 status_line[strcspn(status_line, "\r\n")] = 0;
847 strip (status_line);
848 if (verbose)
849 printf ("STATUS: %s\n", status_line);
851 /* find header info and null-terminate it */
852 header = page;
853 while (strcspn (page, "\r\n") > 0) {
854 page += (size_t) strcspn (page, "\r\n");
855 pos = page;
856 if ((strspn (page, "\r") == 1 && strspn (page, "\r\n") >= 2) ||
857 (strspn (page, "\n") == 1 && strspn (page, "\r\n") >= 2))
858 page += (size_t) 2;
859 else
860 page += (size_t) 1;
861 }
862 page += (size_t) strspn (page, "\r\n");
863 header[pos - header] = 0;
864 if (verbose)
865 printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header,
866 (no_body ? " [[ skipped ]]" : page));
868 /* make sure the status line matches the response we are looking for */
869 if (!strstr (status_line, server_expect)) {
870 if (server_port == HTTP_PORT)
871 asprintf (&msg,
872 _("Invalid HTTP response received from host\n"));
873 else
874 asprintf (&msg,
875 _("Invalid HTTP response received from host on port %d\n"),
876 server_port);
877 die (STATE_CRITICAL, "HTTP CRITICAL - %s", msg);
878 }
880 /* Exit here if server_expect was set by user and not default */
881 if ( server_expect_yn ) {
882 asprintf (&msg,
883 _("HTTP OK: Status line output matched \"%s\"\n"),
884 server_expect);
885 if (verbose)
886 printf ("%s\n",msg);
887 }
888 else {
889 /* Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF */
890 /* HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT */
891 /* Status-Code = 3 DIGITS */
893 status_code = strchr (status_line, ' ') + sizeof (char);
894 if (strspn (status_code, "1234567890") != 3)
895 die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status Line (%s)\n"), status_line);
897 http_status = atoi (status_code);
899 /* check the return code */
901 if (http_status >= 600 || http_status < 100)
902 die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%s)\n"), status_line);
904 /* server errors result in a critical state */
905 else if (http_status >= 500)
906 die (STATE_CRITICAL, _("HTTP CRITICAL: %s\n"), status_line);
908 /* client errors result in a warning state */
909 else if (http_status >= 400)
910 die (STATE_WARNING, _("HTTP WARNING: %s\n"), status_line);
912 /* check redirected page if specified */
913 else if (http_status >= 300) {
915 if (onredirect == STATE_DEPENDENT)
916 redir (header, status_line);
917 else if (onredirect == STATE_UNKNOWN)
918 printf (_("HTTP UNKNOWN"));
919 else if (onredirect == STATE_OK)
920 printf (_("HTTP OK"));
921 else if (onredirect == STATE_WARNING)
922 printf (_("HTTP WARNING"));
923 else if (onredirect == STATE_CRITICAL)
924 printf (_("HTTP CRITICAL"));
925 microsec = deltime (tv);
926 elapsed_time = (double)microsec / 1.0e6;
927 die (onredirect,
928 _(" - %s - %.3f second response time %s|%s %s\n"),
929 status_line, elapsed_time,
930 (display_html ? "</A>" : ""),
931 perfd_time (elapsed_time), perfd_size (pagesize));
932 } /* end if (http_status >= 300) */
934 } /* end else (server_expect_yn) */
936 if (maximum_age >= 0) {
937 check_document_dates (header);
938 }
940 /* check elapsed time */
941 microsec = deltime (tv);
942 elapsed_time = (double)microsec / 1.0e6;
943 asprintf (&msg,
944 _(" - %s - %.3f second response time %s|%s %s\n"),
945 status_line, elapsed_time,
946 (display_html ? "</A>" : ""),
947 perfd_time (elapsed_time), perfd_size (pagesize));
948 if (check_critical_time == TRUE && elapsed_time > critical_time)
949 die (STATE_CRITICAL, "HTTP %s: %s", _("CRITICAL"), msg);
950 if (check_warning_time == TRUE && elapsed_time > warning_time)
951 die (STATE_WARNING, "HTTP %s: %s", _("WARNING"), msg);
953 /* Page and Header content checks go here */
954 /* these checks should be last */
956 if (strlen (string_expect)) {
957 if (strstr (page, string_expect)) {
958 printf (_("HTTP OK %s - %.3f second response time %s|%s %s\n"),
959 status_line, elapsed_time,
960 (display_html ? "</A>" : ""),
961 perfd_time (elapsed_time), perfd_size (pagesize));
962 exit (STATE_OK);
963 }
964 else {
965 printf (_("HTTP CRITICAL - string not found%s|%s %s\n"),
966 (display_html ? "</A>" : ""),
967 perfd_time (elapsed_time), perfd_size (pagesize));
968 exit (STATE_CRITICAL);
969 }
970 }
972 if (strlen (regexp)) {
973 errcode = regexec (&preg, page, REGS, pmatch, 0);
974 if ((errcode == 0 && invert_regex == 0) || (errcode == REG_NOMATCH && invert_regex == 1)) {
975 printf (_("HTTP OK %s - %.3f second response time %s|%s %s\n"),
976 status_line, elapsed_time,
977 (display_html ? "</A>" : ""),
978 perfd_time (elapsed_time), perfd_size (pagesize));
979 exit (STATE_OK);
980 }
981 else if ((errcode == REG_NOMATCH && invert_regex == 0) || (errcode == 0 && invert_regex == 1)) {
982 if (invert_regex == 0)
983 msg = strdup(_("pattern not found"));
984 else
985 msg = strdup(_("pattern found"));
986 printf (("%s - %s%s|%s %s\n"),
987 _("HTTP CRITICAL"),
988 msg,
989 (display_html ? "</A>" : ""),
990 perfd_time (elapsed_time), perfd_size (pagesize));
991 exit (STATE_CRITICAL);
992 }
993 else {
994 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
995 printf (_("HTTP CRITICAL - Execute Error: %s\n"), errbuf);
996 exit (STATE_CRITICAL);
997 }
998 }
1000 /* make sure the page is of an appropriate size */
1001 /* page_len = get_content_length(header); */
1002 page_len = pagesize;
1003 if ((max_page_len > 0) && (page_len > max_page_len)) {
1004 printf (_("HTTP WARNING: page size %d too large%s|%s\n"),
1005 page_len, (display_html ? "</A>" : ""), perfd_size (page_len) );
1006 exit (STATE_WARNING);
1007 } else if ((min_page_len > 0) && (page_len < min_page_len)) {
1008 printf (_("HTTP WARNING: page size %d too small%s|%s\n"),
1009 page_len, (display_html ? "</A>" : ""), perfd_size (page_len) );
1010 exit (STATE_WARNING);
1011 }
1012 /* We only get here if all tests have been passed */
1013 asprintf (&msg, _("HTTP OK %s - %d bytes in %.3f seconds %s|%s %s\n"),
1014 status_line, page_len, elapsed_time,
1015 (display_html ? "</A>" : ""),
1016 perfd_time (elapsed_time), perfd_size (page_len));
1017 die (STATE_OK, "%s", msg);
1018 return STATE_UNKNOWN;
1019 }
1023 /* per RFC 2396 */
1024 #define URI_HTTP "%5[HTPShtps]"
1025 #define URI_HOST "%255[-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
1026 #define URI_PORT "%6d" /* MAX_PORT's width is 5 chars, 6 to detect overflow */
1027 #define URI_PATH "%[-_.!~*'();/?:@&=+$,%#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
1028 #define HD1 URI_HTTP "://" URI_HOST ":" URI_PORT "/" URI_PATH
1029 #define HD2 URI_HTTP "://" URI_HOST "/" URI_PATH
1030 #define HD3 URI_HTTP "://" URI_HOST ":" URI_PORT
1031 #define HD4 URI_HTTP "://" URI_HOST
1032 #define HD5 URI_PATH
1034 void
1035 redir (char *pos, char *status_line)
1036 {
1037 int i = 0;
1038 char *x;
1039 char xx[2];
1040 char type[6];
1041 char *addr;
1042 char *url;
1044 addr = malloc (MAX_IPV4_HOSTLENGTH + 1);
1045 if (addr == NULL)
1046 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate addr\n"));
1048 url = malloc (strcspn (pos, "\r\n"));
1049 if (url == NULL)
1050 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate url\n"));
1052 while (pos) {
1053 sscanf (pos, "%1[Ll]%*1[Oo]%*1[Cc]%*1[Aa]%*1[Tt]%*1[Ii]%*1[Oo]%*1[Nn]:%n", xx, &i);
1054 if (i == 0) {
1055 pos += (size_t) strcspn (pos, "\r\n");
1056 pos += (size_t) strspn (pos, "\r\n");
1057 if (strlen(pos) == 0)
1058 die (STATE_UNKNOWN,
1059 _("HTTP UNKNOWN - Could not find redirect location - %s%s\n"),
1060 status_line, (display_html ? "</A>" : ""));
1061 continue;
1062 }
1064 pos += i;
1065 pos += strspn (pos, " \t");
1067 /*
1068 * RFC 2616 (4.2): ``Header fields can be extended over multiple lines by
1069 * preceding each extra line with at least one SP or HT.''
1070 */
1071 for (; (i = strspn (pos, "\r\n")); pos += i) {
1072 pos += i;
1073 if (!(i = strspn (pos, " \t"))) {
1074 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Empty redirect location%s\n"),
1075 display_html ? "</A>" : "");
1076 }
1077 }
1079 url = realloc (url, strcspn (pos, "\r\n") + 1);
1080 if (url == NULL)
1081 die (STATE_UNKNOWN, _("HTTP UNKNOWN - could not allocate url\n"));
1083 /* URI_HTTP, URI_HOST, URI_PORT, URI_PATH */
1084 if (sscanf (pos, HD1, type, addr, &i, url) == 4)
1085 use_ssl = server_type_check (type);
1087 /* URI_HTTP URI_HOST URI_PATH */
1088 else if (sscanf (pos, HD2, type, addr, url) == 3 ) {
1089 use_ssl = server_type_check (type);
1090 i = server_port_check (use_ssl);
1091 }
1093 /* URI_HTTP URI_HOST URI_PORT */
1094 else if(sscanf (pos, HD3, type, addr, &i) == 3) {
1095 strcpy (url, HTTP_URL);
1096 use_ssl = server_type_check (type);
1097 }
1099 /* URI_HTTP URI_HOST */
1100 else if(sscanf (pos, HD4, type, addr) == 2) {
1101 strcpy (url, HTTP_URL);
1102 use_ssl = server_type_check (type);
1103 i = server_port_check (use_ssl);
1104 }
1106 /* URI_PATH */
1107 else if (sscanf (pos, HD5, url) == 1) {
1108 /* relative url */
1109 if ((url[0] != '/')) {
1110 if ((x = strrchr(server_url, '/')))
1111 *x = '\0';
1112 asprintf (&url, "%s/%s", server_url, url);
1113 }
1114 i = server_port;
1115 strcpy (type, server_type);
1116 strcpy (addr, host_name ? host_name : server_address);
1117 }
1119 else {
1120 die (STATE_UNKNOWN,
1121 _("HTTP UNKNOWN - Could not parse redirect location - %s%s\n"),
1122 pos, (display_html ? "</A>" : ""));
1123 }
1125 break;
1127 } /* end while (pos) */
1129 if (++redir_depth > max_depth)
1130 die (STATE_WARNING,
1131 _("HTTP WARNING - maximum redirection depth %d exceeded - %s://%s:%d%s%s\n"),
1132 max_depth, type, addr, i, url, (display_html ? "</A>" : ""));
1134 if (server_port==i &&
1135 !strcmp(server_address, addr) &&
1136 (host_name && !strcmp(host_name, addr)) &&
1137 !strcmp(server_url, url))
1138 die (STATE_WARNING,
1139 _("HTTP WARNING - redirection creates an infinite loop - %s://%s:%d%s%s\n"),
1140 type, addr, i, url, (display_html ? "</A>" : ""));
1142 strcpy (server_type, type);
1144 free (host_name);
1145 host_name = strdup (addr);
1147 free (server_address);
1148 server_address = strdup (addr);
1150 free (server_url);
1151 if ((url[0] == '/'))
1152 server_url = strdup (url);
1153 else if (asprintf(&server_url, "/%s", url) == -1)
1154 die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate server_url%s\n"),
1155 display_html ? "</A>" : "");
1156 free(url);
1158 if ((server_port = i) > MAX_PORT)
1159 die (STATE_UNKNOWN,
1160 _("HTTP UNKNOWN - Redirection to port above %d - %s://%s:%d%s%s\n"),
1161 MAX_PORT, server_type, server_address, server_port, server_url,
1162 display_html ? "</A>" : "");
1164 if (verbose)
1165 printf (_("Redirection to %s://%s:%d%s\n"), server_type,
1166 host_name ? host_name : server_address, server_port, server_url);
1168 check_http ();
1169 }
1173 int
1174 server_type_check (const char *type)
1175 {
1176 if (strcmp (type, "https"))
1177 return FALSE;
1178 else
1179 return TRUE;
1180 }
1182 int
1183 server_port_check (int ssl_flag)
1184 {
1185 if (ssl_flag)
1186 return HTTPS_PORT;
1187 else
1188 return HTTP_PORT;
1189 }
1191 char *perfd_time (double elapsed_time)
1192 {
1193 return fperfdata ("time", elapsed_time, "s",
1194 check_warning_time, warning_time,
1195 check_critical_time, critical_time,
1196 TRUE, 0, FALSE, 0);
1197 }
1201 char *perfd_size (int page_len)
1202 {
1203 return perfdata ("size", page_len, "B",
1204 (min_page_len>0?TRUE:FALSE), min_page_len,
1205 (min_page_len>0?TRUE:FALSE), 0,
1206 TRUE, 0, FALSE, 0);
1207 }
1209 void
1210 print_help (void)
1211 {
1212 print_revision (progname, revision);
1214 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
1215 printf (COPYRIGHT, copyright, email);
1217 printf ("%s\n", _("This plugin tests the HTTP service on the specified host. It can test"));
1218 printf ("%s\n", _("normal (http) and secure (https) servers, follow redirects, search for"));
1219 printf ("%s\n", _("strings and regular expressions, check connection times, and report on"));
1220 printf ("%s\n", _("certificate expiration times."));
1222 printf ("\n\n");
1224 print_usage ();
1226 printf (_("NOTE: One or both of -H and -I must be specified"));
1228 printf ("\n");
1230 printf (_(UT_HELP_VRSN));
1232 printf (" %s\n", "-H, --hostname=ADDRESS");
1233 printf (" %s\n", _("Host name argument for servers using host headers (virtual host)"));
1234 printf (" %s\n", _("Append a port to include it in the header (eg: example.com:5000)"));
1235 printf (" %s\n", "-I, --IP-address=ADDRESS");
1236 printf (" %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup)."));
1237 printf (" %s\n", "-p, --port=INTEGER");
1238 printf (" %s", _("Port number (default: "));
1239 printf ("%d)\n", HTTP_PORT);
1241 printf (_(UT_IPv46));
1243 #ifdef HAVE_SSL
1244 printf (" %s\n", "-S, --ssl");
1245 printf (" %s\n", _("Connect via SSL. Port defaults to 443"));
1246 printf (" %s\n", "-C, --certificate=INTEGER");
1247 printf (" %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443"));
1248 printf (" %s\n", _("(when this option is used the url is not checked.)\n"));
1249 #endif
1251 printf (" %s\n", "-e, --expect=STRING");
1252 printf (" %s\n", _("String to expect in first (status) line of server response (default: "));
1253 printf ("%s)\n", HTTP_EXPECT);
1254 printf (" %s\n", _("If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)"));
1255 printf (" %s\n", "-s, --string=STRING");
1256 printf (" %s\n", _("String to expect in the content"));
1257 printf (" %s\n", "-u, --url=PATH");
1258 printf (" %s\n", _("URL to GET or POST (default: /)"));
1259 printf (" %s\n", "-P, --post=STRING");
1260 printf (" %s\n", _("URL encoded http POST data"));
1261 printf (" %s\n", "-N, --no-body");
1262 printf (" %s\n", _("Don't wait for document body: stop reading after headers."));
1263 printf (" %s\n", _("(Note that this still does an HTTP GET or POST, not a HEAD.)"));
1264 printf (" %s\n", "-M, --max-age=SECONDS");
1265 printf (" %s\n", _("Warn if document is more than SECONDS old. the number can also be of"));
1266 printf (" %s\n", _("the form \"10m\" for minutes, \"10h\" for hours, or \"10d\" for days."));
1267 printf (" %s\n", "-T, --content-type=STRING");
1268 printf (" %s\n", _("specify Content-Type header media type when POSTing\n"));
1270 printf (" %s\n", "-l, --linespan");
1271 printf (" %s\n", _("Allow regex to span newlines (must precede -r or -R)"));
1272 printf (" %s\n", "-r, --regex, --ereg=STRING");
1273 printf (" %s\n", _("Search page for regex STRING"));
1274 printf (" %s\n", "-R, --eregi=STRING");
1275 printf (" %s\n", _("Search page for case-insensitive regex STRING"));
1276 printf (" %s\n", "--invert-regex");
1277 printf (" %s\n", _("Return CRITICAL if found, OK if not\n"));
1279 printf (" %s\n", "-a, --authorization=AUTH_PAIR");
1280 printf (" %s\n", _("Username:password on sites with basic authentication"));
1281 printf (" %s\n", "-A, --useragent=STRING");
1282 printf (" %s\n", _("String to be sent in http header as \"User Agent\""));
1283 printf (" %s\n", "-k, --header=STRING");
1284 printf (" %s\n", _(" Any other tags to be sent in http header. Use multiple times for additional headers"));
1285 printf (" %s\n", "-L, --link");
1286 printf (" %s\n", _("Wrap output in HTML link (obsoleted by urlize)"));
1287 printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow>");
1288 printf (" %s\n", _("How to handle redirected pages"));
1289 printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>");
1290 printf (" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)"));
1292 printf (_(UT_WARN_CRIT));
1294 printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
1296 printf (_(UT_VERBOSE));
1298 printf (_("Notes:"));
1299 printf (" %s\n", _("This plugin will attempt to open an HTTP connection with the host."));
1300 printf (" %s\n", _("Successful connects return STATE_OK, refusals and timeouts return STATE_CRITICAL"));
1301 printf (" %s\n", _("other errors return STATE_UNKNOWN. Successful connects, but incorrect reponse"));
1302 printf (" %s\n", _("messages from the host result in STATE_WARNING return values. If you are"));
1303 printf (" %s\n", _("checking a virtual server that uses 'host headers' you must supply the FQDN"));
1304 printf (" %s\n", _("(fully qualified domain name) as the [host_name] argument."));
1306 #ifdef HAVE_SSL
1307 printf (" %s\n", _("This plugin can also check whether an SSL enabled web server is able to"));
1308 printf (" %s\n", _("serve content (optionally within a specified time) or whether the X509 "));
1309 printf (" %s\n", _("certificate is still valid for the specified number of days."));
1310 printf (_("Examples:"));
1311 printf (" %s\n\n", "CHECK CONTENT: check_http -w 5 -c 10 --ssl -H www.verisign.com");
1312 printf (" %s\n", _("When the 'www.verisign.com' server returns its content within 5 seconds,"));
1313 printf (" %s\n", _("a STATE_OK will be returned. When the server returns its content but exceeds"));
1314 printf (" %s\n", _("the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,"));
1315 printf (" %s\n\n", _("a STATE_CRITICAL will be returned."));
1317 printf (" %s\n\n", "CHECK CERTIFICATE: check_http -H www.verisign.com -C 14");
1318 printf (" %s\n", _("When the certificate of 'www.verisign.com' is valid for more than 14 days,"));
1319 printf (" %s\n", _("a STATE_OK is returned. When the certificate is still valid, but for less than"));
1320 printf (" %s\n", _("14 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when"));
1321 printf (" %s\n\n", _("the certificate is expired."));
1322 #endif
1324 printf (_(UT_SUPPORT));
1326 }
1330 void
1331 print_usage (void)
1332 {
1333 printf (_("Usage:"));
1334 printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname);
1335 printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L]\n");
1336 printf (" [-a auth] [-f <ok | warn | critcal | follow>] [-e <expect>]\n");
1337 printf (" [-s string] [-l] [-r <regex> | -R <case-insensitive regex>] [-P string]\n");
1338 printf (" [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>] [-A string]\n");
1339 printf (" [-k string] [-S] [-C <age>] [-T <content-type>]\n");
1340 }