Code

Fix short help using "warn" for the -f option instead of "warning" (onredirect).
[nagiosplug.git] / plugins / check_http.c
index 0746741c186d774837f3ec83c76896e619802696..0a4b12bb9a413ead9c58d0d74a3c7159cb0eac25 100644 (file)
@@ -5,8 +5,6 @@
 * License: GPL
 * Copyright (c) 1999-2008 Nagios Plugins Development Team
 * 
 * License: GPL
 * Copyright (c) 1999-2008 Nagios Plugins Development Team
 * 
-* Last Modified: $Date$
-* 
 * Description:
 * 
 * This file contains the check_http plugin
 * Description:
 * 
 * This file contains the check_http plugin
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
-* $Id$
 * 
 *****************************************************************************/
 
 /* splint -I. -I../../plugins -I../../lib/ -I/usr/kerberos/include/ ../../plugins/check_http.c */
 
 const char *progname = "check_http";
 * 
 *****************************************************************************/
 
 /* splint -I. -I../../plugins -I../../lib/ -I/usr/kerberos/include/ ../../plugins/check_http.c */
 
 const char *progname = "check_http";
-const char *revision = "$Revision$";
 const char *copyright = "1999-2008";
 const char *email = "nagiosplug-devel@lists.sourceforge.net";
 
 const char *copyright = "1999-2008";
 const char *email = "nagiosplug-devel@lists.sourceforge.net";
 
@@ -48,6 +44,9 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net";
 #include <ctype.h>
 
 #define INPUT_DELIMITER ";"
 #include <ctype.h>
 
 #define INPUT_DELIMITER ";"
+#define STICKY_NONE 0
+#define STICKY_HOST 1
+#define STICKY_PORT 2
 
 #define HTTP_EXPECT "HTTP/1."
 enum {
 
 #define HTTP_EXPECT "HTTP/1."
 enum {
@@ -106,10 +105,12 @@ int check_warning_time = FALSE;
 double critical_time = 0;
 int check_critical_time = FALSE;
 char user_auth[MAX_INPUT_BUFFER] = "";
 double critical_time = 0;
 int check_critical_time = FALSE;
 char user_auth[MAX_INPUT_BUFFER] = "";
+char proxy_auth[MAX_INPUT_BUFFER] = "";
 int display_html = FALSE;
 char **http_opt_headers;
 int http_opt_headers_count = 0;
 int onredirect = STATE_OK;
 int display_html = FALSE;
 char **http_opt_headers;
 int http_opt_headers_count = 0;
 int onredirect = STATE_OK;
+int followsticky = STICKY_NONE;
 int use_ssl = FALSE;
 int verbose = FALSE;
 int sd;
 int use_ssl = FALSE;
 int verbose = FALSE;
 int sd;
@@ -137,24 +138,24 @@ main (int argc, char **argv)
 {
   int result = STATE_UNKNOWN;
 
 {
   int result = STATE_UNKNOWN;
 
-       setlocale (LC_ALL, "");
-       bindtextdomain (PACKAGE, LOCALEDIR);
-       textdomain (PACKAGE);
+  setlocale (LC_ALL, "");
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
 
   /* Set default URL. Must be malloced for subsequent realloc if --onredirect=follow */
   server_url = strdup(HTTP_URL);
   server_url_length = strlen(server_url);
 
   /* Set default URL. Must be malloced for subsequent realloc if --onredirect=follow */
   server_url = strdup(HTTP_URL);
   server_url_length = strlen(server_url);
-  asprintf (&user_agent, "User-Agent: check_http/%s (nagios-plugins %s)",
-            clean_revstring (revision), VERSION);
+  asprintf (&user_agent, "User-Agent: check_http/v%s (nagios-plugins %s)",
+            NP_VERSION, VERSION);
 
 
-       /* Parse extra opts if any */
-       argv=np_extra_opts (&argc, argv, progname);
+  /* Parse extra opts if any */
+  argv=np_extra_opts (&argc, argv, progname);
 
   if (process_arguments (argc, argv) == ERROR)
     usage4 (_("Could not parse arguments"));
 
   if (display_html == TRUE)
 
   if (process_arguments (argc, argv) == ERROR)
     usage4 (_("Could not parse arguments"));
 
   if (display_html == TRUE)
-    printf ("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">", 
+    printf ("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">",
       use_ssl ? "https" : "http", host_name ? host_name : server_address,
       server_port, server_url);
 
       use_ssl ? "https" : "http", host_name ? host_name : server_address,
       server_port, server_url);
 
@@ -192,6 +193,7 @@ process_arguments (int argc, char **argv)
     {"url", required_argument, 0, 'u'},
     {"port", required_argument, 0, 'p'},
     {"authorization", required_argument, 0, 'a'},
     {"url", required_argument, 0, 'u'},
     {"port", required_argument, 0, 'p'},
     {"authorization", required_argument, 0, 'a'},
+    {"proxy_authorization", required_argument, 0, 'b'},
     {"string", required_argument, 0, 's'},
     {"expect", required_argument, 0, 'e'},
     {"regex", required_argument, 0, 'r'},
     {"string", required_argument, 0, 's'},
     {"expect", required_argument, 0, 'e'},
     {"regex", required_argument, 0, 'r'},
@@ -229,7 +231,7 @@ process_arguments (int argc, char **argv)
   }
 
   while (1) {
   }
 
   while (1) {
-    c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:e:p:s:R:r:u:f:C:nlLSm:M:N", longopts, &option);
+    c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:e:p:s:R:r:u:f:C:nlLSm:M:N", longopts, &option);
     if (c == -1 || c == EOF)
       break;
 
     if (c == -1 || c == EOF)
       break;
 
@@ -242,7 +244,7 @@ process_arguments (int argc, char **argv)
       exit (STATE_OK);
       break;
     case 'V': /* version */
       exit (STATE_OK);
       break;
     case 'V': /* version */
-      print_revision (progname, revision);
+      print_revision (progname, NP_VERSION);
       exit (STATE_OK);
       break;
     case 't': /* timeout period */
       exit (STATE_OK);
       break;
     case 't': /* timeout period */
@@ -303,18 +305,23 @@ process_arguments (int argc, char **argv)
         server_port = HTTPS_PORT;
       break;
     case 'f': /* onredirect */
         server_port = HTTPS_PORT;
       break;
     case 'f': /* onredirect */
-      if (!strcmp (optarg, "follow"))
-        onredirect = STATE_DEPENDENT;
-      if (!strcmp (optarg, "unknown"))
+      if (!strcmp (optarg, "stickyport"))
+        onredirect = STATE_DEPENDENT, followsticky = STICKY_HOST|STICKY_PORT;
+      else if (!strcmp (optarg, "sticky"))
+        onredirect = STATE_DEPENDENT, followsticky = STICKY_HOST;
+      else if (!strcmp (optarg, "follow"))
+        onredirect = STATE_DEPENDENT, followsticky = STICKY_NONE;
+      else if (!strcmp (optarg, "unknown"))
         onredirect = STATE_UNKNOWN;
         onredirect = STATE_UNKNOWN;
-      if (!strcmp (optarg, "ok"))
+      else if (!strcmp (optarg, "ok"))
         onredirect = STATE_OK;
         onredirect = STATE_OK;
-      if (!strcmp (optarg, "warning"))
+      else if (!strcmp (optarg, "warning"))
         onredirect = STATE_WARNING;
         onredirect = STATE_WARNING;
-      if (!strcmp (optarg, "critical"))
+      else if (!strcmp (optarg, "critical"))
         onredirect = STATE_CRITICAL;
         onredirect = STATE_CRITICAL;
+      else usage2 (_("Invalid onredirect option"), optarg);
       if (verbose)
       if (verbose)
-        printf(_("option f:%d \n"), onredirect);  
+        printf(_("option f:%d \n"), onredirect);
       break;
     /* Note: H, I, and u must be malloc'd or will fail on redirects */
     case 'H': /* Host Name (virtual host) */
       break;
     /* Note: H, I, and u must be malloc'd or will fail on redirects */
     case 'H': /* Host Name (virtual host) */
@@ -345,6 +352,10 @@ process_arguments (int argc, char **argv)
       strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1);
       user_auth[MAX_INPUT_BUFFER - 1] = 0;
       break;
       strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1);
       user_auth[MAX_INPUT_BUFFER - 1] = 0;
       break;
+    case 'b': /* proxy-authorization info */
+      strncpy (proxy_auth, optarg, MAX_INPUT_BUFFER - 1);
+      proxy_auth[MAX_INPUT_BUFFER - 1] = 0;
+      break;
     case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */
       if (! http_post_data)
         http_post_data = strdup (optarg);
     case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */
       if (! http_post_data)
         http_post_data = strdup (optarg);
@@ -417,7 +428,7 @@ process_arguments (int argc, char **argv)
           exit (STATE_WARNING);
         } else
           max_page_len = atoi(tmp);
           exit (STATE_WARNING);
         } else
           max_page_len = atoi(tmp);
-      } else 
+      } else
         min_page_len = atoi (optarg);
       break;
       }
         min_page_len = atoi (optarg);
       break;
       }
@@ -556,7 +567,7 @@ parse_time_string (const char *string)
     if (tm.tm_mon < 0 || tm.tm_mday < 1 || tm.tm_mday > 31)
       return 0;
 
     if (tm.tm_mon < 0 || tm.tm_mday < 1 || tm.tm_mday > 31)
       return 0;
 
-    /* 
+    /*
     This is actually wrong: we need to subtract the local timezone
     offset from GMT from this value.  But, that's ok in this usage,
     because we only comparing these two GMT dates against each other,
     This is actually wrong: we need to subtract the local timezone
     offset from GMT from this value.  But, that's ok in this usage,
     because we only comparing these two GMT dates against each other,
@@ -600,12 +611,13 @@ expected_statuscode (const char *reply, const char *statuscodes)
   return result;
 }
 
   return result;
 }
 
-static void
-check_document_dates (const char *headers)
+static int
+check_document_dates (const char *headers, char **msg)
 {
   const char *s;
   char *server_date = 0;
   char *document_date = 0;
 {
   const char *s;
   char *server_date = 0;
   char *document_date = 0;
+  int date_result = STATE_OK;
 
   s = headers;
   while (*s) {
 
   s = headers;
   while (*s) {
@@ -659,34 +671,38 @@ check_document_dates (const char *headers)
 
   /* Done parsing the body.  Now check the dates we (hopefully) parsed.  */
   if (!server_date || !*server_date) {
 
   /* Done parsing the body.  Now check the dates we (hopefully) parsed.  */
   if (!server_date || !*server_date) {
-    die (STATE_UNKNOWN, _("HTTP UNKNOWN - Server date unknown\n"));
+    asprintf (msg, _("%sServer date unknown, "), *msg);
+    date_result = max_state_alt(STATE_UNKNOWN, date_result);
   } else if (!document_date || !*document_date) {
   } else if (!document_date || !*document_date) {
-    die (STATE_CRITICAL, _("HTTP CRITICAL - Document modification date unknown\n"));
+    asprintf (msg, _("%sDocument modification date unknown, "), *msg);
+    date_result = max_state_alt(STATE_CRITICAL, date_result);
   } else {
     time_t srv_data = parse_time_string (server_date);
     time_t doc_data = parse_time_string (document_date);
 
     if (srv_data <= 0) {
   } else {
     time_t srv_data = parse_time_string (server_date);
     time_t doc_data = parse_time_string (document_date);
 
     if (srv_data <= 0) {
-      die (STATE_CRITICAL, _("HTTP CRITICAL - Server date \"%100s\" unparsable"), server_date);
+      asprintf (msg, _("%sServer date \"%100s\" unparsable, "), *msg, server_date);
+      date_result = max_state_alt(STATE_CRITICAL, date_result);
     } else if (doc_data <= 0) {
     } else if (doc_data <= 0) {
-      die (STATE_CRITICAL, _("HTTP CRITICAL - Document date \"%100s\" unparsable"), document_date);
+      asprintf (msg, _("%sDocument date \"%100s\" unparsable, "), *msg, document_date);
+      date_result = max_state_alt(STATE_CRITICAL, date_result);
     } else if (doc_data > srv_data + 30) {
     } else if (doc_data > srv_data + 30) {
-      die (STATE_CRITICAL, _("HTTP CRITICAL - Document is %d seconds in the future\n"), (int)doc_data - (int)srv_data);
+      asprintf (msg, _("%sDocument is %d seconds in the future, "), *msg, (int)doc_data - (int)srv_data);
+      date_result = max_state_alt(STATE_CRITICAL, date_result);
     } else if (doc_data < srv_data - maximum_age) {
     } else if (doc_data < srv_data - maximum_age) {
-    int n = (srv_data - doc_data);
-    if (n > (60 * 60 * 24 * 2))
-      die (STATE_CRITICAL,
-        _("HTTP CRITICAL - Last modified %.1f days ago\n"),
-        ((float) n) / (60 * 60 * 24));
-  else
-    die (STATE_CRITICAL,
-        _("HTTP CRITICAL - Last modified %d:%02d:%02d ago\n"),
-        n / (60 * 60), (n / 60) % 60, n % 60);
+      int n = (srv_data - doc_data);
+      if (n > (60 * 60 * 24 * 2)) {
+        asprintf (msg, _("%sLast modified %.1f days ago, "), *msg, ((float) n) / (60 * 60 * 24));
+        date_result = max_state_alt(STATE_CRITICAL, date_result);
+      } else {
+        asprintf (msg, _("%sLast modified %d:%02d:%02d ago, "), *msg, n / (60 * 60), (n / 60) % 60, n % 60);
+        date_result = max_state_alt(STATE_CRITICAL, date_result);
+      }
     }
     }
-
     free (server_date);
     free (document_date);
   }
     free (server_date);
     free (document_date);
   }
+  return date_result;
 }
 
 int
 }
 
 int
@@ -773,14 +789,14 @@ check_http (void)
   long microsec;
   double elapsed_time;
   int page_len = 0;
   long microsec;
   double elapsed_time;
   int page_len = 0;
-  int result = STATE_UNKNOWN;
+  int result = STATE_OK;
 
   /* try to connect to the host at the given port number */
   if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK)
     die (STATE_CRITICAL, _("HTTP CRITICAL - Unable to open TCP socket\n"));
 #ifdef HAVE_SSL
   if (use_ssl == TRUE) {
 
   /* try to connect to the host at the given port number */
   if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK)
     die (STATE_CRITICAL, _("HTTP CRITICAL - Unable to open TCP socket\n"));
 #ifdef HAVE_SSL
   if (use_ssl == TRUE) {
-    np_net_ssl_init(sd);
+    np_net_ssl_init_with_hostname(sd, host_name);
     if (check_cert == TRUE) {
       result = np_net_ssl_check_cert(days_till_exp);
       np_net_ssl_cleanup();
     if (check_cert == TRUE) {
       result = np_net_ssl_check_cert(days_till_exp);
       np_net_ssl_cleanup();
@@ -790,7 +806,7 @@ check_http (void)
   }
 #endif /* HAVE_SSL */
 
   }
 #endif /* HAVE_SSL */
 
-  asprintf (&buf, "%s %s HTTP/1.0\r\n%s\r\n", http_method, server_url, user_agent);
+  asprintf (&buf, "%s %s %s\r\n%s\r\n", http_method, server_url, host_name ? "HTTP/1.1" : "HTTP/1.0", user_agent);
 
   /* tell HTTP/1.1 servers not to keep the connection alive */
   asprintf (&buf, "%sConnection: close\r\n", buf);
 
   /* tell HTTP/1.1 servers not to keep the connection alive */
   asprintf (&buf, "%sConnection: close\r\n", buf);
@@ -826,6 +842,12 @@ check_http (void)
     asprintf (&buf, "%sAuthorization: Basic %s\r\n", buf, auth);
   }
 
     asprintf (&buf, "%sAuthorization: Basic %s\r\n", buf, auth);
   }
 
+  /* optionally send the proxy authentication info */
+  if (strlen(proxy_auth)) {
+    base64_encode_alloc (proxy_auth, strlen (proxy_auth), &auth);
+    asprintf (&buf, "%sProxy-Authorization: Basic %s\r\n", buf, auth);
+  }
+
   /* either send http POST data (any data, not only POST)*/
   if (http_post_data) {
     if (http_content_type) {
   /* either send http POST data (any data, not only POST)*/
   if (http_post_data) {
     if (http_content_type) {
@@ -890,8 +912,9 @@ check_http (void)
 #endif
   if (sd) close(sd);
 
 #endif
   if (sd) close(sd);
 
-  /* reset the alarm */
-  alarm (0);
+  /* Save check time */
+  microsec = deltime (tv);
+  elapsed_time = (double)microsec / 1.0e6;
 
   /* leave full_page untouched so we can free it later */
   page = full_page;
 
   /* leave full_page untouched so we can free it later */
   page = full_page;
@@ -941,11 +964,11 @@ check_http (void)
     die (STATE_CRITICAL, "HTTP CRITICAL - %s", msg);
   }
 
     die (STATE_CRITICAL, "HTTP CRITICAL - %s", msg);
   }
 
-  /* Exit here if server_expect was set by user and not default */
+  /* Bypass normal status line check if server_expect was set by user and not default */
+  /* NOTE: After this if/else block msg *MUST* be an asprintf-allocated string */
   if ( server_expect_yn  )  {
     asprintf (&msg,
   if ( server_expect_yn  )  {
     asprintf (&msg,
-              _("HTTP OK: Status line output matched \"%s\"\n"),
-              server_expect);
+              _("Status line output matched \"%s\" - "), server_expect);
     if (verbose)
       printf ("%s\n",msg);
   }
     if (verbose)
       printf ("%s\n",msg);
   }
@@ -962,123 +985,110 @@ check_http (void)
 
     /* check the return code */
 
 
     /* check the return code */
 
-    if (http_status >= 600 || http_status < 100)
+    if (http_status >= 600 || http_status < 100) {
       die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%s)\n"), status_line);
       die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%s)\n"), status_line);
-
+    }
     /* server errors result in a critical state */
     /* server errors result in a critical state */
-    else if (http_status >= 500)
-      die (STATE_CRITICAL, _("HTTP CRITICAL: %s\n"), status_line);
-
+    else if (http_status >= 500) {
+      asprintf (&msg, _("%s - "), status_line);
+      result = STATE_CRITICAL;
+    }
     /* client errors result in a warning state */
     /* client errors result in a warning state */
-    else if (http_status >= 400)
-      die (STATE_WARNING, _("HTTP WARNING: %s\n"), status_line);
-
+    else if (http_status >= 400) {
+      asprintf (&msg, _("%s - "), status_line);
+      result = max_state_alt(STATE_WARNING, result);
+    }
     /* check redirected page if specified */
     else if (http_status >= 300) {
 
       if (onredirect == STATE_DEPENDENT)
         redir (header, status_line);
     /* check redirected page if specified */
     else if (http_status >= 300) {
 
       if (onredirect == STATE_DEPENDENT)
         redir (header, status_line);
-      else if (onredirect == STATE_UNKNOWN)
-        printf (_("HTTP UNKNOWN"));
-      else if (onredirect == STATE_OK)
-        printf (_("HTTP OK"));
-      else if (onredirect == STATE_WARNING)
-        printf (_("HTTP WARNING"));
-      else if (onredirect == STATE_CRITICAL)
-        printf (_("HTTP CRITICAL"));
-      microsec = deltime (tv);
-      elapsed_time = (double)microsec / 1.0e6;
-      die (onredirect,
-           _(" - %s - %.3f second response time %s|%s %s\n"),
-           status_line, elapsed_time, 
-           (display_html ? "</A>" : ""),
-           perfd_time (elapsed_time), perfd_size (pagesize));
+      else
+        result = max_state_alt(onredirect, result);
+      asprintf (&msg, _("%s - "), status_line);
     } /* end if (http_status >= 300) */
     } /* end if (http_status >= 300) */
+    else {
+      /* Print OK status anyway */
+      asprintf (&msg, _("%s - "), status_line);
+    }
 
   } /* end else (server_expect_yn)  */
 
 
   } /* end else (server_expect_yn)  */
 
-        if (maximum_age >= 0) {
-          check_document_dates (header);
-        }
+  /* reset the alarm - must be called *after* redir or we'll never die on redirects! */
+  alarm (0);
 
 
-  /* check elapsed time */
-  microsec = deltime (tv);
-  elapsed_time = (double)microsec / 1.0e6;
-  asprintf (&msg,
-            _(" - %s - %.3f second response time %s|%s %s\n"),
-            status_line, elapsed_time, 
-            (display_html ? "</A>" : ""),
-            perfd_time (elapsed_time), perfd_size (pagesize));
-  if (check_critical_time == TRUE && elapsed_time > critical_time)
-    die (STATE_CRITICAL, "HTTP %s: %s", _("CRITICAL"), msg);
-  if (check_warning_time == TRUE && elapsed_time > warning_time)
-    die (STATE_WARNING, "HTTP %s: %s", _("WARNING"), msg);
+  if (maximum_age >= 0) {
+    result = max_state_alt(check_document_dates(header, &msg), result);
+  }
 
   /* Page and Header content checks go here */
 
   /* Page and Header content checks go here */
-  /* these checks should be last */
 
   if (strlen (string_expect)) {
 
   if (strlen (string_expect)) {
-    if (strstr (page, string_expect)) {
-      printf (_("HTTP OK %s - %.3f second response time %s|%s %s\n"),
-              status_line, elapsed_time,
-              (display_html ? "</A>" : ""),
-              perfd_time (elapsed_time), perfd_size (pagesize));
-      exit (STATE_OK);
-    }
-    else {
-      printf (_("HTTP CRITICAL - string not found%s|%s %s\n"),
-              (display_html ? "</A>" : ""),
-              perfd_time (elapsed_time), perfd_size (pagesize));
-      exit (STATE_CRITICAL);
+    if (!strstr (page, string_expect)) {
+      asprintf (&msg, _("%sstring not found, "), msg);
+      result = STATE_CRITICAL;
     }
   }
 
   if (strlen (regexp)) {
     errcode = regexec (&preg, page, REGS, pmatch, 0);
     if ((errcode == 0 && invert_regex == 0) || (errcode == REG_NOMATCH && invert_regex == 1)) {
     }
   }
 
   if (strlen (regexp)) {
     errcode = regexec (&preg, page, REGS, pmatch, 0);
     if ((errcode == 0 && invert_regex == 0) || (errcode == REG_NOMATCH && invert_regex == 1)) {
-      printf (_("HTTP OK %s - %.3f second response time %s|%s %s\n"),
-              status_line, elapsed_time,
-              (display_html ? "</A>" : ""),
-              perfd_time (elapsed_time), perfd_size (pagesize));
-      exit (STATE_OK);
+      /* OK - No-op to avoid changing the logic around it */
+      result = max_state_alt(STATE_OK, result);
     }
     else if ((errcode == REG_NOMATCH && invert_regex == 0) || (errcode == 0 && invert_regex == 1)) {
     }
     else if ((errcode == REG_NOMATCH && invert_regex == 0) || (errcode == 0 && invert_regex == 1)) {
-      if (invert_regex == 0) 
-        msg = strdup(_("pattern not found"));
-      else 
-        msg = strdup(_("pattern found"));
-      printf (("%s - %s%s|%s %s\n"),
-        _("HTTP CRITICAL"),
-        msg,
-        (display_html ? "</A>" : ""),
-        perfd_time (elapsed_time), perfd_size (pagesize));
-      exit (STATE_CRITICAL);
+      if (invert_regex == 0)
+        asprintf (&msg, _("%spattern not found, "), msg);
+      else
+        asprintf (&msg, _("%spattern found, "), msg);
+      result = STATE_CRITICAL;
     }
     else {
     }
     else {
+      /* FIXME: Shouldn't that be UNKNOWN? */
       regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
       regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
-      printf (_("HTTP CRITICAL - Execute Error: %s\n"), errbuf);
-      exit (STATE_CRITICAL);
+      asprintf (&msg, _("%sExecute Error: %s, "), msg, errbuf);
+      result = STATE_CRITICAL;
     }
   }
 
   /* make sure the page is of an appropriate size */
   /* page_len = get_content_length(header); */
     }
   }
 
   /* make sure the page is of an appropriate size */
   /* page_len = get_content_length(header); */
+  /* FIXME: Will this work with -N ? IMHO we should use
+   * get_content_length(header) and always check if it's different than the
+   * returned pagesize
+   */
+  /* FIXME: IIRC pagesize returns headers - shouldn't we make
+   * it == get_content_length(header) ??
+   */
   page_len = pagesize;
   if ((max_page_len > 0) && (page_len > max_page_len)) {
   page_len = pagesize;
   if ((max_page_len > 0) && (page_len > max_page_len)) {
-    printf (_("HTTP WARNING: page size %d too large%s|%s\n"),
-      page_len, (display_html ? "</A>" : ""), perfd_size (page_len) );
-    exit (STATE_WARNING);
+    asprintf (&msg, _("%spage size %d too large, "), msg, page_len);
+    result = max_state_alt(STATE_WARNING, result);
   } else if ((min_page_len > 0) && (page_len < min_page_len)) {
   } else if ((min_page_len > 0) && (page_len < min_page_len)) {
-    printf (_("HTTP WARNING: page size %d too small%s|%s\n"),
-      page_len, (display_html ? "</A>" : ""), perfd_size (page_len) );
-    exit (STATE_WARNING);
+    asprintf (&msg, _("%spage size %d too small, "), msg, page_len);
+    result = max_state_alt(STATE_WARNING, result);
   }
   }
-  /* We only get here if all tests have been passed */
-  asprintf (&msg, _("HTTP OK %s - %d bytes in %.3f seconds %s|%s %s\n"),
-            status_line, page_len, elapsed_time,
+
+  /* Cut-off trailing characters */
+  if(msg[strlen(msg)-2] == ',')
+    msg[strlen(msg)-2] = '\0';
+  else
+    msg[strlen(msg)-3] = '\0';
+
+  /* check elapsed time */
+  asprintf (&msg,
+            _("%s - %d bytes in %.3f second response time %s|%s %s"),
+            msg, page_len, elapsed_time,
             (display_html ? "</A>" : ""),
             perfd_time (elapsed_time), perfd_size (page_len));
             (display_html ? "</A>" : ""),
             perfd_time (elapsed_time), perfd_size (page_len));
-  die (STATE_OK, "%s", msg);
+
+  if (check_critical_time == TRUE && elapsed_time > critical_time)
+    result = STATE_CRITICAL;
+  if (check_warning_time == TRUE && elapsed_time > warning_time)
+    result =  max_state_alt(STATE_WARNING, result);
+
+  die (result, "HTTP %s: %s\n", state_text(result), msg);
+  /* die failed? */
   return STATE_UNKNOWN;
 }
 
   return STATE_UNKNOWN;
 }
 
@@ -1111,14 +1121,14 @@ redir (char *pos, char *status_line)
 
   url = malloc (strcspn (pos, "\r\n"));
   if (url == NULL)
 
   url = malloc (strcspn (pos, "\r\n"));
   if (url == NULL)
-    die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate url\n"));
+    die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n"));
 
   while (pos) {
     sscanf (pos, "%1[Ll]%*1[Oo]%*1[Cc]%*1[Aa]%*1[Tt]%*1[Ii]%*1[Oo]%*1[Nn]:%n", xx, &i);
     if (i == 0) {
       pos += (size_t) strcspn (pos, "\r\n");
       pos += (size_t) strspn (pos, "\r\n");
 
   while (pos) {
     sscanf (pos, "%1[Ll]%*1[Oo]%*1[Cc]%*1[Aa]%*1[Tt]%*1[Ii]%*1[Oo]%*1[Nn]:%n", xx, &i);
     if (i == 0) {
       pos += (size_t) strcspn (pos, "\r\n");
       pos += (size_t) strspn (pos, "\r\n");
-      if (strlen(pos) == 0) 
+      if (strlen(pos) == 0)
         die (STATE_UNKNOWN,
              _("HTTP UNKNOWN - Could not find redirect location - %s%s\n"),
              status_line, (display_html ? "</A>" : ""));
         die (STATE_UNKNOWN,
              _("HTTP UNKNOWN - Could not find redirect location - %s%s\n"),
              status_line, (display_html ? "</A>" : ""));
@@ -1142,7 +1152,7 @@ redir (char *pos, char *status_line)
 
     url = realloc (url, strcspn (pos, "\r\n") + 1);
     if (url == NULL)
 
     url = realloc (url, strcspn (pos, "\r\n") + 1);
     if (url == NULL)
-      die (STATE_UNKNOWN, _("HTTP UNKNOWN - could not allocate url\n"));
+      die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n"));
 
     /* URI_HTTP, URI_HOST, URI_PORT, URI_PATH */
     if (sscanf (pos, HD1, type, addr, &i, url) == 4) {
 
     /* URI_HTTP, URI_HOST, URI_PORT, URI_PATH */
     if (sscanf (pos, HD1, type, addr, &i, url) == 4) {
@@ -1151,7 +1161,7 @@ redir (char *pos, char *status_line)
     }
 
     /* URI_HTTP URI_HOST URI_PATH */
     }
 
     /* URI_HTTP URI_HOST URI_PATH */
-    else if (sscanf (pos, HD2, type, addr, url) == 3 ) { 
+    else if (sscanf (pos, HD2, type, addr, url) == 3 ) {
       url = prepend_slash (url);
       use_ssl = server_type_check (type);
       i = server_port_check (use_ssl);
       url = prepend_slash (url);
       use_ssl = server_type_check (type);
       i = server_port_check (use_ssl);
@@ -1181,7 +1191,7 @@ redir (char *pos, char *status_line)
       i = server_port;
       strcpy (type, server_type);
       strcpy (addr, host_name ? host_name : server_address);
       i = server_port;
       strcpy (type, server_type);
       strcpy (addr, host_name ? host_name : server_address);
-    }           
+    }
 
     else {
       die (STATE_UNKNOWN,
 
     else {
       die (STATE_UNKNOWN,
@@ -1211,13 +1221,18 @@ redir (char *pos, char *status_line)
   free (host_name);
   host_name = strdup (addr);
 
   free (host_name);
   host_name = strdup (addr);
 
-  free (server_address);
-  server_address = strdup (addr);
+  if (!(followsticky & STICKY_HOST)) {
+    free (server_address);
+    server_address = strdup (addr);
+  }
+  if (!(followsticky & STICKY_PORT)) {
+    server_port = i;
+  }
 
   free (server_url);
   server_url = url;
 
 
   free (server_url);
   server_url = url;
 
-  if ((server_port = i) > MAX_PORT)
+  if (server_port > MAX_PORT)
     die (STATE_UNKNOWN,
          _("HTTP UNKNOWN - Redirection to port above %d - %s://%s:%d%s%s\n"),
          MAX_PORT, server_type, server_address, server_port, server_url,
     die (STATE_UNKNOWN,
          _("HTTP UNKNOWN - Redirection to port above %d - %s://%s:%d%s%s\n"),
          MAX_PORT, server_type, server_address, server_port, server_url,
@@ -1231,7 +1246,6 @@ redir (char *pos, char *status_line)
 }
 
 
 }
 
 
-
 int
 server_type_check (const char *type)
 {
 int
 server_type_check (const char *type)
 {
@@ -1271,7 +1285,7 @@ char *perfd_size (int page_len)
 void
 print_help (void)
 {
 void
 print_help (void)
 {
-  print_revision (progname, revision);
+  print_revision (progname, NP_VERSION);
 
   printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
   printf (COPYRIGHT, copyright, email);
 
   printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
   printf (COPYRIGHT, copyright, email);
@@ -1298,7 +1312,7 @@ print_help (void)
   printf (" %s\n", "-I, --IP-address=ADDRESS");
   printf ("    %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup)."));
   printf (" %s\n", "-p, --port=INTEGER");
   printf (" %s\n", "-I, --IP-address=ADDRESS");
   printf ("    %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup)."));
   printf (" %s\n", "-p, --port=INTEGER");
-  printf (" %s", _("Port number (default: "));
+  printf ("    %s", _("Port number (default: "));
   printf ("%d)\n", HTTP_PORT);
 
   printf (_(UT_IPv46));
   printf ("%d)\n", HTTP_PORT);
 
   printf (_(UT_IPv46));
@@ -1308,7 +1322,7 @@ print_help (void)
   printf ("   %s\n", _("Connect via SSL. Port defaults to 443"));
   printf (" %s\n", "-C, --certificate=INTEGER");
   printf ("   %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443"));
   printf ("   %s\n", _("Connect via SSL. Port defaults to 443"));
   printf (" %s\n", "-C, --certificate=INTEGER");
   printf ("   %s\n", _("Minimum number of days a certificate has to be valid. Port defaults to 443"));
-  printf ("   %s\n", _("(when this option is used the url is not checked.)\n"));
+  printf ("   %s\n", _("(when this option is used the URL is not checked.)\n"));
 #endif
 
   printf (" %s\n", "-e, --expect=STRING");
 #endif
 
   printf (" %s\n", "-e, --expect=STRING");
@@ -1344,14 +1358,17 @@ print_help (void)
 
   printf (" %s\n", "-a, --authorization=AUTH_PAIR");
   printf ("    %s\n", _("Username:password on sites with basic authentication"));
 
   printf (" %s\n", "-a, --authorization=AUTH_PAIR");
   printf ("    %s\n", _("Username:password on sites with basic authentication"));
+  printf (" %s\n", "-b, --proxy-authorization=AUTH_PAIR");
+  printf ("    %s\n", _("Username:password on proxy-servers with basic authentication"));
   printf (" %s\n", "-A, --useragent=STRING");
   printf ("    %s\n", _("String to be sent in http header as \"User Agent\""));
   printf (" %s\n", "-k, --header=STRING");
   printf ("    %s\n", _(" Any other tags to be sent in http header. Use multiple times for additional headers"));
   printf (" %s\n", "-L, --link");
   printf ("    %s\n", _("Wrap output in HTML link (obsoleted by urlize)"));
   printf (" %s\n", "-A, --useragent=STRING");
   printf ("    %s\n", _("String to be sent in http header as \"User Agent\""));
   printf (" %s\n", "-k, --header=STRING");
   printf ("    %s\n", _(" Any other tags to be sent in http header. Use multiple times for additional headers"));
   printf (" %s\n", "-L, --link");
   printf ("    %s\n", _("Wrap output in HTML link (obsoleted by urlize)"));
-  printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow>");
-  printf ("    %s\n", _("How to handle redirected pages"));
+  printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport>");
+  printf ("    %s\n", _("How to handle redirected pages. sticky is like follow but stick to the"));
+  printf ("    %s\n", _("specified IP address. stickyport also ensure post stays the same."));
   printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>");
   printf ("    %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)"));
 
   printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>");
   printf ("    %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)"));
 
@@ -1403,9 +1420,9 @@ print_usage (void)
 {
   printf (_("Usage:"));
   printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname);
 {
   printf (_("Usage:"));
   printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname);
-  printf ("       [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L]\n");
-  printf ("       [-a auth] [-f <ok | warn | critcal | follow>] [-e <expect>]\n");
-  printf ("       [-s string] [-l] [-r <regex> | -R <case-insensitive regex>] [-P string]\n");
-  printf ("       [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>] [-A string]\n");
-  printf ("       [-k string] [-S] [-C <age>] [-T <content-type>] [-j method]\n");
+  printf ("       [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-a auth]\n");
+  printf ("       [-b proxy_auth] [-f <ok|warning|critcal|follow|sticky|stickyport>]\n");
+  printf ("       [-e <expect>] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n");
+  printf ("       [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n");
+  printf ("       [-A string] [-k string] [-S] [-C <age>] [-T <content-type>] [-j method]\n");
 }
 }