Back to index

nagios-plugins  1.4.16
Defines | Enumerations | Functions | Variables
check_http.c File Reference
#include "common.h"
#include "netutils.h"
#include "utils.h"
#include "base64.h"
#include <ctype.h>
#include "regex.h"

Go to the source code of this file.

Defines

#define INPUT_DELIMITER   ";"
#define STICKY_NONE   0
#define STICKY_HOST   1
#define STICKY_PORT   2
#define HTTP_EXPECT   "HTTP/1."
#define my_recv(buf, len)   read(sd, buf, len)
#define my_send(buf, len)   send(sd, buf, len, 0)
#define HTTP_URL   "/"
#define CRLF   "\r\n"
#define URI_HTTP   "%5[HTPShtps]"
#define URI_HOST   "%255[-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
#define URI_PORT   "%6d" /* MAX_PORT's width is 5 chars, 6 to detect overflow */
#define URI_PATH   "%[-_.!~*'();/?:@&=+$,%#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"
#define HD1   URI_HTTP "://" URI_HOST ":" URI_PORT "/" URI_PATH
#define HD2   URI_HTTP "://" URI_HOST "/" URI_PATH
#define HD3   URI_HTTP "://" URI_HOST ":" URI_PORT
#define HD4   URI_HTTP "://" URI_HOST
#define HD5   URI_PATH

Enumerations

enum  { MAX_IPV4_HOSTLENGTH = 255, HTTP_PORT = 80, HTTPS_PORT = 443, MAX_PORT = 65535 }
enum  { REGS = 2, MAX_RE_SIZE = 256 }

Functions

int process_arguments (int, char **)
int check_http (void)
void redir (char *pos, char *status_line)
int server_type_check (const char *type)
int server_port_check (int ssl_flag)
char * perfd_time (double microsec)
char * perfd_size (int page_len)
void print_help (void)
void print_usage (void)
int main (int argc, char **argv)
static int document_headers_done (char *full_page)
static time_t parse_time_string (const char *string)
static int expected_statuscode (const char *reply, const char *statuscodes)
static int check_document_dates (const char *headers, char **msg)
int get_content_length (const char *headers)
char * prepend_slash (char *path)

Variables

const char * progname = "check_http"
const char * copyright = "1999-2011"
const char * email = "nagiosplug-devel@lists.sourceforge.net"
int no_body = FALSE
int maximum_age = -1
regex_t preg
regmatch_t pmatch [REGS]
char regexp [MAX_RE_SIZE]
char errbuf [MAX_INPUT_BUFFER]
int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE
int errcode
int invert_regex = 0
int specify_port = FALSE
int server_port = HTTP_PORT
char server_port_text [6] = ""
char server_type [6] = "http"
char * server_address
char * host_name
char * server_url
char * user_agent
int server_url_length
int server_expect_yn = 0
char server_expect [MAX_INPUT_BUFFER] = HTTP_EXPECT
char string_expect [MAX_INPUT_BUFFER] = ""
char output_string_search [30] = ""
char * warning_thresholds = NULL
char * critical_thresholds = NULL
thresholdsthlds
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 followsticky = STICKY_NONE
int use_ssl = FALSE
int use_sni = FALSE
int verbose = FALSE
int sd
int min_page_len = 0
int max_page_len = 0
int redir_depth = 0
int max_depth = 15
char * http_method
char * http_post_data
char * http_content_type
char buffer [MAX_INPUT_BUFFER]

Define Documentation

#define CRLF   "\r\n"

Definition at line 90 of file check_http.c.

#define HD1   URI_HTTP "://" URI_HOST ":" URI_PORT "/" URI_PATH

Definition at line 1130 of file check_http.c.

#define HD2   URI_HTTP "://" URI_HOST "/" URI_PATH

Definition at line 1131 of file check_http.c.

#define HD3   URI_HTTP "://" URI_HOST ":" URI_PORT

Definition at line 1132 of file check_http.c.

#define HD4   URI_HTTP "://" URI_HOST

Definition at line 1133 of file check_http.c.

#define HD5   URI_PATH

Definition at line 1134 of file check_http.c.

#define HTTP_EXPECT   "HTTP/1."

Definition at line 51 of file check_http.c.

#define HTTP_URL   "/"

Definition at line 89 of file check_http.c.

#define INPUT_DELIMITER   ";"

Definition at line 46 of file check_http.c.

#define my_recv (   buf,
  len 
)    read(sd, buf, len)

Definition at line 68 of file check_http.c.

#define my_send (   buf,
  len 
)    send(sd, buf, len, 0)

Definition at line 69 of file check_http.c.

#define STICKY_HOST   1

Definition at line 48 of file check_http.c.

#define STICKY_NONE   0

Definition at line 47 of file check_http.c.

#define STICKY_PORT   2

Definition at line 49 of file check_http.c.

#define URI_HOST   "%255[-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"

Definition at line 1127 of file check_http.c.

#define URI_HTTP   "%5[HTPShtps]"

Definition at line 1126 of file check_http.c.

#define URI_PATH   "%[-_.!~*'();/?:@&=+$,%#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]"

Definition at line 1129 of file check_http.c.

#define URI_PORT   "%6d" /* MAX_PORT's width is 5 chars, 6 to detect overflow */

Definition at line 1128 of file check_http.c.


Enumeration Type Documentation

anonymous enum
Enumerator:
MAX_IPV4_HOSTLENGTH 
HTTP_PORT 
HTTPS_PORT 
MAX_PORT 

Definition at line 52 of file check_http.c.

     {
  MAX_IPV4_HOSTLENGTH = 255,
  HTTP_PORT = 80,
  HTTPS_PORT = 443,
  MAX_PORT = 65535
};
anonymous enum
Enumerator:
REGS 
MAX_RE_SIZE 

Definition at line 74 of file check_http.c.

     {
  REGS = 2,
  MAX_RE_SIZE = 256
};

Function Documentation

static int check_document_dates ( const char *  headers,
char **  msg 
) [static]

Definition at line 634 of file check_http.c.

{
  const char *s;
  char *server_date = 0;
  char *document_date = 0;
  int date_result = STATE_OK;

  s = headers;
  while (*s) {
    const char *field = s;
    const char *value = 0;

    /* Find the end of the header field */
    while (*s && !isspace(*s) && *s != ':')
      s++;

    /* Remember the header value, if any. */
    if (*s == ':')
      value = ++s;

    /* Skip to the end of the header, including continuation lines. */
    while (*s && !(*s == '\n' && (s[1] != ' ' && s[1] != '\t')))
      s++;

    /* Avoid stepping over end-of-string marker */
    if (*s)
      s++;

    /* Process this header. */
    if (value && value > field+2) {
      char *ff = (char *) malloc (value-field);
      char *ss = ff;
      while (field < value-1)
        *ss++ = tolower(*field++);
      *ss++ = 0;

      if (!strcmp (ff, "date") || !strcmp (ff, "last-modified")) {
        const char *e;
        while (*value && isspace (*value))
          value++;
        for (e = value; *e && *e != '\r' && *e != '\n'; e++)
          ;
        ss = (char *) malloc (e - value + 1);
        strncpy (ss, value, e - value);
        ss[e - value] = 0;
        if (!strcmp (ff, "date")) {
          if (server_date) free (server_date);
          server_date = ss;
        } else {
          if (document_date) free (document_date);
          document_date = ss;
        }
      }
      free (ff);
    }
  }

  /* Done parsing the body.  Now check the dates we (hopefully) parsed.  */
  if (!server_date || !*server_date) {
    asprintf (msg, _("%sServer date unknown, "), *msg);
    date_result = max_state_alt(STATE_UNKNOWN, date_result);
  } else if (!document_date || !*document_date) {
    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) {
      asprintf (msg, _("%sServer date \"%100s\" unparsable, "), *msg, server_date);
      date_result = max_state_alt(STATE_CRITICAL, date_result);
    } else if (doc_data <= 0) {
      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) {
      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) {
      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);
  }
  return date_result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int check_http ( void  )

Definition at line 797 of file check_http.c.

{
  char *msg;
  char *status_line;
  char *status_code;
  char *header;
  char *page;
  char *auth;
  int http_status;
  int i = 0;
  size_t pagesize = 0;
  char *full_page;
  char *full_page_new;
  char *buf;
  char *pos;
  long microsec;
  double elapsed_time;
  int page_len = 0;
  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) {
    result = np_net_ssl_init_with_hostname_and_version(sd, (use_sni ? host_name : NULL), ssl_version);
    if (result != STATE_OK)
      return result;
    if (check_cert == TRUE) {
      result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit);
      np_net_ssl_cleanup();
      if (sd) close(sd);
      return result;
    }
  }
#endif /* HAVE_SSL */

  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);

  /* optionally send the host header info */
  if (host_name) {
    /*
     * Specify the port only if we're using a non-default port (see RFC 2616,
     * 14.23).  Some server applications/configurations cause trouble if the
     * (default) port is explicitly specified in the "Host:" header line.
     */
    if ((use_ssl == FALSE && server_port == HTTP_PORT) ||
        (use_ssl == TRUE && server_port == HTTPS_PORT))
      asprintf (&buf, "%sHost: %s\r\n", buf, host_name);
    else
      asprintf (&buf, "%sHost: %s:%d\r\n", buf, host_name, server_port);
  }

  /* optionally send any other header tag */
  if (http_opt_headers_count) {
    for (i = 0; i < http_opt_headers_count ; i++) {
      for ((pos = strtok(http_opt_headers[i], INPUT_DELIMITER)); pos; (pos = strtok(NULL, INPUT_DELIMITER)))
        asprintf (&buf, "%s%s\r\n", buf, pos);
    }
    /* This cannot be free'd here because a redirection will then try to access this and segfault */
    /* Covered in a testcase in tests/check_http.t */
    /* free(http_opt_headers); */
  }

  /* optionally send the authentication info */
  if (strlen(user_auth)) {
    base64_encode_alloc (user_auth, strlen (user_auth), &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) {
      asprintf (&buf, "%sContent-Type: %s\r\n", buf, http_content_type);
    } else {
      asprintf (&buf, "%sContent-Type: application/x-www-form-urlencoded\r\n", buf);
    }

    asprintf (&buf, "%sContent-Length: %i\r\n\r\n", buf, (int)strlen (http_post_data));
    asprintf (&buf, "%s%s%s", buf, http_post_data, CRLF);
  }
  else {
    /* or just a newline so the server knows we're done with the request */
    asprintf (&buf, "%s%s", buf, CRLF);
  }

  if (verbose) printf ("%s\n", buf);
  my_send (buf, strlen (buf));

  /* fetch the page */
  full_page = strdup("");
  while ((i = my_recv (buffer, MAX_INPUT_BUFFER-1)) > 0) {
    buffer[i] = '\0';
    asprintf (&full_page_new, "%s%s", full_page, buffer);
    free (full_page);
    full_page = full_page_new;
    pagesize += i;

                if (no_body && document_headers_done (full_page)) {
                  i = 0;
                  break;
                }
  }

  if (i < 0 && errno != ECONNRESET) {
#ifdef HAVE_SSL
    /*
    if (use_ssl) {
      sslerr=SSL_get_error(ssl, i);
      if ( sslerr == SSL_ERROR_SSL ) {
        die (STATE_WARNING, _("HTTP WARNING - Client Certificate Required\n"));
      } else {
        die (STATE_CRITICAL, _("HTTP CRITICAL - Error on receive\n"));
      }
    }
    else {
    */
#endif
      die (STATE_CRITICAL, _("HTTP CRITICAL - Error on receive\n"));
#ifdef HAVE_SSL
      /* XXX
    }
    */
#endif
  }

  /* return a CRITICAL status if we couldn't read any data */
  if (pagesize == (size_t) 0)
    die (STATE_CRITICAL, _("HTTP CRITICAL - No data received from host\n"));

  /* close the connection */
#ifdef HAVE_SSL
  np_net_ssl_cleanup();
#endif
  if (sd) close(sd);

  /* 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;

  if (verbose)
    printf ("%s://%s:%d%s is %d characters\n",
      use_ssl ? "https" : "http", server_address,
      server_port, server_url, (int)pagesize);

  /* find status line and null-terminate it */
  status_line = page;
  page += (size_t) strcspn (page, "\r\n");
  pos = page;
  page += (size_t) strspn (page, "\r\n");
  status_line[strcspn(status_line, "\r\n")] = 0;
  strip (status_line);
  if (verbose)
    printf ("STATUS: %s\n", status_line);

  /* find header info and null-terminate it */
  header = page;
  while (strcspn (page, "\r\n") > 0) {
    page += (size_t) strcspn (page, "\r\n");
    pos = page;
    if ((strspn (page, "\r") == 1 && strspn (page, "\r\n") >= 2) ||
        (strspn (page, "\n") == 1 && strspn (page, "\r\n") >= 2))
      page += (size_t) 2;
    else
      page += (size_t) 1;
  }
  page += (size_t) strspn (page, "\r\n");
  header[pos - header] = 0;
  if (verbose)
    printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header,
                (no_body ? "  [[ skipped ]]" : page));

  /* make sure the status line matches the response we are looking for */
  if (!expected_statuscode (status_line, server_expect)) {
    if (server_port == HTTP_PORT)
      asprintf (&msg,
                _("Invalid HTTP response received from host: %s\n"),
                status_line);
    else
      asprintf (&msg,
                _("Invalid HTTP response received from host on port %d: %s\n"),
                server_port, status_line);
    die (STATE_CRITICAL, "HTTP CRITICAL - %s", msg);
  }

  /* 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,
              _("Status line output matched \"%s\" - "), server_expect);
    if (verbose)
      printf ("%s\n",msg);
  }
  else {
    /* Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF */
    /* HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT */
    /* Status-Code = 3 DIGITS */

    status_code = strchr (status_line, ' ') + sizeof (char);
    if (strspn (status_code, "1234567890") != 3)
      die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status Line (%s)\n"), status_line);

    http_status = atoi (status_code);

    /* check the return code */

    if (http_status >= 600 || http_status < 100) {
      die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%s)\n"), status_line);
    }
    /* server errors result in a critical state */
    else if (http_status >= 500) {
      asprintf (&msg, _("%s - "), status_line);
      result = STATE_CRITICAL;
    }
    /* client errors result in a warning state */
    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);
      else
        result = max_state_alt(onredirect, result);
      asprintf (&msg, _("%s - "), status_line);
    } /* end if (http_status >= 300) */
    else {
      /* Print OK status anyway */
      asprintf (&msg, _("%s - "), status_line);
    }

  } /* end else (server_expect_yn)  */

  /* reset the alarm - must be called *after* redir or we'll never die on redirects! */
  alarm (0);

  if (maximum_age >= 0) {
    result = max_state_alt(check_document_dates(header, &msg), result);
  }

  /* Page and Header content checks go here */

  if (strlen (string_expect)) {
    if (!strstr (page, string_expect)) {
      strncpy(&output_string_search[0],string_expect,sizeof(output_string_search));
      if(output_string_search[sizeof(output_string_search)-1]!='\0') {
        bcopy("...",&output_string_search[sizeof(output_string_search)-4],4);
      }
      asprintf (&msg, _("%sstring '%s' not found on '%s://%s:%d%s', "), msg, output_string_search, use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url);
      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)) {
      /* 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)) {
      if (invert_regex == 0)
        asprintf (&msg, _("%spattern not found, "), msg);
      else
        asprintf (&msg, _("%spattern found, "), msg);
      result = STATE_CRITICAL;
    }
    else {
      /* FIXME: Shouldn't that be UNKNOWN? */
      regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
      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); */
  /* 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)) {
    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)) {
    asprintf (&msg, _("%spage size %d too small, "), msg, page_len);
    result = max_state_alt(STATE_WARNING, result);
  }

  /* 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));

  result = max_state_alt(get_status(elapsed_time, thlds), result);

  die (result, "HTTP %s: %s\n", state_text(result), msg);
  /* die failed? */
  return STATE_UNKNOWN;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int document_headers_done ( char *  full_page) [static]

Definition at line 506 of file check_http.c.

{
  const char *body;

  for (body = full_page; *body; body++) {
    if (!strncmp (body, "\n\n", 2) || !strncmp (body, "\n\r\n", 3))
      break;
  }

  if (!*body)
    return 0;  /* haven't read end of headers yet */

  full_page[body - full_page] = 0;
  return 1;
}

Here is the caller graph for this function:

static int expected_statuscode ( const char *  reply,
const char *  statuscodes 
) [static]

Definition at line 615 of file check_http.c.

{
  char *expected, *code;
  int result = 0;

  if ((expected = strdup (statuscodes)) == NULL)
    die (STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n"));

  for (code = strtok (expected, ","); code != NULL; code = strtok (NULL, ","))
    if (strstr (reply, code) != NULL) {
      result = 1;
      break;
    }

  free (expected);
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int get_content_length ( const char *  headers)

Definition at line 728 of file check_http.c.

{
  const char *s;
  int content_length = 0;

  s = headers;
  while (*s) {
    const char *field = s;
    const char *value = 0;

    /* Find the end of the header field */
    while (*s && !isspace(*s) && *s != ':')
      s++;

    /* Remember the header value, if any. */
    if (*s == ':')
      value = ++s;

    /* Skip to the end of the header, including continuation lines. */
    while (*s && !(*s == '\n' && (s[1] != ' ' && s[1] != '\t')))
      s++;

    /* Avoid stepping over end-of-string marker */
    if (*s)
      s++;

    /* Process this header. */
    if (value && value > field+2) {
      char *ff = (char *) malloc (value-field);
      char *ss = ff;
      while (field < value-1)
        *ss++ = tolower(*field++);
      *ss++ = 0;

      if (!strcmp (ff, "content-length")) {
        const char *e;
        while (*value && isspace (*value))
          value++;
        for (e = value; *e && *e != '\r' && *e != '\n'; e++)
          ;
        ss = (char *) malloc (e - value + 1);
        strncpy (ss, value, e - value);
        ss[e - value] = 0;
        content_length = atoi(ss);
        free (ss);
      }
      free (ff);
    }
  }
  return (content_length);
}
int main ( int  argc,
char **  argv 
)

Definition at line 139 of file check_http.c.

{
  int result = STATE_UNKNOWN;

  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);
  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);

  if (process_arguments (argc, argv) == ERROR)
    usage4 (_("Could not parse arguments"));

  if (display_html == TRUE)
    printf ("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">",
      use_ssl ? "https" : "http", host_name ? host_name : server_address,
      server_port, server_url);

  /* initialize alarm signal handling, set socket timeout, start timer */
  (void) signal (SIGALRM, socket_timeout_alarm_handler);
  (void) alarm (socket_timeout);
  gettimeofday (&tv, NULL);

  result = check_http ();
  return result;
}

Here is the call graph for this function:

static time_t parse_time_string ( const char *  string) [static]

Definition at line 523 of file check_http.c.

{
  struct tm tm;
  time_t t;
  memset (&tm, 0, sizeof(tm));

  /* Like this: Tue, 25 Dec 2001 02:59:03 GMT */

  if (isupper (string[0])  &&  /* Tue */
    islower (string[1])  &&
    islower (string[2])  &&
    ',' ==   string[3]   &&
    ' ' ==   string[4]   &&
    (isdigit(string[5]) || string[5] == ' ') &&   /* 25 */
    isdigit (string[6])  &&
    ' ' ==   string[7]   &&
    isupper (string[8])  &&  /* Dec */
    islower (string[9])  &&
    islower (string[10]) &&
    ' ' ==   string[11]  &&
    isdigit (string[12]) &&  /* 2001 */
    isdigit (string[13]) &&
    isdigit (string[14]) &&
    isdigit (string[15]) &&
    ' ' ==   string[16]  &&
    isdigit (string[17]) &&  /* 02: */
    isdigit (string[18]) &&
    ':' ==   string[19]  &&
    isdigit (string[20]) &&  /* 59: */
    isdigit (string[21]) &&
    ':' ==   string[22]  &&
    isdigit (string[23]) &&  /* 03 */
    isdigit (string[24]) &&
    ' ' ==   string[25]  &&
    'G' ==   string[26]  &&  /* GMT */
    'M' ==   string[27]  &&  /* GMT */
    'T' ==   string[28]) {

    tm.tm_sec  = 10 * (string[23]-'0') + (string[24]-'0');
    tm.tm_min  = 10 * (string[20]-'0') + (string[21]-'0');
    tm.tm_hour = 10 * (string[17]-'0') + (string[18]-'0');
    tm.tm_mday = 10 * (string[5] == ' ' ? 0 : string[5]-'0') + (string[6]-'0');
    tm.tm_mon = (!strncmp (string+8, "Jan", 3) ? 0 :
      !strncmp (string+8, "Feb", 3) ? 1 :
      !strncmp (string+8, "Mar", 3) ? 2 :
      !strncmp (string+8, "Apr", 3) ? 3 :
      !strncmp (string+8, "May", 3) ? 4 :
      !strncmp (string+8, "Jun", 3) ? 5 :
      !strncmp (string+8, "Jul", 3) ? 6 :
      !strncmp (string+8, "Aug", 3) ? 7 :
      !strncmp (string+8, "Sep", 3) ? 8 :
      !strncmp (string+8, "Oct", 3) ? 9 :
      !strncmp (string+8, "Nov", 3) ? 10 :
      !strncmp (string+8, "Dec", 3) ? 11 :
      -1);
    tm.tm_year = ((1000 * (string[12]-'0') +
      100 * (string[13]-'0') +
      10 * (string[14]-'0') +
      (string[15]-'0'))
      - 1900);

    tm.tm_isdst = 0;  /* GMT is never in DST, right? */

    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,
    so it doesn't matter what time zone we parse them in.
    */

    t = mktime (&tm);
    if (t == (time_t) -1) t = 0;

    if (verbose) {
      const char *s = string;
      while (*s && *s != '\r' && *s != '\n')
      fputc (*s++, stdout);
      printf (" ==> %lu\n", (unsigned long) t);
    }

    return t;

  } else {
    return 0;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

char * perfd_size ( int  page_len)

Definition at line 1305 of file check_http.c.

{
  return perfdata ("size", page_len, "B",
            (min_page_len>0?TRUE:FALSE), min_page_len,
            (min_page_len>0?TRUE:FALSE), 0,
            TRUE, 0, FALSE, 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char * perfd_time ( double  microsec)

Definition at line 1295 of file check_http.c.

{
  return fperfdata ("time", elapsed_time, "s",
            thlds->warning?TRUE:FALSE, thlds->warning?thlds->warning->end:0,
            thlds->critical?TRUE:FALSE, thlds->critical?thlds->critical->end:0,
                   TRUE, 0, FALSE, 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* prepend_slash ( char *  path)

Definition at line 781 of file check_http.c.

{
  char *newpath;

  if (path[0] == '/')
    return path;

  if ((newpath = malloc (strlen(path) + 2)) == NULL)
    die (STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n"));
  newpath[0] = '/';
  strcpy (newpath + 1, path);
  free (path);
  return newpath;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void print_help ( void  )
void print_usage ( void  )

Definition at line 389 of file check_cpqarray.c.

{
  printf("cpqarrayd [options]\n");
  printf("   -h         prints this text\n");
  printf("   -d         enables debugging\n");
}
int process_arguments ( int  argc,
char **  argv 
)
void redir ( char *  pos,
char *  status_line 
)

Definition at line 1137 of file check_http.c.

{
  int i = 0;
  char *x;
  char xx[2];
  char type[6];
  char *addr;
  char *url;

  addr = malloc (MAX_IPV4_HOSTLENGTH + 1);
  if (addr == NULL)
    die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate addr\n"));

  url = malloc (strcspn (pos, "\r\n"));
  if (url == NULL)
    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");
      if (strlen(pos) == 0)
        die (STATE_UNKNOWN,
             _("HTTP UNKNOWN - Could not find redirect location - %s%s\n"),
             status_line, (display_html ? "</A>" : ""));
      continue;
    }

    pos += i;
    pos += strspn (pos, " \t");

    /*
     * RFC 2616 (4.2):  ``Header fields can be extended over multiple lines by
     * preceding each extra line with at least one SP or HT.''
     */
    for (; (i = strspn (pos, "\r\n")); pos += i) {
      pos += i;
      if (!(i = strspn (pos, " \t"))) {
        die (STATE_UNKNOWN, _("HTTP UNKNOWN - Empty redirect location%s\n"),
             display_html ? "</A>" : "");
      }
    }

    url = realloc (url, strcspn (pos, "\r\n") + 1);
    if (url == NULL)
      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) {
      url = prepend_slash (url);
      use_ssl = server_type_check (type);
    }

    /* URI_HTTP URI_HOST URI_PATH */
    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);
    }

    /* URI_HTTP URI_HOST URI_PORT */
    else if (sscanf (pos, HD3, type, addr, &i) == 3) {
      strcpy (url, HTTP_URL);
      use_ssl = server_type_check (type);
    }

    /* URI_HTTP URI_HOST */
    else if (sscanf (pos, HD4, type, addr) == 2) {
      strcpy (url, HTTP_URL);
      use_ssl = server_type_check (type);
      i = server_port_check (use_ssl);
    }

    /* URI_PATH */
    else if (sscanf (pos, HD5, url) == 1) {
      /* relative url */
      if ((url[0] != '/')) {
        if ((x = strrchr(server_url, '/')))
          *x = '\0';
        asprintf (&url, "%s/%s", server_url, url);
      }
      i = server_port;
      strcpy (type, server_type);
      strcpy (addr, host_name ? host_name : server_address);
    }

    else {
      die (STATE_UNKNOWN,
           _("HTTP UNKNOWN - Could not parse redirect location - %s%s\n"),
           pos, (display_html ? "</A>" : ""));
    }

    break;

  } /* end while (pos) */

  if (++redir_depth > max_depth)
    die (STATE_WARNING,
         _("HTTP WARNING - maximum redirection depth %d exceeded - %s://%s:%d%s%s\n"),
         max_depth, type, addr, i, url, (display_html ? "</A>" : ""));

  if (server_port==i &&
      !strcmp(server_address, addr) &&
      (host_name && !strcmp(host_name, addr)) &&
      !strcmp(server_url, url))
    die (STATE_WARNING,
         _("HTTP WARNING - redirection creates an infinite loop - %s://%s:%d%s%s\n"),
         type, addr, i, url, (display_html ? "</A>" : ""));

  strcpy (server_type, type);

  free (host_name);
  host_name = 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;

  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,
         display_html ? "</A>" : "");

  if (verbose)
    printf (_("Redirection to %s://%s:%d%s\n"), server_type,
            host_name ? host_name : server_address, server_port, server_url);

  check_http ();
}

Here is the call graph for this function:

Here is the caller graph for this function:

int server_port_check ( int  ssl_flag)

Definition at line 1287 of file check_http.c.

{
  if (ssl_flag)
    return HTTPS_PORT;
  else
    return HTTP_PORT;
}

Here is the caller graph for this function:

int server_type_check ( const char *  type)

Definition at line 1278 of file check_http.c.

{
  if (strcmp (type, "https"))
    return FALSE;
  else
    return TRUE;
}

Here is the caller graph for this function:


Variable Documentation

Definition at line 126 of file check_http.c.

Definition at line 83 of file check_http.c.

const char* copyright = "1999-2011"

Definition at line 37 of file check_http.c.

Definition at line 106 of file check_http.c.

Definition at line 110 of file check_http.c.

const char* email = "nagiosplug-devel@lists.sourceforge.net"

Definition at line 38 of file check_http.c.

Definition at line 82 of file check_http.c.

int errcode

Definition at line 84 of file check_http.c.

Definition at line 114 of file check_http.c.

char* host_name

Definition at line 97 of file check_http.c.

Definition at line 125 of file check_http.c.

char* http_method

Definition at line 123 of file check_http.c.

Definition at line 111 of file check_http.c.

Definition at line 112 of file check_http.c.

Definition at line 124 of file check_http.c.

int invert_regex = 0

Definition at line 85 of file check_http.c.

int max_depth = 15

Definition at line 122 of file check_http.c.

int max_page_len = 0

Definition at line 120 of file check_http.c.

int maximum_age = -1

Definition at line 72 of file check_http.c.

int min_page_len = 0

Definition at line 119 of file check_http.c.

int no_body = FALSE

Definition at line 71 of file check_http.c.

Definition at line 113 of file check_http.c.

char output_string_search[30] = ""

Definition at line 104 of file check_http.c.

Definition at line 80 of file check_http.c.

regex_t preg

Definition at line 79 of file check_http.c.

const char* progname = "check_http"

Definition at line 36 of file check_http.c.

Definition at line 109 of file check_http.c.

int redir_depth = 0

Definition at line 121 of file check_http.c.

Definition at line 81 of file check_http.c.

int sd

Definition at line 118 of file check_http.c.

Definition at line 96 of file check_http.c.

Definition at line 102 of file check_http.c.

Definition at line 101 of file check_http.c.

Definition at line 93 of file check_http.c.

char server_port_text[6] = ""

Definition at line 94 of file check_http.c.

char server_type[6] = "http"

Definition at line 95 of file check_http.c.

char* server_url

Definition at line 98 of file check_http.c.

Definition at line 100 of file check_http.c.

Definition at line 92 of file check_http.c.

Definition at line 103 of file check_http.c.

Definition at line 107 of file check_http.c.

int use_sni = FALSE

Definition at line 116 of file check_http.c.

int use_ssl = FALSE

Definition at line 115 of file check_http.c.

char* user_agent

Definition at line 99 of file check_http.c.

Definition at line 108 of file check_http.c.

int verbose = FALSE

Definition at line 117 of file check_http.c.

Definition at line 105 of file check_http.c.