From 0b6423f9c99d9edf8c96fefd0f6c453859395aa1 Mon Sep 17 00:00:00 2001 From: Holger Weiss Date: Mon, 30 Sep 2013 00:03:24 +0200 Subject: Import Nagios Plugins site Import the Nagios Plugins web site, Cronjobs, infrastructure scripts, and configuration files. --- web/attachments/427519-http-parser.bundle | 1396 +++++++++++++++++++++++++++++ 1 file changed, 1396 insertions(+) create mode 100644 web/attachments/427519-http-parser.bundle (limited to 'web/attachments/427519-http-parser.bundle') diff --git a/web/attachments/427519-http-parser.bundle b/web/attachments/427519-http-parser.bundle new file mode 100644 index 0000000..74ab9e4 --- /dev/null +++ b/web/attachments/427519-http-parser.bundle @@ -0,0 +1,1396 @@ +From 256d8d15acf98ee405f79b75a52692531d173f49 Mon Sep 17 00:00:00 2001 +From: Ferenc Wagner +Date: Wed, 2 Nov 2011 10:03:38 +0100 +Subject: [PATCH 0/9] check_http: add support for chunked encoding via http-parser + +Hi, + +Here is an attempt to add support for chunked encoding in check_http +by switching to the third-party HTTP parser from Joyent hosted at +https://github.com/joyent/http-parser. The switch makes much of the +in-house ad-hoc parsing code redundant, and induces some changes in +the semantics of the -e switch, but that should be regarded as a step +forward, since the role of that switch was to verify HTTP correctness +(at least in part) and now we have a much better mechanism for that: +the parser itself. The pagesize limits (-m switch) also gained a +clearer semantics: they check the content size now, as that may be +available even when -N is used, and does not depend on the transfer +encoding. + +Ferenc Wagner (9): + check_http: do not print page length if body was not read + Add lib/http-parser submodule and adjust Makefile.am to use it in + check_http + check_http: move status code and redirect location parsing to + http-parser + check_http: whitespace change to fix up indentation by removing dummy + block + check_http: constify and rename the location argument for redir() + check_http: make list of parsed headers configurable + check_http: use header parsing machinery in check_document_dates() + check_http: also read the response content via http-parse + check_http: check content length instead of response length + + .gitmodules | 3 + + lib/Makefile.am | 10 +- + lib/http-parser | 1 + + plugins/Makefile.am | 9 +- + plugins/check_http.c | 596 ++++++++++++++++++++------------------------------ + 5 files changed, 256 insertions(+), 363 deletions(-) + create mode 100644 .gitmodules + create mode 160000 lib/http-parser + +-- +1.7.2.5 + +From abc1d1c539376cb5531a9686e581ff62acf421e5 Mon Sep 17 00:00:00 2001 +From: Ferenc Wagner +Date: Mon, 31 Oct 2011 15:10:54 +0100 +Subject: [PATCH 1/9] check_http: do not print page length if body was not read + + +Signed-off-by: Ferenc Wagner +--- + plugins/check_http.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/plugins/check_http.c b/plugins/check_http.c +index 433c28e..6df9d23 100644 +--- a/plugins/check_http.c ++++ b/plugins/check_http.c +@@ -923,7 +923,7 @@ check_http (void) + /* leave full_page untouched so we can free it later */ + page = full_page; + +- if (verbose) ++ if (verbose && !no_body) + printf ("%s://%s:%d%s is %d characters\n", + use_ssl ? "https" : "http", server_address, + server_port, server_url, (int)pagesize); +-- +1.7.2.5 + + +From 27536d84b73489308f129ff5623ffd1445dfc5fb Mon Sep 17 00:00:00 2001 +From: Ferenc Wagner +Date: Mon, 31 Oct 2011 15:14:38 +0100 +Subject: [PATCH 2/9] Add lib/http-parser submodule and adjust Makefile.am to use it in check_http + + +Signed-off-by: Ferenc Wagner +--- + .gitmodules | 3 +++ + lib/Makefile.am | 10 +++++++++- + lib/http-parser | 1 + + plugins/Makefile.am | 9 +++++---- + 4 files changed, 18 insertions(+), 5 deletions(-) + create mode 100644 .gitmodules + create mode 160000 lib/http-parser + +diff --git a/.gitmodules b/.gitmodules +new file mode 100644 +index 0000000..5270743 +--- /dev/null ++++ b/.gitmodules +@@ -0,0 +1,3 @@ ++[submodule "lib/http-parser"] ++ path = lib/http-parser ++ url = git://github.com/joyent/http-parser.git +diff --git a/lib/Makefile.am b/lib/Makefile.am +index 99fa591..561b7cf 100644 +--- a/lib/Makefile.am ++++ b/lib/Makefile.am +@@ -2,7 +2,7 @@ + + SUBDIRS = . tests + +-noinst_LIBRARIES = libnagiosplug.a ++noinst_LIBRARIES = libnagiosplug.a http-parser/libhttp_parser.a + + AM_CPPFLAGS = -DNP_STATE_DIR_PREFIX=\"$(localstatedir)\" + +@@ -18,3 +18,11 @@ INCLUDES = -I$(srcdir) -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/p + test test-debug: + cd tests && make $@ + ++http-parser/libhttp_parser.a: ++ cd http-parser && $(MAKE) package ++ ++mostlyclean-local: ++ cd http-parser && $(MAKE) clean ++ ++check-local: ++ cd http-parser && $(MAKE) test +diff --git a/lib/http-parser b/lib/http-parser +new file mode 160000 +index 0000000..f1d48aa +--- /dev/null ++++ b/lib/http-parser +@@ -0,0 +1 @@ ++Subproject commit f1d48aa31c932f80a64122a75a87bc909b4073f9 +diff --git a/plugins/Makefile.am b/plugins/Makefile.am +index 36a28b0..2df105e 100644 +--- a/plugins/Makefile.am ++++ b/plugins/Makefile.am +@@ -13,7 +13,7 @@ AM_CFLAGS = -DNP_VERSION='"$(NP_VERSION)"' + + VPATH = $(top_srcdir) $(top_srcdir)/lib $(top_srcdir)/plugins $(top_srcdir)/plugins/t + +-INCLUDES = -I.. -I$(top_srcdir)/lib -I$(top_srcdir)/gl -I$(top_srcdir)/intl @LDAPINCLUDE@ @PGINCLUDE@ @SSLINCLUDE@ ++INCLUDES = -I.. -I$(top_srcdir)/lib -I$(top_srcdir)/lib/http-parser -I$(top_srcdir)/gl -I$(top_srcdir)/intl @LDAPINCLUDE@ @PGINCLUDE@ @SSLINCLUDE@ + + localedir = $(datadir)/locale + # gettext docs say to use AM_CPPFLAGS, but per module_CPPFLAGS override this +@@ -48,6 +48,7 @@ BASEOBJS = utils.o ../lib/libnagiosplug.a ../gl/libgnu.a + NETOBJS = netutils.o $(BASEOBJS) $(EXTRA_NETOBJS) + SSLOBJS = sslutils.o + NETLIBS = $(NETOBJS) $(SOCKETLIBS) ++HTTPPARSER = ../lib/http-parser/libhttp_parser.a + + TESTS_ENVIRONMENT = perl -I $(top_builddir) -I $(top_srcdir) + +@@ -70,7 +71,7 @@ check_dns_LDADD = $(NETLIBS) runcmd.o + check_dummy_LDADD = $(BASEOBJS) + check_fping_LDADD = $(NETLIBS) popen.o + check_game_LDADD = $(BASEOBJS) runcmd.o +-check_http_LDADD = $(SSLOBJS) $(NETLIBS) $(SSLLIBS) ++check_http_LDADD = $(SSLOBJS) $(NETLIBS) $(SSLLIBS) $(HTTPPARSER) + check_hpjd_LDADD = $(NETLIBS) popen.o + check_ldap_LDADD = $(NETLIBS) $(LDAPLIBS) + check_load_LDADD = $(BASEOBJS) popen.o +@@ -115,7 +116,7 @@ check_dns_DEPENDENCIES = check_dns.c $(NETOBJS) runcmd.o $(DEPLIBS) + check_dummy_DEPENDENCIES = check_dummy.c $(DEPLIBS) + check_fping_DEPENDENCIES = check_fping.c $(NETOBJS) popen.o $(DEPLIBS) + check_game_DEPENDENCIES = check_game.c $(DEPLIBS) runcmd.o +-check_http_DEPENDENCIES = check_http.c $(SSLOBJS) $(NETOBJS) $(DEPLIBS) ++check_http_DEPENDENCIES = check_http.c $(SSLOBJS) $(NETOBJS) $(DEPLIBS) $(HTTPPARSER) + check_hpjd_DEPENDENCIES = check_hpjd.c $(NETOBJS) popen.o $(DEPLIBS) + check_ide_smart_DEPENDENCIES = check_ide_smart.c $(BASEOBJS) $(DEPLIBS) + check_ldap_DEPENDENCIES = check_ldap.c $(NETOBJS) $(DEPLIBS) +@@ -170,7 +171,7 @@ install-exec-hook: + cd $(DESTDIR)$(libexecdir) && \ + for i in $(check_tcp_programs) ; do rm -f $$i; ln -s check_tcp $$i ; done ;\ + if [ -x check_ldap ] ; then rm -f check_ldaps ; ln -s check_ldap check_ldaps ; fi +- ++ + clean-local: + rm -f $(check_tcp_programs) + rm -f NP-VERSION-FILE +-- +1.7.2.5 + + +From e8b35f17bf23515dc43233ebbde1c0ccb11d5ecb Mon Sep 17 00:00:00 2001 +From: Ferenc Wagner +Date: Mon, 31 Oct 2011 15:20:48 +0100 +Subject: [PATCH 3/9] check_http: move status code and redirect location parsing to http-parser + +This changes the semantics of the -e switch, as http-parser doesn't make +the status string available. But it does substantial HTTP verification, +so much of the original functionality will be regained once HTTP parsing +errors become CRITICAL. + +This introduces some new gettext strings. + +Signed-off-by: Ferenc Wagner +--- + plugins/check_http.c | 264 +++++++++++++++++++++++++------------------------- + 1 files changed, 131 insertions(+), 133 deletions(-) + +diff --git a/plugins/check_http.c b/plugins/check_http.c +index 6df9d23..ada7a95 100644 +--- a/plugins/check_http.c ++++ b/plugins/check_http.c +@@ -41,6 +41,7 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; + #include "netutils.h" + #include "utils.h" + #include "base64.h" ++#include "http_parser.h" + #include + + #define INPUT_DELIMITER ";" +@@ -48,7 +49,15 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; + #define STICKY_HOST 1 + #define STICKY_PORT 2 + +-#define HTTP_EXPECT "HTTP/1." ++struct parser_data_t { ++ enum http_errno prev_callback; /* use HPE_CB_ macros for identifying callbacks */ ++ char *current_header; ++ size_t current_header_length; ++ int parsing_location; ++ char *location; ++ size_t location_length; ++}; ++ + enum { + MAX_IPV4_HOSTLENGTH = 255, + HTTP_PORT = 80, +@@ -97,8 +106,7 @@ 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; ++int status_expect = -1; + char string_expect[MAX_INPUT_BUFFER] = ""; + char output_string_search[30] = ""; + char *warning_thresholds = NULL; +@@ -126,7 +134,7 @@ char buffer[MAX_INPUT_BUFFER]; + + int process_arguments (int, char **); + int check_http (void); +-void redir (char *pos, char *status_line); ++void redir (char *pos); + int server_type_check(const char *type); + int server_port_check(int ssl_flag); + char *perfd_time (double microsec); +@@ -367,10 +375,8 @@ process_arguments (int argc, char **argv) + strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1); + string_expect[MAX_INPUT_BUFFER - 1] = 0; + break; +- case 'e': /* string or substring */ +- strncpy (server_expect, optarg, MAX_INPUT_BUFFER - 1); +- server_expect[MAX_INPUT_BUFFER - 1] = 0; +- server_expect_yn = 1; ++ case 'e': /* expected HTTP response code */ ++ status_expect = atoi (optarg); + break; + case 'T': /* Content-type */ + asprintf (&http_content_type, "%s", optarg); +@@ -589,26 +595,6 @@ parse_time_string (const char *string) + } + } + +-/* Checks if the server 'reply' is one of the expected 'statuscodes' */ +-static int +-expected_statuscode (const char *reply, const char *statuscodes) +-{ +- 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; +-} +- + static int + check_document_dates (const char *headers, char **msg) + { +@@ -772,16 +758,78 @@ prepend_slash (char *path) + return newpath; + } + ++/* ++Returns 0 on success, 1 if allocation fails. ++Works on binary data, but also zero-terminates the result ++for easier string handling. ++*/ ++int ++append (char **orig, size_t *orig_len, const char *extra, size_t len) ++{ ++ *orig = realloc (*orig, *orig_len + len + 1); ++ if (!*orig) return 1; ++ memcpy (*orig + *orig_len, extra, len); ++ *orig_len += len; ++ (*orig)[*orig_len] = 0; ++ return 0; ++} ++ ++int ++header_field_callback (http_parser *parser, const char *at, size_t length) ++{ ++ struct parser_data_t *data = parser->data; ++ ++ switch (data->prev_callback) { ++ case HPE_CB_header_value: ++ data->current_header_length = 0; ++ /* fall through */ ++ case 0: ++ data->prev_callback = HPE_CB_header_field; ++ /* fall through */ ++ case HPE_CB_header_field: ++ return append (&data->current_header, &data->current_header_length, at, length); ++ default: ++ return 1; ++ } ++} ++ ++int ++header_value_callback (http_parser *parser, const char *at, size_t length) ++{ ++ struct parser_data_t *data = parser->data; ++ ++ switch (data->prev_callback) { ++ case HPE_CB_header_field: ++ data->parsing_location = !strcasecmp (data->current_header, "location"); ++ data->prev_callback = HPE_CB_header_value; ++ /* fall through */ ++ case HPE_CB_header_value: ++ return data->parsing_location && ++ append (&data->location, &data->location_length, at, length); ++ default: ++ return 1; ++ } ++} ++ ++int ++headers_complete_callback (http_parser *parser) ++{ ++ struct parser_data_t *data = parser->data; ++ ++ data->prev_callback = HPE_CB_headers_complete; ++ ++ if (no_body) /* Terminate parsing (thus reading) if the -N option is set */ ++ return 2; /* 1 means don't expect body in this callback */ ++ return 0; ++} ++ + int + check_http (void) + { + 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; +@@ -792,6 +840,9 @@ check_http (void) + double elapsed_time; + int page_len = 0; + int result = STATE_OK; ++ http_parser_settings settings; ++ http_parser parser; ++ struct parser_data_t parser_data; + + /* try to connect to the host at the given port number */ + if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK) +@@ -869,9 +920,29 @@ check_http (void) + if (verbose) printf ("%s\n", buf); + my_send (buf, strlen (buf)); + ++ /* Initialize the HTTP parser */ ++ http_parser_init (&parser, HTTP_RESPONSE); ++ memset (&parser_data, 0, sizeof parser_data); ++ parser.data = &parser_data; ++ memset (&settings, 0, sizeof settings); ++ settings.on_header_field = header_field_callback; ++ settings.on_header_value = header_value_callback; ++ settings.on_headers_complete = headers_complete_callback; ++ + /* fetch the page */ + full_page = strdup(""); +- while ((i = my_recv (buffer, MAX_INPUT_BUFFER-1)) > 0) { ++ while ((i = my_recv (buffer, MAX_INPUT_BUFFER-1)) >= 0) { ++ int nparsed = http_parser_execute(&parser, &settings, buffer, i); ++ if (nparsed != i) { ++ enum http_errno code = HTTP_PARSER_ERRNO (&parser); ++ if (code == HPE_CB_headers_complete) { /* the -N check fired */ ++ /* break; FIXME this would break the current header code */ ++ } else { ++ printf ("http_parser_execute returned %d instead of %i: %s\n", ++ nparsed, i, http_errno_description (code)); ++ } ++ } ++ if (i == 0) break; + buffer[i] = '\0'; + asprintf (&full_page_new, "%s%s", full_page, buffer); + free (full_page); +@@ -928,15 +999,9 @@ check_http (void) + use_ssl ? "https" : "http", server_address, + server_port, server_url, (int)pagesize); + +- /* find status line and null-terminate it */ +- status_line = page; ++ /* skip status line */ + 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; +@@ -955,68 +1020,38 @@ check_http (void) + 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); ++ if (status_expect != -1) { ++ if (parser.status_code == status_expect) ++ asprintf (&msg, _("Got expected code %d - "), status_expect); ++ else { ++ asprintf (&msg, _("Invalid HTTP status received from host: %d\n"), ++ parser.status_code); ++ die (STATE_CRITICAL, "HTTP CRITICAL - %s", msg); ++ } ++ } else { ++ if (parser.status_code >= 600 || parser.status_code < 100) { ++ die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d)\n"), parser.status_code); + } + /* server errors result in a critical state */ +- else if (http_status >= 500) { +- asprintf (&msg, _("%s - "), status_line); ++ else if (parser.status_code >= 500) { + result = STATE_CRITICAL; + } + /* client errors result in a warning state */ +- else if (http_status >= 400) { +- asprintf (&msg, _("%s - "), status_line); ++ else if (parser.status_code >= 400) { + 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 if (parser.status_code >= 300) { ++ if (onredirect == STATE_DEPENDENT) { ++ if (parser_data.location) ++ redir (parser_data.location); ++ else die (STATE_CRITICAL, _("Redirect without Location header\n")); ++ } + 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) */ ++ asprintf (&msg, _("%d - "), parser.status_code); ++ } + + /* reset the alarm - must be called *after* redir or we'll never die on redirects! */ + alarm (0); +@@ -1111,11 +1146,10 @@ check_http (void) + #define HD5 URI_PATH + + void +-redir (char *pos, char *status_line) ++redir (char *pos) + { + int i = 0; + char *x; +- char xx[2]; + char type[6]; + char *addr; + char *url; +@@ -1124,41 +1158,11 @@ redir (char *pos, char *status_line) + if (addr == NULL) + die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate addr\n")); + +- url = malloc (strcspn (pos, "\r\n")); ++ url = malloc (strlen (pos) + 1); + 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 ? "" : "")); +- 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 ? "" : ""); +- } +- } +- +- url = realloc (url, strcspn (pos, "\r\n") + 1); +- if (url == NULL) +- die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n")); +- ++ { /* dummy block to reduce patch diff */ + /* URI_HTTP, URI_HOST, URI_PORT, URI_PATH */ + if (sscanf (pos, HD1, type, addr, &i, url) == 4) { + url = prepend_slash (url); +@@ -1203,10 +1207,7 @@ redir (char *pos, char *status_line) + _("HTTP UNKNOWN - Could not parse redirect location - %s%s\n"), + pos, (display_html ? "" : "")); + } +- +- break; +- +- } /* end while (pos) */ ++ } + + if (++redir_depth > max_depth) + die (STATE_WARNING, +@@ -1332,11 +1333,8 @@ print_help (void) + printf (" %s\n", _("(when this option is used the URL is not checked.)\n")); + #endif + +- printf (" %s\n", "-e, --expect=STRING"); +- printf (" %s\n", _("Comma-delimited list of strings, at least one of them is expected in")); +- printf (" %s", _("the first (status) line of the server response (default: ")); +- printf ("%s)\n", HTTP_EXPECT); +- printf (" %s\n", _("If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)")); ++ printf (" %s\n", "-e, --expect=INTEGER"); ++ printf (" %s\n", _("Expected HTTP status code, overriding the default logic")); + printf (" %s\n", "-s, --string=STRING"); + printf (" %s\n", _("String to expect in the content")); + printf (" %s\n", "-u, --url=PATH"); +-- +1.7.2.5 + + +From a35b05d935f975478c90360ab56fb54d2d82e9c6 Mon Sep 17 00:00:00 2001 +From: Ferenc Wagner +Date: Wed, 2 Nov 2011 09:52:19 +0100 +Subject: [PATCH 4/9] check_http: whitespace change to fix up indentation by removing dummy block + + +Signed-off-by: Ferenc Wagner +--- + plugins/check_http.c | 76 ++++++++++++++++++++++++------------------------- + 1 files changed, 37 insertions(+), 39 deletions(-) + +diff --git a/plugins/check_http.c b/plugins/check_http.c +index ada7a95..3966ab4 100644 +--- a/plugins/check_http.c ++++ b/plugins/check_http.c +@@ -1162,51 +1162,49 @@ redir (char *pos) + if (url == NULL) + die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n")); + +- { /* dummy block to reduce patch diff */ +- /* 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_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_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 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_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); ++ /* 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 ? "" : "")); +- } ++ else { ++ die (STATE_UNKNOWN, ++ _("HTTP UNKNOWN - Could not parse redirect location - %s%s\n"), ++ pos, (display_html ? "" : "")); + } + + if (++redir_depth > max_depth) +-- +1.7.2.5 + + +From 3f410b149eb7cd112466bbb147525c1d497adaa2 Mon Sep 17 00:00:00 2001 +From: Ferenc Wagner +Date: Mon, 31 Oct 2011 17:45:49 +0100 +Subject: [PATCH 5/9] check_http: constify and rename the location argument for redir() + + +Signed-off-by: Ferenc Wagner +--- + plugins/check_http.c | 18 +++++++++--------- + 1 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/plugins/check_http.c b/plugins/check_http.c +index 3966ab4..c4586d5 100644 +--- a/plugins/check_http.c ++++ b/plugins/check_http.c +@@ -134,7 +134,7 @@ char buffer[MAX_INPUT_BUFFER]; + + int process_arguments (int, char **); + int check_http (void); +-void redir (char *pos); ++void redir (const char *location); + int server_type_check(const char *type); + int server_port_check(int ssl_flag); + char *perfd_time (double microsec); +@@ -1146,7 +1146,7 @@ check_http (void) + #define HD5 URI_PATH + + void +-redir (char *pos) ++redir (const char *location) + { + int i = 0; + char *x; +@@ -1158,38 +1158,38 @@ redir (char *pos) + if (addr == NULL) + die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate addr\n")); + +- url = malloc (strlen (pos) + 1); ++ url = malloc (strlen (location) + 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) { ++ if (sscanf (location, 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 ) { ++ else if (sscanf (location, 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) { ++ else if (sscanf (location, 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) { ++ else if (sscanf (location, 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) { ++ else if (sscanf (location, HD5, url) == 1) { + /* relative url */ + if ((url[0] != '/')) { + if ((x = strrchr(server_url, '/'))) +@@ -1204,7 +1204,7 @@ redir (char *pos) + else { + die (STATE_UNKNOWN, + _("HTTP UNKNOWN - Could not parse redirect location - %s%s\n"), +- pos, (display_html ? "" : "")); ++ location, (display_html ? "" : "")); + } + + if (++redir_depth > max_depth) +-- +1.7.2.5 + + +From d1b806941bf6bf94754e86e832a11eabc003a656 Mon Sep 17 00:00:00 2001 +From: Ferenc Wagner +Date: Mon, 31 Oct 2011 17:47:47 +0100 +Subject: [PATCH 6/9] check_http: make list of parsed headers configurable + + +Signed-off-by: Ferenc Wagner +--- + plugins/check_http.c | 58 +++++++++++++++++++++++++++++++++++++++---------- + 1 files changed, 46 insertions(+), 12 deletions(-) + +diff --git a/plugins/check_http.c b/plugins/check_http.c +index c4586d5..5466e06 100644 +--- a/plugins/check_http.c ++++ b/plugins/check_http.c +@@ -49,13 +49,17 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; + #define STICKY_HOST 1 + #define STICKY_PORT 2 + ++struct header_data_t { ++ const char *field; ++ char *value; ++}; ++ + struct parser_data_t { + enum http_errno prev_callback; /* use HPE_CB_ macros for identifying callbacks */ +- char *current_header; +- size_t current_header_length; +- int parsing_location; +- char *location; +- size_t location_length; ++ char *current_field; ++ size_t current_length; ++ struct header_data_t *current_header; ++ struct header_data_t *headers; + }; + + enum { +@@ -758,6 +762,17 @@ prepend_slash (char *path) + return newpath; + } + ++const char * ++get_value (const struct header_data_t *header, const char *field) ++{ ++ while (header->field) { ++ if (!strcasecmp (header->field, field)) ++ return header->value; ++ header++; ++ } ++ return 0; ++} ++ + /* + Returns 0 on success, 1 if allocation fails. + Works on binary data, but also zero-terminates the result +@@ -781,13 +796,13 @@ header_field_callback (http_parser *parser, const char *at, size_t length) + + switch (data->prev_callback) { + case HPE_CB_header_value: +- data->current_header_length = 0; ++ data->current_length = 0; + /* fall through */ + case 0: + data->prev_callback = HPE_CB_header_field; + /* fall through */ + case HPE_CB_header_field: +- return append (&data->current_header, &data->current_header_length, at, length); ++ return append (&data->current_field, &data->current_length, at, length); + default: + return 1; + } +@@ -797,15 +812,23 @@ int + header_value_callback (http_parser *parser, const char *at, size_t length) + { + struct parser_data_t *data = parser->data; ++ struct header_data_t *header; + + switch (data->prev_callback) { + case HPE_CB_header_field: +- data->parsing_location = !strcasecmp (data->current_header, "location"); ++ data->current_header = 0; ++ data->current_length = 0; ++ for (header = data->headers; header->field; header++) ++ if (!strcasecmp (data->current_field, header->field)) { ++ data->current_header = header; ++ break; ++ } + data->prev_callback = HPE_CB_header_value; + /* fall through */ + case HPE_CB_header_value: +- return data->parsing_location && +- append (&data->location, &data->location_length, at, length); ++ return data->current_header && ++ append (&(data->current_header->value), ++ &data->current_length, at, length); + default: + return 1; + } +@@ -816,6 +839,13 @@ headers_complete_callback (http_parser *parser) + { + struct parser_data_t *data = parser->data; + ++ if (verbose) { ++ const struct header_data_t *header; ++ printf ("Parsed headers:\n"); ++ for (header = data->headers; header->field; header++) ++ printf ("%s: %s\n", header->field, header->value); ++ } ++ + data->prev_callback = HPE_CB_headers_complete; + + if (no_body) /* Terminate parsing (thus reading) if the -N option is set */ +@@ -843,6 +873,8 @@ check_http (void) + http_parser_settings settings; + http_parser parser; + struct parser_data_t parser_data; ++ struct header_data_t interesting_headers[] = ++ {{"location", 0}, {"date", 0}, {"last-modified", 0}, {0, 0}}; + + /* try to connect to the host at the given port number */ + if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK) +@@ -923,6 +955,7 @@ check_http (void) + /* Initialize the HTTP parser */ + http_parser_init (&parser, HTTP_RESPONSE); + memset (&parser_data, 0, sizeof parser_data); ++ parser_data.headers = interesting_headers; + parser.data = &parser_data; + memset (&settings, 0, sizeof settings); + settings.on_header_field = header_field_callback; +@@ -1043,8 +1076,9 @@ check_http (void) + /* check redirected page if specified */ + else if (parser.status_code >= 300) { + if (onredirect == STATE_DEPENDENT) { +- if (parser_data.location) +- redir (parser_data.location); ++ const char *location = get_value (parser_data.headers, "location"); ++ if (location) ++ redir (location); + else die (STATE_CRITICAL, _("Redirect without Location header\n")); + } + else +-- +1.7.2.5 + + +From 62e8868bb24c2161ccb7748dba82c6a90618aac3 Mon Sep 17 00:00:00 2001 +From: Ferenc Wagner +Date: Mon, 31 Oct 2011 17:57:11 +0100 +Subject: [PATCH 7/9] check_http: use header parsing machinery in check_document_dates() + + +Signed-off-by: Ferenc Wagner +--- + plugins/check_http.c | 61 +++---------------------------------------------- + 1 files changed, 4 insertions(+), 57 deletions(-) + +diff --git a/plugins/check_http.c b/plugins/check_http.c +index 5466e06..423bb22 100644 +--- a/plugins/check_http.c ++++ b/plugins/check_http.c +@@ -600,63 +600,10 @@ parse_time_string (const char *string) + } + + static int +-check_document_dates (const char *headers, char **msg) ++check_document_dates (const char *server_date, const char *document_date, char **msg) + { +- 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); +@@ -687,8 +634,6 @@ check_document_dates (const char *headers, char **msg) + date_result = max_state_alt(STATE_CRITICAL, date_result); + } + } +- free (server_date); +- free (document_date); + } + return date_result; + } +@@ -1091,7 +1036,9 @@ check_http (void) + alarm (0); + + if (maximum_age >= 0) { +- result = max_state_alt(check_document_dates(header, &msg), result); ++ result = max_state_alt(check_document_dates(get_value (parser_data.headers, "date"), ++ get_value (parser_data.headers, "last-modified"), &msg), ++ result); + } + + /* Page and Header content checks go here */ +-- +1.7.2.5 + + +From efe4e949ae4ba64f333f402d0f4b54f07b18164c Mon Sep 17 00:00:00 2001 +From: Ferenc Wagner +Date: Tue, 1 Nov 2011 16:17:00 +0100 +Subject: [PATCH 8/9] check_http: also read the response content via http-parse + +This gets rid of good a bunch of code, and also gives free decoding of +Transfer-Encoding: chunked, which all HTTP/1.1 clients must support. + +Signed-off-by: Ferenc Wagner +--- + plugins/check_http.c | 86 ++++++++++++------------------------------------- + 1 files changed, 21 insertions(+), 65 deletions(-) + +diff --git a/plugins/check_http.c b/plugins/check_http.c +index 423bb22..deea38c 100644 +--- a/plugins/check_http.c ++++ b/plugins/check_http.c +@@ -60,6 +60,7 @@ struct parser_data_t { + size_t current_length; + struct header_data_t *current_header; + struct header_data_t *headers; ++ char *content; + }; + + enum { +@@ -488,26 +489,6 @@ process_arguments (int argc, char **argv) + return TRUE; + } + +- +- +-/* Returns 1 if we're done processing the document body; 0 to keep going */ +-static int +-document_headers_done (char *full_page) +-{ +- 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; +-} +- + static time_t + parse_time_string (const char *string) + { +@@ -792,6 +773,7 @@ headers_complete_callback (http_parser *parser) + } + + data->prev_callback = HPE_CB_headers_complete; ++ data->current_length = 0; /* prepare for the body */ + + if (no_body) /* Terminate parsing (thus reading) if the -N option is set */ + return 2; /* 1 means don't expect body in this callback */ +@@ -799,16 +781,20 @@ headers_complete_callback (http_parser *parser) + } + + int ++body_callback (http_parser *parser, const char *at, size_t length) ++{ ++ struct parser_data_t *data = parser->data; ++ ++ return append (&data->content, &data->current_length, at, length); ++} ++ ++int + check_http (void) + { + char *msg; +- char *header; +- char *page; + char *auth; + int i = 0; + size_t pagesize = 0; +- char *full_page; +- char *full_page_new; + char *buf; + char *pos; + long microsec; +@@ -906,31 +892,19 @@ check_http (void) + settings.on_header_field = header_field_callback; + settings.on_header_value = header_value_callback; + settings.on_headers_complete = headers_complete_callback; ++ settings.on_body = body_callback; + + /* fetch the page */ +- full_page = strdup(""); + while ((i = my_recv (buffer, MAX_INPUT_BUFFER-1)) >= 0) { + int nparsed = http_parser_execute(&parser, &settings, buffer, i); ++ pagesize += i; + if (nparsed != i) { + enum http_errno code = HTTP_PARSER_ERRNO (&parser); +- if (code == HPE_CB_headers_complete) { /* the -N check fired */ +- /* break; FIXME this would break the current header code */ +- } else { +- printf ("http_parser_execute returned %d instead of %i: %s\n", +- nparsed, i, http_errno_description (code)); +- } ++ if (code == HPE_CB_headers_complete) break; /* the -N check fired */ ++ else die (STATE_CRITICAL, _("HTTP CRITICAL - error parsing response: %s"), ++ http_errno_description (code)); + } + if (i == 0) break; +- 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) { +@@ -969,34 +943,16 @@ check_http (void) + microsec = deltime (tv); + elapsed_time = (double)microsec / 1.0e6; + +- /* leave full_page untouched so we can free it later */ +- page = full_page; +- + if (verbose && !no_body) + printf ("%s://%s:%d%s is %d characters\n", + use_ssl ? "https" : "http", server_address, + server_port, server_url, (int)pagesize); + +- /* skip status line */ +- page += (size_t) strcspn (page, "\r\n"); +- page += (size_t) strspn (page, "\r\n"); +- +- /* 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; ++ if (verbose && !no_body) { ++ puts ("**** CONTENT ****"); ++ fwrite (parser_data.content, parser_data.current_length, 1, stdout); ++ putchar ('\n'); + } +- 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)); + + if (status_expect != -1) { + if (parser.status_code == status_expect) +@@ -1044,7 +1000,7 @@ check_http (void) + /* Page and Header content checks go here */ + + if (strlen (string_expect)) { +- if (!strstr (page, string_expect)) { ++ if (!strstr (parser_data.content, 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); +@@ -1055,7 +1011,7 @@ check_http (void) + } + + if (strlen (regexp)) { +- errcode = regexec (&preg, page, REGS, pmatch, 0); ++ errcode = regexec (&preg, parser_data.content, 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); +-- +1.7.2.5 + + +From 256d8d15acf98ee405f79b75a52692531d173f49 Mon Sep 17 00:00:00 2001 +From: Ferenc Wagner +Date: Wed, 2 Nov 2011 07:57:30 +0100 +Subject: [PATCH 9/9] check_http: check content length instead of response length + +The content length does not depend on the transfer encoding and may +be possible to derive without fetching the entire body (cf. -N option). + +Signed-off-by: Ferenc Wagner +--- + plugins/check_http.c | 93 +++++++++++--------------------------------------- + 1 files changed, 20 insertions(+), 73 deletions(-) + +diff --git a/plugins/check_http.c b/plugins/check_http.c +index deea38c..27f5cd3 100644 +--- a/plugins/check_http.c ++++ b/plugins/check_http.c +@@ -619,59 +619,6 @@ check_document_dates (const char *server_date, const char *document_date, char * + return date_result; + } + +-int +-get_content_length (const char *headers) +-{ +- 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); +-} +- + char * + prepend_slash (char *path) + { +@@ -799,13 +746,13 @@ check_http (void) + char *pos; + long microsec; + double elapsed_time; +- int page_len = 0; ++ int page_len = -1; + int result = STATE_OK; + http_parser_settings settings; + http_parser parser; + struct parser_data_t parser_data; + struct header_data_t interesting_headers[] = +- {{"location", 0}, {"date", 0}, {"last-modified", 0}, {0, 0}}; ++ {{"location", 0}, {"date", 0}, {"last-modified", 0}, {"content-length", 0}, {0, 0}}; + + /* try to connect to the host at the given port number */ + if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK) +@@ -1031,21 +978,21 @@ check_http (void) + } + } + +- /* 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); ++ /* make sure the content is of an appropriate size */ ++ if (no_body) { ++ const char *content_length = get_value (parser_data.headers, "content-length"); ++ if (content_length) page_len = atol (content_length); ++ } else page_len = parser_data.current_length; ++ if (page_len != -1) { ++ 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); ++ } ++ } else if (max_page_len > 0 || min_page_len > 0) { ++ asprintf (&msg, _("%spage size unknown, "), msg); + result = max_state_alt(STATE_WARNING, result); + } + +@@ -1058,7 +1005,7 @@ check_http (void) + /* check elapsed time */ + asprintf (&msg, + _("%s - %d bytes in %.3f second response time %s|%s %s"), +- msg, page_len, elapsed_time, ++ msg, pagesize, elapsed_time, + (display_html ? "" : ""), + perfd_time (elapsed_time), perfd_size (page_len)); + +@@ -1310,7 +1257,7 @@ print_help (void) + printf (" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the")); + printf (" %s\n", _("specified IP address. stickyport also ensures port 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", _("Minimum content size required (bytes) : Maximum content size required (bytes)")); + + printf (UT_WARN_CRIT); + +@@ -1361,7 +1308,7 @@ print_usage (void) + printf (" [-w ] [-c ] [-t ] [-L] [-a auth]\n"); + printf (" [-b proxy_auth] [-f ]\n"); + printf (" [-e ] [-s string] [-l] [-r | -R ]\n"); +- printf (" [-P string] [-m :] [-4|-6] [-N] [-M ]\n"); ++ printf (" [-P string] [-m :] [-4|-6] [-N] [-M ]\n"); + printf (" [-A string] [-k string] [-S] [--sni] [-C ] [-T ]\n"); + printf (" [-j method]\n"); + } +-- +1.7.2.5 + -- cgit v1.2.3-74-g34f1