From 40b062f1bd77d60279555a2f40f853d829b15db6 Mon Sep 17 00:00:00 2001
From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>
Date: Tue, 9 Sep 2025 15:12:03 +0200
Subject: check_curl: more refactoring
---
plugins/check_curl.c | 787 ++++++++++++++++++++++++++++-----------------------
1 file changed, 437 insertions(+), 350 deletions(-)
(limited to 'plugins/check_curl.c')
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 {
#include "regex.h"
// Globals
-static bool curl_global_initialized = false;
-static bool curl_easy_initialized = false;
static int verbose = 0;
-static bool body_buf_initialized = false;
-static curlhelp_write_curlbuf body_buf;
-static bool header_buf_initialized = false;
-static curlhelp_write_curlbuf header_buf;
-static bool status_line_initialized = false;
-static curlhelp_statusline status_line;
-static bool put_buf_initialized = false;
-static curlhelp_read_curlbuf put_buf;
-
-static CURL *curl;
-static struct curl_slist *header_list = NULL;
-static long code;
+
+typedef struct {
+ bool curl_global_initialized;
+ bool curl_easy_initialized;
+ bool body_buf_initialized;
+ curlhelp_write_curlbuf body_buf;
+ bool header_buf_initialized;
+ curlhelp_write_curlbuf header_buf;
+ bool status_line_initialized;
+ curlhelp_statusline status_line;
+ bool put_buf_initialized;
+ curlhelp_read_curlbuf put_buf;
+ CURL *curl;
+} check_curl_global_state;
+
+check_curl_global_state global_state = {
+ .curl_global_initialized = false,
+ .curl_easy_initialized = false,
+ .body_buf_initialized = false,
+ .body_buf = {},
+ .header_buf_initialized = false,
+ .header_buf = {},
+ .status_line_initialized = false,
+ .status_line = {},
+ .put_buf_initialized = false,
+ .put_buf = {},
+ .curl = NULL,
+};
+
+static long httpReturnCode;
static char errbuf[MAX_INPUT_BUFFER];
static char msg[DEFAULT_BUFFER_SIZE];
typedef union {
@@ -143,8 +159,6 @@ static bool add_sslctx_verify_fun = false;
static X509 *cert = NULL;
#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */
-static curlhelp_ssl_library ssl_library = CURLHELP_SSL_LIBRARY_UNKNOWN;
-
typedef struct {
int errorcode;
check_curl_config config;
@@ -152,10 +166,16 @@ typedef struct {
static check_curl_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
static void handle_curl_option_return_code(CURLcode res, const char *option);
-static mp_state_enum check_http(check_curl_config /*config*/, int redir_depth);
+static mp_state_enum check_http(check_curl_config /*config*/, check_curl_working_state workingState,
+ int redir_depth, struct curl_slist *header_list);
-static void redir(curlhelp_write_curlbuf * /*header_buf*/, check_curl_config /*config*/,
- int redir_depth);
+typedef struct {
+ int redir_depth;
+ check_curl_working_state working_state;
+ int error_code;
+} redir_wrapper;
+static redir_wrapper redir(curlhelp_write_curlbuf * /*header_buf*/, check_curl_config /*config*/,
+ int redir_depth, check_curl_working_state working_state);
static char *perfd_time(double elapsed_time, thresholds * /*thlds*/, long /*socket_timeout*/);
static char *perfd_time_connect(double elapsed_time_connect, long /*socket_timeout*/);
@@ -218,14 +238,21 @@ int main(int argc, char **argv) {
}
if (config.display_html) {
- printf("", config.use_ssl ? "https" : "http",
- config.host_name ? config.host_name : config.server_address,
- config.virtual_port ? config.virtual_port : config.server_port, config.server_url);
+ printf("",
+ config.initial_config.use_ssl ? "https" : "http",
+ config.initial_config.host_name ? config.initial_config.host_name
+ : config.initial_config.server_address,
+ config.initial_config.virtualPort ? config.initial_config.virtualPort
+ : config.initial_config.serverPort,
+ config.initial_config.server_url);
}
int redir_depth = 0;
- exit((int)check_http(config, redir_depth));
+ check_curl_working_state working_state = config.initial_config;
+ struct curl_slist *header_list = NULL;
+
+ exit((int)check_http(config, working_state, redir_depth, header_list));
}
#ifdef HAVE_SSL
@@ -243,13 +270,11 @@ int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) {
# endif
if (verbose >= 2) {
puts("* SSL verify callback with certificate:");
- X509_NAME *subject;
- X509_NAME *issuer;
printf("* issuer:\n");
- issuer = X509_get_issuer_name(cert);
+ X509_NAME *issuer = X509_get_issuer_name(cert);
X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE);
printf("* curl verify_callback:\n* subject:\n");
- subject = X509_get_subject_name(cert);
+ X509_NAME *subject = X509_get_subject_name(cert);
X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE);
puts("");
}
@@ -305,9 +330,8 @@ static bool expected_statuscode(const char *reply, const char *statuscodes) {
die(STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n"));
}
- char *code;
bool result = false;
- for (code = strtok(expected, ","); code != NULL; code = strtok(NULL, ",")) {
+ for (char *code = strtok(expected, ","); code != NULL; code = strtok(NULL, ",")) {
if (strstr(reply, code) != NULL) {
result = true;
break;
@@ -328,11 +352,11 @@ void handle_curl_option_return_code(CURLcode res, const char *option) {
}
int lookup_host(const char *host, char *buf, size_t buflen, sa_family_t addr_family) {
- struct addrinfo hints;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = addr_family;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags |= AI_CANONNAME;
+ struct addrinfo hints = {
+ .ai_family = addr_family,
+ .ai_socktype = SOCK_STREAM,
+ .ai_flags = AI_CANONNAME,
+ };
struct addrinfo *result;
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
}
static void cleanup(void) {
- if (status_line_initialized) {
- curlhelp_free_statusline(&status_line);
+ if (global_state.status_line_initialized) {
+ curlhelp_free_statusline(&global_state.status_line);
}
- status_line_initialized = false;
- if (curl_easy_initialized) {
- curl_easy_cleanup(curl);
+ global_state.status_line_initialized = false;
+
+ if (global_state.curl_easy_initialized) {
+ curl_easy_cleanup(global_state.curl);
}
- curl_easy_initialized = false;
- if (curl_global_initialized) {
+ global_state.curl_easy_initialized = false;
+
+ if (global_state.curl_global_initialized) {
curl_global_cleanup();
}
- curl_global_initialized = false;
- if (body_buf_initialized) {
- curlhelp_freewritebuffer(&body_buf);
+ global_state.curl_global_initialized = false;
+
+ if (global_state.body_buf_initialized) {
+ curlhelp_freewritebuffer(&global_state.body_buf);
}
- body_buf_initialized = false;
- if (header_buf_initialized) {
- curlhelp_freewritebuffer(&header_buf);
+ global_state.body_buf_initialized = false;
+
+ if (global_state.header_buf_initialized) {
+ curlhelp_freewritebuffer(&global_state.header_buf);
}
- header_buf_initialized = false;
- if (put_buf_initialized) {
- curlhelp_freereadbuffer(&put_buf);
+ global_state.header_buf_initialized = false;
+
+ if (global_state.put_buf_initialized) {
+ curlhelp_freereadbuffer(&global_state.put_buf);
}
- put_buf_initialized = false;
+ global_state.put_buf_initialized = false;
}
-mp_state_enum check_http(check_curl_config config, int redir_depth) {
+mp_state_enum check_http(const check_curl_config config, check_curl_working_state workingState,
+ int redir_depth, struct curl_slist *header_list) {
/* initialize curl */
if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) {
die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n");
}
- curl_global_initialized = true;
+ global_state.curl_global_initialized = true;
- if ((curl = curl_easy_init()) == NULL) {
+ if ((global_state.curl = curl_easy_init()) == NULL) {
die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n");
}
- curl_easy_initialized = true;
+ global_state.curl_easy_initialized = true;
/* register cleanup function to shut down libcurl properly */
atexit(cleanup);
if (verbose >= 1) {
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_VERBOSE, 1),
+ handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_VERBOSE, 1),
"CURLOPT_VERBOSE");
}
/* print everything on stdout like check_http would do */
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_STDERR, stdout),
+ handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_STDERR, stdout),
"CURLOPT_STDERR");
if (config.automatic_decompression) {
#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6)
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""),
- "CURLOPT_ACCEPT_ENCODING");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_ACCEPT_ENCODING, ""),
+ "CURLOPT_ACCEPT_ENCODING");
#else
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ENCODING, ""),
+ handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_ENCODING, ""),
"CURLOPT_ENCODING");
#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */
}
/* initialize buffer for body of the answer */
- if (curlhelp_initwritebuffer(&body_buf) < 0) {
+ if (curlhelp_initwritebuffer(&global_state.body_buf) < 0) {
die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n");
}
- body_buf_initialized = true;
+ global_state.body_buf_initialized = true;
handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlhelp_buffer_write_callback),
+ curl_easy_setopt(global_state.curl, CURLOPT_WRITEFUNCTION, curlhelp_buffer_write_callback),
"CURLOPT_WRITEFUNCTION");
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&body_buf),
- "CURLOPT_WRITEDATA");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_WRITEDATA, (void *)&global_state.body_buf),
+ "CURLOPT_WRITEDATA");
/* initialize buffer for header of the answer */
- if (curlhelp_initwritebuffer(&header_buf) < 0) {
+ if (curlhelp_initwritebuffer(&global_state.header_buf) < 0) {
die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n");
}
- header_buf_initialized = true;
+ global_state.header_buf_initialized = true;
+
handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, curlhelp_buffer_write_callback),
+ curl_easy_setopt(global_state.curl, CURLOPT_HEADERFUNCTION, curlhelp_buffer_write_callback),
"CURLOPT_HEADERFUNCTION");
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_WRITEHEADER, (void *)&header_buf),
- "CURLOPT_WRITEHEADER");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_WRITEHEADER, (void *)&global_state.header_buf),
+ "CURLOPT_WRITEHEADER");
/* set the error buffer */
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf),
+ handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_ERRORBUFFER, errbuf),
"CURLOPT_ERRORBUFFER");
/* set timeouts */
handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, config.socket_timeout),
+ curl_easy_setopt(global_state.curl, CURLOPT_CONNECTTIMEOUT, config.socket_timeout),
"CURLOPT_CONNECTTIMEOUT");
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_TIMEOUT, config.socket_timeout),
- "CURLOPT_TIMEOUT");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_TIMEOUT, config.socket_timeout),
+ "CURLOPT_TIMEOUT");
/* enable haproxy protocol */
if (config.haproxy_protocol) {
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L),
- "CURLOPT_HAPROXYPROTOCOL");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_HAPROXYPROTOCOL, 1L),
+ "CURLOPT_HAPROXYPROTOCOL");
}
// 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) {
struct curl_slist *host = NULL;
char dnscache[DEFAULT_BUFFER_SIZE];
char addrstr[DEFAULT_BUFFER_SIZE / 2];
- if (config.use_ssl && config.host_name != NULL) {
+ if (workingState.use_ssl && workingState.host_name != NULL) {
int res;
- if ((res = lookup_host(config.server_address, addrstr, DEFAULT_BUFFER_SIZE / 2,
+ if ((res = lookup_host(workingState.server_address, addrstr, DEFAULT_BUFFER_SIZE / 2,
config.sin_family)) != 0) {
snprintf(msg, DEFAULT_BUFFER_SIZE,
_("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"),
- config.server_address, res, gai_strerror(res));
+ workingState.server_address, res, gai_strerror(res));
die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
}
- snprintf(dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", config.host_name, config.server_port,
- addrstr);
+ snprintf(dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", workingState.host_name,
+ workingState.serverPort, addrstr);
host = curl_slist_append(NULL, dnscache);
- curl_easy_setopt(curl, CURLOPT_RESOLVE, host);
+ curl_easy_setopt(global_state.curl, CURLOPT_RESOLVE, host);
if (verbose >= 1) {
printf("* curl CURLOPT_RESOLVE: %s\n", dnscache);
}
@@ -507,66 +543,73 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
// If server_address is an IPv6 address it must be surround by square brackets
struct in6_addr tmp_in_addr;
- if (inet_pton(AF_INET6, config.server_address, &tmp_in_addr) == 1) {
- char *new_server_address = malloc(strlen(config.server_address) + 3);
+ if (inet_pton(AF_INET6, workingState.server_address, &tmp_in_addr) == 1) {
+ char *new_server_address = malloc(strlen(workingState.server_address) + 3);
if (new_server_address == NULL) {
die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n");
}
- snprintf(new_server_address, strlen(config.server_address) + 3, "[%s]",
- config.server_address);
- free(config.server_address);
- config.server_address = new_server_address;
+ snprintf(new_server_address, strlen(workingState.server_address) + 3, "[%s]",
+ workingState.server_address);
+ free(workingState.server_address);
+ workingState.server_address = new_server_address;
}
/* compose URL: use the address we want to connect to, set Host: header later */
char url[DEFAULT_BUFFER_SIZE];
- snprintf(url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", config.use_ssl ? "https" : "http",
- (config.use_ssl & (config.host_name != NULL)) ? config.host_name
- : config.server_address,
- config.server_port, config.server_url);
+ snprintf(url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", workingState.use_ssl ? "https" : "http",
+ (workingState.use_ssl & (workingState.host_name != NULL))
+ ? workingState.host_name
+ : workingState.server_address,
+ workingState.serverPort, workingState.server_url);
if (verbose >= 1) {
printf("* curl CURLOPT_URL: %s\n", url);
}
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_URL, url), "CURLOPT_URL");
+ handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_URL, url),
+ "CURLOPT_URL");
/* extract proxy information for legacy proxy https requests */
- if (!strcmp(config.http_method, "CONNECT") ||
- strstr(config.server_url, "http") == config.server_url) {
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_PROXY, config.server_address),
- "CURLOPT_PROXY");
+ if (!strcmp(workingState.http_method, "CONNECT") ||
+ strstr(workingState.server_url, "http") == workingState.server_url) {
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_PROXY, workingState.server_address),
+ "CURLOPT_PROXY");
handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_PROXYPORT, (long)config.server_port),
+ curl_easy_setopt(global_state.curl, CURLOPT_PROXYPORT, (long)workingState.serverPort),
"CURLOPT_PROXYPORT");
if (verbose >= 2) {
- printf("* curl CURLOPT_PROXY: %s:%d\n", config.server_address, config.server_port);
+ printf("* curl CURLOPT_PROXY: %s:%d\n", workingState.server_address,
+ workingState.serverPort);
}
- config.http_method = "GET";
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_URL, config.server_url),
- "CURLOPT_URL");
+ workingState.http_method = "GET";
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_URL, workingState.server_url),
+ "CURLOPT_URL");
}
/* disable body for HEAD request */
- if (config.http_method && !strcmp(config.http_method, "HEAD")) {
- config.no_body = true;
+ if (workingState.http_method && !strcmp(workingState.http_method, "HEAD")) {
+ workingState.no_body = true;
}
/* set HTTP protocol version */
handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, config.curl_http_version),
+ curl_easy_setopt(global_state.curl, CURLOPT_HTTP_VERSION, config.curl_http_version),
"CURLOPT_HTTP_VERSION");
/* set HTTP method */
- if (config.http_method) {
- if (!strcmp(config.http_method, "POST")) {
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_POST, 1), "CURLOPT_POST");
- } else if (!strcmp(config.http_method, "PUT")) {
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_UPLOAD, 1),
+ if (workingState.http_method) {
+ if (!strcmp(workingState.http_method, "POST")) {
+ handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_POST, 1),
+ "CURLOPT_POST");
+ } else if (!strcmp(workingState.http_method, "PUT")) {
+ handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_UPLOAD, 1),
"CURLOPT_UPLOAD");
} else {
- handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, config.http_method),
- "CURLOPT_CUSTOMREQUEST");
+ handle_curl_option_return_code(curl_easy_setopt(global_state.curl,
+ CURLOPT_CUSTOMREQUEST,
+ workingState.http_method),
+ "CURLOPT_CUSTOMREQUEST");
}
}
@@ -583,13 +626,13 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
/* set hostname (virtual hosts), not needed if CURLOPT_CONNECT_TO is used, but left in
* anyway */
char http_header[DEFAULT_BUFFER_SIZE];
- if (config.host_name != NULL && force_host_header == NULL) {
- if ((config.virtual_port != HTTP_PORT && !config.use_ssl) ||
- (config.virtual_port != HTTPS_PORT && config.use_ssl)) {
- snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", config.host_name,
- config.virtual_port);
+ if (workingState.host_name != NULL && force_host_header == NULL) {
+ if ((workingState.virtualPort != HTTP_PORT && !workingState.use_ssl) ||
+ (workingState.virtualPort != HTTPS_PORT && workingState.use_ssl)) {
+ snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", workingState.host_name,
+ workingState.virtualPort);
} else {
- snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s", config.host_name);
+ snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s", workingState.host_name);
}
header_list = curl_slist_append(header_list, http_header);
}
@@ -604,57 +647,63 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
for (size_t i = 0; i < config.http_opt_headers_count; i++) {
header_list = curl_slist_append(header_list, config.http_opt_headers[i]);
}
- /* This cannot be free'd here because a redirection will then try to access this and
- * segfault */
- /* Covered in a testcase in tests/check_http.t */
- /* free(http_opt_headers); */
}
/* set HTTP headers */
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list),
- "CURLOPT_HTTPHEADER");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_HTTPHEADER, header_list), "CURLOPT_HTTPHEADER");
#ifdef LIBCURL_FEATURE_SSL
/* set SSL version, warn about insecure or unsupported versions */
- if (config.use_ssl) {
+ if (workingState.use_ssl) {
handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_SSLVERSION, config.ssl_version), "CURLOPT_SSLVERSION");
+ curl_easy_setopt(global_state.curl, CURLOPT_SSLVERSION, config.ssl_version),
+ "CURLOPT_SSLVERSION");
}
/* client certificate and key to present to server (SSL) */
if (config.client_cert) {
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSLCERT, config.client_cert),
- "CURLOPT_SSLCERT");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_SSLCERT, config.client_cert),
+ "CURLOPT_SSLCERT");
}
+
if (config.client_privkey) {
handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_SSLKEY, config.client_privkey), "CURLOPT_SSLKEY");
+ curl_easy_setopt(global_state.curl, CURLOPT_SSLKEY, config.client_privkey),
+ "CURLOPT_SSLKEY");
}
+
if (config.ca_cert) {
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CAINFO, config.ca_cert),
- "CURLOPT_CAINFO");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_CAINFO, config.ca_cert), "CURLOPT_CAINFO");
}
+
if (config.ca_cert || config.verify_peer_and_host) {
/* per default if we have a CA verify both the peer and the
* hostname in the certificate, can be switched off later */
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1),
- "CURLOPT_SSL_VERIFYPEER");
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2),
- "CURLOPT_SSL_VERIFYHOST");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_SSL_VERIFYPEER, 1),
+ "CURLOPT_SSL_VERIFYPEER");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_SSL_VERIFYHOST, 2),
+ "CURLOPT_SSL_VERIFYHOST");
} else {
/* backward-compatible behaviour, be tolerant in checks
* TODO: depending on more options have aspects we want
* to be less tolerant about ssl verfications
*/
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0),
- "CURLOPT_SSL_VERIFYPEER");
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0),
- "CURLOPT_SSL_VERIFYHOST");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_SSL_VERIFYPEER, 0),
+ "CURLOPT_SSL_VERIFYPEER");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_SSL_VERIFYHOST, 0),
+ "CURLOPT_SSL_VERIFYHOST");
}
/* detect SSL library used by libcurl */
- ssl_library = curlhelp_get_ssl_library();
+ curlhelp_ssl_library ssl_library = curlhelp_get_ssl_library();
/* try hard to get a stack of certificates to verify against */
if (config.check_cert) {
@@ -672,15 +721,15 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
# endif /* USE_OPENSSL */
/* libcurl is built with OpenSSL, monitoring plugins, so falling
* back to manually extracting certificate information */
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L),
- "CURLOPT_CERTINFO");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
break;
case CURLHELP_SSL_LIBRARY_NSS:
# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
/* NSS: support for CERTINFO is implemented since 7.34.0 */
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L),
- "CURLOPT_CERTINFO");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
die(STATE_CRITICAL,
"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) {
case CURLHELP_SSL_LIBRARY_GNUTLS:
# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0)
/* GnuTLS: support for CERTINFO is implemented since 7.42.0 */
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L),
- "CURLOPT_CERTINFO");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */
die(STATE_CRITICAL,
"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) {
# if LIBCURL_VERSION_NUM >= \
MAKE_LIBCURL_VERSION(7, 10, 6) /* required for CURLOPT_SSL_CTX_FUNCTION */
// ssl ctx function is not available with all ssl backends
- if (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, NULL) != CURLE_UNKNOWN_OPTION) {
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun),
- "CURLOPT_SSL_CTX_FUNCTION");
+ if (curl_easy_setopt(global_state.curl, CURLOPT_SSL_CTX_FUNCTION, NULL) !=
+ CURLE_UNKNOWN_OPTION) {
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun),
+ "CURLOPT_SSL_CTX_FUNCTION");
}
# endif
#endif /* LIBCURL_FEATURE_SSL */
/* set default or user-given user agent identification */
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_USERAGENT, config.user_agent),
- "CURLOPT_USERAGENT");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_USERAGENT, config.user_agent),
+ "CURLOPT_USERAGENT");
/* proxy-authentication */
if (strcmp(config.proxy_auth, "")) {
handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, config.proxy_auth),
+ curl_easy_setopt(global_state.curl, CURLOPT_PROXYUSERPWD, config.proxy_auth),
"CURLOPT_PROXYUSERPWD");
}
/* authentication */
if (strcmp(config.user_auth, "")) {
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_USERPWD, config.user_auth),
- "CURLOPT_USERPWD");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_USERPWD, config.user_auth),
+ "CURLOPT_USERPWD");
}
/* TODO: parameter auth method, bitfield of following methods:
@@ -770,25 +823,27 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
/* handle redirections */
if (config.onredirect == STATE_DEPENDENT) {
if (config.followmethod == FOLLOW_LIBCURL) {
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1),
- "CURLOPT_FOLLOWLOCATION");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_FOLLOWLOCATION, 1),
+ "CURLOPT_FOLLOWLOCATION");
/* default -1 is infinite, not good, could lead to zombie plugins!
Setting it to one bigger than maximal limit to handle errors nicely below
*/
handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_MAXREDIRS, config.max_depth + 1),
+ curl_easy_setopt(global_state.curl, CURLOPT_MAXREDIRS, config.max_depth + 1),
"CURLOPT_MAXREDIRS");
/* for now allow only http and https (we are a http(s) check plugin in the end) */
#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 85, 0)
handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https"),
+ curl_easy_setopt(global_state.curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https"),
"CURLOPT_REDIR_PROTOCOLS_STR");
#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4)
- handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS),
- "CURLOPT_REDIRECT_PROTOCOLS");
+ handle_curl_option_return_code(curl_easy_setopt(global_state.curl,
+ CURLOPT_REDIR_PROTOCOLS,
+ CURLPROTO_HTTP | CURLPROTO_HTTPS),
+ "CURLOPT_REDIRECT_PROTOCOLS");
#endif
/* 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) {
}
/* no-body */
- if (config.no_body) {
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_NOBODY, 1), "CURLOPT_NOBODY");
+ if (workingState.no_body) {
+ handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_NOBODY, 1),
+ "CURLOPT_NOBODY");
}
/* IPv4 or IPv6 forced DNS resolution */
if (config.sin_family == AF_UNSPEC) {
handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER),
+ curl_easy_setopt(global_state.curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER),
"CURLOPT_IPRESOLVE(CURL_IPRESOLVE_WHATEVER)");
} else if (config.sin_family == AF_INET) {
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4),
- "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4),
+ "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)");
}
#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6)
else if (config.sin_family == AF_INET6) {
- handle_curl_option_return_code(curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6),
- "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V6)");
+ handle_curl_option_return_code(
+ curl_easy_setopt(global_state.curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6),
+ "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V6)");
}
#endif
/* either send http POST data (any data, not only POST)*/
- if (!strcmp(config.http_method, "POST") || !strcmp(config.http_method, "PUT")) {
+ if (!strcmp(workingState.http_method, "POST") || !strcmp(workingState.http_method, "PUT")) {
/* set content of payload for POST and PUT */
if (config.http_content_type) {
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) {
}
/* NULL indicates "HTTP Continue" in libcurl, provide an empty string
* in case of no POST/PUT data */
- if (!config.http_post_data) {
- config.http_post_data = "";
+ if (!workingState.http_post_data) {
+ workingState.http_post_data = "";
}
- if (!strcmp(config.http_method, "POST")) {
+ if (!strcmp(workingState.http_method, "POST")) {
/* POST method, set payload with CURLOPT_POSTFIELDS */
+ handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_POSTFIELDS,
+ workingState.http_post_data),
+ "CURLOPT_POSTFIELDS");
+ } else if (!strcmp(workingState.http_method, "PUT")) {
handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, config.http_post_data),
- "CURLOPT_POSTFIELDS");
- } else if (!strcmp(config.http_method, "PUT")) {
- handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_READFUNCTION,
+ curl_easy_setopt(global_state.curl, CURLOPT_READFUNCTION,
(curl_read_callback)curlhelp_buffer_read_callback),
"CURLOPT_READFUNCTION");
- if (curlhelp_initreadbuffer(&put_buf, config.http_post_data,
- strlen(config.http_post_data)) < 0) {
+ if (curlhelp_initreadbuffer(&global_state.put_buf, workingState.http_post_data,
+ strlen(workingState.http_post_data)) < 0) {
die(STATE_UNKNOWN,
"HTTP CRITICAL - out of memory allocating read buffer for PUT\n");
}
- put_buf_initialized = true;
- handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_READDATA, (void *)&put_buf), "CURLOPT_READDATA");
+ global_state.put_buf_initialized = true;
+
+ handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_READDATA,
+ (void *)&global_state.put_buf),
+ "CURLOPT_READDATA");
handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_INFILESIZE,
- (curl_off_t)strlen(config.http_post_data)),
+ curl_easy_setopt(global_state.curl, CURLOPT_INFILESIZE,
+ (curl_off_t)strlen(workingState.http_post_data)),
"CURLOPT_INFILESIZE");
}
}
@@ -868,22 +928,22 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
/* enable reading cookies from a file, and if the filename is an empty string, only
* enable the curl cookie engine */
handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_COOKIEFILE, config.cookie_jar_file),
+ curl_easy_setopt(global_state.curl, CURLOPT_COOKIEFILE, config.cookie_jar_file),
"CURLOPT_COOKIEFILE");
/* now enable saving cookies to a file, but only if the filename is not an empty string,
* since writing it would fail */
if (*config.cookie_jar_file) {
handle_curl_option_return_code(
- curl_easy_setopt(curl, CURLOPT_COOKIEJAR, config.cookie_jar_file),
+ curl_easy_setopt(global_state.curl, CURLOPT_COOKIEJAR, config.cookie_jar_file),
"CURLOPT_COOKIEJAR");
}
}
/* do the request */
- CURLcode res = curl_easy_perform(curl);
+ CURLcode res = curl_easy_perform(global_state.curl);
- if (verbose >= 2 && config.http_post_data) {
- printf("**** REQUEST CONTENT ****\n%s\n", config.http_post_data);
+ if (verbose >= 2 && workingState.http_post_data) {
+ printf("**** REQUEST CONTENT ****\n%s\n", workingState.http_post_data);
}
/* 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) {
if (res != CURLE_OK) {
snprintf(msg, DEFAULT_BUFFER_SIZE,
_("Invalid HTTP response received from host on port %d: cURL returned %d - %s"),
- config.server_port, res, errbuf[0] ? errbuf : curl_easy_strerror(res));
+ workingState.serverPort, res, errbuf[0] ? errbuf : curl_easy_strerror(res));
die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
}
mp_state_enum result_ssl = STATE_OK;
/* certificate checks */
#ifdef LIBCURL_FEATURE_SSL
- if (config.use_ssl) {
+ if (workingState.use_ssl) {
if (config.check_cert) {
if (is_openssl_callback) {
# ifdef USE_OPENSSL
@@ -927,7 +987,7 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
cert_ptr_union cert_ptr = {0};
cert_ptr.to_info = NULL;
- res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &cert_ptr.to_info);
+ res = curl_easy_getinfo(global_state.curl, CURLINFO_CERTINFO, &cert_ptr.to_info);
if (!res && cert_ptr.to_info) {
# ifdef USE_OPENSSL
/* 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) {
* performance data to the answer always
*/
double total_time;
- handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total_time),
- "CURLINFO_TOTAL_TIME");
- size_t page_len = get_content_length(&header_buf, &body_buf);
+ handle_curl_option_return_code(
+ curl_easy_getinfo(global_state.curl, CURLINFO_TOTAL_TIME, &total_time),
+ "CURLINFO_TOTAL_TIME");
+ size_t page_len = get_content_length(&global_state.header_buf, &global_state.body_buf);
char perfstring[DEFAULT_BUFFER_SIZE];
if (config.show_extended_perfdata) {
double time_connect;
handle_curl_option_return_code(
- curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &time_connect), "CURLINFO_CONNECT_TIME");
+ curl_easy_getinfo(global_state.curl, CURLINFO_CONNECT_TIME, &time_connect),
+ "CURLINFO_CONNECT_TIME");
+
double time_appconnect;
handle_curl_option_return_code(
- curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, &time_appconnect),
+ curl_easy_getinfo(global_state.curl, CURLINFO_APPCONNECT_TIME, &time_appconnect),
"CURLINFO_APPCONNECT_TIME");
+
double time_headers;
handle_curl_option_return_code(
- curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &time_headers),
+ curl_easy_getinfo(global_state.curl, CURLINFO_PRETRANSFER_TIME, &time_headers),
"CURLINFO_PRETRANSFER_TIME");
+
double time_firstbyte;
handle_curl_option_return_code(
- curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &time_firstbyte),
+ curl_easy_getinfo(global_state.curl, CURLINFO_STARTTRANSFER_TIME, &time_firstbyte),
"CURLINFO_STARTTRANSFER_TIME");
snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s %s %s %s %s %s",
perfd_time(total_time, config.thlds, config.socket_timeout),
perfd_size(page_len, config.min_page_len),
perfd_time_connect(time_connect, config.socket_timeout),
- config.use_ssl
+ workingState.use_ssl
? perfd_time_ssl(time_appconnect - time_connect, config.socket_timeout)
: "",
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) {
}
/* return a CRITICAL status if we couldn't read any data */
- if (strlen(header_buf.buf) == 0 && strlen(body_buf.buf) == 0) {
+ if (strlen(global_state.header_buf.buf) == 0 && strlen(global_state.body_buf.buf) == 0) {
die(STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n"));
}
/* get status line of answer, check sanity of HTTP code */
- if (curlhelp_parse_statusline(header_buf.buf, &status_line) < 0) {
+ if (curlhelp_parse_statusline(global_state.header_buf.buf, &global_state.status_line) < 0) {
snprintf(msg, DEFAULT_BUFFER_SIZE,
"Unparsable status line in %.3g seconds response time|%s\n", total_time,
perfstring);
/* we cannot know the major/minor version here for sure as we cannot parse the first
* line */
- die(STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", code, msg);
+ die(STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x %ld unknown - %s", httpReturnCode, msg);
}
- status_line_initialized = true;
+ global_state.status_line_initialized = true;
/* get result code from cURL */
- handle_curl_option_return_code(curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code),
- "CURLINFO_RESPONSE_CODE");
+ handle_curl_option_return_code(
+ curl_easy_getinfo(global_state.curl, CURLINFO_RESPONSE_CODE, &httpReturnCode),
+ "CURLINFO_RESPONSE_CODE");
if (verbose >= 2) {
- printf("* curl CURLINFO_RESPONSE_CODE is %ld\n", code);
+ printf("* curl CURLINFO_RESPONSE_CODE is %ld\n", httpReturnCode);
}
/* print status line, header, body if verbose */
if (verbose >= 2) {
- printf("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header_buf.buf,
- (config.no_body ? " [[ skipped ]]" : body_buf.buf));
+ printf("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", global_state.header_buf.buf,
+ (workingState.no_body ? " [[ skipped ]]" : global_state.body_buf.buf));
}
/* make sure the status line matches the response we are looking for */
- if (!expected_statuscode(status_line.first_line, config.server_expect)) {
- if (config.server_port == HTTP_PORT) {
+ if (!expected_statuscode(global_state.status_line.first_line, config.server_expect)) {
+ if (workingState.serverPort == HTTP_PORT) {
snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"),
- status_line.first_line);
+ global_state.status_line.first_line);
} else {
snprintf(msg, DEFAULT_BUFFER_SIZE,
_("Invalid HTTP response received from host on port %d: %s\n"),
- config.server_port, status_line.first_line);
+ workingState.serverPort, global_state.status_line.first_line);
}
die(STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg, config.show_body ? "\n" : "",
- config.show_body ? body_buf.buf : "");
+ config.show_body ? global_state.body_buf.buf : "");
}
mp_state_enum result = STATE_OK;
@@ -1084,26 +1150,29 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
result = STATE_OK;
} else {
/* illegal return codes result in a critical state */
- if (code >= 600 || code < 100) {
+ if (httpReturnCode >= 600 || httpReturnCode < 100) {
die(STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"),
- status_line.http_code, status_line.msg);
+ global_state.status_line.http_code, global_state.status_line.msg);
/* server errors result in a critical state */
- } else if (code >= 500) {
+ } else if (httpReturnCode >= 500) {
result = STATE_CRITICAL;
/* client errors result in a warning state */
- } else if (code >= 400) {
+ } else if (httpReturnCode >= 400) {
result = STATE_WARNING;
/* check redirected page if specified */
- } else if (code >= 300) {
+ } else if (httpReturnCode >= 300) {
if (config.onredirect == STATE_DEPENDENT) {
if (config.followmethod == FOLLOW_LIBCURL) {
- code = status_line.http_code;
+ httpReturnCode = global_state.status_line.http_code;
} else {
/* old check_http style redirection, if we come
* back here, we are in the same status as with
* the libcurl method
*/
- redir(&header_buf, config, redir_depth);
+ redir_wrapper redir_result =
+ redir(&global_state.header_buf, config, redir_depth, workingState);
+ check_http(config, redir_result.working_state, redir_result.redir_depth,
+ header_list);
}
} else {
/* 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) {
/* libcurl redirection internally, handle error states here */
if (config.followmethod == FOLLOW_LIBCURL) {
handle_curl_option_return_code(
- curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &redir_depth),
+ curl_easy_getinfo(global_state.curl, CURLINFO_REDIRECT_COUNT, &redir_depth),
"CURLINFO_REDIRECT_COUNT");
if (verbose >= 2) {
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) {
}
/* check status codes, set exit status accordingly */
- if (status_line.http_code != code) {
+ if (global_state.status_line.http_code != httpReturnCode) {
die(STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"),
- string_statuscode(status_line.http_major, status_line.http_minor),
- status_line.http_code, status_line.msg, code);
+ string_statuscode(global_state.status_line.http_major,
+ global_state.status_line.http_minor),
+ global_state.status_line.http_code, global_state.status_line.msg, httpReturnCode);
}
if (config.maximum_age >= 0) {
- result = max_state_alt(check_document_dates(&header_buf, &msg, config.maximum_age), result);
+ result = max_state_alt(
+ check_document_dates(&global_state.header_buf, &msg, config.maximum_age), result);
}
/* Page and Header content checks go here */
if (strlen(config.header_expect)) {
- if (!strstr(header_buf.buf, config.header_expect)) {
+ if (!strstr(global_state.header_buf.buf, config.header_expect)) {
char output_header_search[30] = "";
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) {
char tmp[DEFAULT_BUFFER_SIZE];
snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sheader '%s' not found on '%s://%s:%d%s', "),
- msg, output_header_search, config.use_ssl ? "https" : "http",
- config.host_name ? config.host_name : config.server_address,
- config.server_port, config.server_url);
+ msg, output_header_search, workingState.use_ssl ? "https" : "http",
+ workingState.host_name ? workingState.host_name : workingState.server_address,
+ workingState.serverPort, workingState.server_url);
strcpy(msg, tmp);
@@ -1169,7 +1240,7 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
}
if (strlen(config.string_expect)) {
- if (!strstr(body_buf.buf, config.string_expect)) {
+ if (!strstr(global_state.body_buf.buf, config.string_expect)) {
char output_string_search[30] = "";
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) {
char tmp[DEFAULT_BUFFER_SIZE];
snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sstring '%s' not found on '%s://%s:%d%s', "),
- msg, output_string_search, config.use_ssl ? "https" : "http",
- config.host_name ? config.host_name : config.server_address,
- config.server_port, config.server_url);
+ msg, output_string_search, workingState.use_ssl ? "https" : "http",
+ workingState.host_name ? workingState.host_name : workingState.server_address,
+ workingState.serverPort, workingState.server_url);
strcpy(msg, tmp);
@@ -1194,7 +1265,7 @@ mp_state_enum check_http(check_curl_config config, int redir_depth) {
if (strlen(config.regexp)) {
regex_t preg;
regmatch_t pmatch[REGS];
- int errcode = regexec(&preg, body_buf.buf, REGS, pmatch, 0);
+ int errcode = regexec(&preg, global_state.body_buf.buf, REGS, pmatch, 0);
if ((errcode == 0 && !config.invert_regex) ||
(errcode == REG_NOMATCH && config.invert_regex)) {
/* 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) {
* msg); */
die((int)max_state_alt(result, result_ssl),
"HTTP %s: %s %d %s%s%s - %zu bytes in %.3f second response time %s|%s\n%s%s",
- state_text(result), string_statuscode(status_line.http_major, status_line.http_minor),
- status_line.http_code, status_line.msg, strlen(msg) > 0 ? " - " : "", msg, page_len,
- total_time, (config.display_html ? "" : ""), perfstring,
- (config.show_body ? body_buf.buf : ""), (config.show_body ? "\n" : ""));
+ state_text(result),
+ string_statuscode(global_state.status_line.http_major, global_state.status_line.http_minor),
+ global_state.status_line.http_code, global_state.status_line.msg,
+ strlen(msg) > 0 ? " - " : "", msg, page_len, total_time,
+ (config.display_html ? "" : ""), perfstring,
+ (config.show_body ? global_state.body_buf.buf : ""), (config.show_body ? "\n" : ""));
return max_state_alt(result, result_ssl);
}
-int uri_strcmp(const UriTextRangeA range, const char *s) {
+int uri_strcmp(const UriTextRangeA range, const char *stringToCompare) {
if (!range.first) {
return -1;
}
- if ((size_t)(range.afterLast - range.first) < strlen(s)) {
+ if ((size_t)(range.afterLast - range.first) < strlen(stringToCompare)) {
return -1;
}
- return strncmp(s, range.first, min((size_t)(range.afterLast - range.first), strlen(s)));
+ return strncmp(stringToCompare, range.first,
+ min((size_t)(range.afterLast - range.first), strlen(stringToCompare)));
}
char *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) {
return buf;
}
-void redir(curlhelp_write_curlbuf *header_buf, check_curl_config config, int redir_depth) {
-
+redir_wrapper redir(curlhelp_write_curlbuf *header_buf, const check_curl_config config,
+ int redir_depth, check_curl_working_state working_state) {
curlhelp_statusline status_line;
struct phr_header headers[255];
size_t msglen;
@@ -1340,9 +1414,9 @@ void redir(curlhelp_write_curlbuf *header_buf, check_curl_config config, int red
}
if (uri.pathHead) {
printf(_("** path: "));
- const UriPathSegmentA *p = uri.pathHead;
- for (; p; p = p->next) {
- printf("/%s", uri_string(p->text, buf, DEFAULT_BUFFER_SIZE));
+ for (UriPathSegmentA *path_segment = uri.pathHead; path_segment;
+ path_segment = path_segment->next) {
+ printf("/%s", uri_string(path_segment->text, buf, DEFAULT_BUFFER_SIZE));
}
puts("");
}
@@ -1355,7 +1429,7 @@ void redir(curlhelp_write_curlbuf *header_buf, check_curl_config config, int red
}
if (uri.scheme.first) {
- config.use_ssl = (bool)(!uri_strcmp(uri.scheme, "https"));
+ working_state.use_ssl = (bool)(!uri_strcmp(uri.scheme, "https"));
}
/* 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
new_port = atoi(uri_string(uri.portText, buf, DEFAULT_BUFFER_SIZE));
} else {
new_port = HTTP_PORT;
- if (config.use_ssl) {
+ if (working_state.use_ssl) {
new_port = HTTPS_PORT;
}
}
@@ -1380,9 +1454,10 @@ void redir(curlhelp_write_curlbuf *header_buf, check_curl_config config, int red
*/
char *new_host;
if (!uri.scheme.first && !uri.hostText.first) {
- new_host = strdup(config.host_name ? config.host_name : config.server_address);
- new_port = config.server_port;
- if (config.use_ssl) {
+ new_host = strdup(working_state.host_name ? working_state.host_name
+ : working_state.server_address);
+ new_port = working_state.serverPort;
+ if (working_state.use_ssl) {
uri_string(uri.scheme, "https", DEFAULT_BUFFER_SIZE);
}
} else {
@@ -1393,50 +1468,51 @@ void redir(curlhelp_write_curlbuf *header_buf, check_curl_config config, int red
/* TODO: handle fragments and query part of URL */
char *new_url = (char *)calloc(1, DEFAULT_BUFFER_SIZE);
if (uri.pathHead) {
- const UriPathSegmentA *p = uri.pathHead;
- for (; p; p = p->next) {
+ for (UriPathSegmentA *pathSegment = uri.pathHead; pathSegment;
+ pathSegment = pathSegment->next) {
strncat(new_url, "/", DEFAULT_BUFFER_SIZE);
- strncat(new_url, uri_string(p->text, buf, DEFAULT_BUFFER_SIZE),
+ strncat(new_url, uri_string(pathSegment->text, buf, DEFAULT_BUFFER_SIZE),
DEFAULT_BUFFER_SIZE - 1);
}
}
- if (config.server_port == new_port &&
- !strncmp(config.server_address, new_host, MAX_IPV4_HOSTLENGTH) &&
- (config.host_name && !strncmp(config.host_name, new_host, MAX_IPV4_HOSTLENGTH)) &&
- !strcmp(config.server_url, new_url)) {
+ if (working_state.serverPort == new_port &&
+ !strncmp(working_state.server_address, new_host, MAX_IPV4_HOSTLENGTH) &&
+ (working_state.host_name &&
+ !strncmp(working_state.host_name, new_host, MAX_IPV4_HOSTLENGTH)) &&
+ !strcmp(working_state.server_url, new_url)) {
die(STATE_CRITICAL,
_("HTTP CRITICAL - redirection creates an infinite loop - %s://%s:%d%s%s\n"),
- config.use_ssl ? "https" : "http", new_host, new_port, new_url,
+ working_state.use_ssl ? "https" : "http", new_host, new_port, new_url,
(config.display_html ? "" : ""));
}
/* set new values for redirected request */
if (!(config.followsticky & STICKY_HOST)) {
- free(config.server_address);
- config.server_address = strndup(new_host, MAX_IPV4_HOSTLENGTH);
+ free(working_state.server_address);
+ working_state.server_address = strndup(new_host, MAX_IPV4_HOSTLENGTH);
}
if (!(config.followsticky & STICKY_PORT)) {
- config.server_port = (unsigned short)new_port;
+ working_state.serverPort = (unsigned short)new_port;
}
- free(config.host_name);
- config.host_name = strndup(new_host, MAX_IPV4_HOSTLENGTH);
+ free(working_state.host_name);
+ working_state.host_name = strndup(new_host, MAX_IPV4_HOSTLENGTH);
/* reset virtual port */
- config.virtual_port = config.server_port;
+ working_state.virtualPort = working_state.serverPort;
free(new_host);
- free(config.server_url);
- config.server_url = new_url;
+ free(working_state.server_url);
+ working_state.server_url = new_url;
uriFreeUriMembersA(&uri);
if (verbose) {
- printf(_("Redirection to %s://%s:%d%s\n"), config.use_ssl ? "https" : "http",
- config.host_name ? config.host_name : config.server_address, config.server_port,
- config.server_url);
+ printf(_("Redirection to %s://%s:%d%s\n"), working_state.use_ssl ? "https" : "http",
+ working_state.host_name ? working_state.host_name : working_state.server_address,
+ working_state.serverPort, working_state.server_url);
}
/* 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
*/
cleanup();
- check_http(config, redir_depth);
+
+ redir_wrapper result = {
+ .redir_depth = redir_depth,
+ .working_state = working_state,
+ .error_code = OK,
+ };
+ return result;
}
/* check whether a file exists */
@@ -1585,31 +1667,34 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
warning_thresholds = optarg;
break;
case 'H': /* virtual host */
- result.config.host_name = strdup(optarg);
- char *p;
+ result.config.initial_config.host_name = strdup(optarg);
+ char *tmp_string;
size_t host_name_length;
- if (result.config.host_name[0] == '[') {
- if ((p = strstr(result.config.host_name, "]:")) != NULL) { /* [IPv6]:port */
- result.config.virtual_port = atoi(p + 2);
+ if (result.config.initial_config.host_name[0] == '[') {
+ if ((tmp_string = strstr(result.config.initial_config.host_name, "]:")) !=
+ NULL) { /* [IPv6]:port */
+ result.config.initial_config.virtualPort = atoi(tmp_string + 2);
/* cut off the port */
- host_name_length = strlen(result.config.host_name) - strlen(p) - 1;
- free(result.config.host_name);
- result.config.host_name = strndup(optarg, host_name_length);
+ host_name_length =
+ strlen(result.config.initial_config.host_name) - strlen(tmp_string) - 1;
+ free(result.config.initial_config.host_name);
+ result.config.initial_config.host_name = strndup(optarg, host_name_length);
}
- } else if ((p = strchr(result.config.host_name, ':')) != NULL &&
- strchr(++p, ':') == NULL) { /* IPv4:port or host:port */
- result.config.virtual_port = atoi(p);
+ } else if ((tmp_string = strchr(result.config.initial_config.host_name, ':')) != NULL &&
+ strchr(++tmp_string, ':') == NULL) { /* IPv4:port or host:port */
+ result.config.initial_config.virtualPort = atoi(tmp_string);
/* cut off the port */
- host_name_length = strlen(result.config.host_name) - strlen(p) - 1;
- free(result.config.host_name);
- result.config.host_name = strndup(optarg, host_name_length);
+ host_name_length =
+ strlen(result.config.initial_config.host_name) - strlen(tmp_string) - 1;
+ free(result.config.initial_config.host_name);
+ result.config.initial_config.host_name = strndup(optarg, host_name_length);
}
break;
case 'I': /* internet address */
- result.config.server_address = strdup(optarg);
+ result.config.initial_config.server_address = strdup(optarg);
break;
case 'u': /* URL path */
- result.config.server_url = strdup(optarg);
+ result.config.initial_config.server_url = strdup(optarg);
break;
case 'p': /* Server port */
if (!is_intnonneg(optarg)) {
@@ -1618,7 +1703,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
if (strtol(optarg, NULL, 10) > MAX_PORT) {
usage2(_("Invalid port number, supplied port number is too big"), optarg);
}
- result.config.server_port = (unsigned short)strtol(optarg, NULL, 10);
+ result.config.initial_config.serverPort = (unsigned short)strtol(optarg, NULL, 10);
specify_port = true;
}
break;
@@ -1631,18 +1716,18 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
result.config.proxy_auth[MAX_INPUT_BUFFER - 1] = 0;
break;
case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */
- if (!result.config.http_post_data) {
- result.config.http_post_data = strdup(optarg);
+ if (!result.config.initial_config.http_post_data) {
+ result.config.initial_config.http_post_data = strdup(optarg);
}
- if (!result.config.http_method) {
- result.config.http_method = strdup("POST");
+ if (!result.config.initial_config.http_method) {
+ result.config.initial_config.http_method = strdup("POST");
}
break;
case 'j': /* Set HTTP method */
- if (result.config.http_method) {
- free(result.config.http_method);
+ if (result.config.initial_config.http_method) {
+ free(result.config.initial_config.http_method);
}
- result.config.http_method = strdup(optarg);
+ result.config.initial_config.http_method = strdup(optarg);
break;
case 'A': /* useragent */
strncpy(result.config.user_agent, optarg, DEFAULT_BUFFER_SIZE);
@@ -1723,7 +1808,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
{
enable_ssl:
bool got_plus = false;
- result.config.use_ssl = true;
+ result.config.initial_config.use_ssl = true;
/* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default.
* Only set if it's non-zero. This helps when we include multiple
* parameters, like -S and -C combinations */
@@ -1801,7 +1886,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
printf(_("* Set SSL/TLS version to %d\n"), result.config.ssl_version);
}
if (!specify_port) {
- result.config.server_port = HTTPS_PORT;
+ result.config.initial_config.serverPort = HTTPS_PORT;
}
} break;
#else /* LIBCURL_FEATURE_SSL */
@@ -1935,7 +2020,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
break;
}
case 'N': /* no-body */
- result.config.no_body = true;
+ result.config.initial_config.no_body = true;
break;
case 'M': /* max-age */
{
@@ -1996,21 +2081,22 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
}
}
- int c = optind;
+ int option_counter = optind;
- if (result.config.server_address == NULL && c < argc) {
- result.config.server_address = strdup(argv[c++]);
+ if (result.config.initial_config.server_address == NULL && option_counter < argc) {
+ result.config.initial_config.server_address = strdup(argv[option_counter++]);
}
- if (result.config.host_name == NULL && c < argc) {
- result.config.host_name = strdup(argv[c++]);
+ if (result.config.initial_config.host_name == NULL && option_counter < argc) {
+ result.config.initial_config.host_name = strdup(argv[option_counter++]);
}
- if (result.config.server_address == NULL) {
- if (result.config.host_name == NULL) {
+ if (result.config.initial_config.server_address == NULL) {
+ if (result.config.initial_config.host_name == NULL) {
usage4(_("You must specify a server address or host name"));
} else {
- result.config.server_address = strdup(result.config.host_name);
+ result.config.initial_config.server_address =
+ strdup(result.config.initial_config.host_name);
}
}
@@ -2024,21 +2110,23 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
printf("* Socket timeout set to %ld seconds\n", result.config.socket_timeout);
}
- if (result.config.http_method == NULL) {
- result.config.http_method = strdup("GET");
+ if (result.config.initial_config.http_method == NULL) {
+ result.config.initial_config.http_method = strdup("GET");
}
if (result.config.client_cert && !result.config.client_privkey) {
usage4(_("If you use a client certificate you must also specify a private key file"));
}
- if (result.config.virtual_port == 0) {
- result.config.virtual_port = result.config.server_port;
+ if (result.config.initial_config.virtualPort == 0) {
+ result.config.initial_config.virtualPort = result.config.initial_config.serverPort;
} else {
- if ((result.config.use_ssl && result.config.server_port == HTTPS_PORT) ||
- (!result.config.use_ssl && result.config.server_port == HTTP_PORT)) {
+ if ((result.config.initial_config.use_ssl &&
+ result.config.initial_config.serverPort == HTTPS_PORT) ||
+ (!result.config.initial_config.use_ssl &&
+ result.config.initial_config.serverPort == HTTP_PORT)) {
if (!specify_port) {
- result.config.server_port = result.config.virtual_port;
+ result.config.initial_config.serverPort = result.config.initial_config.virtualPort;
}
}
}
@@ -2389,12 +2477,12 @@ size_t curlhelp_buffer_write_callback(void *buffer, size_t size, size_t nmemb, v
size_t curlhelp_buffer_read_callback(void *buffer, size_t size, size_t nmemb, void *stream) {
curlhelp_read_curlbuf *buf = (curlhelp_read_curlbuf *)stream;
- size_t n = min(nmemb * size, buf->buflen - buf->pos);
+ size_t minimalSize = min(nmemb * size, buf->buflen - buf->pos);
- memcpy(buffer, buf->buf + buf->pos, n);
- buf->pos += n;
+ memcpy(buffer, buf->buf + buf->pos, minimalSize);
+ buf->pos += minimalSize;
- return n;
+ return minimalSize;
}
void curlhelp_freewritebuffer(curlhelp_write_curlbuf *buf) {
@@ -2473,86 +2561,85 @@ int curlhelp_parse_statusline(const char *buf, curlhelp_statusline *status_line)
char *first_line_buf = strdup(status_line->first_line);
/* protocol and version: "HTTP/x.x" SP or "HTTP/2" SP */
- char *p = strtok(first_line_buf, "/");
- if (p == NULL) {
+ char *temp_string = strtok(first_line_buf, "/");
+ if (temp_string == NULL) {
free(first_line_buf);
return -1;
}
- if (strcmp(p, "HTTP") != 0) {
+ if (strcmp(temp_string, "HTTP") != 0) {
free(first_line_buf);
return -1;
}
- p = strtok(NULL, " ");
- if (p == NULL) {
+ temp_string = strtok(NULL, " ");
+ if (temp_string == NULL) {
free(first_line_buf);
return -1;
}
- char *pp;
- if (strchr(p, '.') != NULL) {
+ char *temp_string_2;
+ if (strchr(temp_string, '.') != NULL) {
/* HTTP 1.x case */
- strtok(p, ".");
- status_line->http_major = (int)strtol(p, &pp, 10);
- if (*pp != '\0') {
+ strtok(temp_string, ".");
+ status_line->http_major = (int)strtol(temp_string, &temp_string_2, 10);
+ if (*temp_string_2 != '\0') {
free(first_line_buf);
return -1;
}
strtok(NULL, " ");
- status_line->http_minor = (int)strtol(p, &pp, 10);
- if (*pp != '\0') {
+ status_line->http_minor = (int)strtol(temp_string, &temp_string_2, 10);
+ if (*temp_string_2 != '\0') {
free(first_line_buf);
return -1;
}
- p += 4; /* 1.x SP */
+ temp_string += 4; /* 1.x SP */
} else {
/* HTTP 2 case */
- status_line->http_major = (int)strtol(p, &pp, 10);
+ status_line->http_major = (int)strtol(temp_string, &temp_string_2, 10);
status_line->http_minor = 0;
- p += 2; /* 2 SP */
+ temp_string += 2; /* 2 SP */
}
/* status code: "404" or "404.1", then SP */
-
- p = strtok(p, " ");
- if (p == NULL) {
+ temp_string = strtok(temp_string, " ");
+ if (temp_string == NULL) {
free(first_line_buf);
return -1;
}
- if (strchr(p, '.') != NULL) {
+ if (strchr(temp_string, '.') != NULL) {
char *ppp;
- ppp = strtok(p, ".");
- status_line->http_code = (int)strtol(ppp, &pp, 10);
- if (*pp != '\0') {
+ ppp = strtok(temp_string, ".");
+ status_line->http_code = (int)strtol(ppp, &temp_string_2, 10);
+ if (*temp_string_2 != '\0') {
free(first_line_buf);
return -1;
}
ppp = strtok(NULL, "");
- status_line->http_subcode = (int)strtol(ppp, &pp, 10);
- if (*pp != '\0') {
+ status_line->http_subcode = (int)strtol(ppp, &temp_string_2, 10);
+ if (*temp_string_2 != '\0') {
free(first_line_buf);
return -1;
}
- p += 6; /* 400.1 SP */
+ temp_string += 6; /* 400.1 SP */
} else {
- status_line->http_code = (int)strtol(p, &pp, 10);
+ status_line->http_code = (int)strtol(temp_string, &temp_string_2, 10);
status_line->http_subcode = -1;
- if (*pp != '\0') {
+ if (*temp_string_2 != '\0') {
free(first_line_buf);
return -1;
}
- p += 4; /* 400 SP */
+ temp_string += 4; /* 400 SP */
}
/* Human readable message: "Not Found" CRLF */
- p = strtok(p, "");
- if (p == NULL) {
+ temp_string = strtok(temp_string, "");
+ if (temp_string == NULL) {
status_line->msg = "";
return 0;
}
- status_line->msg = status_line->first_line + (p - first_line_buf);
+ status_line->msg = status_line->first_line + (temp_string - first_line_buf);
free(first_line_buf);
return 0;
--
cgit v1.2.3-74-g34f1