diff options
Diffstat (limited to 'web/attachments/427519-http-parser.bundle')
| -rw-r--r-- | web/attachments/427519-http-parser.bundle | 1396 |
1 files changed, 1396 insertions, 0 deletions
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 @@ | |||
| 1 | From 256d8d15acf98ee405f79b75a52692531d173f49 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Ferenc Wagner <wferi@niif.hu> | ||
| 3 | Date: Wed, 2 Nov 2011 10:03:38 +0100 | ||
| 4 | Subject: [PATCH 0/9] check_http: add support for chunked encoding via http-parser | ||
| 5 | |||
| 6 | Hi, | ||
| 7 | |||
| 8 | Here is an attempt to add support for chunked encoding in check_http | ||
| 9 | by switching to the third-party HTTP parser from Joyent hosted at | ||
| 10 | https://github.com/joyent/http-parser. The switch makes much of the | ||
| 11 | in-house ad-hoc parsing code redundant, and induces some changes in | ||
| 12 | the semantics of the -e switch, but that should be regarded as a step | ||
| 13 | forward, since the role of that switch was to verify HTTP correctness | ||
| 14 | (at least in part) and now we have a much better mechanism for that: | ||
| 15 | the parser itself. The pagesize limits (-m switch) also gained a | ||
| 16 | clearer semantics: they check the content size now, as that may be | ||
| 17 | available even when -N is used, and does not depend on the transfer | ||
| 18 | encoding. | ||
| 19 | |||
| 20 | Ferenc Wagner (9): | ||
| 21 | check_http: do not print page length if body was not read | ||
| 22 | Add lib/http-parser submodule and adjust Makefile.am to use it in | ||
| 23 | check_http | ||
| 24 | check_http: move status code and redirect location parsing to | ||
| 25 | http-parser | ||
| 26 | check_http: whitespace change to fix up indentation by removing dummy | ||
| 27 | block | ||
| 28 | check_http: constify and rename the location argument for redir() | ||
| 29 | check_http: make list of parsed headers configurable | ||
| 30 | check_http: use header parsing machinery in check_document_dates() | ||
| 31 | check_http: also read the response content via http-parse | ||
| 32 | check_http: check content length instead of response length | ||
| 33 | |||
| 34 | .gitmodules | 3 + | ||
| 35 | lib/Makefile.am | 10 +- | ||
| 36 | lib/http-parser | 1 + | ||
| 37 | plugins/Makefile.am | 9 +- | ||
| 38 | plugins/check_http.c | 596 ++++++++++++++++++++------------------------------ | ||
| 39 | 5 files changed, 256 insertions(+), 363 deletions(-) | ||
| 40 | create mode 100644 .gitmodules | ||
| 41 | create mode 160000 lib/http-parser | ||
| 42 | |||
| 43 | -- | ||
| 44 | 1.7.2.5 | ||
| 45 | |||
| 46 | From abc1d1c539376cb5531a9686e581ff62acf421e5 Mon Sep 17 00:00:00 2001 | ||
| 47 | From: Ferenc Wagner <wferi@niif.hu> | ||
| 48 | Date: Mon, 31 Oct 2011 15:10:54 +0100 | ||
| 49 | Subject: [PATCH 1/9] check_http: do not print page length if body was not read | ||
| 50 | |||
| 51 | |||
| 52 | Signed-off-by: Ferenc Wagner <wferi@niif.hu> | ||
| 53 | --- | ||
| 54 | plugins/check_http.c | 2 +- | ||
| 55 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
| 56 | |||
| 57 | diff --git a/plugins/check_http.c b/plugins/check_http.c | ||
| 58 | index 433c28e..6df9d23 100644 | ||
| 59 | --- a/plugins/check_http.c | ||
| 60 | +++ b/plugins/check_http.c | ||
| 61 | @@ -923,7 +923,7 @@ check_http (void) | ||
| 62 | /* leave full_page untouched so we can free it later */ | ||
| 63 | page = full_page; | ||
| 64 | |||
| 65 | - if (verbose) | ||
| 66 | + if (verbose && !no_body) | ||
| 67 | printf ("%s://%s:%d%s is %d characters\n", | ||
| 68 | use_ssl ? "https" : "http", server_address, | ||
| 69 | server_port, server_url, (int)pagesize); | ||
| 70 | -- | ||
| 71 | 1.7.2.5 | ||
| 72 | |||
| 73 | |||
| 74 | From 27536d84b73489308f129ff5623ffd1445dfc5fb Mon Sep 17 00:00:00 2001 | ||
| 75 | From: Ferenc Wagner <wferi@niif.hu> | ||
| 76 | Date: Mon, 31 Oct 2011 15:14:38 +0100 | ||
| 77 | Subject: [PATCH 2/9] Add lib/http-parser submodule and adjust Makefile.am to use it in check_http | ||
| 78 | |||
| 79 | |||
| 80 | Signed-off-by: Ferenc Wagner <wferi@niif.hu> | ||
| 81 | --- | ||
| 82 | .gitmodules | 3 +++ | ||
| 83 | lib/Makefile.am | 10 +++++++++- | ||
| 84 | lib/http-parser | 1 + | ||
| 85 | plugins/Makefile.am | 9 +++++---- | ||
| 86 | 4 files changed, 18 insertions(+), 5 deletions(-) | ||
| 87 | create mode 100644 .gitmodules | ||
| 88 | create mode 160000 lib/http-parser | ||
| 89 | |||
| 90 | diff --git a/.gitmodules b/.gitmodules | ||
| 91 | new file mode 100644 | ||
| 92 | index 0000000..5270743 | ||
| 93 | --- /dev/null | ||
| 94 | +++ b/.gitmodules | ||
| 95 | @@ -0,0 +1,3 @@ | ||
| 96 | +[submodule "lib/http-parser"] | ||
| 97 | + path = lib/http-parser | ||
| 98 | + url = git://github.com/joyent/http-parser.git | ||
| 99 | diff --git a/lib/Makefile.am b/lib/Makefile.am | ||
| 100 | index 99fa591..561b7cf 100644 | ||
| 101 | --- a/lib/Makefile.am | ||
| 102 | +++ b/lib/Makefile.am | ||
| 103 | @@ -2,7 +2,7 @@ | ||
| 104 | |||
| 105 | SUBDIRS = . tests | ||
| 106 | |||
| 107 | -noinst_LIBRARIES = libnagiosplug.a | ||
| 108 | +noinst_LIBRARIES = libnagiosplug.a http-parser/libhttp_parser.a | ||
| 109 | |||
| 110 | AM_CPPFLAGS = -DNP_STATE_DIR_PREFIX=\"$(localstatedir)\" | ||
| 111 | |||
| 112 | @@ -18,3 +18,11 @@ INCLUDES = -I$(srcdir) -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/p | ||
| 113 | test test-debug: | ||
| 114 | cd tests && make $@ | ||
| 115 | |||
| 116 | +http-parser/libhttp_parser.a: | ||
| 117 | + cd http-parser && $(MAKE) package | ||
| 118 | + | ||
| 119 | +mostlyclean-local: | ||
| 120 | + cd http-parser && $(MAKE) clean | ||
| 121 | + | ||
| 122 | +check-local: | ||
| 123 | + cd http-parser && $(MAKE) test | ||
| 124 | diff --git a/lib/http-parser b/lib/http-parser | ||
| 125 | new file mode 160000 | ||
| 126 | index 0000000..f1d48aa | ||
| 127 | --- /dev/null | ||
| 128 | +++ b/lib/http-parser | ||
| 129 | @@ -0,0 +1 @@ | ||
| 130 | +Subproject commit f1d48aa31c932f80a64122a75a87bc909b4073f9 | ||
| 131 | diff --git a/plugins/Makefile.am b/plugins/Makefile.am | ||
| 132 | index 36a28b0..2df105e 100644 | ||
| 133 | --- a/plugins/Makefile.am | ||
| 134 | +++ b/plugins/Makefile.am | ||
| 135 | @@ -13,7 +13,7 @@ AM_CFLAGS = -DNP_VERSION='"$(NP_VERSION)"' | ||
| 136 | |||
| 137 | VPATH = $(top_srcdir) $(top_srcdir)/lib $(top_srcdir)/plugins $(top_srcdir)/plugins/t | ||
| 138 | |||
| 139 | -INCLUDES = -I.. -I$(top_srcdir)/lib -I$(top_srcdir)/gl -I$(top_srcdir)/intl @LDAPINCLUDE@ @PGINCLUDE@ @SSLINCLUDE@ | ||
| 140 | +INCLUDES = -I.. -I$(top_srcdir)/lib -I$(top_srcdir)/lib/http-parser -I$(top_srcdir)/gl -I$(top_srcdir)/intl @LDAPINCLUDE@ @PGINCLUDE@ @SSLINCLUDE@ | ||
| 141 | |||
| 142 | localedir = $(datadir)/locale | ||
| 143 | # gettext docs say to use AM_CPPFLAGS, but per module_CPPFLAGS override this | ||
| 144 | @@ -48,6 +48,7 @@ BASEOBJS = utils.o ../lib/libnagiosplug.a ../gl/libgnu.a | ||
| 145 | NETOBJS = netutils.o $(BASEOBJS) $(EXTRA_NETOBJS) | ||
| 146 | SSLOBJS = sslutils.o | ||
| 147 | NETLIBS = $(NETOBJS) $(SOCKETLIBS) | ||
| 148 | +HTTPPARSER = ../lib/http-parser/libhttp_parser.a | ||
| 149 | |||
| 150 | TESTS_ENVIRONMENT = perl -I $(top_builddir) -I $(top_srcdir) | ||
| 151 | |||
| 152 | @@ -70,7 +71,7 @@ check_dns_LDADD = $(NETLIBS) runcmd.o | ||
| 153 | check_dummy_LDADD = $(BASEOBJS) | ||
| 154 | check_fping_LDADD = $(NETLIBS) popen.o | ||
| 155 | check_game_LDADD = $(BASEOBJS) runcmd.o | ||
| 156 | -check_http_LDADD = $(SSLOBJS) $(NETLIBS) $(SSLLIBS) | ||
| 157 | +check_http_LDADD = $(SSLOBJS) $(NETLIBS) $(SSLLIBS) $(HTTPPARSER) | ||
| 158 | check_hpjd_LDADD = $(NETLIBS) popen.o | ||
| 159 | check_ldap_LDADD = $(NETLIBS) $(LDAPLIBS) | ||
| 160 | check_load_LDADD = $(BASEOBJS) popen.o | ||
| 161 | @@ -115,7 +116,7 @@ check_dns_DEPENDENCIES = check_dns.c $(NETOBJS) runcmd.o $(DEPLIBS) | ||
| 162 | check_dummy_DEPENDENCIES = check_dummy.c $(DEPLIBS) | ||
| 163 | check_fping_DEPENDENCIES = check_fping.c $(NETOBJS) popen.o $(DEPLIBS) | ||
| 164 | check_game_DEPENDENCIES = check_game.c $(DEPLIBS) runcmd.o | ||
| 165 | -check_http_DEPENDENCIES = check_http.c $(SSLOBJS) $(NETOBJS) $(DEPLIBS) | ||
| 166 | +check_http_DEPENDENCIES = check_http.c $(SSLOBJS) $(NETOBJS) $(DEPLIBS) $(HTTPPARSER) | ||
| 167 | check_hpjd_DEPENDENCIES = check_hpjd.c $(NETOBJS) popen.o $(DEPLIBS) | ||
| 168 | check_ide_smart_DEPENDENCIES = check_ide_smart.c $(BASEOBJS) $(DEPLIBS) | ||
| 169 | check_ldap_DEPENDENCIES = check_ldap.c $(NETOBJS) $(DEPLIBS) | ||
| 170 | @@ -170,7 +171,7 @@ install-exec-hook: | ||
| 171 | cd $(DESTDIR)$(libexecdir) && \ | ||
| 172 | for i in $(check_tcp_programs) ; do rm -f $$i; ln -s check_tcp $$i ; done ;\ | ||
| 173 | if [ -x check_ldap ] ; then rm -f check_ldaps ; ln -s check_ldap check_ldaps ; fi | ||
| 174 | - | ||
| 175 | + | ||
| 176 | clean-local: | ||
| 177 | rm -f $(check_tcp_programs) | ||
| 178 | rm -f NP-VERSION-FILE | ||
| 179 | -- | ||
| 180 | 1.7.2.5 | ||
| 181 | |||
| 182 | |||
| 183 | From e8b35f17bf23515dc43233ebbde1c0ccb11d5ecb Mon Sep 17 00:00:00 2001 | ||
| 184 | From: Ferenc Wagner <wferi@niif.hu> | ||
| 185 | Date: Mon, 31 Oct 2011 15:20:48 +0100 | ||
| 186 | Subject: [PATCH 3/9] check_http: move status code and redirect location parsing to http-parser | ||
| 187 | |||
| 188 | This changes the semantics of the -e switch, as http-parser doesn't make | ||
| 189 | the status string available. But it does substantial HTTP verification, | ||
| 190 | so much of the original functionality will be regained once HTTP parsing | ||
| 191 | errors become CRITICAL. | ||
| 192 | |||
| 193 | This introduces some new gettext strings. | ||
| 194 | |||
| 195 | Signed-off-by: Ferenc Wagner <wferi@niif.hu> | ||
| 196 | --- | ||
| 197 | plugins/check_http.c | 264 +++++++++++++++++++++++++------------------------- | ||
| 198 | 1 files changed, 131 insertions(+), 133 deletions(-) | ||
| 199 | |||
| 200 | diff --git a/plugins/check_http.c b/plugins/check_http.c | ||
| 201 | index 6df9d23..ada7a95 100644 | ||
| 202 | --- a/plugins/check_http.c | ||
| 203 | +++ b/plugins/check_http.c | ||
| 204 | @@ -41,6 +41,7 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; | ||
| 205 | #include "netutils.h" | ||
| 206 | #include "utils.h" | ||
| 207 | #include "base64.h" | ||
| 208 | +#include "http_parser.h" | ||
| 209 | #include <ctype.h> | ||
| 210 | |||
| 211 | #define INPUT_DELIMITER ";" | ||
| 212 | @@ -48,7 +49,15 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; | ||
| 213 | #define STICKY_HOST 1 | ||
| 214 | #define STICKY_PORT 2 | ||
| 215 | |||
| 216 | -#define HTTP_EXPECT "HTTP/1." | ||
| 217 | +struct parser_data_t { | ||
| 218 | + enum http_errno prev_callback; /* use HPE_CB_ macros for identifying callbacks */ | ||
| 219 | + char *current_header; | ||
| 220 | + size_t current_header_length; | ||
| 221 | + int parsing_location; | ||
| 222 | + char *location; | ||
| 223 | + size_t location_length; | ||
| 224 | +}; | ||
| 225 | + | ||
| 226 | enum { | ||
| 227 | MAX_IPV4_HOSTLENGTH = 255, | ||
| 228 | HTTP_PORT = 80, | ||
| 229 | @@ -97,8 +106,7 @@ char *host_name; | ||
| 230 | char *server_url; | ||
| 231 | char *user_agent; | ||
| 232 | int server_url_length; | ||
| 233 | -int server_expect_yn = 0; | ||
| 234 | -char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT; | ||
| 235 | +int status_expect = -1; | ||
| 236 | char string_expect[MAX_INPUT_BUFFER] = ""; | ||
| 237 | char output_string_search[30] = ""; | ||
| 238 | char *warning_thresholds = NULL; | ||
| 239 | @@ -126,7 +134,7 @@ char buffer[MAX_INPUT_BUFFER]; | ||
| 240 | |||
| 241 | int process_arguments (int, char **); | ||
| 242 | int check_http (void); | ||
| 243 | -void redir (char *pos, char *status_line); | ||
| 244 | +void redir (char *pos); | ||
| 245 | int server_type_check(const char *type); | ||
| 246 | int server_port_check(int ssl_flag); | ||
| 247 | char *perfd_time (double microsec); | ||
| 248 | @@ -367,10 +375,8 @@ process_arguments (int argc, char **argv) | ||
| 249 | strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1); | ||
| 250 | string_expect[MAX_INPUT_BUFFER - 1] = 0; | ||
| 251 | break; | ||
| 252 | - case 'e': /* string or substring */ | ||
| 253 | - strncpy (server_expect, optarg, MAX_INPUT_BUFFER - 1); | ||
| 254 | - server_expect[MAX_INPUT_BUFFER - 1] = 0; | ||
| 255 | - server_expect_yn = 1; | ||
| 256 | + case 'e': /* expected HTTP response code */ | ||
| 257 | + status_expect = atoi (optarg); | ||
| 258 | break; | ||
| 259 | case 'T': /* Content-type */ | ||
| 260 | asprintf (&http_content_type, "%s", optarg); | ||
| 261 | @@ -589,26 +595,6 @@ parse_time_string (const char *string) | ||
| 262 | } | ||
| 263 | } | ||
| 264 | |||
| 265 | -/* Checks if the server 'reply' is one of the expected 'statuscodes' */ | ||
| 266 | -static int | ||
| 267 | -expected_statuscode (const char *reply, const char *statuscodes) | ||
| 268 | -{ | ||
| 269 | - char *expected, *code; | ||
| 270 | - int result = 0; | ||
| 271 | - | ||
| 272 | - if ((expected = strdup (statuscodes)) == NULL) | ||
| 273 | - die (STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n")); | ||
| 274 | - | ||
| 275 | - for (code = strtok (expected, ","); code != NULL; code = strtok (NULL, ",")) | ||
| 276 | - if (strstr (reply, code) != NULL) { | ||
| 277 | - result = 1; | ||
| 278 | - break; | ||
| 279 | - } | ||
| 280 | - | ||
| 281 | - free (expected); | ||
| 282 | - return result; | ||
| 283 | -} | ||
| 284 | - | ||
| 285 | static int | ||
| 286 | check_document_dates (const char *headers, char **msg) | ||
| 287 | { | ||
| 288 | @@ -772,16 +758,78 @@ prepend_slash (char *path) | ||
| 289 | return newpath; | ||
| 290 | } | ||
| 291 | |||
| 292 | +/* | ||
| 293 | +Returns 0 on success, 1 if allocation fails. | ||
| 294 | +Works on binary data, but also zero-terminates the result | ||
| 295 | +for easier string handling. | ||
| 296 | +*/ | ||
| 297 | +int | ||
| 298 | +append (char **orig, size_t *orig_len, const char *extra, size_t len) | ||
| 299 | +{ | ||
| 300 | + *orig = realloc (*orig, *orig_len + len + 1); | ||
| 301 | + if (!*orig) return 1; | ||
| 302 | + memcpy (*orig + *orig_len, extra, len); | ||
| 303 | + *orig_len += len; | ||
| 304 | + (*orig)[*orig_len] = 0; | ||
| 305 | + return 0; | ||
| 306 | +} | ||
| 307 | + | ||
| 308 | +int | ||
| 309 | +header_field_callback (http_parser *parser, const char *at, size_t length) | ||
| 310 | +{ | ||
| 311 | + struct parser_data_t *data = parser->data; | ||
| 312 | + | ||
| 313 | + switch (data->prev_callback) { | ||
| 314 | + case HPE_CB_header_value: | ||
| 315 | + data->current_header_length = 0; | ||
| 316 | + /* fall through */ | ||
| 317 | + case 0: | ||
| 318 | + data->prev_callback = HPE_CB_header_field; | ||
| 319 | + /* fall through */ | ||
| 320 | + case HPE_CB_header_field: | ||
| 321 | + return append (&data->current_header, &data->current_header_length, at, length); | ||
| 322 | + default: | ||
| 323 | + return 1; | ||
| 324 | + } | ||
| 325 | +} | ||
| 326 | + | ||
| 327 | +int | ||
| 328 | +header_value_callback (http_parser *parser, const char *at, size_t length) | ||
| 329 | +{ | ||
| 330 | + struct parser_data_t *data = parser->data; | ||
| 331 | + | ||
| 332 | + switch (data->prev_callback) { | ||
| 333 | + case HPE_CB_header_field: | ||
| 334 | + data->parsing_location = !strcasecmp (data->current_header, "location"); | ||
| 335 | + data->prev_callback = HPE_CB_header_value; | ||
| 336 | + /* fall through */ | ||
| 337 | + case HPE_CB_header_value: | ||
| 338 | + return data->parsing_location && | ||
| 339 | + append (&data->location, &data->location_length, at, length); | ||
| 340 | + default: | ||
| 341 | + return 1; | ||
| 342 | + } | ||
| 343 | +} | ||
| 344 | + | ||
| 345 | +int | ||
| 346 | +headers_complete_callback (http_parser *parser) | ||
| 347 | +{ | ||
| 348 | + struct parser_data_t *data = parser->data; | ||
| 349 | + | ||
| 350 | + data->prev_callback = HPE_CB_headers_complete; | ||
| 351 | + | ||
| 352 | + if (no_body) /* Terminate parsing (thus reading) if the -N option is set */ | ||
| 353 | + return 2; /* 1 means don't expect body in this callback */ | ||
| 354 | + return 0; | ||
| 355 | +} | ||
| 356 | + | ||
| 357 | int | ||
| 358 | check_http (void) | ||
| 359 | { | ||
| 360 | char *msg; | ||
| 361 | - char *status_line; | ||
| 362 | - char *status_code; | ||
| 363 | char *header; | ||
| 364 | char *page; | ||
| 365 | char *auth; | ||
| 366 | - int http_status; | ||
| 367 | int i = 0; | ||
| 368 | size_t pagesize = 0; | ||
| 369 | char *full_page; | ||
| 370 | @@ -792,6 +840,9 @@ check_http (void) | ||
| 371 | double elapsed_time; | ||
| 372 | int page_len = 0; | ||
| 373 | int result = STATE_OK; | ||
| 374 | + http_parser_settings settings; | ||
| 375 | + http_parser parser; | ||
| 376 | + struct parser_data_t parser_data; | ||
| 377 | |||
| 378 | /* try to connect to the host at the given port number */ | ||
| 379 | if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK) | ||
| 380 | @@ -869,9 +920,29 @@ check_http (void) | ||
| 381 | if (verbose) printf ("%s\n", buf); | ||
| 382 | my_send (buf, strlen (buf)); | ||
| 383 | |||
| 384 | + /* Initialize the HTTP parser */ | ||
| 385 | + http_parser_init (&parser, HTTP_RESPONSE); | ||
| 386 | + memset (&parser_data, 0, sizeof parser_data); | ||
| 387 | + parser.data = &parser_data; | ||
| 388 | + memset (&settings, 0, sizeof settings); | ||
| 389 | + settings.on_header_field = header_field_callback; | ||
| 390 | + settings.on_header_value = header_value_callback; | ||
| 391 | + settings.on_headers_complete = headers_complete_callback; | ||
| 392 | + | ||
| 393 | /* fetch the page */ | ||
| 394 | full_page = strdup(""); | ||
| 395 | - while ((i = my_recv (buffer, MAX_INPUT_BUFFER-1)) > 0) { | ||
| 396 | + while ((i = my_recv (buffer, MAX_INPUT_BUFFER-1)) >= 0) { | ||
| 397 | + int nparsed = http_parser_execute(&parser, &settings, buffer, i); | ||
| 398 | + if (nparsed != i) { | ||
| 399 | + enum http_errno code = HTTP_PARSER_ERRNO (&parser); | ||
| 400 | + if (code == HPE_CB_headers_complete) { /* the -N check fired */ | ||
| 401 | + /* break; FIXME this would break the current header code */ | ||
| 402 | + } else { | ||
| 403 | + printf ("http_parser_execute returned %d instead of %i: %s\n", | ||
| 404 | + nparsed, i, http_errno_description (code)); | ||
| 405 | + } | ||
| 406 | + } | ||
| 407 | + if (i == 0) break; | ||
| 408 | buffer[i] = '\0'; | ||
| 409 | asprintf (&full_page_new, "%s%s", full_page, buffer); | ||
| 410 | free (full_page); | ||
| 411 | @@ -928,15 +999,9 @@ check_http (void) | ||
| 412 | use_ssl ? "https" : "http", server_address, | ||
| 413 | server_port, server_url, (int)pagesize); | ||
| 414 | |||
| 415 | - /* find status line and null-terminate it */ | ||
| 416 | - status_line = page; | ||
| 417 | + /* skip status line */ | ||
| 418 | page += (size_t) strcspn (page, "\r\n"); | ||
| 419 | - pos = page; | ||
| 420 | page += (size_t) strspn (page, "\r\n"); | ||
| 421 | - status_line[strcspn(status_line, "\r\n")] = 0; | ||
| 422 | - strip (status_line); | ||
| 423 | - if (verbose) | ||
| 424 | - printf ("STATUS: %s\n", status_line); | ||
| 425 | |||
| 426 | /* find header info and null-terminate it */ | ||
| 427 | header = page; | ||
| 428 | @@ -955,68 +1020,38 @@ check_http (void) | ||
| 429 | printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header, | ||
| 430 | (no_body ? " [[ skipped ]]" : page)); | ||
| 431 | |||
| 432 | - /* make sure the status line matches the response we are looking for */ | ||
| 433 | - if (!expected_statuscode (status_line, server_expect)) { | ||
| 434 | - if (server_port == HTTP_PORT) | ||
| 435 | - asprintf (&msg, | ||
| 436 | - _("Invalid HTTP response received from host: %s\n"), | ||
| 437 | - status_line); | ||
| 438 | - else | ||
| 439 | - asprintf (&msg, | ||
| 440 | - _("Invalid HTTP response received from host on port %d: %s\n"), | ||
| 441 | - server_port, status_line); | ||
| 442 | - die (STATE_CRITICAL, "HTTP CRITICAL - %s", msg); | ||
| 443 | - } | ||
| 444 | - | ||
| 445 | - /* Bypass normal status line check if server_expect was set by user and not default */ | ||
| 446 | - /* NOTE: After this if/else block msg *MUST* be an asprintf-allocated string */ | ||
| 447 | - if ( server_expect_yn ) { | ||
| 448 | - asprintf (&msg, | ||
| 449 | - _("Status line output matched \"%s\" - "), server_expect); | ||
| 450 | - if (verbose) | ||
| 451 | - printf ("%s\n",msg); | ||
| 452 | - } | ||
| 453 | - else { | ||
| 454 | - /* Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF */ | ||
| 455 | - /* HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT */ | ||
| 456 | - /* Status-Code = 3 DIGITS */ | ||
| 457 | - | ||
| 458 | - status_code = strchr (status_line, ' ') + sizeof (char); | ||
| 459 | - if (strspn (status_code, "1234567890") != 3) | ||
| 460 | - die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status Line (%s)\n"), status_line); | ||
| 461 | - | ||
| 462 | - http_status = atoi (status_code); | ||
| 463 | - | ||
| 464 | - /* check the return code */ | ||
| 465 | - | ||
| 466 | - if (http_status >= 600 || http_status < 100) { | ||
| 467 | - die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%s)\n"), status_line); | ||
| 468 | + if (status_expect != -1) { | ||
| 469 | + if (parser.status_code == status_expect) | ||
| 470 | + asprintf (&msg, _("Got expected code %d - "), status_expect); | ||
| 471 | + else { | ||
| 472 | + asprintf (&msg, _("Invalid HTTP status received from host: %d\n"), | ||
| 473 | + parser.status_code); | ||
| 474 | + die (STATE_CRITICAL, "HTTP CRITICAL - %s", msg); | ||
| 475 | + } | ||
| 476 | + } else { | ||
| 477 | + if (parser.status_code >= 600 || parser.status_code < 100) { | ||
| 478 | + die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d)\n"), parser.status_code); | ||
| 479 | } | ||
| 480 | /* server errors result in a critical state */ | ||
| 481 | - else if (http_status >= 500) { | ||
| 482 | - asprintf (&msg, _("%s - "), status_line); | ||
| 483 | + else if (parser.status_code >= 500) { | ||
| 484 | result = STATE_CRITICAL; | ||
| 485 | } | ||
| 486 | /* client errors result in a warning state */ | ||
| 487 | - else if (http_status >= 400) { | ||
| 488 | - asprintf (&msg, _("%s - "), status_line); | ||
| 489 | + else if (parser.status_code >= 400) { | ||
| 490 | result = max_state_alt(STATE_WARNING, result); | ||
| 491 | } | ||
| 492 | /* check redirected page if specified */ | ||
| 493 | - else if (http_status >= 300) { | ||
| 494 | - | ||
| 495 | - if (onredirect == STATE_DEPENDENT) | ||
| 496 | - redir (header, status_line); | ||
| 497 | + else if (parser.status_code >= 300) { | ||
| 498 | + if (onredirect == STATE_DEPENDENT) { | ||
| 499 | + if (parser_data.location) | ||
| 500 | + redir (parser_data.location); | ||
| 501 | + else die (STATE_CRITICAL, _("Redirect without Location header\n")); | ||
| 502 | + } | ||
| 503 | else | ||
| 504 | result = max_state_alt(onredirect, result); | ||
| 505 | - asprintf (&msg, _("%s - "), status_line); | ||
| 506 | - } /* end if (http_status >= 300) */ | ||
| 507 | - else { | ||
| 508 | - /* Print OK status anyway */ | ||
| 509 | - asprintf (&msg, _("%s - "), status_line); | ||
| 510 | } | ||
| 511 | - | ||
| 512 | - } /* end else (server_expect_yn) */ | ||
| 513 | + asprintf (&msg, _("%d - "), parser.status_code); | ||
| 514 | + } | ||
| 515 | |||
| 516 | /* reset the alarm - must be called *after* redir or we'll never die on redirects! */ | ||
| 517 | alarm (0); | ||
| 518 | @@ -1111,11 +1146,10 @@ check_http (void) | ||
| 519 | #define HD5 URI_PATH | ||
| 520 | |||
| 521 | void | ||
| 522 | -redir (char *pos, char *status_line) | ||
| 523 | +redir (char *pos) | ||
| 524 | { | ||
| 525 | int i = 0; | ||
| 526 | char *x; | ||
| 527 | - char xx[2]; | ||
| 528 | char type[6]; | ||
| 529 | char *addr; | ||
| 530 | char *url; | ||
| 531 | @@ -1124,41 +1158,11 @@ redir (char *pos, char *status_line) | ||
| 532 | if (addr == NULL) | ||
| 533 | die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate addr\n")); | ||
| 534 | |||
| 535 | - url = malloc (strcspn (pos, "\r\n")); | ||
| 536 | + url = malloc (strlen (pos) + 1); | ||
| 537 | if (url == NULL) | ||
| 538 | die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n")); | ||
| 539 | |||
| 540 | - while (pos) { | ||
| 541 | - sscanf (pos, "%1[Ll]%*1[Oo]%*1[Cc]%*1[Aa]%*1[Tt]%*1[Ii]%*1[Oo]%*1[Nn]:%n", xx, &i); | ||
| 542 | - if (i == 0) { | ||
| 543 | - pos += (size_t) strcspn (pos, "\r\n"); | ||
| 544 | - pos += (size_t) strspn (pos, "\r\n"); | ||
| 545 | - if (strlen(pos) == 0) | ||
| 546 | - die (STATE_UNKNOWN, | ||
| 547 | - _("HTTP UNKNOWN - Could not find redirect location - %s%s\n"), | ||
| 548 | - status_line, (display_html ? "</A>" : "")); | ||
| 549 | - continue; | ||
| 550 | - } | ||
| 551 | - | ||
| 552 | - pos += i; | ||
| 553 | - pos += strspn (pos, " \t"); | ||
| 554 | - | ||
| 555 | - /* | ||
| 556 | - * RFC 2616 (4.2): ``Header fields can be extended over multiple lines by | ||
| 557 | - * preceding each extra line with at least one SP or HT.'' | ||
| 558 | - */ | ||
| 559 | - for (; (i = strspn (pos, "\r\n")); pos += i) { | ||
| 560 | - pos += i; | ||
| 561 | - if (!(i = strspn (pos, " \t"))) { | ||
| 562 | - die (STATE_UNKNOWN, _("HTTP UNKNOWN - Empty redirect location%s\n"), | ||
| 563 | - display_html ? "</A>" : ""); | ||
| 564 | - } | ||
| 565 | - } | ||
| 566 | - | ||
| 567 | - url = realloc (url, strcspn (pos, "\r\n") + 1); | ||
| 568 | - if (url == NULL) | ||
| 569 | - die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n")); | ||
| 570 | - | ||
| 571 | + { /* dummy block to reduce patch diff */ | ||
| 572 | /* URI_HTTP, URI_HOST, URI_PORT, URI_PATH */ | ||
| 573 | if (sscanf (pos, HD1, type, addr, &i, url) == 4) { | ||
| 574 | url = prepend_slash (url); | ||
| 575 | @@ -1203,10 +1207,7 @@ redir (char *pos, char *status_line) | ||
| 576 | _("HTTP UNKNOWN - Could not parse redirect location - %s%s\n"), | ||
| 577 | pos, (display_html ? "</A>" : "")); | ||
| 578 | } | ||
| 579 | - | ||
| 580 | - break; | ||
| 581 | - | ||
| 582 | - } /* end while (pos) */ | ||
| 583 | + } | ||
| 584 | |||
| 585 | if (++redir_depth > max_depth) | ||
| 586 | die (STATE_WARNING, | ||
| 587 | @@ -1332,11 +1333,8 @@ print_help (void) | ||
| 588 | printf (" %s\n", _("(when this option is used the URL is not checked.)\n")); | ||
| 589 | #endif | ||
| 590 | |||
| 591 | - printf (" %s\n", "-e, --expect=STRING"); | ||
| 592 | - printf (" %s\n", _("Comma-delimited list of strings, at least one of them is expected in")); | ||
| 593 | - printf (" %s", _("the first (status) line of the server response (default: ")); | ||
| 594 | - printf ("%s)\n", HTTP_EXPECT); | ||
| 595 | - printf (" %s\n", _("If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)")); | ||
| 596 | + printf (" %s\n", "-e, --expect=INTEGER"); | ||
| 597 | + printf (" %s\n", _("Expected HTTP status code, overriding the default logic")); | ||
| 598 | printf (" %s\n", "-s, --string=STRING"); | ||
| 599 | printf (" %s\n", _("String to expect in the content")); | ||
| 600 | printf (" %s\n", "-u, --url=PATH"); | ||
| 601 | -- | ||
| 602 | 1.7.2.5 | ||
| 603 | |||
| 604 | |||
| 605 | From a35b05d935f975478c90360ab56fb54d2d82e9c6 Mon Sep 17 00:00:00 2001 | ||
| 606 | From: Ferenc Wagner <wferi@niif.hu> | ||
| 607 | Date: Wed, 2 Nov 2011 09:52:19 +0100 | ||
| 608 | Subject: [PATCH 4/9] check_http: whitespace change to fix up indentation by removing dummy block | ||
| 609 | |||
| 610 | |||
| 611 | Signed-off-by: Ferenc Wagner <wferi@niif.hu> | ||
| 612 | --- | ||
| 613 | plugins/check_http.c | 76 ++++++++++++++++++++++++------------------------- | ||
| 614 | 1 files changed, 37 insertions(+), 39 deletions(-) | ||
| 615 | |||
| 616 | diff --git a/plugins/check_http.c b/plugins/check_http.c | ||
| 617 | index ada7a95..3966ab4 100644 | ||
| 618 | --- a/plugins/check_http.c | ||
| 619 | +++ b/plugins/check_http.c | ||
| 620 | @@ -1162,51 +1162,49 @@ redir (char *pos) | ||
| 621 | if (url == NULL) | ||
| 622 | die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n")); | ||
| 623 | |||
| 624 | - { /* dummy block to reduce patch diff */ | ||
| 625 | - /* URI_HTTP, URI_HOST, URI_PORT, URI_PATH */ | ||
| 626 | - if (sscanf (pos, HD1, type, addr, &i, url) == 4) { | ||
| 627 | - url = prepend_slash (url); | ||
| 628 | - use_ssl = server_type_check (type); | ||
| 629 | - } | ||
| 630 | + /* URI_HTTP, URI_HOST, URI_PORT, URI_PATH */ | ||
| 631 | + if (sscanf (pos, HD1, type, addr, &i, url) == 4) { | ||
| 632 | + url = prepend_slash (url); | ||
| 633 | + use_ssl = server_type_check (type); | ||
| 634 | + } | ||
| 635 | |||
| 636 | - /* URI_HTTP URI_HOST URI_PATH */ | ||
| 637 | - else if (sscanf (pos, HD2, type, addr, url) == 3 ) { | ||
| 638 | - url = prepend_slash (url); | ||
| 639 | - use_ssl = server_type_check (type); | ||
| 640 | - i = server_port_check (use_ssl); | ||
| 641 | - } | ||
| 642 | + /* URI_HTTP URI_HOST URI_PATH */ | ||
| 643 | + else if (sscanf (pos, HD2, type, addr, url) == 3 ) { | ||
| 644 | + url = prepend_slash (url); | ||
| 645 | + use_ssl = server_type_check (type); | ||
| 646 | + i = server_port_check (use_ssl); | ||
| 647 | + } | ||
| 648 | |||
| 649 | - /* URI_HTTP URI_HOST URI_PORT */ | ||
| 650 | - else if (sscanf (pos, HD3, type, addr, &i) == 3) { | ||
| 651 | - strcpy (url, HTTP_URL); | ||
| 652 | - use_ssl = server_type_check (type); | ||
| 653 | - } | ||
| 654 | + /* URI_HTTP URI_HOST URI_PORT */ | ||
| 655 | + else if (sscanf (pos, HD3, type, addr, &i) == 3) { | ||
| 656 | + strcpy (url, HTTP_URL); | ||
| 657 | + use_ssl = server_type_check (type); | ||
| 658 | + } | ||
| 659 | |||
| 660 | - /* URI_HTTP URI_HOST */ | ||
| 661 | - else if (sscanf (pos, HD4, type, addr) == 2) { | ||
| 662 | - strcpy (url, HTTP_URL); | ||
| 663 | - use_ssl = server_type_check (type); | ||
| 664 | - i = server_port_check (use_ssl); | ||
| 665 | - } | ||
| 666 | + /* URI_HTTP URI_HOST */ | ||
| 667 | + else if (sscanf (pos, HD4, type, addr) == 2) { | ||
| 668 | + strcpy (url, HTTP_URL); | ||
| 669 | + use_ssl = server_type_check (type); | ||
| 670 | + i = server_port_check (use_ssl); | ||
| 671 | + } | ||
| 672 | |||
| 673 | - /* URI_PATH */ | ||
| 674 | - else if (sscanf (pos, HD5, url) == 1) { | ||
| 675 | - /* relative url */ | ||
| 676 | - if ((url[0] != '/')) { | ||
| 677 | - if ((x = strrchr(server_url, '/'))) | ||
| 678 | - *x = '\0'; | ||
| 679 | - asprintf (&url, "%s/%s", server_url, url); | ||
| 680 | - } | ||
| 681 | - i = server_port; | ||
| 682 | - strcpy (type, server_type); | ||
| 683 | - strcpy (addr, host_name ? host_name : server_address); | ||
| 684 | + /* URI_PATH */ | ||
| 685 | + else if (sscanf (pos, HD5, url) == 1) { | ||
| 686 | + /* relative url */ | ||
| 687 | + if ((url[0] != '/')) { | ||
| 688 | + if ((x = strrchr(server_url, '/'))) | ||
| 689 | + *x = '\0'; | ||
| 690 | + asprintf (&url, "%s/%s", server_url, url); | ||
| 691 | } | ||
| 692 | + i = server_port; | ||
| 693 | + strcpy (type, server_type); | ||
| 694 | + strcpy (addr, host_name ? host_name : server_address); | ||
| 695 | + } | ||
| 696 | |||
| 697 | - else { | ||
| 698 | - die (STATE_UNKNOWN, | ||
| 699 | - _("HTTP UNKNOWN - Could not parse redirect location - %s%s\n"), | ||
| 700 | - pos, (display_html ? "</A>" : "")); | ||
| 701 | - } | ||
| 702 | + else { | ||
| 703 | + die (STATE_UNKNOWN, | ||
| 704 | + _("HTTP UNKNOWN - Could not parse redirect location - %s%s\n"), | ||
| 705 | + pos, (display_html ? "</A>" : "")); | ||
| 706 | } | ||
| 707 | |||
| 708 | if (++redir_depth > max_depth) | ||
| 709 | -- | ||
| 710 | 1.7.2.5 | ||
| 711 | |||
| 712 | |||
| 713 | From 3f410b149eb7cd112466bbb147525c1d497adaa2 Mon Sep 17 00:00:00 2001 | ||
| 714 | From: Ferenc Wagner <wferi@niif.hu> | ||
| 715 | Date: Mon, 31 Oct 2011 17:45:49 +0100 | ||
| 716 | Subject: [PATCH 5/9] check_http: constify and rename the location argument for redir() | ||
| 717 | |||
| 718 | |||
| 719 | Signed-off-by: Ferenc Wagner <wferi@niif.hu> | ||
| 720 | --- | ||
| 721 | plugins/check_http.c | 18 +++++++++--------- | ||
| 722 | 1 files changed, 9 insertions(+), 9 deletions(-) | ||
| 723 | |||
| 724 | diff --git a/plugins/check_http.c b/plugins/check_http.c | ||
| 725 | index 3966ab4..c4586d5 100644 | ||
| 726 | --- a/plugins/check_http.c | ||
| 727 | +++ b/plugins/check_http.c | ||
| 728 | @@ -134,7 +134,7 @@ char buffer[MAX_INPUT_BUFFER]; | ||
| 729 | |||
| 730 | int process_arguments (int, char **); | ||
| 731 | int check_http (void); | ||
| 732 | -void redir (char *pos); | ||
| 733 | +void redir (const char *location); | ||
| 734 | int server_type_check(const char *type); | ||
| 735 | int server_port_check(int ssl_flag); | ||
| 736 | char *perfd_time (double microsec); | ||
| 737 | @@ -1146,7 +1146,7 @@ check_http (void) | ||
| 738 | #define HD5 URI_PATH | ||
| 739 | |||
| 740 | void | ||
| 741 | -redir (char *pos) | ||
| 742 | +redir (const char *location) | ||
| 743 | { | ||
| 744 | int i = 0; | ||
| 745 | char *x; | ||
| 746 | @@ -1158,38 +1158,38 @@ redir (char *pos) | ||
| 747 | if (addr == NULL) | ||
| 748 | die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate addr\n")); | ||
| 749 | |||
| 750 | - url = malloc (strlen (pos) + 1); | ||
| 751 | + url = malloc (strlen (location) + 1); | ||
| 752 | if (url == NULL) | ||
| 753 | die (STATE_UNKNOWN, _("HTTP UNKNOWN - Could not allocate URL\n")); | ||
| 754 | |||
| 755 | /* URI_HTTP, URI_HOST, URI_PORT, URI_PATH */ | ||
| 756 | - if (sscanf (pos, HD1, type, addr, &i, url) == 4) { | ||
| 757 | + if (sscanf (location, HD1, type, addr, &i, url) == 4) { | ||
| 758 | url = prepend_slash (url); | ||
| 759 | use_ssl = server_type_check (type); | ||
| 760 | } | ||
| 761 | |||
| 762 | /* URI_HTTP URI_HOST URI_PATH */ | ||
| 763 | - else if (sscanf (pos, HD2, type, addr, url) == 3 ) { | ||
| 764 | + else if (sscanf (location, HD2, type, addr, url) == 3 ) { | ||
| 765 | url = prepend_slash (url); | ||
| 766 | use_ssl = server_type_check (type); | ||
| 767 | i = server_port_check (use_ssl); | ||
| 768 | } | ||
| 769 | |||
| 770 | /* URI_HTTP URI_HOST URI_PORT */ | ||
| 771 | - else if (sscanf (pos, HD3, type, addr, &i) == 3) { | ||
| 772 | + else if (sscanf (location, HD3, type, addr, &i) == 3) { | ||
| 773 | strcpy (url, HTTP_URL); | ||
| 774 | use_ssl = server_type_check (type); | ||
| 775 | } | ||
| 776 | |||
| 777 | /* URI_HTTP URI_HOST */ | ||
| 778 | - else if (sscanf (pos, HD4, type, addr) == 2) { | ||
| 779 | + else if (sscanf (location, HD4, type, addr) == 2) { | ||
| 780 | strcpy (url, HTTP_URL); | ||
| 781 | use_ssl = server_type_check (type); | ||
| 782 | i = server_port_check (use_ssl); | ||
| 783 | } | ||
| 784 | |||
| 785 | /* URI_PATH */ | ||
| 786 | - else if (sscanf (pos, HD5, url) == 1) { | ||
| 787 | + else if (sscanf (location, HD5, url) == 1) { | ||
| 788 | /* relative url */ | ||
| 789 | if ((url[0] != '/')) { | ||
| 790 | if ((x = strrchr(server_url, '/'))) | ||
| 791 | @@ -1204,7 +1204,7 @@ redir (char *pos) | ||
| 792 | else { | ||
| 793 | die (STATE_UNKNOWN, | ||
| 794 | _("HTTP UNKNOWN - Could not parse redirect location - %s%s\n"), | ||
| 795 | - pos, (display_html ? "</A>" : "")); | ||
| 796 | + location, (display_html ? "</A>" : "")); | ||
| 797 | } | ||
| 798 | |||
| 799 | if (++redir_depth > max_depth) | ||
| 800 | -- | ||
| 801 | 1.7.2.5 | ||
| 802 | |||
| 803 | |||
| 804 | From d1b806941bf6bf94754e86e832a11eabc003a656 Mon Sep 17 00:00:00 2001 | ||
| 805 | From: Ferenc Wagner <wferi@niif.hu> | ||
| 806 | Date: Mon, 31 Oct 2011 17:47:47 +0100 | ||
| 807 | Subject: [PATCH 6/9] check_http: make list of parsed headers configurable | ||
| 808 | |||
| 809 | |||
| 810 | Signed-off-by: Ferenc Wagner <wferi@niif.hu> | ||
| 811 | --- | ||
| 812 | plugins/check_http.c | 58 +++++++++++++++++++++++++++++++++++++++---------- | ||
| 813 | 1 files changed, 46 insertions(+), 12 deletions(-) | ||
| 814 | |||
| 815 | diff --git a/plugins/check_http.c b/plugins/check_http.c | ||
| 816 | index c4586d5..5466e06 100644 | ||
| 817 | --- a/plugins/check_http.c | ||
| 818 | +++ b/plugins/check_http.c | ||
| 819 | @@ -49,13 +49,17 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; | ||
| 820 | #define STICKY_HOST 1 | ||
| 821 | #define STICKY_PORT 2 | ||
| 822 | |||
| 823 | +struct header_data_t { | ||
| 824 | + const char *field; | ||
| 825 | + char *value; | ||
| 826 | +}; | ||
| 827 | + | ||
| 828 | struct parser_data_t { | ||
| 829 | enum http_errno prev_callback; /* use HPE_CB_ macros for identifying callbacks */ | ||
| 830 | - char *current_header; | ||
| 831 | - size_t current_header_length; | ||
| 832 | - int parsing_location; | ||
| 833 | - char *location; | ||
| 834 | - size_t location_length; | ||
| 835 | + char *current_field; | ||
| 836 | + size_t current_length; | ||
| 837 | + struct header_data_t *current_header; | ||
| 838 | + struct header_data_t *headers; | ||
| 839 | }; | ||
| 840 | |||
| 841 | enum { | ||
| 842 | @@ -758,6 +762,17 @@ prepend_slash (char *path) | ||
| 843 | return newpath; | ||
| 844 | } | ||
| 845 | |||
| 846 | +const char * | ||
| 847 | +get_value (const struct header_data_t *header, const char *field) | ||
| 848 | +{ | ||
| 849 | + while (header->field) { | ||
| 850 | + if (!strcasecmp (header->field, field)) | ||
| 851 | + return header->value; | ||
| 852 | + header++; | ||
| 853 | + } | ||
| 854 | + return 0; | ||
| 855 | +} | ||
| 856 | + | ||
| 857 | /* | ||
| 858 | Returns 0 on success, 1 if allocation fails. | ||
| 859 | Works on binary data, but also zero-terminates the result | ||
| 860 | @@ -781,13 +796,13 @@ header_field_callback (http_parser *parser, const char *at, size_t length) | ||
| 861 | |||
| 862 | switch (data->prev_callback) { | ||
| 863 | case HPE_CB_header_value: | ||
| 864 | - data->current_header_length = 0; | ||
| 865 | + data->current_length = 0; | ||
| 866 | /* fall through */ | ||
| 867 | case 0: | ||
| 868 | data->prev_callback = HPE_CB_header_field; | ||
| 869 | /* fall through */ | ||
| 870 | case HPE_CB_header_field: | ||
| 871 | - return append (&data->current_header, &data->current_header_length, at, length); | ||
| 872 | + return append (&data->current_field, &data->current_length, at, length); | ||
| 873 | default: | ||
| 874 | return 1; | ||
| 875 | } | ||
| 876 | @@ -797,15 +812,23 @@ int | ||
| 877 | header_value_callback (http_parser *parser, const char *at, size_t length) | ||
| 878 | { | ||
| 879 | struct parser_data_t *data = parser->data; | ||
| 880 | + struct header_data_t *header; | ||
| 881 | |||
| 882 | switch (data->prev_callback) { | ||
| 883 | case HPE_CB_header_field: | ||
| 884 | - data->parsing_location = !strcasecmp (data->current_header, "location"); | ||
| 885 | + data->current_header = 0; | ||
| 886 | + data->current_length = 0; | ||
| 887 | + for (header = data->headers; header->field; header++) | ||
| 888 | + if (!strcasecmp (data->current_field, header->field)) { | ||
| 889 | + data->current_header = header; | ||
| 890 | + break; | ||
| 891 | + } | ||
| 892 | data->prev_callback = HPE_CB_header_value; | ||
| 893 | /* fall through */ | ||
| 894 | case HPE_CB_header_value: | ||
| 895 | - return data->parsing_location && | ||
| 896 | - append (&data->location, &data->location_length, at, length); | ||
| 897 | + return data->current_header && | ||
| 898 | + append (&(data->current_header->value), | ||
| 899 | + &data->current_length, at, length); | ||
| 900 | default: | ||
| 901 | return 1; | ||
| 902 | } | ||
| 903 | @@ -816,6 +839,13 @@ headers_complete_callback (http_parser *parser) | ||
| 904 | { | ||
| 905 | struct parser_data_t *data = parser->data; | ||
| 906 | |||
| 907 | + if (verbose) { | ||
| 908 | + const struct header_data_t *header; | ||
| 909 | + printf ("Parsed headers:\n"); | ||
| 910 | + for (header = data->headers; header->field; header++) | ||
| 911 | + printf ("%s: %s\n", header->field, header->value); | ||
| 912 | + } | ||
| 913 | + | ||
| 914 | data->prev_callback = HPE_CB_headers_complete; | ||
| 915 | |||
| 916 | if (no_body) /* Terminate parsing (thus reading) if the -N option is set */ | ||
| 917 | @@ -843,6 +873,8 @@ check_http (void) | ||
| 918 | http_parser_settings settings; | ||
| 919 | http_parser parser; | ||
| 920 | struct parser_data_t parser_data; | ||
| 921 | + struct header_data_t interesting_headers[] = | ||
| 922 | + {{"location", 0}, {"date", 0}, {"last-modified", 0}, {0, 0}}; | ||
| 923 | |||
| 924 | /* try to connect to the host at the given port number */ | ||
| 925 | if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK) | ||
| 926 | @@ -923,6 +955,7 @@ check_http (void) | ||
| 927 | /* Initialize the HTTP parser */ | ||
| 928 | http_parser_init (&parser, HTTP_RESPONSE); | ||
| 929 | memset (&parser_data, 0, sizeof parser_data); | ||
| 930 | + parser_data.headers = interesting_headers; | ||
| 931 | parser.data = &parser_data; | ||
| 932 | memset (&settings, 0, sizeof settings); | ||
| 933 | settings.on_header_field = header_field_callback; | ||
| 934 | @@ -1043,8 +1076,9 @@ check_http (void) | ||
| 935 | /* check redirected page if specified */ | ||
| 936 | else if (parser.status_code >= 300) { | ||
| 937 | if (onredirect == STATE_DEPENDENT) { | ||
| 938 | - if (parser_data.location) | ||
| 939 | - redir (parser_data.location); | ||
| 940 | + const char *location = get_value (parser_data.headers, "location"); | ||
| 941 | + if (location) | ||
| 942 | + redir (location); | ||
| 943 | else die (STATE_CRITICAL, _("Redirect without Location header\n")); | ||
| 944 | } | ||
| 945 | else | ||
| 946 | -- | ||
| 947 | 1.7.2.5 | ||
| 948 | |||
| 949 | |||
| 950 | From 62e8868bb24c2161ccb7748dba82c6a90618aac3 Mon Sep 17 00:00:00 2001 | ||
| 951 | From: Ferenc Wagner <wferi@niif.hu> | ||
| 952 | Date: Mon, 31 Oct 2011 17:57:11 +0100 | ||
| 953 | Subject: [PATCH 7/9] check_http: use header parsing machinery in check_document_dates() | ||
| 954 | |||
| 955 | |||
| 956 | Signed-off-by: Ferenc Wagner <wferi@niif.hu> | ||
| 957 | --- | ||
| 958 | plugins/check_http.c | 61 +++---------------------------------------------- | ||
| 959 | 1 files changed, 4 insertions(+), 57 deletions(-) | ||
| 960 | |||
| 961 | diff --git a/plugins/check_http.c b/plugins/check_http.c | ||
| 962 | index 5466e06..423bb22 100644 | ||
| 963 | --- a/plugins/check_http.c | ||
| 964 | +++ b/plugins/check_http.c | ||
| 965 | @@ -600,63 +600,10 @@ parse_time_string (const char *string) | ||
| 966 | } | ||
| 967 | |||
| 968 | static int | ||
| 969 | -check_document_dates (const char *headers, char **msg) | ||
| 970 | +check_document_dates (const char *server_date, const char *document_date, char **msg) | ||
| 971 | { | ||
| 972 | - const char *s; | ||
| 973 | - char *server_date = 0; | ||
| 974 | - char *document_date = 0; | ||
| 975 | int date_result = STATE_OK; | ||
| 976 | |||
| 977 | - s = headers; | ||
| 978 | - while (*s) { | ||
| 979 | - const char *field = s; | ||
| 980 | - const char *value = 0; | ||
| 981 | - | ||
| 982 | - /* Find the end of the header field */ | ||
| 983 | - while (*s && !isspace(*s) && *s != ':') | ||
| 984 | - s++; | ||
| 985 | - | ||
| 986 | - /* Remember the header value, if any. */ | ||
| 987 | - if (*s == ':') | ||
| 988 | - value = ++s; | ||
| 989 | - | ||
| 990 | - /* Skip to the end of the header, including continuation lines. */ | ||
| 991 | - while (*s && !(*s == '\n' && (s[1] != ' ' && s[1] != '\t'))) | ||
| 992 | - s++; | ||
| 993 | - | ||
| 994 | - /* Avoid stepping over end-of-string marker */ | ||
| 995 | - if (*s) | ||
| 996 | - s++; | ||
| 997 | - | ||
| 998 | - /* Process this header. */ | ||
| 999 | - if (value && value > field+2) { | ||
| 1000 | - char *ff = (char *) malloc (value-field); | ||
| 1001 | - char *ss = ff; | ||
| 1002 | - while (field < value-1) | ||
| 1003 | - *ss++ = tolower(*field++); | ||
| 1004 | - *ss++ = 0; | ||
| 1005 | - | ||
| 1006 | - if (!strcmp (ff, "date") || !strcmp (ff, "last-modified")) { | ||
| 1007 | - const char *e; | ||
| 1008 | - while (*value && isspace (*value)) | ||
| 1009 | - value++; | ||
| 1010 | - for (e = value; *e && *e != '\r' && *e != '\n'; e++) | ||
| 1011 | - ; | ||
| 1012 | - ss = (char *) malloc (e - value + 1); | ||
| 1013 | - strncpy (ss, value, e - value); | ||
| 1014 | - ss[e - value] = 0; | ||
| 1015 | - if (!strcmp (ff, "date")) { | ||
| 1016 | - if (server_date) free (server_date); | ||
| 1017 | - server_date = ss; | ||
| 1018 | - } else { | ||
| 1019 | - if (document_date) free (document_date); | ||
| 1020 | - document_date = ss; | ||
| 1021 | - } | ||
| 1022 | - } | ||
| 1023 | - free (ff); | ||
| 1024 | - } | ||
| 1025 | - } | ||
| 1026 | - | ||
| 1027 | /* Done parsing the body. Now check the dates we (hopefully) parsed. */ | ||
| 1028 | if (!server_date || !*server_date) { | ||
| 1029 | asprintf (msg, _("%sServer date unknown, "), *msg); | ||
| 1030 | @@ -687,8 +634,6 @@ check_document_dates (const char *headers, char **msg) | ||
| 1031 | date_result = max_state_alt(STATE_CRITICAL, date_result); | ||
| 1032 | } | ||
| 1033 | } | ||
| 1034 | - free (server_date); | ||
| 1035 | - free (document_date); | ||
| 1036 | } | ||
| 1037 | return date_result; | ||
| 1038 | } | ||
| 1039 | @@ -1091,7 +1036,9 @@ check_http (void) | ||
| 1040 | alarm (0); | ||
| 1041 | |||
| 1042 | if (maximum_age >= 0) { | ||
| 1043 | - result = max_state_alt(check_document_dates(header, &msg), result); | ||
| 1044 | + result = max_state_alt(check_document_dates(get_value (parser_data.headers, "date"), | ||
| 1045 | + get_value (parser_data.headers, "last-modified"), &msg), | ||
| 1046 | + result); | ||
| 1047 | } | ||
| 1048 | |||
| 1049 | /* Page and Header content checks go here */ | ||
| 1050 | -- | ||
| 1051 | 1.7.2.5 | ||
| 1052 | |||
| 1053 | |||
| 1054 | From efe4e949ae4ba64f333f402d0f4b54f07b18164c Mon Sep 17 00:00:00 2001 | ||
| 1055 | From: Ferenc Wagner <wferi@niif.hu> | ||
| 1056 | Date: Tue, 1 Nov 2011 16:17:00 +0100 | ||
| 1057 | Subject: [PATCH 8/9] check_http: also read the response content via http-parse | ||
| 1058 | |||
| 1059 | This gets rid of good a bunch of code, and also gives free decoding of | ||
| 1060 | Transfer-Encoding: chunked, which all HTTP/1.1 clients must support. | ||
| 1061 | |||
| 1062 | Signed-off-by: Ferenc Wagner <wferi@niif.hu> | ||
| 1063 | --- | ||
| 1064 | plugins/check_http.c | 86 ++++++++++++------------------------------------- | ||
| 1065 | 1 files changed, 21 insertions(+), 65 deletions(-) | ||
| 1066 | |||
| 1067 | diff --git a/plugins/check_http.c b/plugins/check_http.c | ||
| 1068 | index 423bb22..deea38c 100644 | ||
| 1069 | --- a/plugins/check_http.c | ||
| 1070 | +++ b/plugins/check_http.c | ||
| 1071 | @@ -60,6 +60,7 @@ struct parser_data_t { | ||
| 1072 | size_t current_length; | ||
| 1073 | struct header_data_t *current_header; | ||
| 1074 | struct header_data_t *headers; | ||
| 1075 | + char *content; | ||
| 1076 | }; | ||
| 1077 | |||
| 1078 | enum { | ||
| 1079 | @@ -488,26 +489,6 @@ process_arguments (int argc, char **argv) | ||
| 1080 | return TRUE; | ||
| 1081 | } | ||
| 1082 | |||
| 1083 | - | ||
| 1084 | - | ||
| 1085 | -/* Returns 1 if we're done processing the document body; 0 to keep going */ | ||
| 1086 | -static int | ||
| 1087 | -document_headers_done (char *full_page) | ||
| 1088 | -{ | ||
| 1089 | - const char *body; | ||
| 1090 | - | ||
| 1091 | - for (body = full_page; *body; body++) { | ||
| 1092 | - if (!strncmp (body, "\n\n", 2) || !strncmp (body, "\n\r\n", 3)) | ||
| 1093 | - break; | ||
| 1094 | - } | ||
| 1095 | - | ||
| 1096 | - if (!*body) | ||
| 1097 | - return 0; /* haven't read end of headers yet */ | ||
| 1098 | - | ||
| 1099 | - full_page[body - full_page] = 0; | ||
| 1100 | - return 1; | ||
| 1101 | -} | ||
| 1102 | - | ||
| 1103 | static time_t | ||
| 1104 | parse_time_string (const char *string) | ||
| 1105 | { | ||
| 1106 | @@ -792,6 +773,7 @@ headers_complete_callback (http_parser *parser) | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | data->prev_callback = HPE_CB_headers_complete; | ||
| 1110 | + data->current_length = 0; /* prepare for the body */ | ||
| 1111 | |||
| 1112 | if (no_body) /* Terminate parsing (thus reading) if the -N option is set */ | ||
| 1113 | return 2; /* 1 means don't expect body in this callback */ | ||
| 1114 | @@ -799,16 +781,20 @@ headers_complete_callback (http_parser *parser) | ||
| 1115 | } | ||
| 1116 | |||
| 1117 | int | ||
| 1118 | +body_callback (http_parser *parser, const char *at, size_t length) | ||
| 1119 | +{ | ||
| 1120 | + struct parser_data_t *data = parser->data; | ||
| 1121 | + | ||
| 1122 | + return append (&data->content, &data->current_length, at, length); | ||
| 1123 | +} | ||
| 1124 | + | ||
| 1125 | +int | ||
| 1126 | check_http (void) | ||
| 1127 | { | ||
| 1128 | char *msg; | ||
| 1129 | - char *header; | ||
| 1130 | - char *page; | ||
| 1131 | char *auth; | ||
| 1132 | int i = 0; | ||
| 1133 | size_t pagesize = 0; | ||
| 1134 | - char *full_page; | ||
| 1135 | - char *full_page_new; | ||
| 1136 | char *buf; | ||
| 1137 | char *pos; | ||
| 1138 | long microsec; | ||
| 1139 | @@ -906,31 +892,19 @@ check_http (void) | ||
| 1140 | settings.on_header_field = header_field_callback; | ||
| 1141 | settings.on_header_value = header_value_callback; | ||
| 1142 | settings.on_headers_complete = headers_complete_callback; | ||
| 1143 | + settings.on_body = body_callback; | ||
| 1144 | |||
| 1145 | /* fetch the page */ | ||
| 1146 | - full_page = strdup(""); | ||
| 1147 | while ((i = my_recv (buffer, MAX_INPUT_BUFFER-1)) >= 0) { | ||
| 1148 | int nparsed = http_parser_execute(&parser, &settings, buffer, i); | ||
| 1149 | + pagesize += i; | ||
| 1150 | if (nparsed != i) { | ||
| 1151 | enum http_errno code = HTTP_PARSER_ERRNO (&parser); | ||
| 1152 | - if (code == HPE_CB_headers_complete) { /* the -N check fired */ | ||
| 1153 | - /* break; FIXME this would break the current header code */ | ||
| 1154 | - } else { | ||
| 1155 | - printf ("http_parser_execute returned %d instead of %i: %s\n", | ||
| 1156 | - nparsed, i, http_errno_description (code)); | ||
| 1157 | - } | ||
| 1158 | + if (code == HPE_CB_headers_complete) break; /* the -N check fired */ | ||
| 1159 | + else die (STATE_CRITICAL, _("HTTP CRITICAL - error parsing response: %s"), | ||
| 1160 | + http_errno_description (code)); | ||
| 1161 | } | ||
| 1162 | if (i == 0) break; | ||
| 1163 | - buffer[i] = '\0'; | ||
| 1164 | - asprintf (&full_page_new, "%s%s", full_page, buffer); | ||
| 1165 | - free (full_page); | ||
| 1166 | - full_page = full_page_new; | ||
| 1167 | - pagesize += i; | ||
| 1168 | - | ||
| 1169 | - if (no_body && document_headers_done (full_page)) { | ||
| 1170 | - i = 0; | ||
| 1171 | - break; | ||
| 1172 | - } | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | if (i < 0 && errno != ECONNRESET) { | ||
| 1176 | @@ -969,34 +943,16 @@ check_http (void) | ||
| 1177 | microsec = deltime (tv); | ||
| 1178 | elapsed_time = (double)microsec / 1.0e6; | ||
| 1179 | |||
| 1180 | - /* leave full_page untouched so we can free it later */ | ||
| 1181 | - page = full_page; | ||
| 1182 | - | ||
| 1183 | if (verbose && !no_body) | ||
| 1184 | printf ("%s://%s:%d%s is %d characters\n", | ||
| 1185 | use_ssl ? "https" : "http", server_address, | ||
| 1186 | server_port, server_url, (int)pagesize); | ||
| 1187 | |||
| 1188 | - /* skip status line */ | ||
| 1189 | - page += (size_t) strcspn (page, "\r\n"); | ||
| 1190 | - page += (size_t) strspn (page, "\r\n"); | ||
| 1191 | - | ||
| 1192 | - /* find header info and null-terminate it */ | ||
| 1193 | - header = page; | ||
| 1194 | - while (strcspn (page, "\r\n") > 0) { | ||
| 1195 | - page += (size_t) strcspn (page, "\r\n"); | ||
| 1196 | - pos = page; | ||
| 1197 | - if ((strspn (page, "\r") == 1 && strspn (page, "\r\n") >= 2) || | ||
| 1198 | - (strspn (page, "\n") == 1 && strspn (page, "\r\n") >= 2)) | ||
| 1199 | - page += (size_t) 2; | ||
| 1200 | - else | ||
| 1201 | - page += (size_t) 1; | ||
| 1202 | + if (verbose && !no_body) { | ||
| 1203 | + puts ("**** CONTENT ****"); | ||
| 1204 | + fwrite (parser_data.content, parser_data.current_length, 1, stdout); | ||
| 1205 | + putchar ('\n'); | ||
| 1206 | } | ||
| 1207 | - page += (size_t) strspn (page, "\r\n"); | ||
| 1208 | - header[pos - header] = 0; | ||
| 1209 | - if (verbose) | ||
| 1210 | - printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header, | ||
| 1211 | - (no_body ? " [[ skipped ]]" : page)); | ||
| 1212 | |||
| 1213 | if (status_expect != -1) { | ||
| 1214 | if (parser.status_code == status_expect) | ||
| 1215 | @@ -1044,7 +1000,7 @@ check_http (void) | ||
| 1216 | /* Page and Header content checks go here */ | ||
| 1217 | |||
| 1218 | if (strlen (string_expect)) { | ||
| 1219 | - if (!strstr (page, string_expect)) { | ||
| 1220 | + if (!strstr (parser_data.content, string_expect)) { | ||
| 1221 | strncpy(&output_string_search[0],string_expect,sizeof(output_string_search)); | ||
| 1222 | if(output_string_search[sizeof(output_string_search)-1]!='\0') { | ||
| 1223 | bcopy("...",&output_string_search[sizeof(output_string_search)-4],4); | ||
| 1224 | @@ -1055,7 +1011,7 @@ check_http (void) | ||
| 1225 | } | ||
| 1226 | |||
| 1227 | if (strlen (regexp)) { | ||
| 1228 | - errcode = regexec (&preg, page, REGS, pmatch, 0); | ||
| 1229 | + errcode = regexec (&preg, parser_data.content, REGS, pmatch, 0); | ||
| 1230 | if ((errcode == 0 && invert_regex == 0) || (errcode == REG_NOMATCH && invert_regex == 1)) { | ||
| 1231 | /* OK - No-op to avoid changing the logic around it */ | ||
| 1232 | result = max_state_alt(STATE_OK, result); | ||
| 1233 | -- | ||
| 1234 | 1.7.2.5 | ||
| 1235 | |||
| 1236 | |||
| 1237 | From 256d8d15acf98ee405f79b75a52692531d173f49 Mon Sep 17 00:00:00 2001 | ||
| 1238 | From: Ferenc Wagner <wferi@niif.hu> | ||
| 1239 | Date: Wed, 2 Nov 2011 07:57:30 +0100 | ||
| 1240 | Subject: [PATCH 9/9] check_http: check content length instead of response length | ||
| 1241 | |||
| 1242 | The content length does not depend on the transfer encoding and may | ||
| 1243 | be possible to derive without fetching the entire body (cf. -N option). | ||
| 1244 | |||
| 1245 | Signed-off-by: Ferenc Wagner <wferi@niif.hu> | ||
| 1246 | --- | ||
| 1247 | plugins/check_http.c | 93 +++++++++++--------------------------------------- | ||
| 1248 | 1 files changed, 20 insertions(+), 73 deletions(-) | ||
| 1249 | |||
| 1250 | diff --git a/plugins/check_http.c b/plugins/check_http.c | ||
| 1251 | index deea38c..27f5cd3 100644 | ||
| 1252 | --- a/plugins/check_http.c | ||
| 1253 | +++ b/plugins/check_http.c | ||
| 1254 | @@ -619,59 +619,6 @@ check_document_dates (const char *server_date, const char *document_date, char * | ||
| 1255 | return date_result; | ||
| 1256 | } | ||
| 1257 | |||
| 1258 | -int | ||
| 1259 | -get_content_length (const char *headers) | ||
| 1260 | -{ | ||
| 1261 | - const char *s; | ||
| 1262 | - int content_length = 0; | ||
| 1263 | - | ||
| 1264 | - s = headers; | ||
| 1265 | - while (*s) { | ||
| 1266 | - const char *field = s; | ||
| 1267 | - const char *value = 0; | ||
| 1268 | - | ||
| 1269 | - /* Find the end of the header field */ | ||
| 1270 | - while (*s && !isspace(*s) && *s != ':') | ||
| 1271 | - s++; | ||
| 1272 | - | ||
| 1273 | - /* Remember the header value, if any. */ | ||
| 1274 | - if (*s == ':') | ||
| 1275 | - value = ++s; | ||
| 1276 | - | ||
| 1277 | - /* Skip to the end of the header, including continuation lines. */ | ||
| 1278 | - while (*s && !(*s == '\n' && (s[1] != ' ' && s[1] != '\t'))) | ||
| 1279 | - s++; | ||
| 1280 | - | ||
| 1281 | - /* Avoid stepping over end-of-string marker */ | ||
| 1282 | - if (*s) | ||
| 1283 | - s++; | ||
| 1284 | - | ||
| 1285 | - /* Process this header. */ | ||
| 1286 | - if (value && value > field+2) { | ||
| 1287 | - char *ff = (char *) malloc (value-field); | ||
| 1288 | - char *ss = ff; | ||
| 1289 | - while (field < value-1) | ||
| 1290 | - *ss++ = tolower(*field++); | ||
| 1291 | - *ss++ = 0; | ||
| 1292 | - | ||
| 1293 | - if (!strcmp (ff, "content-length")) { | ||
| 1294 | - const char *e; | ||
| 1295 | - while (*value && isspace (*value)) | ||
| 1296 | - value++; | ||
| 1297 | - for (e = value; *e && *e != '\r' && *e != '\n'; e++) | ||
| 1298 | - ; | ||
| 1299 | - ss = (char *) malloc (e - value + 1); | ||
| 1300 | - strncpy (ss, value, e - value); | ||
| 1301 | - ss[e - value] = 0; | ||
| 1302 | - content_length = atoi(ss); | ||
| 1303 | - free (ss); | ||
| 1304 | - } | ||
| 1305 | - free (ff); | ||
| 1306 | - } | ||
| 1307 | - } | ||
| 1308 | - return (content_length); | ||
| 1309 | -} | ||
| 1310 | - | ||
| 1311 | char * | ||
| 1312 | prepend_slash (char *path) | ||
| 1313 | { | ||
| 1314 | @@ -799,13 +746,13 @@ check_http (void) | ||
| 1315 | char *pos; | ||
| 1316 | long microsec; | ||
| 1317 | double elapsed_time; | ||
| 1318 | - int page_len = 0; | ||
| 1319 | + int page_len = -1; | ||
| 1320 | int result = STATE_OK; | ||
| 1321 | http_parser_settings settings; | ||
| 1322 | http_parser parser; | ||
| 1323 | struct parser_data_t parser_data; | ||
| 1324 | struct header_data_t interesting_headers[] = | ||
| 1325 | - {{"location", 0}, {"date", 0}, {"last-modified", 0}, {0, 0}}; | ||
| 1326 | + {{"location", 0}, {"date", 0}, {"last-modified", 0}, {"content-length", 0}, {0, 0}}; | ||
| 1327 | |||
| 1328 | /* try to connect to the host at the given port number */ | ||
| 1329 | if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK) | ||
| 1330 | @@ -1031,21 +978,21 @@ check_http (void) | ||
| 1331 | } | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | - /* make sure the page is of an appropriate size */ | ||
| 1335 | - /* page_len = get_content_length(header); */ | ||
| 1336 | - /* FIXME: Will this work with -N ? IMHO we should use | ||
| 1337 | - * get_content_length(header) and always check if it's different than the | ||
| 1338 | - * returned pagesize | ||
| 1339 | - */ | ||
| 1340 | - /* FIXME: IIRC pagesize returns headers - shouldn't we make | ||
| 1341 | - * it == get_content_length(header) ?? | ||
| 1342 | - */ | ||
| 1343 | - page_len = pagesize; | ||
| 1344 | - if ((max_page_len > 0) && (page_len > max_page_len)) { | ||
| 1345 | - asprintf (&msg, _("%spage size %d too large, "), msg, page_len); | ||
| 1346 | - result = max_state_alt(STATE_WARNING, result); | ||
| 1347 | - } else if ((min_page_len > 0) && (page_len < min_page_len)) { | ||
| 1348 | - asprintf (&msg, _("%spage size %d too small, "), msg, page_len); | ||
| 1349 | + /* make sure the content is of an appropriate size */ | ||
| 1350 | + if (no_body) { | ||
| 1351 | + const char *content_length = get_value (parser_data.headers, "content-length"); | ||
| 1352 | + if (content_length) page_len = atol (content_length); | ||
| 1353 | + } else page_len = parser_data.current_length; | ||
| 1354 | + if (page_len != -1) { | ||
| 1355 | + if ((max_page_len > 0) && (page_len > max_page_len)) { | ||
| 1356 | + asprintf (&msg, _("%spage size %d too large, "), msg, page_len); | ||
| 1357 | + result = max_state_alt(STATE_WARNING, result); | ||
| 1358 | + } else if ((min_page_len > 0) && (page_len < min_page_len)) { | ||
| 1359 | + asprintf (&msg, _("%spage size %d too small, "), msg, page_len); | ||
| 1360 | + result = max_state_alt(STATE_WARNING, result); | ||
| 1361 | + } | ||
| 1362 | + } else if (max_page_len > 0 || min_page_len > 0) { | ||
| 1363 | + asprintf (&msg, _("%spage size unknown, "), msg); | ||
| 1364 | result = max_state_alt(STATE_WARNING, result); | ||
| 1365 | } | ||
| 1366 | |||
| 1367 | @@ -1058,7 +1005,7 @@ check_http (void) | ||
| 1368 | /* check elapsed time */ | ||
| 1369 | asprintf (&msg, | ||
| 1370 | _("%s - %d bytes in %.3f second response time %s|%s %s"), | ||
| 1371 | - msg, page_len, elapsed_time, | ||
| 1372 | + msg, pagesize, elapsed_time, | ||
| 1373 | (display_html ? "</A>" : ""), | ||
| 1374 | perfd_time (elapsed_time), perfd_size (page_len)); | ||
| 1375 | |||
| 1376 | @@ -1310,7 +1257,7 @@ print_help (void) | ||
| 1377 | printf (" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the")); | ||
| 1378 | printf (" %s\n", _("specified IP address. stickyport also ensures port stays the same.")); | ||
| 1379 | printf (" %s\n", "-m, --pagesize=INTEGER<:INTEGER>"); | ||
| 1380 | - printf (" %s\n", _("Minimum page size required (bytes) : Maximum page size required (bytes)")); | ||
| 1381 | + printf (" %s\n", _("Minimum content size required (bytes) : Maximum content size required (bytes)")); | ||
| 1382 | |||
| 1383 | printf (UT_WARN_CRIT); | ||
| 1384 | |||
| 1385 | @@ -1361,7 +1308,7 @@ print_usage (void) | ||
| 1386 | printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-a auth]\n"); | ||
| 1387 | printf (" [-b proxy_auth] [-f <ok|warning|critcal|follow|sticky|stickyport>]\n"); | ||
| 1388 | printf (" [-e <expect>] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n"); | ||
| 1389 | - printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n"); | ||
| 1390 | + printf (" [-P string] [-m <min_cnt_size>:<max_cnt_size>] [-4|-6] [-N] [-M <age>]\n"); | ||
| 1391 | printf (" [-A string] [-k string] [-S] [--sni] [-C <age>] [-T <content-type>]\n"); | ||
| 1392 | printf (" [-j method]\n"); | ||
| 1393 | } | ||
| 1394 | -- | ||
| 1395 | 1.7.2.5 | ||
| 1396 | |||
