summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/check_curl.c787
-rw-r--r--plugins/check_curl.d/config.h48
2 files changed, 469 insertions, 366 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index 94b726d0..76dcbfd8 100644
--- a/plugins/check_curl.c
+++ b/plugins/check_curl.c
@@ -115,21 +115,37 @@ enum {
115#include "regex.h" 115#include "regex.h"
116 116
117// Globals 117// Globals
118static bool curl_global_initialized = false;
119static bool curl_easy_initialized = false;
120static int verbose = 0; 118static int verbose = 0;
121static bool body_buf_initialized = false; 119
122static curlhelp_write_curlbuf body_buf; 120typedef struct {
123static bool header_buf_initialized = false; 121 bool curl_global_initialized;
124static curlhelp_write_curlbuf header_buf; 122 bool curl_easy_initialized;
125static bool status_line_initialized = false; 123 bool body_buf_initialized;
126static curlhelp_statusline status_line; 124 curlhelp_write_curlbuf body_buf;
127static bool put_buf_initialized = false; 125 bool header_buf_initialized;
128static curlhelp_read_curlbuf put_buf; 126 curlhelp_write_curlbuf header_buf;
129 127 bool status_line_initialized;
130static CURL *curl; 128 curlhelp_statusline status_line;
131static struct curl_slist *header_list = NULL; 129 bool put_buf_initialized;
132static long code; 130 curlhelp_read_curlbuf put_buf;
131 CURL *curl;
132} check_curl_global_state;
133
134check_curl_global_state global_state = {
135 .curl_global_initialized = false,
136 .curl_easy_initialized = false,
137 .body_buf_initialized = false,
138 .body_buf = {},
139 .header_buf_initialized = false,
140 .header_buf = {},
141 .status_line_initialized = false,
142 .status_line = {},
143 .put_buf_initialized = false,
144 .put_buf = {},
145 .curl = NULL,
146};
147
148static long httpReturnCode;
133static char errbuf[MAX_INPUT_BUFFER]; 149static char errbuf[MAX_INPUT_BUFFER];
134static char msg[DEFAULT_BUFFER_SIZE]; 150static char msg[DEFAULT_BUFFER_SIZE];
135typedef union { 151typedef union {
@@ -143,8 +159,6 @@ static bool add_sslctx_verify_fun = false;
143static X509 *cert = NULL; 159static X509 *cert = NULL;
144#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */ 160#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */
145 161
146static curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN;
147
148typedef struct { 162typedef struct {
149 int errorcode; 163 int errorcode;
150 check_curl_config config; 164 check_curl_config config;
@@ -152,10 +166,16 @@ typedef struct {
152static check_curl_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); 166static check_curl_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
153 167
154static void handle_curl_option_return_code(CURLcode res, const char *option); 168static void handle_curl_option_return_code(CURLcode res, const char *option);
155static mp_state_enum check_http(check_curl_config /*config*/, int redir_depth); 169static mp_state_enum check_http(check_curl_config /*config*/, check_curl_working_state workingState,
170 int redir_depth, struct curl_slist *header_list);
156 171
157static void redir(curlhelp_write_curlbuf * /*header_buf*/, check_curl_config /*config*/, 172typedef struct {
158 int redir_depth); 173 int redir_depth;
174 check_curl_working_state working_state;
175 int error_code;
176} redir_wrapper;
177static redir_wrapper redir(curlhelp_write_curlbuf * /*header_buf*/, check_curl_config /*config*/,
178 int redir_depth, check_curl_working_state working_state);
159 179
160static char *perfd_time(double elapsed_time, thresholds * /*thlds*/, long /*socket_timeout*/); 180static char *perfd_time(double elapsed_time, thresholds * /*thlds*/, long /*socket_timeout*/);
161static char *perfd_time_connect(double elapsed_time_connect, long /*socket_timeout*/); 181static char *perfd_time_connect(double elapsed_time_connect, long /*socket_timeout*/);
@@ -218,14 +238,21 @@ int main(int argc, char **argv) {
218 } 238 }
219 239
220 if (config.display_html) { 240 if (config.display_html) {
221 printf("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">", config.use_ssl ? "https" : "http", 241 printf("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">",
222 config.host_name ? config.host_name : config.server_address, 242 config.initial_config.use_ssl ? "https" : "http",
223 config.virtual_port ? config.virtual_port : config.server_port, config.server_url); 243 config.initial_config.host_name ? config.initial_config.host_name
244 : config.initial_config.server_address,
245 config.initial_config.virtualPort ? config.initial_config.virtualPort
246 : config.initial_config.serverPort,
247 config.initial_config.server_url);
224 } 248 }
225 249
226 int redir_depth = 0; 250 int redir_depth = 0;
227 251
228 exit((int)check_http(config, redir_depth)); 252 check_curl_working_state working_state = config.initial_config;
253 struct curl_slist *header_list = NULL;
254
255 exit((int)check_http(config, working_state, redir_depth, header_list));
229} 256}
230 257
231#ifdef HAVE_SSL 258#ifdef HAVE_SSL
@@ -243,13 +270,11 @@ int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) {
243# endif 270# endif
244 if (verbose >= 2) { 271 if (verbose >= 2) {
245 puts("* SSL verify callback with certificate:"); 272 puts("* SSL verify callback with certificate:");
246 X509_NAME *subject;
247 X509_NAME *issuer;
248 printf("* issuer:\n"); 273 printf("* issuer:\n");
249 issuer = X509_get_issuer_name(cert); 274 X509_NAME *issuer = X509_get_issuer_name(cert);
250 X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE); 275 X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE);
251 printf("* curl verify_callback:\n* subject:\n"); 276 printf("* curl verify_callback:\n* subject:\n");
252 subject = X509_get_subject_name(cert); 277 X509_NAME *subject = X509_get_subject_name(cert);
253 X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE); 278 X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE);
254 puts(""); 279 puts("");
255 } 280 }
@@ -305,9 +330,8 @@ static bool expected_statuscode(const char *reply, const char *statuscodes) {
305 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n")); 330 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n"));
306 } 331 }
307 332
308 char *code;
309 bool result = false; 333 bool result = false;
310 for (code = strtok(expected, ","); code != NULL; code = strtok(NULL, ",")) { 334 for (char *code = strtok(expected, ","); code != NULL; code = strtok(NULL, ",")) {
311 if (strstr(reply, code) != NULL) { 335 if (strstr(reply, code) != NULL) {
312 result = true; 336 result = true;
313 break; 337 break;
@@ -328,11 +352,11 @@ void handle_curl_option_return_code(CURLcode res, const char *option) {
328} 352}
329 353
330int lookup_host(const char *host, char *buf, size_t buflen, sa_family_t addr_family) { 354int lookup_host(const char *host, char *buf, size_t buflen, sa_family_t addr_family) {
331 struct addrinfo hints; 355 struct addrinfo hints = {
332 memset(&hints, 0, sizeof(hints)); 356 .ai_family = addr_family,
333 hints.ai_family = addr_family; 357 .ai_socktype = SOCK_STREAM,
334 hints.ai_socktype = SOCK_STREAM; 358 .ai_flags = AI_CANONNAME,
335 hints.ai_flags |= AI_CANONNAME; 359 };
336 360
337 struct addrinfo *result; 361 struct addrinfo *result;
338 int errcode = getaddrinfo(host, NULL, &hints, &result); 362 int errcode = getaddrinfo(host, NULL, &hints, &result);
@@ -383,103 +407,115 @@ int lookup_host(const char *host, char *buf, size_t buflen, sa_family_t addr_fam
383} 407}
384 408
385static void cleanup(void) { 409static void cleanup(void) {
386 if (status_line_initialized) { 410 if (global_state.status_line_initialized) {
387 curlhelp_free_statusline(&status_line); 411 curlhelp_free_statusline(&global_state.status_line);
388 } 412 }
389 status_line_initialized = false; 413 global_state.status_line_initialized = false;
390 if (curl_easy_initialized) { 414
391 curl_easy_cleanup(curl); 415 if (global_state.curl_easy_initialized) {
416 curl_easy_cleanup(global_state.curl);
392 } 417 }
393 curl_easy_initialized = false; 418 global_state.curl_easy_initialized = false;
394 if (curl_global_initialized) { 419
420 if (global_state.curl_global_initialized) {
395 curl_global_cleanup(); 421 curl_global_cleanup();
396 } 422 }
397 curl_global_initialized = false; 423 global_state.curl_global_initialized = false;
398 if (body_buf_initialized) { 424
399 curlhelp_freewritebuffer(&body_buf); 425 if (global_state.body_buf_initialized) {
426 curlhelp_freewritebuffer(&global_state.body_buf);
400 } 427 }
401 body_buf_initialized = false; 428 global_state.body_buf_initialized = false;
402 if (header_buf_initialized) { 429
403 curlhelp_freewritebuffer(&header_buf); 430 if (global_state.header_buf_initialized) {
431 curlhelp_freewritebuffer(&global_state.header_buf);
404 } 432 }
405 header_buf_initialized = false; 433 global_state.header_buf_initialized = false;
406 if (put_buf_initialized) { 434
407 curlhelp_freereadbuffer(&put_buf); 435 if (global_state.put_buf_initialized) {
436 curlhelp_freereadbuffer(&global_state.put_buf);
408 } 437 }
409 put_buf_initialized = false; 438 global_state.put_buf_initialized = false;
410} 439}
411 440
412mp_state_enum check_http(check_curl_config config, int redir_depth) { 441mp_state_enum check_http(const check_curl_config config, check_curl_working_state workingState,
442 int redir_depth, struct curl_slist *header_list) {
413 /* initialize curl */ 443 /* initialize curl */
414 if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) { 444 if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) {
415 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n"); 445 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n");
416 } 446 }
417 curl_global_initialized = true; 447 global_state.curl_global_initialized = true;
418 448
419 if ((curl = curl_easy_init()) == NULL) { 449 if ((global_state.curl = curl_easy_init()) == NULL) {
420 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n"); 450 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n");
421 } 451 }
422 curl_easy_initialized = true; 452 global_state.curl_easy_initialized = true;
423 453
424 /* register cleanup function to shut down libcurl properly */ 454 /* register cleanup function to shut down libcurl properly */
425 atexit(cleanup); 455 atexit(cleanup);
426 456
427 if (verbose >= 1) { 457 if (verbose >= 1) {
428 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_VERBOSE, 1), 458 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_VERBOSE, 1),
429 "CURLOPT_VERBOSE"); 459 "CURLOPT_VERBOSE");
430 } 460 }
431 461
432 /* print everything on stdout like check_http would do */ 462 /* print everything on stdout like check_http would do */
433 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_STDERR, stdout), 463 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_STDERR, stdout),
434 "CURLOPT_STDERR"); 464 "CURLOPT_STDERR");
435 465
436 if (config.automatic_decompression) { 466 if (config.automatic_decompression) {
437#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) 467#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6)
438 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""), 468 handle_curl_option_return_code(
439 "CURLOPT_ACCEPT_ENCODING"); 469 curl_easy_setopt(global_state.curl, CURLOPT_ACCEPT_ENCODING, ""),
470 "CURLOPT_ACCEPT_ENCODING");
440#else 471#else
441 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ENCODING, ""), 472 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_ENCODING, ""),
442 "CURLOPT_ENCODING"); 473 "CURLOPT_ENCODING");
443#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */ 474#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */
444 } 475 }
445 476
446 /* initialize buffer for body of the answer */ 477 /* initialize buffer for body of the answer */
447 if (curlhelp_initwritebuffer(&body_buf) < 0) { 478 if (curlhelp_initwritebuffer(&global_state.body_buf) < 0) {
448 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n"); 479 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n");
449 } 480 }
450 body_buf_initialized = true; 481 global_state.body_buf_initialized = true;
451 handle_curl_option_return_code( 482 handle_curl_option_return_code(
452 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlhelp_buffer_write_callback), 483 curl_easy_setopt(global_state.curl, CURLOPT_WRITEFUNCTION, curlhelp_buffer_write_callback),
453 "CURLOPT_WRITEFUNCTION"); 484 "CURLOPT_WRITEFUNCTION");
454 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&body_buf), 485 handle_curl_option_return_code(
455 "CURLOPT_WRITEDATA"); 486 curl_easy_setopt(global_state.curl, CURLOPT_WRITEDATA, (void *)&global_state.body_buf),
487 "CURLOPT_WRITEDATA");
456 488
457 /* initialize buffer for header of the answer */ 489 /* initialize buffer for header of the answer */
458 if (curlhelp_initwritebuffer(&header_buf) < 0) { 490 if (curlhelp_initwritebuffer(&global_state.header_buf) < 0) {
459 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n"); 491 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n");
460 } 492 }
461 header_buf_initialized = true; 493 global_state.header_buf_initialized = true;
494
462 handle_curl_option_return_code( 495 handle_curl_option_return_code(
463 curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curlhelp_buffer_write_callback), 496 curl_easy_setopt(global_state.curl, CURLOPT_HEADERFUNCTION, curlhelp_buffer_write_callback),
464 "CURLOPT_HEADERFUNCTION"); 497 "CURLOPT_HEADERFUNCTION");
465 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEHEADER, (void *)&header_buf), 498 handle_curl_option_return_code(
466 "CURLOPT_WRITEHEADER"); 499 curl_easy_setopt(global_state.curl, CURLOPT_WRITEHEADER, (void *)&global_state.header_buf),
500 "CURLOPT_WRITEHEADER");
467 501
468 /* set the error buffer */ 502 /* set the error buffer */
469 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf), 503 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_ERRORBUFFER, errbuf),
470 "CURLOPT_ERRORBUFFER"); 504 "CURLOPT_ERRORBUFFER");
471 505
472 /* set timeouts */ 506 /* set timeouts */
473 handle_curl_option_return_code( 507 handle_curl_option_return_code(
474 curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, config.socket_timeout), 508 curl_easy_setopt(global_state.curl, CURLOPT_CONNECTTIMEOUT, config.socket_timeout),
475 "CURLOPT_CONNECTTIMEOUT"); 509 "CURLOPT_CONNECTTIMEOUT");
476 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_TIMEOUT, config.socket_timeout), 510 handle_curl_option_return_code(
477 "CURLOPT_TIMEOUT"); 511 curl_easy_setopt(global_state.curl, CURLOPT_TIMEOUT, config.socket_timeout),
512 "CURLOPT_TIMEOUT");
478 513
479 /* enable haproxy protocol */ 514 /* enable haproxy protocol */
480 if (config.haproxy_protocol) { 515 if (config.haproxy_protocol) {
481 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L), 516 handle_curl_option_return_code(
482 "CURLOPT_HAPROXYPROTOCOL"); 517 curl_easy_setopt(global_state.curl, CURLOPT_HAPROXYPROTOCOL, 1L),
518 "CURLOPT_HAPROXYPROTOCOL");
483 } 519 }
484 520
485 // fill dns resolve cache to make curl connect to the given server_address instead of the 521 // fill dns resolve cache to make curl connect to the given server_address instead of the
@@ -487,19 +523,19 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
487 struct curl_slist *host = NULL; 523 struct curl_slist *host = NULL;
488 char dnscache[DEFAULT_BUFFER_SIZE]; 524 char dnscache[DEFAULT_BUFFER_SIZE];
489 char addrstr[DEFAULT_BUFFER_SIZE / 2]; 525 char addrstr[DEFAULT_BUFFER_SIZE / 2];
490 if (config.use_ssl && config.host_name != NULL) { 526 if (workingState.use_ssl && workingState.host_name != NULL) {
491 int res; 527 int res;
492 if ((res = lookup_host(config.server_address, addrstr, DEFAULT_BUFFER_SIZE / 2, 528 if ((res = lookup_host(workingState.server_address, addrstr, DEFAULT_BUFFER_SIZE / 2,
493 config.sin_family)) != 0) { 529 config.sin_family)) != 0) {
494 snprintf(msg, DEFAULT_BUFFER_SIZE, 530 snprintf(msg, DEFAULT_BUFFER_SIZE,
495 _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"), 531 _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"),
496 config.server_address, res, gai_strerror(res)); 532 workingState.server_address, res, gai_strerror(res));
497 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 533 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
498 } 534 }
499 snprintf(dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", config.host_name, config.server_port, 535 snprintf(dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", workingState.host_name,
500 addrstr); 536 workingState.serverPort, addrstr);
501 host = curl_slist_append(NULL, dnscache); 537 host = curl_slist_append(NULL, dnscache);
502 curl_easy_setopt(curl, CURLOPT_RESOLVE, host); 538 curl_easy_setopt(global_state.curl, CURLOPT_RESOLVE, host);
503 if (verbose >= 1) { 539 if (verbose >= 1) {
504 printf("* curl CURLOPT_RESOLVE: %s\n", dnscache); 540 printf("* curl CURLOPT_RESOLVE: %s\n", dnscache);
505 } 541 }
@@ -507,66 +543,73 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
507 543
508 // If server_address is an IPv6 address it must be surround by square brackets 544 // If server_address is an IPv6 address it must be surround by square brackets
509 struct in6_addr tmp_in_addr; 545 struct in6_addr tmp_in_addr;
510 if (inet_pton(AF_INET6, config.server_address, &tmp_in_addr) == 1) { 546 if (inet_pton(AF_INET6, workingState.server_address, &tmp_in_addr) == 1) {
511 char *new_server_address = malloc(strlen(config.server_address) + 3); 547 char *new_server_address = malloc(strlen(workingState.server_address) + 3);
512 if (new_server_address == NULL) { 548 if (new_server_address == NULL) {
513 die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n"); 549 die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n");
514 } 550 }
515 snprintf(new_server_address, strlen(config.server_address) + 3, "[%s]", 551 snprintf(new_server_address, strlen(workingState.server_address) + 3, "[%s]",
516 config.server_address); 552 workingState.server_address);
517 free(config.server_address); 553 free(workingState.server_address);
518 config.server_address = new_server_address; 554 workingState.server_address = new_server_address;
519 } 555 }
520 556
521 /* compose URL: use the address we want to connect to, set Host: header later */ 557 /* compose URL: use the address we want to connect to, set Host: header later */
522 char url[DEFAULT_BUFFER_SIZE]; 558 char url[DEFAULT_BUFFER_SIZE];
523 snprintf(url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", config.use_ssl ? "https" : "http", 559 snprintf(url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", workingState.use_ssl ? "https" : "http",
524 (config.use_ssl & (config.host_name != NULL)) ? config.host_name 560 (workingState.use_ssl & (workingState.host_name != NULL))
525 : config.server_address, 561 ? workingState.host_name
526 config.server_port, config.server_url); 562 : workingState.server_address,
563 workingState.serverPort, workingState.server_url);
527 564
528 if (verbose >= 1) { 565 if (verbose >= 1) {
529 printf("* curl CURLOPT_URL: %s\n", url); 566 printf("* curl CURLOPT_URL: %s\n", url);
530 } 567 }
531 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_URL, url), "CURLOPT_URL"); 568 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_URL, url),
569 "CURLOPT_URL");
532 570
533 /* extract proxy information for legacy proxy https requests */ 571 /* extract proxy information for legacy proxy https requests */
534 if (!strcmp(config.http_method, "CONNECT") || 572 if (!strcmp(workingState.http_method, "CONNECT") ||
535 strstr(config.server_url, "http") == config.server_url) { 573 strstr(workingState.server_url, "http") == workingState.server_url) {
536 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_PROXY, config.server_address), 574 handle_curl_option_return_code(
537 "CURLOPT_PROXY"); 575 curl_easy_setopt(global_state.curl, CURLOPT_PROXY, workingState.server_address),
576 "CURLOPT_PROXY");
538 handle_curl_option_return_code( 577 handle_curl_option_return_code(
539 curl_easy_setopt(curl, CURLOPT_PROXYPORT, (long)config.server_port), 578 curl_easy_setopt(global_state.curl, CURLOPT_PROXYPORT, (long)workingState.serverPort),
540 "CURLOPT_PROXYPORT"); 579 "CURLOPT_PROXYPORT");
541 if (verbose >= 2) { 580 if (verbose >= 2) {
542 printf("* curl CURLOPT_PROXY: %s:%d\n", config.server_address, config.server_port); 581 printf("* curl CURLOPT_PROXY: %s:%d\n", workingState.server_address,
582 workingState.serverPort);
543 } 583 }
544 config.http_method = "GET"; 584 workingState.http_method = "GET";
545 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_URL, config.server_url), 585 handle_curl_option_return_code(
546 "CURLOPT_URL"); 586 curl_easy_setopt(global_state.curl, CURLOPT_URL, workingState.server_url),
587 "CURLOPT_URL");
547 } 588 }
548 589
549 /* disable body for HEAD request */ 590 /* disable body for HEAD request */
550 if (config.http_method && !strcmp(config.http_method, "HEAD")) { 591 if (workingState.http_method && !strcmp(workingState.http_method, "HEAD")) {
551 config.no_body = true; 592 workingState.no_body = true;
552 } 593 }
553 594
554 /* set HTTP protocol version */ 595 /* set HTTP protocol version */
555 handle_curl_option_return_code( 596 handle_curl_option_return_code(
556 curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, config.curl_http_version), 597 curl_easy_setopt(global_state.curl, CURLOPT_HTTP_VERSION, config.curl_http_version),
557 "CURLOPT_HTTP_VERSION"); 598 "CURLOPT_HTTP_VERSION");
558 599
559 /* set HTTP method */ 600 /* set HTTP method */
560 if (config.http_method) { 601 if (workingState.http_method) {
561 if (!strcmp(config.http_method, "POST")) { 602 if (!strcmp(workingState.http_method, "POST")) {
562 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_POST, 1), "CURLOPT_POST"); 603 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_POST, 1),
563 } else if (!strcmp(config.http_method, "PUT")) { 604 "CURLOPT_POST");
564 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_UPLOAD, 1), 605 } else if (!strcmp(workingState.http_method, "PUT")) {
606 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_UPLOAD, 1),
565 "CURLOPT_UPLOAD"); 607 "CURLOPT_UPLOAD");
566 } else { 608 } else {
567 handle_curl_option_return_code( 609 handle_curl_option_return_code(curl_easy_setopt(global_state.curl,
568 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, config.http_method), 610 CURLOPT_CUSTOMREQUEST,
569 "CURLOPT_CUSTOMREQUEST"); 611 workingState.http_method),
612 "CURLOPT_CUSTOMREQUEST");
570 } 613 }
571 } 614 }
572 615
@@ -583,13 +626,13 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
583 /* set hostname (virtual hosts), not needed if CURLOPT_CONNECT_TO is used, but left in 626 /* set hostname (virtual hosts), not needed if CURLOPT_CONNECT_TO is used, but left in
584 * anyway */ 627 * anyway */
585 char http_header[DEFAULT_BUFFER_SIZE]; 628 char http_header[DEFAULT_BUFFER_SIZE];
586 if (config.host_name != NULL && force_host_header == NULL) { 629 if (workingState.host_name != NULL && force_host_header == NULL) {
587 if ((config.virtual_port != HTTP_PORT && !config.use_ssl) || 630 if ((workingState.virtualPort != HTTP_PORT && !workingState.use_ssl) ||
588 (config.virtual_port != HTTPS_PORT && config.use_ssl)) { 631 (workingState.virtualPort != HTTPS_PORT && workingState.use_ssl)) {
589 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", config.host_name, 632 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", workingState.host_name,
590 config.virtual_port); 633 workingState.virtualPort);
591 } else { 634 } else {
592 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s", config.host_name); 635 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s", workingState.host_name);
593 } 636 }
594 header_list = curl_slist_append(header_list, http_header); 637 header_list = curl_slist_append(header_list, http_header);
595 } 638 }
@@ -604,57 +647,63 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
604 for (size_t i = 0; i < config.http_opt_headers_count; i++) { 647 for (size_t i = 0; i < config.http_opt_headers_count; i++) {
605 header_list = curl_slist_append(header_list, config.http_opt_headers[i]); 648 header_list = curl_slist_append(header_list, config.http_opt_headers[i]);
606 } 649 }
607 /* This cannot be free'd here because a redirection will then try to access this and
608 * segfault */
609 /* Covered in a testcase in tests/check_http.t */
610 /* free(http_opt_headers); */
611 } 650 }
612 651
613 /* set HTTP headers */ 652 /* set HTTP headers */
614 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list), 653 handle_curl_option_return_code(
615 "CURLOPT_HTTPHEADER"); 654 curl_easy_setopt(global_state.curl, CURLOPT_HTTPHEADER, header_list), "CURLOPT_HTTPHEADER");
616 655
617#ifdef LIBCURL_FEATURE_SSL 656#ifdef LIBCURL_FEATURE_SSL
618 657
619 /* set SSL version, warn about insecure or unsupported versions */ 658 /* set SSL version, warn about insecure or unsupported versions */
620 if (config.use_ssl) { 659 if (workingState.use_ssl) {
621 handle_curl_option_return_code( 660 handle_curl_option_return_code(
622 curl_easy_setopt(curl, CURLOPT_SSLVERSION, config.ssl_version), "CURLOPT_SSLVERSION"); 661 curl_easy_setopt(global_state.curl, CURLOPT_SSLVERSION, config.ssl_version),
662 "CURLOPT_SSLVERSION");
623 } 663 }
624 664
625 /* client certificate and key to present to server (SSL) */ 665 /* client certificate and key to present to server (SSL) */
626 if (config.client_cert) { 666 if (config.client_cert) {
627 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSLCERT, config.client_cert), 667 handle_curl_option_return_code(
628 "CURLOPT_SSLCERT"); 668 curl_easy_setopt(global_state.curl, CURLOPT_SSLCERT, config.client_cert),
669 "CURLOPT_SSLCERT");
629 } 670 }
671
630 if (config.client_privkey) { 672 if (config.client_privkey) {
631 handle_curl_option_return_code( 673 handle_curl_option_return_code(
632 curl_easy_setopt(curl, CURLOPT_SSLKEY, config.client_privkey), "CURLOPT_SSLKEY"); 674 curl_easy_setopt(global_state.curl, CURLOPT_SSLKEY, config.client_privkey),
675 "CURLOPT_SSLKEY");
633 } 676 }
677
634 if (config.ca_cert) { 678 if (config.ca_cert) {
635 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CAINFO, config.ca_cert), 679 handle_curl_option_return_code(
636 "CURLOPT_CAINFO"); 680 curl_easy_setopt(global_state.curl, CURLOPT_CAINFO, config.ca_cert), "CURLOPT_CAINFO");
637 } 681 }
682
638 if (config.ca_cert || config.verify_peer_and_host) { 683 if (config.ca_cert || config.verify_peer_and_host) {
639 /* per default if we have a CA verify both the peer and the 684 /* per default if we have a CA verify both the peer and the
640 * hostname in the certificate, can be switched off later */ 685 * hostname in the certificate, can be switched off later */
641 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1), 686 handle_curl_option_return_code(
642 "CURLOPT_SSL_VERIFYPEER"); 687 curl_easy_setopt(global_state.curl, CURLOPT_SSL_VERIFYPEER, 1),
643 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2), 688 "CURLOPT_SSL_VERIFYPEER");
644 "CURLOPT_SSL_VERIFYHOST"); 689 handle_curl_option_return_code(
690 curl_easy_setopt(global_state.curl, CURLOPT_SSL_VERIFYHOST, 2),
691 "CURLOPT_SSL_VERIFYHOST");
645 } else { 692 } else {
646 /* backward-compatible behaviour, be tolerant in checks 693 /* backward-compatible behaviour, be tolerant in checks
647 * TODO: depending on more options have aspects we want 694 * TODO: depending on more options have aspects we want
648 * to be less tolerant about ssl verfications 695 * to be less tolerant about ssl verfications
649 */ 696 */
650 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0), 697 handle_curl_option_return_code(
651 "CURLOPT_SSL_VERIFYPEER"); 698 curl_easy_setopt(global_state.curl, CURLOPT_SSL_VERIFYPEER, 0),
652 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0), 699 "CURLOPT_SSL_VERIFYPEER");
653 "CURLOPT_SSL_VERIFYHOST"); 700 handle_curl_option_return_code(
701 curl_easy_setopt(global_state.curl, CURLOPT_SSL_VERIFYHOST, 0),
702 "CURLOPT_SSL_VERIFYHOST");
654 } 703 }
655 704
656 /* detect SSL library used by libcurl */ 705 /* detect SSL library used by libcurl */
657 ssl_library = curlhelp_get_ssl_library(); 706 curlhelp_ssl_library ssl_library = curlhelp_get_ssl_library();
658 707
659 /* try hard to get a stack of certificates to verify against */ 708 /* try hard to get a stack of certificates to verify against */
660 if (config.check_cert) { 709 if (config.check_cert) {
@@ -672,15 +721,15 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
672# endif /* USE_OPENSSL */ 721# endif /* USE_OPENSSL */
673 /* libcurl is built with OpenSSL, monitoring plugins, so falling 722 /* libcurl is built with OpenSSL, monitoring plugins, so falling
674 * back to manually extracting certificate information */ 723 * back to manually extracting certificate information */
675 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), 724 handle_curl_option_return_code(
676 "CURLOPT_CERTINFO"); 725 curl_easy_setopt(global_state.curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
677 break; 726 break;
678 727
679 case CURLHELP_SSL_LIBRARY_NSS: 728 case CURLHELP_SSL_LIBRARY_NSS:
680# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 729# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
681 /* NSS: support for CERTINFO is implemented since 7.34.0 */ 730 /* NSS: support for CERTINFO is implemented since 7.34.0 */
682 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), 731 handle_curl_option_return_code(
683 "CURLOPT_CERTINFO"); 732 curl_easy_setopt(global_state.curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
684# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 733# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
685 die(STATE_CRITICAL, 734 die(STATE_CRITICAL,
686 "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library " 735 "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library "
@@ -692,8 +741,8 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
692 case CURLHELP_SSL_LIBRARY_GNUTLS: 741 case CURLHELP_SSL_LIBRARY_GNUTLS:
693# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) 742# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0)
694 /* GnuTLS: support for CERTINFO is implemented since 7.42.0 */ 743 /* GnuTLS: support for CERTINFO is implemented since 7.42.0 */
695 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L), 744 handle_curl_option_return_code(
696 "CURLOPT_CERTINFO"); 745 curl_easy_setopt(global_state.curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
697# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */ 746# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */
698 die(STATE_CRITICAL, 747 die(STATE_CRITICAL,
699 "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library " 748 "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library "
@@ -726,29 +775,33 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
726# if LIBCURL_VERSION_NUM >= \ 775# if LIBCURL_VERSION_NUM >= \
727 MAKE_LIBCURL_VERSION(7, 10, 6) /* required for CURLOPT_SSL_CTX_FUNCTION */ 776 MAKE_LIBCURL_VERSION(7, 10, 6) /* required for CURLOPT_SSL_CTX_FUNCTION */
728 // ssl ctx function is not available with all ssl backends 777 // ssl ctx function is not available with all ssl backends
729 if (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, NULL) != CURLE_UNKNOWN_OPTION) { 778 if (curl_easy_setopt(global_state.curl, CURLOPT_SSL_CTX_FUNCTION, NULL) !=
730 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), 779 CURLE_UNKNOWN_OPTION) {
731 "CURLOPT_SSL_CTX_FUNCTION"); 780 handle_curl_option_return_code(
781 curl_easy_setopt(global_state.curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun),
782 "CURLOPT_SSL_CTX_FUNCTION");
732 } 783 }
733# endif 784# endif
734 785
735#endif /* LIBCURL_FEATURE_SSL */ 786#endif /* LIBCURL_FEATURE_SSL */
736 787
737 /* set default or user-given user agent identification */ 788 /* set default or user-given user agent identification */
738 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_USERAGENT, config.user_agent), 789 handle_curl_option_return_code(
739 "CURLOPT_USERAGENT"); 790 curl_easy_setopt(global_state.curl, CURLOPT_USERAGENT, config.user_agent),
791 "CURLOPT_USERAGENT");
740 792
741 /* proxy-authentication */ 793 /* proxy-authentication */
742 if (strcmp(config.proxy_auth, "")) { 794 if (strcmp(config.proxy_auth, "")) {
743 handle_curl_option_return_code( 795 handle_curl_option_return_code(
744 curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, config.proxy_auth), 796 curl_easy_setopt(global_state.curl, CURLOPT_PROXYUSERPWD, config.proxy_auth),
745 "CURLOPT_PROXYUSERPWD"); 797 "CURLOPT_PROXYUSERPWD");
746 } 798 }
747 799
748 /* authentication */ 800 /* authentication */
749 if (strcmp(config.user_auth, "")) { 801 if (strcmp(config.user_auth, "")) {
750 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_USERPWD, config.user_auth), 802 handle_curl_option_return_code(
751 "CURLOPT_USERPWD"); 803 curl_easy_setopt(global_state.curl, CURLOPT_USERPWD, config.user_auth),
804 "CURLOPT_USERPWD");
752 } 805 }
753 806
754 /* TODO: parameter auth method, bitfield of following methods: 807 /* TODO: parameter auth method, bitfield of following methods:
@@ -770,25 +823,27 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
770 /* handle redirections */ 823 /* handle redirections */
771 if (config.onredirect == STATE_DEPENDENT) { 824 if (config.onredirect == STATE_DEPENDENT) {
772 if (config.followmethod == FOLLOW_LIBCURL) { 825 if (config.followmethod == FOLLOW_LIBCURL) {
773 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1), 826 handle_curl_option_return_code(
774 "CURLOPT_FOLLOWLOCATION"); 827 curl_easy_setopt(global_state.curl, CURLOPT_FOLLOWLOCATION, 1),
828 "CURLOPT_FOLLOWLOCATION");
775 829
776 /* default -1 is infinite, not good, could lead to zombie plugins! 830 /* default -1 is infinite, not good, could lead to zombie plugins!
777 Setting it to one bigger than maximal limit to handle errors nicely below 831 Setting it to one bigger than maximal limit to handle errors nicely below
778 */ 832 */
779 handle_curl_option_return_code( 833 handle_curl_option_return_code(
780 curl_easy_setopt(curl, CURLOPT_MAXREDIRS, config.max_depth + 1), 834 curl_easy_setopt(global_state.curl, CURLOPT_MAXREDIRS, config.max_depth + 1),
781 "CURLOPT_MAXREDIRS"); 835 "CURLOPT_MAXREDIRS");
782 836
783 /* for now allow only http and https (we are a http(s) check plugin in the end) */ 837 /* for now allow only http and https (we are a http(s) check plugin in the end) */
784#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 85, 0) 838#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 85, 0)
785 handle_curl_option_return_code( 839 handle_curl_option_return_code(
786 curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https"), 840 curl_easy_setopt(global_state.curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https"),
787 "CURLOPT_REDIR_PROTOCOLS_STR"); 841 "CURLOPT_REDIR_PROTOCOLS_STR");
788#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4) 842#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4)
789 handle_curl_option_return_code( 843 handle_curl_option_return_code(curl_easy_setopt(global_state.curl,
790 curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS), 844 CURLOPT_REDIR_PROTOCOLS,
791 "CURLOPT_REDIRECT_PROTOCOLS"); 845 CURLPROTO_HTTP | CURLPROTO_HTTPS),
846 "CURLOPT_REDIRECT_PROTOCOLS");
792#endif 847#endif
793 848
794 /* TODO: handle the following aspects of redirection, make them 849 /* TODO: handle the following aspects of redirection, make them
@@ -805,28 +860,31 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
805 } 860 }
806 861
807 /* no-body */ 862 /* no-body */
808 if (config.no_body) { 863 if (workingState.no_body) {
809 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_NOBODY, 1), "CURLOPT_NOBODY"); 864 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_NOBODY, 1),
865 "CURLOPT_NOBODY");
810 } 866 }
811 867
812 /* IPv4 or IPv6 forced DNS resolution */ 868 /* IPv4 or IPv6 forced DNS resolution */
813 if (config.sin_family == AF_UNSPEC) { 869 if (config.sin_family == AF_UNSPEC) {
814 handle_curl_option_return_code( 870 handle_curl_option_return_code(
815 curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER), 871 curl_easy_setopt(global_state.curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER),
816 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_WHATEVER)"); 872 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_WHATEVER)");
817 } else if (config.sin_family == AF_INET) { 873 } else if (config.sin_family == AF_INET) {
818 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4), 874 handle_curl_option_return_code(
819 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)"); 875 curl_easy_setopt(global_state.curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4),
876 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)");
820 } 877 }
821#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6) 878#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6)
822 else if (config.sin_family == AF_INET6) { 879 else if (config.sin_family == AF_INET6) {
823 handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6), 880 handle_curl_option_return_code(
824 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V6)"); 881 curl_easy_setopt(global_state.curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6),
882 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V6)");
825 } 883 }
826#endif 884#endif
827 885
828 /* either send http POST data (any data, not only POST)*/ 886 /* either send http POST data (any data, not only POST)*/
829 if (!strcmp(config.http_method, "POST") || !strcmp(config.http_method, "PUT")) { 887 if (!strcmp(workingState.http_method, "POST") || !strcmp(workingState.http_method, "PUT")) {
830 /* set content of payload for POST and PUT */ 888 /* set content of payload for POST and PUT */
831 if (config.http_content_type) { 889 if (config.http_content_type) {
832 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Content-Type: %s", 890 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Content-Type: %s",
@@ -835,30 +893,32 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
835 } 893 }
836 /* NULL indicates "HTTP Continue" in libcurl, provide an empty string 894 /* NULL indicates "HTTP Continue" in libcurl, provide an empty string
837 * in case of no POST/PUT data */ 895 * in case of no POST/PUT data */
838 if (!config.http_post_data) { 896 if (!workingState.http_post_data) {
839 config.http_post_data = ""; 897 workingState.http_post_data = "";
840 } 898 }
841 if (!strcmp(config.http_method, "POST")) { 899 if (!strcmp(workingState.http_method, "POST")) {
842 /* POST method, set payload with CURLOPT_POSTFIELDS */ 900 /* POST method, set payload with CURLOPT_POSTFIELDS */
901 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_POSTFIELDS,
902 workingState.http_post_data),
903 "CURLOPT_POSTFIELDS");
904 } else if (!strcmp(workingState.http_method, "PUT")) {
843 handle_curl_option_return_code( 905 handle_curl_option_return_code(
844 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, config.http_post_data), 906 curl_easy_setopt(global_state.curl, CURLOPT_READFUNCTION,
845 "CURLOPT_POSTFIELDS");
846 } else if (!strcmp(config.http_method, "PUT")) {
847 handle_curl_option_return_code(
848 curl_easy_setopt(curl, CURLOPT_READFUNCTION,
849 (curl_read_callback)curlhelp_buffer_read_callback), 907 (curl_read_callback)curlhelp_buffer_read_callback),
850 "CURLOPT_READFUNCTION"); 908 "CURLOPT_READFUNCTION");
851 if (curlhelp_initreadbuffer(&put_buf, config.http_post_data, 909 if (curlhelp_initreadbuffer(&global_state.put_buf, workingState.http_post_data,
852 strlen(config.http_post_data)) < 0) { 910 strlen(workingState.http_post_data)) < 0) {
853 die(STATE_UNKNOWN, 911 die(STATE_UNKNOWN,
854 "HTTP CRITICAL - out of memory allocating read buffer for PUT\n"); 912 "HTTP CRITICAL - out of memory allocating read buffer for PUT\n");
855 } 913 }
856 put_buf_initialized = true; 914 global_state.put_buf_initialized = true;
857 handle_curl_option_return_code( 915
858 curl_easy_setopt(curl, CURLOPT_READDATA, (void *)&put_buf), "CURLOPT_READDATA"); 916 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_READDATA,
917 (void *)&global_state.put_buf),
918 "CURLOPT_READDATA");
859 handle_curl_option_return_code( 919 handle_curl_option_return_code(
860 curl_easy_setopt(curl, CURLOPT_INFILESIZE, 920 curl_easy_setopt(global_state.curl, CURLOPT_INFILESIZE,
861 (curl_off_t)strlen(config.http_post_data)), 921 (curl_off_t)strlen(workingState.http_post_data)),
862 "CURLOPT_INFILESIZE"); 922 "CURLOPT_INFILESIZE");
863 } 923 }
864 } 924 }
@@ -868,22 +928,22 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
868 /* enable reading cookies from a file, and if the filename is an empty string, only 928 /* enable reading cookies from a file, and if the filename is an empty string, only
869 * enable the curl cookie engine */ 929 * enable the curl cookie engine */
870 handle_curl_option_return_code( 930 handle_curl_option_return_code(
871 curl_easy_setopt(curl, CURLOPT_COOKIEFILE, config.cookie_jar_file), 931 curl_easy_setopt(global_state.curl, CURLOPT_COOKIEFILE, config.cookie_jar_file),
872 "CURLOPT_COOKIEFILE"); 932 "CURLOPT_COOKIEFILE");
873 /* now enable saving cookies to a file, but only if the filename is not an empty string, 933 /* now enable saving cookies to a file, but only if the filename is not an empty string,
874 * since writing it would fail */ 934 * since writing it would fail */
875 if (*config.cookie_jar_file) { 935 if (*config.cookie_jar_file) {
876 handle_curl_option_return_code( 936 handle_curl_option_return_code(
877 curl_easy_setopt(curl, CURLOPT_COOKIEJAR, config.cookie_jar_file), 937 curl_easy_setopt(global_state.curl, CURLOPT_COOKIEJAR, config.cookie_jar_file),
878 "CURLOPT_COOKIEJAR"); 938 "CURLOPT_COOKIEJAR");
879 } 939 }
880 } 940 }
881 941
882 /* do the request */ 942 /* do the request */
883 CURLcode res = curl_easy_perform(curl); 943 CURLcode res = curl_easy_perform(global_state.curl);
884 944
885 if (verbose >= 2 && config.http_post_data) { 945 if (verbose >= 2 && workingState.http_post_data) {
886 printf("**** REQUEST CONTENT ****\n%s\n", config.http_post_data); 946 printf("**** REQUEST CONTENT ****\n%s\n", workingState.http_post_data);
887 } 947 }
888 948
889 /* free header and server IP resolve lists, we don't need it anymore */ 949 /* free header and server IP resolve lists, we don't need it anymore */
@@ -899,14 +959,14 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
899 if (res != CURLE_OK) { 959 if (res != CURLE_OK) {
900 snprintf(msg, DEFAULT_BUFFER_SIZE, 960 snprintf(msg, DEFAULT_BUFFER_SIZE,
901 _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"), 961 _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"),
902 config.server_port, res, errbuf[0] ? errbuf : curl_easy_strerror(res)); 962 workingState.serverPort, res, errbuf[0] ? errbuf : curl_easy_strerror(res));
903 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 963 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
904 } 964 }
905 965
906 mp_state_enum result_ssl = STATE_OK; 966 mp_state_enum result_ssl = STATE_OK;
907 /* certificate checks */ 967 /* certificate checks */
908#ifdef LIBCURL_FEATURE_SSL 968#ifdef LIBCURL_FEATURE_SSL
909 if (config.use_ssl) { 969 if (workingState.use_ssl) {
910 if (config.check_cert) { 970 if (config.check_cert) {
911 if (is_openssl_callback) { 971 if (is_openssl_callback) {
912# ifdef USE_OPENSSL 972# ifdef USE_OPENSSL
@@ -927,7 +987,7 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
927 987
928 cert_ptr_union cert_ptr = {0}; 988 cert_ptr_union cert_ptr = {0};
929 cert_ptr.to_info = NULL; 989 cert_ptr.to_info = NULL;
930 res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &cert_ptr.to_info); 990 res = curl_easy_getinfo(global_state.curl, CURLINFO_CERTINFO, &cert_ptr.to_info);
931 if (!res && cert_ptr.to_info) { 991 if (!res && cert_ptr.to_info) {
932# ifdef USE_OPENSSL 992# ifdef USE_OPENSSL
933 /* We have no OpenSSL in libcurl, but we can use OpenSSL for X509 cert 993 /* We have no OpenSSL in libcurl, but we can use OpenSSL for X509 cert
@@ -994,32 +1054,37 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
994 * performance data to the answer always 1054 * performance data to the answer always
995 */ 1055 */
996 double total_time; 1056 double total_time;
997 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total_time), 1057 handle_curl_option_return_code(
998 "CURLINFO_TOTAL_TIME"); 1058 curl_easy_getinfo(global_state.curl, CURLINFO_TOTAL_TIME, &total_time),
999 size_t page_len = get_content_length(&header_buf, &body_buf); 1059 "CURLINFO_TOTAL_TIME");
1060 size_t page_len = get_content_length(&global_state.header_buf, &global_state.body_buf);
1000 char perfstring[DEFAULT_BUFFER_SIZE]; 1061 char perfstring[DEFAULT_BUFFER_SIZE];
1001 if (config.show_extended_perfdata) { 1062 if (config.show_extended_perfdata) {
1002 double time_connect; 1063 double time_connect;
1003 handle_curl_option_return_code( 1064 handle_curl_option_return_code(
1004 curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &time_connect), "CURLINFO_CONNECT_TIME"); 1065 curl_easy_getinfo(global_state.curl, CURLINFO_CONNECT_TIME, &time_connect),
1066 "CURLINFO_CONNECT_TIME");
1067
1005 double time_appconnect; 1068 double time_appconnect;
1006 handle_curl_option_return_code( 1069 handle_curl_option_return_code(
1007 curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, &time_appconnect), 1070 curl_easy_getinfo(global_state.curl, CURLINFO_APPCONNECT_TIME, &time_appconnect),
1008 "CURLINFO_APPCONNECT_TIME"); 1071 "CURLINFO_APPCONNECT_TIME");
1072
1009 double time_headers; 1073 double time_headers;
1010 handle_curl_option_return_code( 1074 handle_curl_option_return_code(
1011 curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &time_headers), 1075 curl_easy_getinfo(global_state.curl, CURLINFO_PRETRANSFER_TIME, &time_headers),
1012 "CURLINFO_PRETRANSFER_TIME"); 1076 "CURLINFO_PRETRANSFER_TIME");
1077
1013 double time_firstbyte; 1078 double time_firstbyte;
1014 handle_curl_option_return_code( 1079 handle_curl_option_return_code(
1015 curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &time_firstbyte), 1080 curl_easy_getinfo(global_state.curl, CURLINFO_STARTTRANSFER_TIME, &time_firstbyte),
1016 "CURLINFO_STARTTRANSFER_TIME"); 1081 "CURLINFO_STARTTRANSFER_TIME");
1017 1082
1018 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s %s %s %s %s %s", 1083 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s %s %s %s %s %s",
1019 perfd_time(total_time, config.thlds, config.socket_timeout), 1084 perfd_time(total_time, config.thlds, config.socket_timeout),
1020 perfd_size(page_len, config.min_page_len), 1085 perfd_size(page_len, config.min_page_len),
1021 perfd_time_connect(time_connect, config.socket_timeout), 1086 perfd_time_connect(time_connect, config.socket_timeout),
1022 config.use_ssl 1087 workingState.use_ssl
1023 ? perfd_time_ssl(time_appconnect - time_connect, config.socket_timeout) 1088 ? perfd_time_ssl(time_appconnect - time_connect, config.socket_timeout)
1024 : "", 1089 : "",
1025 perfd_time_headers(time_headers - time_appconnect, config.socket_timeout), 1090 perfd_time_headers(time_headers - time_appconnect, config.socket_timeout),
@@ -1032,46 +1097,47 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
1032 } 1097 }
1033 1098
1034 /* return a CRITICAL status if we couldn't read any data */ 1099 /* return a CRITICAL status if we couldn't read any data */
1035 if (strlen(header_buf.buf) == 0 && strlen(body_buf.buf) == 0) { 1100 if (strlen(global_state.header_buf.buf) == 0 && strlen(global_state.body_buf.buf) == 0) {
1036 die(STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n")); 1101 die(STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n"));
1037 } 1102 }
1038 1103
1039 /* get status line of answer, check sanity of HTTP code */ 1104 /* get status line of answer, check sanity of HTTP code */
1040 if (curlhelp_parse_statusline(header_buf.buf, &status_line) < 0) { 1105 if (curlhelp_parse_statusline(global_state.header_buf.buf, &global_state.status_line) < 0) {
1041 snprintf(msg, DEFAULT_BUFFER_SIZE, 1106 snprintf(msg, DEFAULT_BUFFER_SIZE,
1042 "Unparsable status line in %.3g seconds response time|%s\n", total_time, 1107 "Unparsable status line in %.3g seconds response time|%s\n", total_time,
1043 perfstring); 1108 perfstring);
1044 /* we cannot know the major/minor version here for sure as we cannot parse the first 1109 /* we cannot know the major/minor version here for sure as we cannot parse the first
1045 * line */ 1110 * line */
1046 die(STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", code, msg); 1111 die(STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", httpReturnCode, msg);
1047 } 1112 }
1048 status_line_initialized = true; 1113 global_state.status_line_initialized = true;
1049 1114
1050 /* get result code from cURL */ 1115 /* get result code from cURL */
1051 handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code), 1116 handle_curl_option_return_code(
1052 "CURLINFO_RESPONSE_CODE"); 1117 curl_easy_getinfo(global_state.curl, CURLINFO_RESPONSE_CODE, &httpReturnCode),
1118 "CURLINFO_RESPONSE_CODE");
1053 if (verbose >= 2) { 1119 if (verbose >= 2) {
1054 printf("* curl CURLINFO_RESPONSE_CODE is %ld\n", code); 1120 printf("* curl CURLINFO_RESPONSE_CODE is %ld\n", httpReturnCode);
1055 } 1121 }
1056 1122
1057 /* print status line, header, body if verbose */ 1123 /* print status line, header, body if verbose */
1058 if (verbose >= 2) { 1124 if (verbose >= 2) {
1059 printf("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header_buf.buf, 1125 printf("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", global_state.header_buf.buf,
1060 (config.no_body ? " [[ skipped ]]" : body_buf.buf)); 1126 (workingState.no_body ? " [[ skipped ]]" : global_state.body_buf.buf));
1061 } 1127 }
1062 1128
1063 /* make sure the status line matches the response we are looking for */ 1129 /* make sure the status line matches the response we are looking for */
1064 if (!expected_statuscode(status_line.first_line, config.server_expect)) { 1130 if (!expected_statuscode(global_state.status_line.first_line, config.server_expect)) {
1065 if (config.server_port == HTTP_PORT) { 1131 if (workingState.serverPort == HTTP_PORT) {
1066 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"), 1132 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"),
1067 status_line.first_line); 1133 global_state.status_line.first_line);
1068 } else { 1134 } else {
1069 snprintf(msg, DEFAULT_BUFFER_SIZE, 1135 snprintf(msg, DEFAULT_BUFFER_SIZE,
1070 _("Invalid HTTP response received from host on port %d: %s\n"), 1136 _("Invalid HTTP response received from host on port %d: %s\n"),
1071 config.server_port, status_line.first_line); 1137 workingState.serverPort, global_state.status_line.first_line);
1072 } 1138 }
1073 die(STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg, config.show_body ? "\n" : "", 1139 die(STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg, config.show_body ? "\n" : "",
1074 config.show_body ? body_buf.buf : ""); 1140 config.show_body ? global_state.body_buf.buf : "");
1075 } 1141 }
1076 1142
1077 mp_state_enum result = STATE_OK; 1143 mp_state_enum result = STATE_OK;
@@ -1084,26 +1150,29 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
1084 result = STATE_OK; 1150 result = STATE_OK;
1085 } else { 1151 } else {
1086 /* illegal return codes result in a critical state */ 1152 /* illegal return codes result in a critical state */
1087 if (code >= 600 || code < 100) { 1153 if (httpReturnCode >= 600 || httpReturnCode < 100) {
1088 die(STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"), 1154 die(STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"),
1089 status_line.http_code, status_line.msg); 1155 global_state.status_line.http_code, global_state.status_line.msg);
1090 /* server errors result in a critical state */ 1156 /* server errors result in a critical state */
1091 } else if (code >= 500) { 1157 } else if (httpReturnCode >= 500) {
1092 result = STATE_CRITICAL; 1158 result = STATE_CRITICAL;
1093 /* client errors result in a warning state */ 1159 /* client errors result in a warning state */
1094 } else if (code >= 400) { 1160 } else if (httpReturnCode >= 400) {
1095 result = STATE_WARNING; 1161 result = STATE_WARNING;
1096 /* check redirected page if specified */ 1162 /* check redirected page if specified */
1097 } else if (code >= 300) { 1163 } else if (httpReturnCode >= 300) {
1098 if (config.onredirect == STATE_DEPENDENT) { 1164 if (config.onredirect == STATE_DEPENDENT) {
1099 if (config.followmethod == FOLLOW_LIBCURL) { 1165 if (config.followmethod == FOLLOW_LIBCURL) {
1100 code = status_line.http_code; 1166 httpReturnCode = global_state.status_line.http_code;
1101 } else { 1167 } else {
1102 /* old check_http style redirection, if we come 1168 /* old check_http style redirection, if we come
1103 * back here, we are in the same status as with 1169 * back here, we are in the same status as with
1104 * the libcurl method 1170 * the libcurl method
1105 */ 1171 */
1106 redir(&header_buf, config, redir_depth); 1172 redir_wrapper redir_result =
1173 redir(&global_state.header_buf, config, redir_depth, workingState);
1174 check_http(config, redir_result.working_state, redir_result.redir_depth,
1175 header_list);
1107 } 1176 }
1108 } else { 1177 } else {
1109 /* this is a specific code in the command line to 1178 /* this is a specific code in the command line to
@@ -1120,7 +1189,7 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
1120 /* libcurl redirection internally, handle error states here */ 1189 /* libcurl redirection internally, handle error states here */
1121 if (config.followmethod == FOLLOW_LIBCURL) { 1190 if (config.followmethod == FOLLOW_LIBCURL) {
1122 handle_curl_option_return_code( 1191 handle_curl_option_return_code(
1123 curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &redir_depth), 1192 curl_easy_getinfo(global_state.curl, CURLINFO_REDIRECT_COUNT, &redir_depth),
1124 "CURLINFO_REDIRECT_COUNT"); 1193 "CURLINFO_REDIRECT_COUNT");
1125 if (verbose >= 2) { 1194 if (verbose >= 2) {
1126 printf(_("* curl LIBINFO_REDIRECT_COUNT is %d\n"), redir_depth); 1195 printf(_("* curl LIBINFO_REDIRECT_COUNT is %d\n"), redir_depth);
@@ -1133,20 +1202,22 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
1133 } 1202 }
1134 1203
1135 /* check status codes, set exit status accordingly */ 1204 /* check status codes, set exit status accordingly */
1136 if (status_line.http_code != code) { 1205 if (global_state.status_line.http_code != httpReturnCode) {
1137 die(STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"), 1206 die(STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"),
1138 string_statuscode(status_line.http_major, status_line.http_minor), 1207 string_statuscode(global_state.status_line.http_major,
1139 status_line.http_code, status_line.msg, code); 1208 global_state.status_line.http_minor),
1209 global_state.status_line.http_code, global_state.status_line.msg, httpReturnCode);
1140 } 1210 }
1141 1211
1142 if (config.maximum_age >= 0) { 1212 if (config.maximum_age >= 0) {
1143 result = max_state_alt(check_document_dates(&header_buf, &msg, config.maximum_age), result); 1213 result = max_state_alt(
1214 check_document_dates(&global_state.header_buf, &msg, config.maximum_age), result);
1144 } 1215 }
1145 1216
1146 /* Page and Header content checks go here */ 1217 /* Page and Header content checks go here */
1147 1218
1148 if (strlen(config.header_expect)) { 1219 if (strlen(config.header_expect)) {
1149 if (!strstr(header_buf.buf, config.header_expect)) { 1220 if (!strstr(global_state.header_buf.buf, config.header_expect)) {
1150 1221
1151 char output_header_search[30] = ""; 1222 char output_header_search[30] = "";
1152 strncpy(&output_header_search[0], config.header_expect, sizeof(output_header_search)); 1223 strncpy(&output_header_search[0], config.header_expect, sizeof(output_header_search));
@@ -1158,9 +1229,9 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
1158 char tmp[DEFAULT_BUFFER_SIZE]; 1229 char tmp[DEFAULT_BUFFER_SIZE];
1159 1230
1160 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sheader '%s' not found on '%s://%s:%d%s', "), 1231 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sheader '%s' not found on '%s://%s:%d%s', "),
1161 msg, output_header_search, config.use_ssl ? "https" : "http", 1232 msg, output_header_search, workingState.use_ssl ? "https" : "http",
1162 config.host_name ? config.host_name : config.server_address, 1233 workingState.host_name ? workingState.host_name : workingState.server_address,
1163 config.server_port, config.server_url); 1234 workingState.serverPort, workingState.server_url);
1164 1235
1165 strcpy(msg, tmp); 1236 strcpy(msg, tmp);
1166 1237
@@ -1169,7 +1240,7 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
1169 } 1240 }
1170 1241
1171 if (strlen(config.string_expect)) { 1242 if (strlen(config.string_expect)) {
1172 if (!strstr(body_buf.buf, config.string_expect)) { 1243 if (!strstr(global_state.body_buf.buf, config.string_expect)) {
1173 1244
1174 char output_string_search[30] = ""; 1245 char output_string_search[30] = "";
1175 strncpy(&output_string_search[0], config.string_expect, sizeof(output_string_search)); 1246 strncpy(&output_string_search[0], config.string_expect, sizeof(output_string_search));
@@ -1181,9 +1252,9 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
1181 char tmp[DEFAULT_BUFFER_SIZE]; 1252 char tmp[DEFAULT_BUFFER_SIZE];
1182 1253
1183 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sstring '%s' not found on '%s://%s:%d%s', "), 1254 snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sstring '%s' not found on '%s://%s:%d%s', "),
1184 msg, output_string_search, config.use_ssl ? "https" : "http", 1255 msg, output_string_search, workingState.use_ssl ? "https" : "http",
1185 config.host_name ? config.host_name : config.server_address, 1256 workingState.host_name ? workingState.host_name : workingState.server_address,
1186 config.server_port, config.server_url); 1257 workingState.serverPort, workingState.server_url);
1187 1258
1188 strcpy(msg, tmp); 1259 strcpy(msg, tmp);
1189 1260
@@ -1194,7 +1265,7 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
1194 if (strlen(config.regexp)) { 1265 if (strlen(config.regexp)) {
1195 regex_t preg; 1266 regex_t preg;
1196 regmatch_t pmatch[REGS]; 1267 regmatch_t pmatch[REGS];
1197 int errcode = regexec(&preg, body_buf.buf, REGS, pmatch, 0); 1268 int errcode = regexec(&preg, global_state.body_buf.buf, REGS, pmatch, 0);
1198 if ((errcode == 0 && !config.invert_regex) || 1269 if ((errcode == 0 && !config.invert_regex) ||
1199 (errcode == REG_NOMATCH && config.invert_regex)) { 1270 (errcode == REG_NOMATCH && config.invert_regex)) {
1200 /* OK - No-op to avoid changing the logic around it */ 1271 /* OK - No-op to avoid changing the logic around it */
@@ -1259,22 +1330,25 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
1259 * msg); */ 1330 * msg); */
1260 die((int)max_state_alt(result, result_ssl), 1331 die((int)max_state_alt(result, result_ssl),
1261 "HTTP %s: %s %d %s%s%s - %zu bytes in %.3f second response time %s|%s\n%s%s", 1332 "HTTP %s: %s %d %s%s%s - %zu bytes in %.3f second response time %s|%s\n%s%s",
1262 state_text(result), string_statuscode(status_line.http_major, status_line.http_minor), 1333 state_text(result),
1263 status_line.http_code, status_line.msg, strlen(msg) > 0 ? " - " : "", msg, page_len, 1334 string_statuscode(global_state.status_line.http_major, global_state.status_line.http_minor),
1264 total_time, (config.display_html ? "</A>" : ""), perfstring, 1335 global_state.status_line.http_code, global_state.status_line.msg,
1265 (config.show_body ? body_buf.buf : ""), (config.show_body ? "\n" : "")); 1336 strlen(msg) > 0 ? " - " : "", msg, page_len, total_time,
1337 (config.display_html ? "</A>" : ""), perfstring,
1338 (config.show_body ? global_state.body_buf.buf : ""), (config.show_body ? "\n" : ""));
1266 1339
1267 return max_state_alt(result, result_ssl); 1340 return max_state_alt(result, result_ssl);
1268} 1341}
1269 1342
1270int uri_strcmp(const UriTextRangeA range, const char *s) { 1343int uri_strcmp(const UriTextRangeA range, const char *stringToCompare) {
1271 if (!range.first) { 1344 if (!range.first) {
1272 return -1; 1345 return -1;
1273 } 1346 }
1274 if ((size_t)(range.afterLast - range.first) < strlen(s)) { 1347 if ((size_t)(range.afterLast - range.first) < strlen(stringToCompare)) {
1275 return -1; 1348 return -1;
1276 } 1349 }
1277 return strncmp(s, range.first, min((size_t)(range.afterLast - range.first), strlen(s))); 1350 return strncmp(stringToCompare, range.first,
1351 min((size_t)(range.afterLast - range.first), strlen(stringToCompare)));
1278} 1352}
1279 1353
1280char *uri_string(const UriTextRangeA range, char *buf, size_t buflen) { 1354char *uri_string(const UriTextRangeA range, char *buf, size_t buflen) {
@@ -1287,8 +1361,8 @@ char *uri_string(const UriTextRangeA range, char *buf, size_t buflen) {
1287 return buf; 1361 return buf;
1288} 1362}
1289 1363
1290void redir(curlhelp_write_curlbuf *header_buf, check_curl_config config, int redir_depth) { 1364redir_wrapper redir(curlhelp_write_curlbuf *header_buf, const check_curl_config config,
1291 1365 int redir_depth, check_curl_working_state working_state) {
1292 curlhelp_statusline status_line; 1366 curlhelp_statusline status_line;
1293 struct phr_header headers[255]; 1367 struct phr_header headers[255];
1294 size_t msglen; 1368 size_t msglen;
@@ -1340,9 +1414,9 @@ void redir(curlhelp_write_curlbuf *header_buf, check_curl_config config, int red
1340 } 1414 }
1341 if (uri.pathHead) { 1415 if (uri.pathHead) {
1342 printf(_("** path: ")); 1416 printf(_("** path: "));
1343 const UriPathSegmentA *p = uri.pathHead; 1417 for (UriPathSegmentA *path_segment = uri.pathHead; path_segment;
1344 for (; p; p = p->next) { 1418 path_segment = path_segment->next) {
1345 printf("/%s", uri_string(p->text, buf, DEFAULT_BUFFER_SIZE)); 1419 printf("/%s", uri_string(path_segment->text, buf, DEFAULT_BUFFER_SIZE));
1346 } 1420 }
1347 puts(""); 1421 puts("");
1348 } 1422 }
@@ -1355,7 +1429,7 @@ void redir(curlhelp_write_curlbuf *header_buf, check_curl_config config, int red
1355 } 1429 }
1356 1430
1357 if (uri.scheme.first) { 1431 if (uri.scheme.first) {
1358 config.use_ssl = (bool)(!uri_strcmp(uri.scheme, "https")); 1432 working_state.use_ssl = (bool)(!uri_strcmp(uri.scheme, "https"));
1359 } 1433 }
1360 1434
1361 /* we do a sloppy test here only, because uriparser would have failed 1435 /* we do a sloppy test here only, because uriparser would have failed
@@ -1366,7 +1440,7 @@ void redir(curlhelp_write_curlbuf *header_buf, check_curl_config config, int red
1366 new_port = atoi(uri_string(uri.portText, buf, DEFAULT_BUFFER_SIZE)); 1440 new_port = atoi(uri_string(uri.portText, buf, DEFAULT_BUFFER_SIZE));
1367 } else { 1441 } else {
1368 new_port = HTTP_PORT; 1442 new_port = HTTP_PORT;
1369 if (config.use_ssl) { 1443 if (working_state.use_ssl) {
1370 new_port = HTTPS_PORT; 1444 new_port = HTTPS_PORT;
1371 } 1445 }
1372 } 1446 }
@@ -1380,9 +1454,10 @@ void redir(curlhelp_write_curlbuf *header_buf, check_curl_config config, int red
1380 */ 1454 */
1381 char *new_host; 1455 char *new_host;
1382 if (!uri.scheme.first && !uri.hostText.first) { 1456 if (!uri.scheme.first && !uri.hostText.first) {
1383 new_host = strdup(config.host_name ? config.host_name : config.server_address); 1457 new_host = strdup(working_state.host_name ? working_state.host_name
1384 new_port = config.server_port; 1458 : working_state.server_address);
1385 if (config.use_ssl) { 1459 new_port = working_state.serverPort;
1460 if (working_state.use_ssl) {
1386 uri_string(uri.scheme, "https", DEFAULT_BUFFER_SIZE); 1461 uri_string(uri.scheme, "https", DEFAULT_BUFFER_SIZE);
1387 } 1462 }
1388 } else { 1463 } else {
@@ -1393,50 +1468,51 @@ void redir(curlhelp_write_curlbuf *header_buf, check_curl_config config, int red
1393 /* TODO: handle fragments and query part of URL */ 1468 /* TODO: handle fragments and query part of URL */
1394 char *new_url = (char *)calloc(1, DEFAULT_BUFFER_SIZE); 1469 char *new_url = (char *)calloc(1, DEFAULT_BUFFER_SIZE);
1395 if (uri.pathHead) { 1470 if (uri.pathHead) {
1396 const UriPathSegmentA *p = uri.pathHead; 1471 for (UriPathSegmentA *pathSegment = uri.pathHead; pathSegment;
1397 for (; p; p = p->next) { 1472 pathSegment = pathSegment->next) {
1398 strncat(new_url, "/", DEFAULT_BUFFER_SIZE); 1473 strncat(new_url, "/", DEFAULT_BUFFER_SIZE);
1399 strncat(new_url, uri_string(p->text, buf, DEFAULT_BUFFER_SIZE), 1474 strncat(new_url, uri_string(pathSegment->text, buf, DEFAULT_BUFFER_SIZE),
1400 DEFAULT_BUFFER_SIZE - 1); 1475 DEFAULT_BUFFER_SIZE - 1);
1401 } 1476 }
1402 } 1477 }
1403 1478
1404 if (config.server_port == new_port && 1479 if (working_state.serverPort == new_port &&
1405 !strncmp(config.server_address, new_host, MAX_IPV4_HOSTLENGTH) && 1480 !strncmp(working_state.server_address, new_host, MAX_IPV4_HOSTLENGTH) &&
1406 (config.host_name && !strncmp(config.host_name, new_host, MAX_IPV4_HOSTLENGTH)) && 1481 (working_state.host_name &&
1407 !strcmp(config.server_url, new_url)) { 1482 !strncmp(working_state.host_name, new_host, MAX_IPV4_HOSTLENGTH)) &&
1483 !strcmp(working_state.server_url, new_url)) {
1408 die(STATE_CRITICAL, 1484 die(STATE_CRITICAL,
1409 _("HTTP CRITICAL - redirection creates an infinite loop - %s://%s:%d%s%s\n"), 1485 _("HTTP CRITICAL - redirection creates an infinite loop - %s://%s:%d%s%s\n"),
1410 config.use_ssl ? "https" : "http", new_host, new_port, new_url, 1486 working_state.use_ssl ? "https" : "http", new_host, new_port, new_url,
1411 (config.display_html ? "</A>" : "")); 1487 (config.display_html ? "</A>" : ""));
1412 } 1488 }
1413 1489
1414 /* set new values for redirected request */ 1490 /* set new values for redirected request */
1415 1491
1416 if (!(config.followsticky & STICKY_HOST)) { 1492 if (!(config.followsticky & STICKY_HOST)) {
1417 free(config.server_address); 1493 free(working_state.server_address);
1418 config.server_address = strndup(new_host, MAX_IPV4_HOSTLENGTH); 1494 working_state.server_address = strndup(new_host, MAX_IPV4_HOSTLENGTH);
1419 } 1495 }
1420 if (!(config.followsticky & STICKY_PORT)) { 1496 if (!(config.followsticky & STICKY_PORT)) {
1421 config.server_port = (unsigned short)new_port; 1497 working_state.serverPort = (unsigned short)new_port;
1422 } 1498 }
1423 1499
1424 free(config.host_name); 1500 free(working_state.host_name);
1425 config.host_name = strndup(new_host, MAX_IPV4_HOSTLENGTH); 1501 working_state.host_name = strndup(new_host, MAX_IPV4_HOSTLENGTH);
1426 1502
1427 /* reset virtual port */ 1503 /* reset virtual port */
1428 config.virtual_port = config.server_port; 1504 working_state.virtualPort = working_state.serverPort;
1429 1505
1430 free(new_host); 1506 free(new_host);
1431 free(config.server_url); 1507 free(working_state.server_url);
1432 config.server_url = new_url; 1508 working_state.server_url = new_url;
1433 1509
1434 uriFreeUriMembersA(&uri); 1510 uriFreeUriMembersA(&uri);
1435 1511
1436 if (verbose) { 1512 if (verbose) {
1437 printf(_("Redirection to %s://%s:%d%s\n"), config.use_ssl ? "https" : "http", 1513 printf(_("Redirection to %s://%s:%d%s\n"), working_state.use_ssl ? "https" : "http",
1438 config.host_name ? config.host_name : config.server_address, config.server_port, 1514 working_state.host_name ? working_state.host_name : working_state.server_address,
1439 config.server_url); 1515 working_state.serverPort, working_state.server_url);
1440 } 1516 }
1441 1517
1442 /* TODO: the hash component MUST be taken from the original URL and 1518 /* TODO: the hash component MUST be taken from the original URL and
@@ -1444,7 +1520,13 @@ void redir(curlhelp_write_curlbuf *header_buf, check_curl_config config, int red
1444 */ 1520 */
1445 1521
1446 cleanup(); 1522 cleanup();
1447 check_http(config, redir_depth); 1523
1524 redir_wrapper result = {
1525 .redir_depth = redir_depth,
1526 .working_state = working_state,
1527 .error_code = OK,
1528 };
1529 return result;
1448} 1530}
1449 1531
1450/* check whether a file exists */ 1532/* check whether a file exists */
@@ -1585,31 +1667,34 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1585 warning_thresholds = optarg; 1667 warning_thresholds = optarg;
1586 break; 1668 break;
1587 case 'H': /* virtual host */ 1669 case 'H': /* virtual host */
1588 result.config.host_name = strdup(optarg); 1670 result.config.initial_config.host_name = strdup(optarg);
1589 char *p; 1671 char *tmp_string;
1590 size_t host_name_length; 1672 size_t host_name_length;
1591 if (result.config.host_name[0] == '[') { 1673 if (result.config.initial_config.host_name[0] == '[') {
1592 if ((p = strstr(result.config.host_name, "]:")) != NULL) { /* [IPv6]:port */ 1674 if ((tmp_string = strstr(result.config.initial_config.host_name, "]:")) !=
1593 result.config.virtual_port = atoi(p + 2); 1675 NULL) { /* [IPv6]:port */
1676 result.config.initial_config.virtualPort = atoi(tmp_string + 2);
1594 /* cut off the port */ 1677 /* cut off the port */
1595 host_name_length = strlen(result.config.host_name) - strlen(p) - 1; 1678 host_name_length =
1596 free(result.config.host_name); 1679 strlen(result.config.initial_config.host_name) - strlen(tmp_string) - 1;
1597 result.config.host_name = strndup(optarg, host_name_length); 1680 free(result.config.initial_config.host_name);
1681 result.config.initial_config.host_name = strndup(optarg, host_name_length);
1598 } 1682 }
1599 } else if ((p = strchr(result.config.host_name, ':')) != NULL && 1683 } else if ((tmp_string = strchr(result.config.initial_config.host_name, ':')) != NULL &&
1600 strchr(++p, ':') == NULL) { /* IPv4:port or host:port */ 1684 strchr(++tmp_string, ':') == NULL) { /* IPv4:port or host:port */
1601 result.config.virtual_port = atoi(p); 1685 result.config.initial_config.virtualPort = atoi(tmp_string);
1602 /* cut off the port */ 1686 /* cut off the port */
1603 host_name_length = strlen(result.config.host_name) - strlen(p) - 1; 1687 host_name_length =
1604 free(result.config.host_name); 1688 strlen(result.config.initial_config.host_name) - strlen(tmp_string) - 1;
1605 result.config.host_name = strndup(optarg, host_name_length); 1689 free(result.config.initial_config.host_name);
1690 result.config.initial_config.host_name = strndup(optarg, host_name_length);
1606 } 1691 }
1607 break; 1692 break;
1608 case 'I': /* internet address */ 1693 case 'I': /* internet address */
1609 result.config.server_address = strdup(optarg); 1694 result.config.initial_config.server_address = strdup(optarg);
1610 break; 1695 break;
1611 case 'u': /* URL path */ 1696 case 'u': /* URL path */
1612 result.config.server_url = strdup(optarg); 1697 result.config.initial_config.server_url = strdup(optarg);
1613 break; 1698 break;
1614 case 'p': /* Server port */ 1699 case 'p': /* Server port */
1615 if (!is_intnonneg(optarg)) { 1700 if (!is_intnonneg(optarg)) {
@@ -1618,7 +1703,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1618 if (strtol(optarg, NULL, 10) > MAX_PORT) { 1703 if (strtol(optarg, NULL, 10) > MAX_PORT) {
1619 usage2(_("Invalid port number, supplied port number is too big"), optarg); 1704 usage2(_("Invalid port number, supplied port number is too big"), optarg);
1620 } 1705 }
1621 result.config.server_port = (unsigned short)strtol(optarg, NULL, 10); 1706 result.config.initial_config.serverPort = (unsigned short)strtol(optarg, NULL, 10);
1622 specify_port = true; 1707 specify_port = true;
1623 } 1708 }
1624 break; 1709 break;
@@ -1631,18 +1716,18 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1631 result.config.proxy_auth[MAX_INPUT_BUFFER - 1] = 0; 1716 result.config.proxy_auth[MAX_INPUT_BUFFER - 1] = 0;
1632 break; 1717 break;
1633 case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */ 1718 case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */
1634 if (!result.config.http_post_data) { 1719 if (!result.config.initial_config.http_post_data) {
1635 result.config.http_post_data = strdup(optarg); 1720 result.config.initial_config.http_post_data = strdup(optarg);
1636 } 1721 }
1637 if (!result.config.http_method) { 1722 if (!result.config.initial_config.http_method) {
1638 result.config.http_method = strdup("POST"); 1723 result.config.initial_config.http_method = strdup("POST");
1639 } 1724 }
1640 break; 1725 break;
1641 case 'j': /* Set HTTP method */ 1726 case 'j': /* Set HTTP method */
1642 if (result.config.http_method) { 1727 if (result.config.initial_config.http_method) {
1643 free(result.config.http_method); 1728 free(result.config.initial_config.http_method);
1644 } 1729 }
1645 result.config.http_method = strdup(optarg); 1730 result.config.initial_config.http_method = strdup(optarg);
1646 break; 1731 break;
1647 case 'A': /* useragent */ 1732 case 'A': /* useragent */
1648 strncpy(result.config.user_agent, optarg, DEFAULT_BUFFER_SIZE); 1733 strncpy(result.config.user_agent, optarg, DEFAULT_BUFFER_SIZE);
@@ -1723,7 +1808,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1723 { 1808 {
1724 enable_ssl: 1809 enable_ssl:
1725 bool got_plus = false; 1810 bool got_plus = false;
1726 result.config.use_ssl = true; 1811 result.config.initial_config.use_ssl = true;
1727 /* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default. 1812 /* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default.
1728 * Only set if it's non-zero. This helps when we include multiple 1813 * Only set if it's non-zero. This helps when we include multiple
1729 * parameters, like -S and -C combinations */ 1814 * parameters, like -S and -C combinations */
@@ -1801,7 +1886,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1801 printf(_("* Set SSL/TLS version to %d\n"), result.config.ssl_version); 1886 printf(_("* Set SSL/TLS version to %d\n"), result.config.ssl_version);
1802 } 1887 }
1803 if (!specify_port) { 1888 if (!specify_port) {
1804 result.config.server_port = HTTPS_PORT; 1889 result.config.initial_config.serverPort = HTTPS_PORT;
1805 } 1890 }
1806 } break; 1891 } break;
1807#else /* LIBCURL_FEATURE_SSL */ 1892#else /* LIBCURL_FEATURE_SSL */
@@ -1935,7 +2020,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1935 break; 2020 break;
1936 } 2021 }
1937 case 'N': /* no-body */ 2022 case 'N': /* no-body */
1938 result.config.no_body = true; 2023 result.config.initial_config.no_body = true;
1939 break; 2024 break;
1940 case 'M': /* max-age */ 2025 case 'M': /* max-age */
1941 { 2026 {
@@ -1996,21 +2081,22 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1996 } 2081 }
1997 } 2082 }
1998 2083
1999 int c = optind; 2084 int option_counter = optind;
2000 2085
2001 if (result.config.server_address == NULL && c < argc) { 2086 if (result.config.initial_config.server_address == NULL && option_counter < argc) {
2002 result.config.server_address = strdup(argv[c++]); 2087 result.config.initial_config.server_address = strdup(argv[option_counter++]);
2003 } 2088 }
2004 2089
2005 if (result.config.host_name == NULL && c < argc) { 2090 if (result.config.initial_config.host_name == NULL && option_counter < argc) {
2006 result.config.host_name = strdup(argv[c++]); 2091 result.config.initial_config.host_name = strdup(argv[option_counter++]);
2007 } 2092 }
2008 2093
2009 if (result.config.server_address == NULL) { 2094 if (result.config.initial_config.server_address == NULL) {
2010 if (result.config.host_name == NULL) { 2095 if (result.config.initial_config.host_name == NULL) {
2011 usage4(_("You must specify a server address or host name")); 2096 usage4(_("You must specify a server address or host name"));
2012 } else { 2097 } else {
2013 result.config.server_address = strdup(result.config.host_name); 2098 result.config.initial_config.server_address =
2099 strdup(result.config.initial_config.host_name);
2014 } 2100 }
2015 } 2101 }
2016 2102
@@ -2024,21 +2110,23 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
2024 printf("* Socket timeout set to %ld seconds\n", result.config.socket_timeout); 2110 printf("* Socket timeout set to %ld seconds\n", result.config.socket_timeout);
2025 } 2111 }
2026 2112
2027 if (result.config.http_method == NULL) { 2113 if (result.config.initial_config.http_method == NULL) {
2028 result.config.http_method = strdup("GET"); 2114 result.config.initial_config.http_method = strdup("GET");
2029 } 2115 }
2030 2116
2031 if (result.config.client_cert && !result.config.client_privkey) { 2117 if (result.config.client_cert && !result.config.client_privkey) {
2032 usage4(_("If you use a client certificate you must also specify a private key file")); 2118 usage4(_("If you use a client certificate you must also specify a private key file"));
2033 } 2119 }
2034 2120
2035 if (result.config.virtual_port == 0) { 2121 if (result.config.initial_config.virtualPort == 0) {
2036 result.config.virtual_port = result.config.server_port; 2122 result.config.initial_config.virtualPort = result.config.initial_config.serverPort;
2037 } else { 2123 } else {
2038 if ((result.config.use_ssl && result.config.server_port == HTTPS_PORT) || 2124 if ((result.config.initial_config.use_ssl &&
2039 (!result.config.use_ssl && result.config.server_port == HTTP_PORT)) { 2125 result.config.initial_config.serverPort == HTTPS_PORT) ||
2126 (!result.config.initial_config.use_ssl &&
2127 result.config.initial_config.serverPort == HTTP_PORT)) {
2040 if (!specify_port) { 2128 if (!specify_port) {
2041 result.config.server_port = result.config.virtual_port; 2129 result.config.initial_config.serverPort = result.config.initial_config.virtualPort;
2042 } 2130 }
2043 } 2131 }
2044 } 2132 }
@@ -2389,12 +2477,12 @@ size_t curlhelp_buffer_write_callback(void *buffer, size_t size, size_t nmemb, v
2389size_t curlhelp_buffer_read_callback(void *buffer, size_t size, size_t nmemb, void *stream) { 2477size_t curlhelp_buffer_read_callback(void *buffer, size_t size, size_t nmemb, void *stream) {
2390 curlhelp_read_curlbuf *buf = (curlhelp_read_curlbuf *)stream; 2478 curlhelp_read_curlbuf *buf = (curlhelp_read_curlbuf *)stream;
2391 2479
2392 size_t n = min(nmemb * size, buf->buflen - buf->pos); 2480 size_t minimalSize = min(nmemb * size, buf->buflen - buf->pos);
2393 2481
2394 memcpy(buffer, buf->buf + buf->pos, n); 2482 memcpy(buffer, buf->buf + buf->pos, minimalSize);
2395 buf->pos += n; 2483 buf->pos += minimalSize;
2396 2484
2397 return n; 2485 return minimalSize;
2398} 2486}
2399 2487
2400void curlhelp_freewritebuffer(curlhelp_write_curlbuf *buf) { 2488void curlhelp_freewritebuffer(curlhelp_write_curlbuf *buf) {
@@ -2473,86 +2561,85 @@ int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line)
2473 char *first_line_buf = strdup(status_line->first_line); 2561 char *first_line_buf = strdup(status_line->first_line);
2474 2562
2475 /* protocol and version: "HTTP/x.x" SP or "HTTP/2" SP */ 2563 /* protocol and version: "HTTP/x.x" SP or "HTTP/2" SP */
2476 char *p = strtok(first_line_buf, "/"); 2564 char *temp_string = strtok(first_line_buf, "/");
2477 if (p == NULL) { 2565 if (temp_string == NULL) {
2478 free(first_line_buf); 2566 free(first_line_buf);
2479 return -1; 2567 return -1;
2480 } 2568 }
2481 if (strcmp(p, "HTTP") != 0) { 2569 if (strcmp(temp_string, "HTTP") != 0) {
2482 free(first_line_buf); 2570 free(first_line_buf);
2483 return -1; 2571 return -1;
2484 } 2572 }
2485 2573
2486 p = strtok(NULL, " "); 2574 temp_string = strtok(NULL, " ");
2487 if (p == NULL) { 2575 if (temp_string == NULL) {
2488 free(first_line_buf); 2576 free(first_line_buf);
2489 return -1; 2577 return -1;
2490 } 2578 }
2491 2579
2492 char *pp; 2580 char *temp_string_2;
2493 if (strchr(p, '.') != NULL) { 2581 if (strchr(temp_string, '.') != NULL) {
2494 2582
2495 /* HTTP 1.x case */ 2583 /* HTTP 1.x case */
2496 strtok(p, "."); 2584 strtok(temp_string, ".");
2497 status_line->http_major = (int)strtol(p, &pp, 10); 2585 status_line->http_major = (int)strtol(temp_string, &temp_string_2, 10);
2498 if (*pp != '\0') { 2586 if (*temp_string_2 != '\0') {
2499 free(first_line_buf); 2587 free(first_line_buf);
2500 return -1; 2588 return -1;
2501 } 2589 }
2502 strtok(NULL, " "); 2590 strtok(NULL, " ");
2503 status_line->http_minor = (int)strtol(p, &pp, 10); 2591 status_line->http_minor = (int)strtol(temp_string, &temp_string_2, 10);
2504 if (*pp != '\0') { 2592 if (*temp_string_2 != '\0') {
2505 free(first_line_buf); 2593 free(first_line_buf);
2506 return -1; 2594 return -1;
2507 } 2595 }
2508 p += 4; /* 1.x SP */ 2596 temp_string += 4; /* 1.x SP */
2509 } else { 2597 } else {
2510 /* HTTP 2 case */ 2598 /* HTTP 2 case */
2511 status_line->http_major = (int)strtol(p, &pp, 10); 2599 status_line->http_major = (int)strtol(temp_string, &temp_string_2, 10);
2512 status_line->http_minor = 0; 2600 status_line->http_minor = 0;
2513 p += 2; /* 2 SP */ 2601 temp_string += 2; /* 2 SP */
2514 } 2602 }
2515 2603
2516 /* status code: "404" or "404.1", then SP */ 2604 /* status code: "404" or "404.1", then SP */
2517 2605 temp_string = strtok(temp_string, " ");
2518 p = strtok(p, " "); 2606 if (temp_string == NULL) {
2519 if (p == NULL) {
2520 free(first_line_buf); 2607 free(first_line_buf);
2521 return -1; 2608 return -1;
2522 } 2609 }
2523 if (strchr(p, '.') != NULL) { 2610 if (strchr(temp_string, '.') != NULL) {
2524 char *ppp; 2611 char *ppp;
2525 ppp = strtok(p, "."); 2612 ppp = strtok(temp_string, ".");
2526 status_line->http_code = (int)strtol(ppp, &pp, 10); 2613 status_line->http_code = (int)strtol(ppp, &temp_string_2, 10);
2527 if (*pp != '\0') { 2614 if (*temp_string_2 != '\0') {
2528 free(first_line_buf); 2615 free(first_line_buf);
2529 return -1; 2616 return -1;
2530 } 2617 }
2531 ppp = strtok(NULL, ""); 2618 ppp = strtok(NULL, "");
2532 status_line->http_subcode = (int)strtol(ppp, &pp, 10); 2619 status_line->http_subcode = (int)strtol(ppp, &temp_string_2, 10);
2533 if (*pp != '\0') { 2620 if (*temp_string_2 != '\0') {
2534 free(first_line_buf); 2621 free(first_line_buf);
2535 return -1; 2622 return -1;
2536 } 2623 }
2537 p += 6; /* 400.1 SP */ 2624 temp_string += 6; /* 400.1 SP */
2538 } else { 2625 } else {
2539 status_line->http_code = (int)strtol(p, &pp, 10); 2626 status_line->http_code = (int)strtol(temp_string, &temp_string_2, 10);
2540 status_line->http_subcode = -1; 2627 status_line->http_subcode = -1;
2541 if (*pp != '\0') { 2628 if (*temp_string_2 != '\0') {
2542 free(first_line_buf); 2629 free(first_line_buf);
2543 return -1; 2630 return -1;
2544 } 2631 }
2545 p += 4; /* 400 SP */ 2632 temp_string += 4; /* 400 SP */
2546 } 2633 }
2547 2634
2548 /* Human readable message: "Not Found" CRLF */ 2635 /* Human readable message: "Not Found" CRLF */
2549 2636
2550 p = strtok(p, ""); 2637 temp_string = strtok(temp_string, "");
2551 if (p == NULL) { 2638 if (temp_string == NULL) {
2552 status_line->msg = ""; 2639 status_line->msg = "";
2553 return 0; 2640 return 0;
2554 } 2641 }
2555 status_line->msg = status_line->first_line + (p - first_line_buf); 2642 status_line->msg = status_line->first_line + (temp_string - first_line_buf);
2556 free(first_line_buf); 2643 free(first_line_buf);
2557 2644
2558 return 0; 2645 return 0;
diff --git a/plugins/check_curl.d/config.h b/plugins/check_curl.d/config.h
index 97fbcaab..9de68713 100644
--- a/plugins/check_curl.d/config.h
+++ b/plugins/check_curl.d/config.h
@@ -34,10 +34,37 @@ enum {
34 34
35typedef struct { 35typedef struct {
36 char *server_address; 36 char *server_address;
37 unsigned short server_port;
38 unsigned short virtual_port;
39 char *host_name;
40 char *server_url; 37 char *server_url;
38 char *host_name;
39
40 char *http_method;
41
42 char *http_post_data;
43
44 unsigned short virtualPort;
45 unsigned short serverPort;
46
47 bool use_ssl;
48 bool no_body;
49} check_curl_working_state;
50
51check_curl_working_state check_curl_working_state_init() {
52 check_curl_working_state result = {
53 .server_address = NULL,
54 .server_url = DEFAULT_SERVER_URL,
55 .host_name = NULL,
56 .http_method = NULL,
57 .http_post_data = NULL,
58 .virtualPort = 0,
59 .serverPort = 0,
60 .use_ssl = false,
61 .no_body = false,
62 };
63 return result;
64}
65
66typedef struct {
67 check_curl_working_state initial_config;
41 sa_family_t sin_family; 68 sa_family_t sin_family;
42 69
43 bool automatic_decompression; 70 bool automatic_decompression;
@@ -45,13 +72,10 @@ typedef struct {
45 char *client_cert; 72 char *client_cert;
46 char *client_privkey; 73 char *client_privkey;
47 char *ca_cert; 74 char *ca_cert;
48 bool use_ssl;
49 int ssl_version; 75 int ssl_version;
50 char *http_method;
51 char user_agent[DEFAULT_BUFFER_SIZE]; 76 char user_agent[DEFAULT_BUFFER_SIZE];
52 char **http_opt_headers; 77 char **http_opt_headers;
53 size_t http_opt_headers_count; 78 size_t http_opt_headers_count;
54 char *http_post_data;
55 int max_depth; 79 int max_depth;
56 char *http_content_type; 80 char *http_content_type;
57 long socket_timeout; 81 long socket_timeout;
@@ -59,7 +83,6 @@ typedef struct {
59 char proxy_auth[MAX_INPUT_BUFFER]; 83 char proxy_auth[MAX_INPUT_BUFFER];
60 int followmethod; 84 int followmethod;
61 int followsticky; 85 int followsticky;
62 bool no_body;
63 int curl_http_version; 86 int curl_http_version;
64 char *cookie_jar_file; 87 char *cookie_jar_file;
65 88
@@ -88,11 +111,8 @@ typedef struct {
88 111
89check_curl_config check_curl_config_init() { 112check_curl_config check_curl_config_init() {
90 check_curl_config tmp = { 113 check_curl_config tmp = {
91 .server_address = NULL, 114 .initial_config = check_curl_working_state_init(),
92 .server_port = HTTP_PORT, 115
93 .virtual_port = 0,
94 .host_name = NULL,
95 .server_url = strdup(DEFAULT_SERVER_URL),
96 .sin_family = AF_UNSPEC, 116 .sin_family = AF_UNSPEC,
97 117
98 .automatic_decompression = false, 118 .automatic_decompression = false,
@@ -100,13 +120,10 @@ check_curl_config check_curl_config_init() {
100 .client_cert = NULL, 120 .client_cert = NULL,
101 .client_privkey = NULL, 121 .client_privkey = NULL,
102 .ca_cert = NULL, 122 .ca_cert = NULL,
103 .use_ssl = false,
104 .ssl_version = CURL_SSLVERSION_DEFAULT, 123 .ssl_version = CURL_SSLVERSION_DEFAULT,
105 .http_method = NULL,
106 .user_agent = {'\0'}, 124 .user_agent = {'\0'},
107 .http_opt_headers = NULL, 125 .http_opt_headers = NULL,
108 .http_opt_headers_count = 0, 126 .http_opt_headers_count = 0,
109 .http_post_data = NULL,
110 .max_depth = DEFAULT_MAX_REDIRS, 127 .max_depth = DEFAULT_MAX_REDIRS,
111 .http_content_type = NULL, 128 .http_content_type = NULL,
112 .socket_timeout = DEFAULT_SOCKET_TIMEOUT, 129 .socket_timeout = DEFAULT_SOCKET_TIMEOUT,
@@ -114,7 +131,6 @@ check_curl_config check_curl_config_init() {
114 .proxy_auth = "", 131 .proxy_auth = "",
115 .followmethod = FOLLOW_HTTP_CURL, 132 .followmethod = FOLLOW_HTTP_CURL,
116 .followsticky = STICKY_NONE, 133 .followsticky = STICKY_NONE,
117 .no_body = false,
118 .curl_http_version = CURL_HTTP_VERSION_NONE, 134 .curl_http_version = CURL_HTTP_VERSION_NONE,
119 .cookie_jar_file = NULL, 135 .cookie_jar_file = NULL,
120 136