summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-09-11 13:44:55 +0200
committerLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-09-11 13:44:55 +0200
commit99206dab7aa272e5c16c672dca81e6044ac7a4eb (patch)
tree4741f0d1cb261a9d13ab705f71522fbbf3db059b
parent6969f5719268dec6459d9107e11a711dab3a18dd (diff)
downloadmonitoring-plugins-99206dab7aa272e5c16c672dca81e6044ac7a4eb.tar.gz
check_curl: refactoring to modularize code
-rw-r--r--plugins/check_curl.c1055
-rw-r--r--plugins/check_curl.d/config.h78
2 files changed, 594 insertions, 539 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index 485a8744..f3cf7422 100644
--- a/plugins/check_curl.c
+++ b/plugins/check_curl.c
@@ -129,6 +129,9 @@ typedef struct {
129 bool put_buf_initialized; 129 bool put_buf_initialized;
130 curlhelp_read_curlbuf put_buf; 130 curlhelp_read_curlbuf put_buf;
131 CURL *curl; 131 CURL *curl;
132
133 struct curl_slist *header_list;
134 struct curl_slist *host;
132} check_curl_global_state; 135} check_curl_global_state;
133 136
134static char errbuf[MAX_INPUT_BUFFER]; 137static char errbuf[MAX_INPUT_BUFFER];
@@ -152,8 +155,7 @@ static check_curl_config_wrapper process_arguments(int /*argc*/, char ** /*argv*
152 155
153static void handle_curl_option_return_code(CURLcode res, const char *option); 156static void handle_curl_option_return_code(CURLcode res, const char *option);
154static mp_state_enum check_http(check_curl_config /*config*/, check_curl_working_state workingState, 157static mp_state_enum check_http(check_curl_config /*config*/, check_curl_working_state workingState,
155 int redir_depth, struct curl_slist *header_list, 158 int redir_depth);
156 check_curl_global_state global_state);
157 159
158typedef struct { 160typedef struct {
159 int redir_depth; 161 int redir_depth;
@@ -162,8 +164,7 @@ typedef struct {
162 check_curl_global_state curl_state; 164 check_curl_global_state curl_state;
163} redir_wrapper; 165} redir_wrapper;
164static redir_wrapper redir(curlhelp_write_curlbuf * /*header_buf*/, check_curl_config /*config*/, 166static redir_wrapper redir(curlhelp_write_curlbuf * /*header_buf*/, check_curl_config /*config*/,
165 int redir_depth, check_curl_working_state working_state, 167 int redir_depth, check_curl_working_state working_state);
166 check_curl_global_state global_state);
167 168
168static char *perfd_time(double elapsed_time, thresholds * /*thlds*/, long /*socket_timeout*/); 169static char *perfd_time(double elapsed_time, thresholds * /*thlds*/, long /*socket_timeout*/);
169static char *perfd_time_connect(double elapsed_time_connect, long /*socket_timeout*/); 170static char *perfd_time_connect(double elapsed_time_connect, long /*socket_timeout*/);
@@ -172,371 +173,169 @@ static char *perfd_time_firstbyte(double elapsed_time_firstbyte, long /*socket_t
172static char *perfd_time_headers(double elapsed_time_headers, long /*socket_timeout*/); 173static char *perfd_time_headers(double elapsed_time_headers, long /*socket_timeout*/);
173static char *perfd_time_transfer(double elapsed_time_transfer, long /*socket_timeout*/); 174static char *perfd_time_transfer(double elapsed_time_transfer, long /*socket_timeout*/);
174static char *perfd_size(size_t page_len, int /*min_page_len*/); 175static char *perfd_size(size_t page_len, int /*min_page_len*/);
176
175static void print_help(void); 177static void print_help(void);
176void print_usage(void); 178void print_usage(void);
179
177static void print_curl_version(void); 180static void print_curl_version(void);
181
178static int curlhelp_initwritebuffer(curlhelp_write_curlbuf * /*buf*/); 182static int curlhelp_initwritebuffer(curlhelp_write_curlbuf * /*buf*/);
179static size_t curlhelp_buffer_write_callback(void * /*buffer*/, size_t /*size*/, size_t /*nmemb*/, 183static size_t curlhelp_buffer_write_callback(void * /*buffer*/, size_t /*size*/, size_t /*nmemb*/,
180 void * /*stream*/); 184 void * /*stream*/);
181static void curlhelp_freewritebuffer(curlhelp_write_curlbuf * /*buf*/); 185static void curlhelp_freewritebuffer(curlhelp_write_curlbuf * /*buf*/);
186
182static int curlhelp_initreadbuffer(curlhelp_read_curlbuf * /*buf*/, const char * /*data*/, 187static int curlhelp_initreadbuffer(curlhelp_read_curlbuf * /*buf*/, const char * /*data*/,
183 size_t /*datalen*/); 188 size_t /*datalen*/);
184static size_t curlhelp_buffer_read_callback(void * /*buffer*/, size_t /*size*/, size_t /*nmemb*/, 189static size_t curlhelp_buffer_read_callback(void * /*buffer*/, size_t /*size*/, size_t /*nmemb*/,
185 void * /*stream*/); 190 void * /*stream*/);
186static void curlhelp_freereadbuffer(curlhelp_read_curlbuf * /*buf*/); 191static void curlhelp_freereadbuffer(curlhelp_read_curlbuf * /*buf*/);
192
187static curlhelp_ssl_library curlhelp_get_ssl_library(void); 193static curlhelp_ssl_library curlhelp_get_ssl_library(void);
188static const char *curlhelp_get_ssl_library_string(curlhelp_ssl_library /*ssl_library*/); 194static const char *curlhelp_get_ssl_library_string(curlhelp_ssl_library /*ssl_library*/);
195
189int net_noopenssl_check_certificate(cert_ptr_union *, int, int); 196int net_noopenssl_check_certificate(cert_ptr_union *, int, int);
190 197
191static int curlhelp_parse_statusline(const char * /*buf*/, curlhelp_statusline * /*status_line*/); 198static int curlhelp_parse_statusline(const char * /*buf*/, curlhelp_statusline * /*status_line*/);
192static void curlhelp_free_statusline(curlhelp_statusline * /*status_line*/); 199static void curlhelp_free_statusline(curlhelp_statusline * /*status_line*/);
200
193static char *get_header_value(const struct phr_header *headers, size_t nof_headers, 201static char *get_header_value(const struct phr_header *headers, size_t nof_headers,
194 const char *header); 202 const char *header);
195static mp_state_enum check_document_dates(const curlhelp_write_curlbuf * /*header_buf*/, 203static mp_state_enum check_document_dates(const curlhelp_write_curlbuf * /*header_buf*/,
196 char (*msg)[DEFAULT_BUFFER_SIZE], int /*maximum_age*/); 204 char (*msg)[DEFAULT_BUFFER_SIZE], int /*maximum_age*/);
197static size_t get_content_length(const curlhelp_write_curlbuf *header_buf, 205static size_t get_content_length(const curlhelp_write_curlbuf *header_buf,
198 const curlhelp_write_curlbuf *body_buf); 206 const curlhelp_write_curlbuf *body_buf);
207static int lookup_host(const char *host, char *buf, size_t buflen, sa_family_t addr_family);
199 208
200#if defined(HAVE_SSL) && defined(USE_OPENSSL) 209// typedef struct {
201mp_state_enum np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, 210// int errorcode;
202 int days_till_exp_crit); 211// } check_curl_evaluation_wrapper;
203#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */ 212// check_curl_evaluation_wrapper check_curl_evaluate(check_curl_config config,
204 213// mp_check overall[static 1]) {}
205static void test_file(char * /*path*/);
206
207int main(int argc, char **argv) {
208 setlocale(LC_ALL, "");
209 bindtextdomain(PACKAGE, LOCALEDIR);
210 textdomain(PACKAGE);
211
212 /* Parse extra opts if any */
213 argv = np_extra_opts(&argc, argv, progname);
214
215 /* parse arguments */
216 check_curl_config_wrapper tmp_config = process_arguments(argc, argv);
217 if (tmp_config.errorcode == ERROR) {
218 usage4(_("Could not parse arguments"));
219 }
220
221 const check_curl_config config = tmp_config.config;
222
223 /* set defaults */
224 if (strlen(config.user_agent) == 0) {
225 snprintf(config.user_agent, DEFAULT_BUFFER_SIZE, "%s/v%s (monitoring-plugins %s, %s)",
226 progname, NP_VERSION, VERSION, curl_version());
227 }
228
229 if (config.display_html) {
230 printf("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">",
231 config.initial_config.use_ssl ? "https" : "http",
232 config.initial_config.host_name ? config.initial_config.host_name
233 : config.initial_config.server_address,
234 config.initial_config.virtualPort ? config.initial_config.virtualPort
235 : config.initial_config.serverPort,
236 config.initial_config.server_url);
237 }
238
239 check_curl_global_state global_state = {
240 .curl_global_initialized = false,
241 .curl_easy_initialized = false,
242 .body_buf_initialized = false,
243 .body_buf = {},
244 .header_buf_initialized = false,
245 .header_buf = {},
246 .status_line_initialized = false,
247 .status_line = {},
248 .put_buf_initialized = false,
249 .put_buf = {},
250 .curl = NULL,
251 };
252
253 check_curl_working_state working_state = config.initial_config;
254 struct curl_slist *header_list = NULL;
255 214
256 exit((int)check_http(config, working_state, 0, header_list, global_state)); 215CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm);
257}
258 216
259#ifdef HAVE_SSL 217typedef struct {
260# ifdef USE_OPENSSL 218 int errorcode;
261int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) { 219 check_curl_global_state curl_state;
262 (void)preverify_ok; 220} check_curl_configure_curl_wrapper;
263 /* TODO: we get all certificates of the chain, so which ones 221check_curl_configure_curl_wrapper
264 * should we test? 222check_curl_configure_curl(const check_curl_static_curl_config config,
265 * TODO: is the last certificate always the server certificate? 223 check_curl_working_state working_state, bool check_cert,
266 */ 224 bool on_redirect_dependent, int follow_method, int max_depth) {
267 cert = X509_STORE_CTX_get_current_cert(x509_ctx); 225 check_curl_configure_curl_wrapper result = {
268# if OPENSSL_VERSION_NUMBER >= 0x10100000L 226 .errorcode = OK,
269 X509_up_ref(cert); 227 .curl_state =
270# endif 228 {
271 if (verbose >= 2) { 229 .curl_global_initialized = false,
272 puts("* SSL verify callback with certificate:"); 230 .curl_easy_initialized = false,
273 printf("* issuer:\n"); 231 .curl = NULL,
274 X509_NAME *issuer = X509_get_issuer_name(cert); 232
275 X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE); 233 .body_buf_initialized = false,
276 printf("* curl verify_callback:\n* subject:\n"); 234 .body_buf = {},
277 X509_NAME *subject = X509_get_subject_name(cert); 235 .header_buf_initialized = false,
278 X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE); 236 .header_buf = {},
279 puts(""); 237 .status_line_initialized = false,
280 } 238 .status_line = {},
281 return 1; 239 .put_buf_initialized = false,
282} 240 .put_buf = {},
283 241
284CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) { 242 .header_list = NULL,
285 (void)curl; // ignore unused parameter 243 .host = NULL,
286 (void)parm; // ignore unused parameter 244 },
287 if (add_sslctx_verify_fun) {
288 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback);
289 }
290
291 // workaround for issue:
292 // OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0
293 // see discussion https://github.com/openssl/openssl/discussions/22690
294# ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
295 SSL_CTX_set_options(sslctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
296# endif
297
298 return CURLE_OK;
299}
300# endif /* USE_OPENSSL */
301#endif /* HAVE_SSL */
302
303/* returns a string "HTTP/1.x" or "HTTP/2" */
304static char *string_statuscode(int major, int minor) {
305 static char buf[10];
306
307 switch (major) {
308 case 1:
309 snprintf(buf, sizeof(buf), "HTTP/%d.%d", major, minor);
310 break;
311 case 2:
312 case 3:
313 snprintf(buf, sizeof(buf), "HTTP/%d", major);
314 break;
315 default:
316 /* assuming here HTTP/N with N>=4 */
317 snprintf(buf, sizeof(buf), "HTTP/%d", major);
318 break;
319 }
320
321 return buf;
322}
323
324/* Checks if the server 'reply' is one of the expected 'statuscodes' */
325static bool expected_statuscode(const char *reply, const char *statuscodes) {
326 char *expected;
327
328 if ((expected = strdup(statuscodes)) == NULL) {
329 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n"));
330 }
331
332 bool result = false;
333 for (char *code = strtok(expected, ","); code != NULL; code = strtok(NULL, ",")) {
334 if (strstr(reply, code) != NULL) {
335 result = true;
336 break;
337 }
338 }
339
340 free(expected);
341 return result;
342}
343
344void handle_curl_option_return_code(CURLcode res, const char *option) {
345 if (res != CURLE_OK) {
346 snprintf(msg, DEFAULT_BUFFER_SIZE,
347 _("Error while setting cURL option '%s': cURL returned %d - %s"), option, res,
348 curl_easy_strerror(res));
349 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
350 }
351}
352
353int lookup_host(const char *host, char *buf, size_t buflen, sa_family_t addr_family) {
354 struct addrinfo hints = {
355 .ai_family = addr_family,
356 .ai_socktype = SOCK_STREAM,
357 .ai_flags = AI_CANONNAME,
358 }; 245 };
359 246
360 struct addrinfo *result;
361 int errcode = getaddrinfo(host, NULL, &hints, &result);
362 if (errcode != 0) {
363 return errcode;
364 }
365
366 strcpy(buf, "");
367 struct addrinfo *res = result;
368
369 size_t buflen_remaining = buflen - 1;
370 size_t addrstr_len;
371 char addrstr[100];
372 void *ptr = {0};
373 while (res) {
374 switch (res->ai_family) {
375 case AF_INET:
376 ptr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
377 break;
378 case AF_INET6:
379 ptr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
380 break;
381 }
382
383 inet_ntop(res->ai_family, ptr, addrstr, 100);
384 if (verbose >= 1) {
385 printf("* getaddrinfo IPv%d address: %s\n", res->ai_family == PF_INET6 ? 6 : 4,
386 addrstr);
387 }
388
389 // Append all IPs to buf as a comma-separated string
390 addrstr_len = strlen(addrstr);
391 if (buflen_remaining > addrstr_len + 1) {
392 if (buf[0] != '\0') {
393 strncat(buf, ",", buflen_remaining);
394 buflen_remaining -= 1;
395 }
396 strncat(buf, addrstr, buflen_remaining);
397 buflen_remaining -= addrstr_len;
398 }
399
400 res = res->ai_next;
401 }
402
403 freeaddrinfo(result);
404
405 return 0;
406}
407
408static void cleanup(check_curl_global_state global_state) {
409 if (global_state.status_line_initialized) {
410 curlhelp_free_statusline(&global_state.status_line);
411 }
412 global_state.status_line_initialized = false;
413
414 if (global_state.curl_easy_initialized) {
415 curl_easy_cleanup(global_state.curl);
416 }
417 global_state.curl_easy_initialized = false;
418
419 if (global_state.curl_global_initialized) {
420 curl_global_cleanup();
421 }
422 global_state.curl_global_initialized = false;
423
424 if (global_state.body_buf_initialized) {
425 curlhelp_freewritebuffer(&global_state.body_buf);
426 }
427 global_state.body_buf_initialized = false;
428
429 if (global_state.header_buf_initialized) {
430 curlhelp_freewritebuffer(&global_state.header_buf);
431 }
432 global_state.header_buf_initialized = false;
433
434 if (global_state.put_buf_initialized) {
435 curlhelp_freereadbuffer(&global_state.put_buf);
436 }
437 global_state.put_buf_initialized = false;
438}
439
440mp_state_enum check_http(const check_curl_config config, check_curl_working_state workingState,
441 int redir_depth, struct curl_slist *header_list,
442 check_curl_global_state global_state) {
443
444 // =======================
445 // Initialisation for curl
446 // =======================
447 /* initialize curl */
448 if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) { 247 if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) {
449 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n"); 248 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n");
450 } 249 }
451 global_state.curl_global_initialized = true; 250 result.curl_state.curl_global_initialized = true;
452 251
453 if ((global_state.curl = curl_easy_init()) == NULL) { 252 if ((result.curl_state.curl = curl_easy_init()) == NULL) {
454 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n"); 253 die(STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n");
455 } 254 }
456 global_state.curl_easy_initialized = true; 255 result.curl_state.curl_easy_initialized = true;
457 256
458 if (verbose >= 1) { 257 if (verbose >= 1) {
459 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_VERBOSE, 1), 258 handle_curl_option_return_code(curl_easy_setopt(result.curl_state.curl, CURLOPT_VERBOSE, 1),
460 "CURLOPT_VERBOSE"); 259 "CURLOPT_VERBOSE");
461 } 260 }
462
463 /* print everything on stdout like check_http would do */ 261 /* print everything on stdout like check_http would do */
464 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_STDERR, stdout), 262 handle_curl_option_return_code(curl_easy_setopt(result.curl_state.curl, CURLOPT_STDERR, stdout),
465 "CURLOPT_STDERR"); 263 "CURLOPT_STDERR");
466 264
467 if (config.automatic_decompression) { 265 if (config.automatic_decompression) {
468#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) 266#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6)
469 handle_curl_option_return_code( 267 handle_curl_option_return_code(
470 curl_easy_setopt(global_state.curl, CURLOPT_ACCEPT_ENCODING, ""), 268 curl_easy_setopt(result.curl_state.curl, CURLOPT_ACCEPT_ENCODING, ""),
471 "CURLOPT_ACCEPT_ENCODING"); 269 "CURLOPT_ACCEPT_ENCODING");
472#else 270#else
473 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_ENCODING, ""), 271 handle_curl_option_return_code(
474 "CURLOPT_ENCODING"); 272 curl_easy_setopt(result.curl_state.curl, CURLOPT_ENCODING, ""), "CURLOPT_ENCODING");
475#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */ 273#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 21, 6) */
476 } 274 }
477 275
478 /* initialize buffer for body of the answer */ 276 /* initialize buffer for body of the answer */
479 if (curlhelp_initwritebuffer(&global_state.body_buf) < 0) { 277 if (curlhelp_initwritebuffer(&result.curl_state.body_buf) < 0) {
480 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n"); 278 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n");
481 } 279 }
482 global_state.body_buf_initialized = true; 280 result.curl_state.body_buf_initialized = true;
483 handle_curl_option_return_code( 281
484 curl_easy_setopt(global_state.curl, CURLOPT_WRITEFUNCTION, curlhelp_buffer_write_callback), 282 handle_curl_option_return_code(curl_easy_setopt(result.curl_state.curl, CURLOPT_WRITEFUNCTION,
485 "CURLOPT_WRITEFUNCTION"); 283 curlhelp_buffer_write_callback),
486 handle_curl_option_return_code( 284 "CURLOPT_WRITEFUNCTION");
487 curl_easy_setopt(global_state.curl, CURLOPT_WRITEDATA, (void *)&global_state.body_buf), 285 handle_curl_option_return_code(curl_easy_setopt(result.curl_state.curl, CURLOPT_WRITEDATA,
488 "CURLOPT_WRITEDATA"); 286 (void *)&result.curl_state.body_buf),
287 "CURLOPT_WRITEDATA");
489 288
490 /* initialize buffer for header of the answer */ 289 /* initialize buffer for header of the answer */
491 if (curlhelp_initwritebuffer(&global_state.header_buf) < 0) { 290 if (curlhelp_initwritebuffer(&result.curl_state.header_buf) < 0) {
492 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n"); 291 die(STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n");
493 } 292 }
494 global_state.header_buf_initialized = true; 293 result.curl_state.header_buf_initialized = true;
495 294
496 handle_curl_option_return_code( 295 handle_curl_option_return_code(curl_easy_setopt(result.curl_state.curl, CURLOPT_HEADERFUNCTION,
497 curl_easy_setopt(global_state.curl, CURLOPT_HEADERFUNCTION, curlhelp_buffer_write_callback), 296 curlhelp_buffer_write_callback),
498 "CURLOPT_HEADERFUNCTION"); 297 "CURLOPT_HEADERFUNCTION");
499 handle_curl_option_return_code( 298 handle_curl_option_return_code(curl_easy_setopt(result.curl_state.curl, CURLOPT_WRITEHEADER,
500 curl_easy_setopt(global_state.curl, CURLOPT_WRITEHEADER, (void *)&global_state.header_buf), 299 (void *)&result.curl_state.header_buf),
501 "CURLOPT_WRITEHEADER"); 300 "CURLOPT_WRITEHEADER");
502 301
503 /* set the error buffer */ 302 /* set the error buffer */
504 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_ERRORBUFFER, errbuf), 303 handle_curl_option_return_code(
505 "CURLOPT_ERRORBUFFER"); 304 curl_easy_setopt(result.curl_state.curl, CURLOPT_ERRORBUFFER, errbuf),
305 "CURLOPT_ERRORBUFFER");
506 306
507 /* set timeouts */ 307 /* set timeouts */
508 handle_curl_option_return_code( 308 handle_curl_option_return_code(
509 curl_easy_setopt(global_state.curl, CURLOPT_CONNECTTIMEOUT, config.socket_timeout), 309 curl_easy_setopt(result.curl_state.curl, CURLOPT_CONNECTTIMEOUT, config.socket_timeout),
510 "CURLOPT_CONNECTTIMEOUT"); 310 "CURLOPT_CONNECTTIMEOUT");
511 handle_curl_option_return_code( 311 handle_curl_option_return_code(
512 curl_easy_setopt(global_state.curl, CURLOPT_TIMEOUT, config.socket_timeout), 312 curl_easy_setopt(result.curl_state.curl, CURLOPT_TIMEOUT, config.socket_timeout),
513 "CURLOPT_TIMEOUT"); 313 "CURLOPT_TIMEOUT");
514 314
515 /* enable haproxy protocol */ 315 /* enable haproxy protocol */
516 if (config.haproxy_protocol) { 316 if (config.haproxy_protocol) {
517 handle_curl_option_return_code( 317 handle_curl_option_return_code(
518 curl_easy_setopt(global_state.curl, CURLOPT_HAPROXYPROTOCOL, 1L), 318 curl_easy_setopt(result.curl_state.curl, CURLOPT_HAPROXYPROTOCOL, 1L),
519 "CURLOPT_HAPROXYPROTOCOL"); 319 "CURLOPT_HAPROXYPROTOCOL");
520 } 320 }
521 321
522 // fill dns resolve cache to make curl connect to the given server_address instead of the 322 // fill dns resolve cache to make curl connect to the given server_address instead of the
523 // host_name, only required for ssl, because we use the host_name later on to make SNI happy 323 // host_name, only required for ssl, because we use the host_name later on to make SNI happy
524 struct curl_slist *host = NULL;
525 char dnscache[DEFAULT_BUFFER_SIZE]; 324 char dnscache[DEFAULT_BUFFER_SIZE];
526 char addrstr[DEFAULT_BUFFER_SIZE / 2]; 325 char addrstr[DEFAULT_BUFFER_SIZE / 2];
527 if (workingState.use_ssl && workingState.host_name != NULL) { 326 if (working_state.use_ssl && working_state.host_name != NULL) {
528 int res; 327 int res;
529 if ((res = lookup_host(workingState.server_address, addrstr, DEFAULT_BUFFER_SIZE / 2, 328 if ((res = lookup_host(working_state.server_address, addrstr, DEFAULT_BUFFER_SIZE / 2,
530 config.sin_family)) != 0) { 329 config.sin_family)) != 0) {
531 snprintf(msg, DEFAULT_BUFFER_SIZE, 330 snprintf(msg, DEFAULT_BUFFER_SIZE,
532 _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"), 331 _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"),
533 workingState.server_address, res, gai_strerror(res)); 332 working_state.server_address, res, gai_strerror(res));
534 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 333 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
535 } 334 }
536 snprintf(dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", workingState.host_name, 335 snprintf(dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", working_state.host_name,
537 workingState.serverPort, addrstr); 336 working_state.serverPort, addrstr);
538 host = curl_slist_append(NULL, dnscache); 337 result.curl_state.host = curl_slist_append(NULL, dnscache);
539 curl_easy_setopt(global_state.curl, CURLOPT_RESOLVE, host); 338 curl_easy_setopt(result.curl_state.curl, CURLOPT_RESOLVE, result.curl_state.host);
540 if (verbose >= 1) { 339 if (verbose >= 1) {
541 printf("* curl CURLOPT_RESOLVE: %s\n", dnscache); 340 printf("* curl CURLOPT_RESOLVE: %s\n", dnscache);
542 } 341 }
@@ -544,72 +343,71 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
544 343
545 // If server_address is an IPv6 address it must be surround by square brackets 344 // If server_address is an IPv6 address it must be surround by square brackets
546 struct in6_addr tmp_in_addr; 345 struct in6_addr tmp_in_addr;
547 if (inet_pton(AF_INET6, workingState.server_address, &tmp_in_addr) == 1) { 346 if (inet_pton(AF_INET6, working_state.server_address, &tmp_in_addr) == 1) {
548 char *new_server_address = malloc(strlen(workingState.server_address) + 3); 347 char *new_server_address = malloc(strlen(working_state.server_address) + 3);
549 if (new_server_address == NULL) { 348 if (new_server_address == NULL) {
550 die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n"); 349 die(STATE_UNKNOWN, "HTTP UNKNOWN - Unable to allocate memory\n");
551 } 350 }
552 snprintf(new_server_address, strlen(workingState.server_address) + 3, "[%s]", 351 snprintf(new_server_address, strlen(working_state.server_address) + 3, "[%s]",
553 workingState.server_address); 352 working_state.server_address);
554 free(workingState.server_address); 353 working_state.server_address = new_server_address;
555 workingState.server_address = new_server_address;
556 } 354 }
557 355
558 /* compose URL: use the address we want to connect to, set Host: header later */ 356 /* compose URL: use the address we want to connect to, set Host: header later */
559 char url[DEFAULT_BUFFER_SIZE]; 357 char url[DEFAULT_BUFFER_SIZE];
560 snprintf(url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", workingState.use_ssl ? "https" : "http", 358 snprintf(url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", working_state.use_ssl ? "https" : "http",
561 (workingState.use_ssl & (workingState.host_name != NULL)) 359 (working_state.use_ssl & (working_state.host_name != NULL))
562 ? workingState.host_name 360 ? working_state.host_name
563 : workingState.server_address, 361 : working_state.server_address,
564 workingState.serverPort, workingState.server_url); 362 working_state.serverPort, working_state.server_url);
565 363
566 if (verbose >= 1) { 364 if (verbose >= 1) {
567 printf("* curl CURLOPT_URL: %s\n", url); 365 printf("* curl CURLOPT_URL: %s\n", url);
568 } 366 }
569 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_URL, url), 367 handle_curl_option_return_code(curl_easy_setopt(result.curl_state.curl, CURLOPT_URL, url),
570 "CURLOPT_URL"); 368 "CURLOPT_URL");
571 369
572 /* extract proxy information for legacy proxy https requests */ 370 /* extract proxy information for legacy proxy https requests */
573 if (!strcmp(workingState.http_method, "CONNECT") || 371 if (!strcmp(working_state.http_method, "CONNECT") ||
574 strstr(workingState.server_url, "http") == workingState.server_url) { 372 strstr(working_state.server_url, "http") == working_state.server_url) {
575 handle_curl_option_return_code( 373 handle_curl_option_return_code(
576 curl_easy_setopt(global_state.curl, CURLOPT_PROXY, workingState.server_address), 374 curl_easy_setopt(result.curl_state.curl, CURLOPT_PROXY, working_state.server_address),
577 "CURLOPT_PROXY"); 375 "CURLOPT_PROXY");
578 handle_curl_option_return_code( 376 handle_curl_option_return_code(curl_easy_setopt(result.curl_state.curl, CURLOPT_PROXYPORT,
579 curl_easy_setopt(global_state.curl, CURLOPT_PROXYPORT, (long)workingState.serverPort), 377 (long)working_state.serverPort),
580 "CURLOPT_PROXYPORT"); 378 "CURLOPT_PROXYPORT");
581 if (verbose >= 2) { 379 if (verbose >= 2) {
582 printf("* curl CURLOPT_PROXY: %s:%d\n", workingState.server_address, 380 printf("* curl CURLOPT_PROXY: %s:%d\n", working_state.server_address,
583 workingState.serverPort); 381 working_state.serverPort);
584 } 382 }
585 workingState.http_method = "GET"; 383 working_state.http_method = "GET";
586 handle_curl_option_return_code( 384 handle_curl_option_return_code(
587 curl_easy_setopt(global_state.curl, CURLOPT_URL, workingState.server_url), 385 curl_easy_setopt(result.curl_state.curl, CURLOPT_URL, working_state.server_url),
588 "CURLOPT_URL"); 386 "CURLOPT_URL");
589 } 387 }
590 388
591 /* disable body for HEAD request */ 389 /* disable body for HEAD request */
592 if (workingState.http_method && !strcmp(workingState.http_method, "HEAD")) { 390 if (working_state.http_method && !strcmp(working_state.http_method, "HEAD")) {
593 workingState.no_body = true; 391 working_state.no_body = true;
594 } 392 }
595 393
596 /* set HTTP protocol version */ 394 /* set HTTP protocol version */
597 handle_curl_option_return_code( 395 handle_curl_option_return_code(
598 curl_easy_setopt(global_state.curl, CURLOPT_HTTP_VERSION, config.curl_http_version), 396 curl_easy_setopt(result.curl_state.curl, CURLOPT_HTTP_VERSION, config.curl_http_version),
599 "CURLOPT_HTTP_VERSION"); 397 "CURLOPT_HTTP_VERSION");
600 398
601 /* set HTTP method */ 399 /* set HTTP method */
602 if (workingState.http_method) { 400 if (working_state.http_method) {
603 if (!strcmp(workingState.http_method, "POST")) { 401 if (!strcmp(working_state.http_method, "POST")) {
604 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_POST, 1), 402 handle_curl_option_return_code(
605 "CURLOPT_POST"); 403 curl_easy_setopt(result.curl_state.curl, CURLOPT_POST, 1), "CURLOPT_POST");
606 } else if (!strcmp(workingState.http_method, "PUT")) { 404 } else if (!strcmp(working_state.http_method, "PUT")) {
607 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_UPLOAD, 1), 405 handle_curl_option_return_code(
608 "CURLOPT_UPLOAD"); 406 curl_easy_setopt(result.curl_state.curl, CURLOPT_UPLOAD, 1), "CURLOPT_UPLOAD");
609 } else { 407 } else {
610 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, 408 handle_curl_option_return_code(curl_easy_setopt(result.curl_state.curl,
611 CURLOPT_CUSTOMREQUEST, 409 CURLOPT_CUSTOMREQUEST,
612 workingState.http_method), 410 working_state.http_method),
613 "CURLOPT_CUSTOMREQUEST"); 411 "CURLOPT_CUSTOMREQUEST");
614 } 412 }
615 } 413 }
@@ -627,67 +425,71 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
627 /* set hostname (virtual hosts), not needed if CURLOPT_CONNECT_TO is used, but left in 425 /* set hostname (virtual hosts), not needed if CURLOPT_CONNECT_TO is used, but left in
628 * anyway */ 426 * anyway */
629 char http_header[DEFAULT_BUFFER_SIZE]; 427 char http_header[DEFAULT_BUFFER_SIZE];
630 if (workingState.host_name != NULL && force_host_header == NULL) { 428 if (working_state.host_name != NULL && force_host_header == NULL) {
631 if ((workingState.virtualPort != HTTP_PORT && !workingState.use_ssl) || 429 if ((working_state.virtualPort != HTTP_PORT && !working_state.use_ssl) ||
632 (workingState.virtualPort != HTTPS_PORT && workingState.use_ssl)) { 430 (working_state.virtualPort != HTTPS_PORT && working_state.use_ssl)) {
633 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", workingState.host_name, 431 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s:%d", working_state.host_name,
634 workingState.virtualPort); 432 working_state.virtualPort);
635 } else { 433 } else {
636 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s", workingState.host_name); 434 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Host: %s", working_state.host_name);
637 } 435 }
638 header_list = curl_slist_append(header_list, http_header); 436 result.curl_state.header_list =
437 curl_slist_append(result.curl_state.header_list, http_header);
639 } 438 }
640 439
641 /* always close connection, be nice to servers */ 440 /* always close connection, be nice to servers */
642 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Connection: close"); 441 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Connection: close");
643 header_list = curl_slist_append(header_list, http_header); 442 result.curl_state.header_list = curl_slist_append(result.curl_state.header_list, http_header);
644 443
645 /* attach additional headers supplied by the user */ 444 /* attach additional headers supplied by the user */
646 /* optionally send any other header tag */ 445 /* optionally send any other header tag */
647 if (config.http_opt_headers_count) { 446 if (config.http_opt_headers_count) {
648 for (size_t i = 0; i < config.http_opt_headers_count; i++) { 447 for (size_t i = 0; i < config.http_opt_headers_count; i++) {
649 header_list = curl_slist_append(header_list, config.http_opt_headers[i]); 448 result.curl_state.header_list =
449 curl_slist_append(result.curl_state.header_list, config.http_opt_headers[i]);
650 } 450 }
651 } 451 }
652 452
653 /* set HTTP headers */ 453 /* set HTTP headers */
654 handle_curl_option_return_code( 454 handle_curl_option_return_code(
655 curl_easy_setopt(global_state.curl, CURLOPT_HTTPHEADER, header_list), "CURLOPT_HTTPHEADER"); 455 curl_easy_setopt(result.curl_state.curl, CURLOPT_HTTPHEADER, result.curl_state.header_list),
456 "CURLOPT_HTTPHEADER");
656 457
657#ifdef LIBCURL_FEATURE_SSL 458#ifdef LIBCURL_FEATURE_SSL
658 /* set SSL version, warn about insecure or unsupported versions */ 459 /* set SSL version, warn about insecure or unsupported versions */
659 if (workingState.use_ssl) { 460 if (working_state.use_ssl) {
660 handle_curl_option_return_code( 461 handle_curl_option_return_code(
661 curl_easy_setopt(global_state.curl, CURLOPT_SSLVERSION, config.ssl_version), 462 curl_easy_setopt(result.curl_state.curl, CURLOPT_SSLVERSION, config.ssl_version),
662 "CURLOPT_SSLVERSION"); 463 "CURLOPT_SSLVERSION");
663 } 464 }
664 465
665 /* client certificate and key to present to server (SSL) */ 466 /* client certificate and key to present to server (SSL) */
666 if (config.client_cert) { 467 if (config.client_cert) {
667 handle_curl_option_return_code( 468 handle_curl_option_return_code(
668 curl_easy_setopt(global_state.curl, CURLOPT_SSLCERT, config.client_cert), 469 curl_easy_setopt(result.curl_state.curl, CURLOPT_SSLCERT, config.client_cert),
669 "CURLOPT_SSLCERT"); 470 "CURLOPT_SSLCERT");
670 } 471 }
671 472
672 if (config.client_privkey) { 473 if (config.client_privkey) {
673 handle_curl_option_return_code( 474 handle_curl_option_return_code(
674 curl_easy_setopt(global_state.curl, CURLOPT_SSLKEY, config.client_privkey), 475 curl_easy_setopt(result.curl_state.curl, CURLOPT_SSLKEY, config.client_privkey),
675 "CURLOPT_SSLKEY"); 476 "CURLOPT_SSLKEY");
676 } 477 }
677 478
678 if (config.ca_cert) { 479 if (config.ca_cert) {
679 handle_curl_option_return_code( 480 handle_curl_option_return_code(
680 curl_easy_setopt(global_state.curl, CURLOPT_CAINFO, config.ca_cert), "CURLOPT_CAINFO"); 481 curl_easy_setopt(result.curl_state.curl, CURLOPT_CAINFO, config.ca_cert),
482 "CURLOPT_CAINFO");
681 } 483 }
682 484
683 if (config.ca_cert || config.verify_peer_and_host) { 485 if (config.ca_cert || config.verify_peer_and_host) {
684 /* per default if we have a CA verify both the peer and the 486 /* per default if we have a CA verify both the peer and the
685 * hostname in the certificate, can be switched off later */ 487 * hostname in the certificate, can be switched off later */
686 handle_curl_option_return_code( 488 handle_curl_option_return_code(
687 curl_easy_setopt(global_state.curl, CURLOPT_SSL_VERIFYPEER, 1), 489 curl_easy_setopt(result.curl_state.curl, CURLOPT_SSL_VERIFYPEER, 1),
688 "CURLOPT_SSL_VERIFYPEER"); 490 "CURLOPT_SSL_VERIFYPEER");
689 handle_curl_option_return_code( 491 handle_curl_option_return_code(
690 curl_easy_setopt(global_state.curl, CURLOPT_SSL_VERIFYHOST, 2), 492 curl_easy_setopt(result.curl_state.curl, CURLOPT_SSL_VERIFYHOST, 2),
691 "CURLOPT_SSL_VERIFYHOST"); 493 "CURLOPT_SSL_VERIFYHOST");
692 } else { 494 } else {
693 /* backward-compatible behaviour, be tolerant in checks 495 /* backward-compatible behaviour, be tolerant in checks
@@ -695,10 +497,10 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
695 * to be less tolerant about ssl verfications 497 * to be less tolerant about ssl verfications
696 */ 498 */
697 handle_curl_option_return_code( 499 handle_curl_option_return_code(
698 curl_easy_setopt(global_state.curl, CURLOPT_SSL_VERIFYPEER, 0), 500 curl_easy_setopt(result.curl_state.curl, CURLOPT_SSL_VERIFYPEER, 0),
699 "CURLOPT_SSL_VERIFYPEER"); 501 "CURLOPT_SSL_VERIFYPEER");
700 handle_curl_option_return_code( 502 handle_curl_option_return_code(
701 curl_easy_setopt(global_state.curl, CURLOPT_SSL_VERIFYHOST, 0), 503 curl_easy_setopt(result.curl_state.curl, CURLOPT_SSL_VERIFYHOST, 0),
702 "CURLOPT_SSL_VERIFYHOST"); 504 "CURLOPT_SSL_VERIFYHOST");
703 } 505 }
704 506
@@ -706,7 +508,7 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
706 curlhelp_ssl_library ssl_library = curlhelp_get_ssl_library(); 508 curlhelp_ssl_library ssl_library = curlhelp_get_ssl_library();
707 509
708 /* try hard to get a stack of certificates to verify against */ 510 /* try hard to get a stack of certificates to verify against */
709 if (config.check_cert) { 511 if (check_cert) {
710# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1) 512# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 1)
711 /* inform curl to report back certificates */ 513 /* inform curl to report back certificates */
712 switch (ssl_library) { 514 switch (ssl_library) {
@@ -722,14 +524,14 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
722 /* libcurl is built with OpenSSL, monitoring plugins, so falling 524 /* libcurl is built with OpenSSL, monitoring plugins, so falling
723 * back to manually extracting certificate information */ 525 * back to manually extracting certificate information */
724 handle_curl_option_return_code( 526 handle_curl_option_return_code(
725 curl_easy_setopt(global_state.curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 527 curl_easy_setopt(result.curl_state.curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
726 break; 528 break;
727 529
728 case CURLHELP_SSL_LIBRARY_NSS: 530 case CURLHELP_SSL_LIBRARY_NSS:
729# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 531# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
730 /* NSS: support for CERTINFO is implemented since 7.34.0 */ 532 /* NSS: support for CERTINFO is implemented since 7.34.0 */
731 handle_curl_option_return_code( 533 handle_curl_option_return_code(
732 curl_easy_setopt(global_state.curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 534 curl_easy_setopt(result.curl_state.curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
733# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 535# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
734 die(STATE_CRITICAL, 536 die(STATE_CRITICAL,
735 "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library " 537 "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library "
@@ -742,7 +544,7 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
742# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) 544# if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0)
743 /* GnuTLS: support for CERTINFO is implemented since 7.42.0 */ 545 /* GnuTLS: support for CERTINFO is implemented since 7.42.0 */
744 handle_curl_option_return_code( 546 handle_curl_option_return_code(
745 curl_easy_setopt(global_state.curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO"); 547 curl_easy_setopt(result.curl_state.curl, CURLOPT_CERTINFO, 1L), "CURLOPT_CERTINFO");
746# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */ 548# else /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 42, 0) */
747 die(STATE_CRITICAL, 549 die(STATE_CRITICAL,
748 "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library " 550 "HTTP CRITICAL - Cannot retrieve certificates (libcurl linked with SSL library "
@@ -775,10 +577,10 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
775# if LIBCURL_VERSION_NUM >= \ 577# if LIBCURL_VERSION_NUM >= \
776 MAKE_LIBCURL_VERSION(7, 10, 6) /* required for CURLOPT_SSL_CTX_FUNCTION */ 578 MAKE_LIBCURL_VERSION(7, 10, 6) /* required for CURLOPT_SSL_CTX_FUNCTION */
777 // ssl ctx function is not available with all ssl backends 579 // ssl ctx function is not available with all ssl backends
778 if (curl_easy_setopt(global_state.curl, CURLOPT_SSL_CTX_FUNCTION, NULL) != 580 if (curl_easy_setopt(result.curl_state.curl, CURLOPT_SSL_CTX_FUNCTION, NULL) !=
779 CURLE_UNKNOWN_OPTION) { 581 CURLE_UNKNOWN_OPTION) {
780 handle_curl_option_return_code( 582 handle_curl_option_return_code(
781 curl_easy_setopt(global_state.curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), 583 curl_easy_setopt(result.curl_state.curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun),
782 "CURLOPT_SSL_CTX_FUNCTION"); 584 "CURLOPT_SSL_CTX_FUNCTION");
783 } 585 }
784# endif 586# endif
@@ -786,23 +588,22 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
786 588
787 /* set default or user-given user agent identification */ 589 /* set default or user-given user agent identification */
788 handle_curl_option_return_code( 590 handle_curl_option_return_code(
789 curl_easy_setopt(global_state.curl, CURLOPT_USERAGENT, config.user_agent), 591 curl_easy_setopt(result.curl_state.curl, CURLOPT_USERAGENT, config.user_agent),
790 "CURLOPT_USERAGENT"); 592 "CURLOPT_USERAGENT");
791 593
792 /* proxy-authentication */ 594 /* proxy-authentication */
793 if (strcmp(config.proxy_auth, "")) { 595 if (strcmp(config.proxy_auth, "")) {
794 handle_curl_option_return_code( 596 handle_curl_option_return_code(
795 curl_easy_setopt(global_state.curl, CURLOPT_PROXYUSERPWD, config.proxy_auth), 597 curl_easy_setopt(result.curl_state.curl, CURLOPT_PROXYUSERPWD, config.proxy_auth),
796 "CURLOPT_PROXYUSERPWD"); 598 "CURLOPT_PROXYUSERPWD");
797 } 599 }
798 600
799 /* authentication */ 601 /* authentication */
800 if (strcmp(config.user_auth, "")) { 602 if (strcmp(config.user_auth, "")) {
801 handle_curl_option_return_code( 603 handle_curl_option_return_code(
802 curl_easy_setopt(global_state.curl, CURLOPT_USERPWD, config.user_auth), 604 curl_easy_setopt(result.curl_state.curl, CURLOPT_USERPWD, config.user_auth),
803 "CURLOPT_USERPWD"); 605 "CURLOPT_USERPWD");
804 } 606 }
805
806 /* TODO: parameter auth method, bitfield of following methods: 607 /* TODO: parameter auth method, bitfield of following methods:
807 * CURLAUTH_BASIC (default) 608 * CURLAUTH_BASIC (default)
808 * CURLAUTH_DIGEST 609 * CURLAUTH_DIGEST
@@ -820,26 +621,26 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
820 */ 621 */
821 622
822 /* handle redirections */ 623 /* handle redirections */
823 if (config.onredirect == STATE_DEPENDENT) { 624 if (on_redirect_dependent) {
824 if (config.followmethod == FOLLOW_LIBCURL) { 625 if (follow_method == FOLLOW_LIBCURL) {
825 handle_curl_option_return_code( 626 handle_curl_option_return_code(
826 curl_easy_setopt(global_state.curl, CURLOPT_FOLLOWLOCATION, 1), 627 curl_easy_setopt(result.curl_state.curl, CURLOPT_FOLLOWLOCATION, 1),
827 "CURLOPT_FOLLOWLOCATION"); 628 "CURLOPT_FOLLOWLOCATION");
828 629
829 /* default -1 is infinite, not good, could lead to zombie plugins! 630 /* default -1 is infinite, not good, could lead to zombie plugins!
830 Setting it to one bigger than maximal limit to handle errors nicely below 631 Setting it to one bigger than maximal limit to handle errors nicely below
831 */ 632 */
832 handle_curl_option_return_code( 633 handle_curl_option_return_code(
833 curl_easy_setopt(global_state.curl, CURLOPT_MAXREDIRS, config.max_depth + 1), 634 curl_easy_setopt(result.curl_state.curl, CURLOPT_MAXREDIRS, max_depth + 1),
834 "CURLOPT_MAXREDIRS"); 635 "CURLOPT_MAXREDIRS");
835 636
836 /* for now allow only http and https (we are a http(s) check plugin in the end) */ 637 /* for now allow only http and https (we are a http(s) check plugin in the end) */
837#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 85, 0) 638#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 85, 0)
838 handle_curl_option_return_code( 639 handle_curl_option_return_code(
839 curl_easy_setopt(global_state.curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https"), 640 curl_easy_setopt(result.curl_state.curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https"),
840 "CURLOPT_REDIR_PROTOCOLS_STR"); 641 "CURLOPT_REDIR_PROTOCOLS_STR");
841#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4) 642#elif LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 19, 4)
842 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, 643 handle_curl_option_return_code(curl_easy_setopt(result.curl_state.curl,
843 CURLOPT_REDIR_PROTOCOLS, 644 CURLOPT_REDIR_PROTOCOLS,
844 CURLPROTO_HTTP | CURLPROTO_HTTPS), 645 CURLPROTO_HTTP | CURLPROTO_HTTPS),
845 "CURLOPT_REDIRECT_PROTOCOLS"); 646 "CURLOPT_REDIRECT_PROTOCOLS");
@@ -854,70 +655,72 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
854 option here is nice like for expected page size? 655 option here is nice like for expected page size?
855 */ 656 */
856 } else { 657 } else {
857 /* old style redirection is handled below */ 658 /* old style redirection*/
858 } 659 }
859 } 660 }
860
861 /* no-body */ 661 /* no-body */
862 if (workingState.no_body) { 662 if (working_state.no_body) {
863 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_NOBODY, 1), 663 handle_curl_option_return_code(curl_easy_setopt(result.curl_state.curl, CURLOPT_NOBODY, 1),
864 "CURLOPT_NOBODY"); 664 "CURLOPT_NOBODY");
865 } 665 }
866 666
867 /* IPv4 or IPv6 forced DNS resolution */ 667 /* IPv4 or IPv6 forced DNS resolution */
868 if (config.sin_family == AF_UNSPEC) { 668 if (config.sin_family == AF_UNSPEC) {
869 handle_curl_option_return_code( 669 handle_curl_option_return_code(
870 curl_easy_setopt(global_state.curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER), 670 curl_easy_setopt(result.curl_state.curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER),
871 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_WHATEVER)"); 671 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_WHATEVER)");
872 } else if (config.sin_family == AF_INET) { 672 } else if (config.sin_family == AF_INET) {
873 handle_curl_option_return_code( 673 handle_curl_option_return_code(
874 curl_easy_setopt(global_state.curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4), 674 curl_easy_setopt(result.curl_state.curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4),
875 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)"); 675 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)");
876 } 676 }
877#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6) 677#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6)
878 else if (config.sin_family == AF_INET6) { 678 else if (config.sin_family == AF_INET6) {
879 handle_curl_option_return_code( 679 handle_curl_option_return_code(
880 curl_easy_setopt(global_state.curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6), 680 curl_easy_setopt(result.curl_state.curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6),
881 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V6)"); 681 "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V6)");
882 } 682 }
883#endif 683#endif
884 684
885 /* either send http POST data (any data, not only POST)*/ 685 /* either send http POST data (any data, not only POST)*/
886 if (!strcmp(workingState.http_method, "POST") || !strcmp(workingState.http_method, "PUT")) { 686 if (!strcmp(working_state.http_method, "POST") || !strcmp(working_state.http_method, "PUT")) {
887 /* set content of payload for POST and PUT */ 687 /* set content of payload for POST and PUT */
888 if (config.http_content_type) { 688 if (config.http_content_type) {
889 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Content-Type: %s", 689 snprintf(http_header, DEFAULT_BUFFER_SIZE, "Content-Type: %s",
890 config.http_content_type); 690 config.http_content_type);
891 header_list = curl_slist_append(header_list, http_header); 691 result.curl_state.header_list =
692 curl_slist_append(result.curl_state.header_list, http_header);
892 } 693 }
893 /* NULL indicates "HTTP Continue" in libcurl, provide an empty string 694 /* NULL indicates "HTTP Continue" in libcurl, provide an empty string
894 * in case of no POST/PUT data */ 695 * in case of no POST/PUT data */
895 if (!workingState.http_post_data) { 696 if (!working_state.http_post_data) {
896 workingState.http_post_data = ""; 697 working_state.http_post_data = "";
897 } 698 }
898 if (!strcmp(workingState.http_method, "POST")) { 699
700 if (!strcmp(working_state.http_method, "POST")) {
899 /* POST method, set payload with CURLOPT_POSTFIELDS */ 701 /* POST method, set payload with CURLOPT_POSTFIELDS */
900 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_POSTFIELDS, 702 handle_curl_option_return_code(curl_easy_setopt(result.curl_state.curl,
901 workingState.http_post_data), 703 CURLOPT_POSTFIELDS,
704 working_state.http_post_data),
902 "CURLOPT_POSTFIELDS"); 705 "CURLOPT_POSTFIELDS");
903 } else if (!strcmp(workingState.http_method, "PUT")) { 706 } else if (!strcmp(working_state.http_method, "PUT")) {
904 handle_curl_option_return_code( 707 handle_curl_option_return_code(
905 curl_easy_setopt(global_state.curl, CURLOPT_READFUNCTION, 708 curl_easy_setopt(result.curl_state.curl, CURLOPT_READFUNCTION,
906 (curl_read_callback)curlhelp_buffer_read_callback), 709 (curl_read_callback)curlhelp_buffer_read_callback),
907 "CURLOPT_READFUNCTION"); 710 "CURLOPT_READFUNCTION");
908 if (curlhelp_initreadbuffer(&global_state.put_buf, workingState.http_post_data, 711 if (curlhelp_initreadbuffer(&result.curl_state.put_buf, working_state.http_post_data,
909 strlen(workingState.http_post_data)) < 0) { 712 strlen(working_state.http_post_data)) < 0) {
910 die(STATE_UNKNOWN, 713 die(STATE_UNKNOWN,
911 "HTTP CRITICAL - out of memory allocating read buffer for PUT\n"); 714 "HTTP CRITICAL - out of memory allocating read buffer for PUT\n");
912 } 715 }
913 global_state.put_buf_initialized = true; 716 result.curl_state.put_buf_initialized = true;
914 717 handle_curl_option_return_code(curl_easy_setopt(result.curl_state.curl,
915 handle_curl_option_return_code(curl_easy_setopt(global_state.curl, CURLOPT_READDATA, 718 CURLOPT_READDATA,
916 (void *)&global_state.put_buf), 719 (void *)&result.curl_state.put_buf),
917 "CURLOPT_READDATA"); 720 "CURLOPT_READDATA");
918 handle_curl_option_return_code( 721 handle_curl_option_return_code(
919 curl_easy_setopt(global_state.curl, CURLOPT_INFILESIZE, 722 curl_easy_setopt(result.curl_state.curl, CURLOPT_INFILESIZE,
920 (curl_off_t)strlen(workingState.http_post_data)), 723 (curl_off_t)strlen(working_state.http_post_data)),
921 "CURLOPT_INFILESIZE"); 724 "CURLOPT_INFILESIZE");
922 } 725 }
923 } 726 }
@@ -927,35 +730,267 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
927 /* enable reading cookies from a file, and if the filename is an empty string, only 730 /* enable reading cookies from a file, and if the filename is an empty string, only
928 * enable the curl cookie engine */ 731 * enable the curl cookie engine */
929 handle_curl_option_return_code( 732 handle_curl_option_return_code(
930 curl_easy_setopt(global_state.curl, CURLOPT_COOKIEFILE, config.cookie_jar_file), 733 curl_easy_setopt(result.curl_state.curl, CURLOPT_COOKIEFILE, config.cookie_jar_file),
931 "CURLOPT_COOKIEFILE"); 734 "CURLOPT_COOKIEFILE");
932 /* now enable saving cookies to a file, but only if the filename is not an empty string, 735 /* now enable saving cookies to a file, but only if the filename is not an empty string,
933 * since writing it would fail */ 736 * since writing it would fail */
934 if (*config.cookie_jar_file) { 737 if (*config.cookie_jar_file) {
935 handle_curl_option_return_code( 738 handle_curl_option_return_code(
936 curl_easy_setopt(global_state.curl, CURLOPT_COOKIEJAR, config.cookie_jar_file), 739 curl_easy_setopt(result.curl_state.curl, CURLOPT_COOKIEJAR, config.cookie_jar_file),
937 "CURLOPT_COOKIEJAR"); 740 "CURLOPT_COOKIEJAR");
938 } 741 }
939 } 742 }
743 return result;
744}
745
746#if defined(HAVE_SSL) && defined(USE_OPENSSL)
747mp_state_enum np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn,
748 int days_till_exp_crit);
749#endif /* defined(HAVE_SSL) && defined(USE_OPENSSL) */
750
751static void test_file(char * /*path*/);
752
753int main(int argc, char **argv) {
754 setlocale(LC_ALL, "");
755 bindtextdomain(PACKAGE, LOCALEDIR);
756 textdomain(PACKAGE);
757
758 /* Parse extra opts if any */
759 argv = np_extra_opts(&argc, argv, progname);
760
761 /* parse arguments */
762 check_curl_config_wrapper tmp_config = process_arguments(argc, argv);
763 if (tmp_config.errorcode == ERROR) {
764 usage4(_("Could not parse arguments"));
765 }
766
767 const check_curl_config config = tmp_config.config;
768
769 if (config.display_html) {
770 printf("<A HREF=\"%s://%s:%d%s\" target=\"_blank\">",
771 config.initial_config.use_ssl ? "https" : "http",
772 config.initial_config.host_name ? config.initial_config.host_name
773 : config.initial_config.server_address,
774 config.initial_config.virtualPort ? config.initial_config.virtualPort
775 : config.initial_config.serverPort,
776 config.initial_config.server_url);
777 }
778
779 check_curl_working_state working_state = config.initial_config;
780
781 exit((int)check_http(config, working_state, 0));
782}
783
784#ifdef HAVE_SSL
785# ifdef USE_OPENSSL
786int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) {
787 (void)preverify_ok;
788 /* TODO: we get all certificates of the chain, so which ones
789 * should we test?
790 * TODO: is the last certificate always the server certificate?
791 */
792 cert = X509_STORE_CTX_get_current_cert(x509_ctx);
793# if OPENSSL_VERSION_NUMBER >= 0x10100000L
794 X509_up_ref(cert);
795# endif
796 if (verbose >= 2) {
797 puts("* SSL verify callback with certificate:");
798 printf("* issuer:\n");
799 X509_NAME *issuer = X509_get_issuer_name(cert);
800 X509_NAME_print_ex_fp(stdout, issuer, 5, XN_FLAG_MULTILINE);
801 printf("* curl verify_callback:\n* subject:\n");
802 X509_NAME *subject = X509_get_subject_name(cert);
803 X509_NAME_print_ex_fp(stdout, subject, 5, XN_FLAG_MULTILINE);
804 puts("");
805 }
806 return 1;
807}
808
809CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) {
810 (void)curl; // ignore unused parameter
811 (void)parm; // ignore unused parameter
812 if (add_sslctx_verify_fun) {
813 SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, verify_callback);
814 }
815
816 // workaround for issue:
817 // OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0
818 // see discussion https://github.com/openssl/openssl/discussions/22690
819# ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
820 SSL_CTX_set_options(sslctx, SSL_OP_IGNORE_UNEXPECTED_EOF);
821# endif
822
823 return CURLE_OK;
824}
825# endif /* USE_OPENSSL */
826#endif /* HAVE_SSL */
827
828/* returns a string "HTTP/1.x" or "HTTP/2" */
829static char *string_statuscode(int major, int minor) {
830 static char buf[10];
831
832 switch (major) {
833 case 1:
834 snprintf(buf, sizeof(buf), "HTTP/%d.%d", major, minor);
835 break;
836 case 2:
837 case 3:
838 snprintf(buf, sizeof(buf), "HTTP/%d", major);
839 break;
840 default:
841 /* assuming here HTTP/N with N>=4 */
842 snprintf(buf, sizeof(buf), "HTTP/%d", major);
843 break;
844 }
845
846 return buf;
847}
848
849/* Checks if the server 'reply' is one of the expected 'statuscodes' */
850static bool expected_statuscode(const char *reply, const char *statuscodes) {
851 char *expected;
852
853 if ((expected = strdup(statuscodes)) == NULL) {
854 die(STATE_UNKNOWN, _("HTTP UNKNOWN - Memory allocation error\n"));
855 }
856
857 bool result = false;
858 for (char *code = strtok(expected, ","); code != NULL; code = strtok(NULL, ",")) {
859 if (strstr(reply, code) != NULL) {
860 result = true;
861 break;
862 }
863 }
864
865 free(expected);
866 return result;
867}
868
869void handle_curl_option_return_code(CURLcode res, const char *option) {
870 if (res != CURLE_OK) {
871 snprintf(msg, DEFAULT_BUFFER_SIZE,
872 _("Error while setting cURL option '%s': cURL returned %d - %s"), option, res,
873 curl_easy_strerror(res));
874 die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
875 }
876}
877
878int lookup_host(const char *host, char *buf, size_t buflen, sa_family_t addr_family) {
879 struct addrinfo hints = {
880 .ai_family = addr_family,
881 .ai_socktype = SOCK_STREAM,
882 .ai_flags = AI_CANONNAME,
883 };
884
885 struct addrinfo *result;
886 int errcode = getaddrinfo(host, NULL, &hints, &result);
887 if (errcode != 0) {
888 return errcode;
889 }
890
891 strcpy(buf, "");
892 struct addrinfo *res = result;
893
894 size_t buflen_remaining = buflen - 1;
895 size_t addrstr_len;
896 char addrstr[100];
897 void *ptr = {0};
898 while (res) {
899 switch (res->ai_family) {
900 case AF_INET:
901 ptr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
902 break;
903 case AF_INET6:
904 ptr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
905 break;
906 }
907
908 inet_ntop(res->ai_family, ptr, addrstr, 100);
909 if (verbose >= 1) {
910 printf("* getaddrinfo IPv%d address: %s\n", res->ai_family == PF_INET6 ? 6 : 4,
911 addrstr);
912 }
913
914 // Append all IPs to buf as a comma-separated string
915 addrstr_len = strlen(addrstr);
916 if (buflen_remaining > addrstr_len + 1) {
917 if (buf[0] != '\0') {
918 strncat(buf, ",", buflen_remaining);
919 buflen_remaining -= 1;
920 }
921 strncat(buf, addrstr, buflen_remaining);
922 buflen_remaining -= addrstr_len;
923 }
924
925 res = res->ai_next;
926 }
927
928 freeaddrinfo(result);
929
930 return 0;
931}
932
933static void cleanup(check_curl_global_state global_state) {
934 if (global_state.status_line_initialized) {
935 curlhelp_free_statusline(&global_state.status_line);
936 }
937 global_state.status_line_initialized = false;
938
939 if (global_state.curl_easy_initialized) {
940 curl_easy_cleanup(global_state.curl);
941 }
942 global_state.curl_easy_initialized = false;
943
944 if (global_state.curl_global_initialized) {
945 curl_global_cleanup();
946 }
947 global_state.curl_global_initialized = false;
948
949 if (global_state.body_buf_initialized) {
950 curlhelp_freewritebuffer(&global_state.body_buf);
951 }
952 global_state.body_buf_initialized = false;
953
954 if (global_state.header_buf_initialized) {
955 curlhelp_freewritebuffer(&global_state.header_buf);
956 }
957 global_state.header_buf_initialized = false;
958
959 if (global_state.put_buf_initialized) {
960 curlhelp_freereadbuffer(&global_state.put_buf);
961 }
962 global_state.put_buf_initialized = false;
963
964 if (global_state.header_list) {
965 curl_slist_free_all(global_state.header_list);
966 }
967
968 if (global_state.host) {
969 curl_slist_free_all(global_state.host);
970 }
971}
972
973mp_state_enum check_http(const check_curl_config config, check_curl_working_state workingState,
974 int redir_depth) {
975
976 // =======================
977 // Initialisation for curl
978 // =======================
979 check_curl_configure_curl_wrapper conf_curl_struct = check_curl_configure_curl(
980 config.curl_config, workingState, config.check_cert, config.on_redirect_dependent,
981 config.followmethod, config.max_depth);
982
983 check_curl_global_state curl_state = conf_curl_struct.curl_state;
940 984
941 // ============== 985 // ==============
942 // do the request 986 // do the request
943 // ============== 987 // ==============
944 CURLcode res = curl_easy_perform(global_state.curl); 988 CURLcode res = curl_easy_perform(curl_state.curl);
945 989
946 if (verbose >= 2 && workingState.http_post_data) { 990 if (verbose >= 2 && workingState.http_post_data) {
947 printf("**** REQUEST CONTENT ****\n%s\n", workingState.http_post_data); 991 printf("**** REQUEST CONTENT ****\n%s\n", workingState.http_post_data);
948 } 992 }
949 993
950 /* free header and server IP resolve lists, we don't need it anymore */
951 curl_slist_free_all(header_list);
952 header_list = NULL;
953
954 if (host) {
955 curl_slist_free_all(host);
956 host = NULL;
957 }
958
959 /* Curl errors, result in critical Nagios state */ 994 /* Curl errors, result in critical Nagios state */
960 if (res != CURLE_OK) { 995 if (res != CURLE_OK) {
961 snprintf(msg, DEFAULT_BUFFER_SIZE, 996 snprintf(msg, DEFAULT_BUFFER_SIZE,
@@ -969,7 +1004,7 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
969 // ========== 1004 // ==========
970 1005
971 mp_state_enum result_ssl = STATE_OK; 1006 mp_state_enum result_ssl = STATE_OK;
972 /* certificate checks */ 1007/* certificate checks */
973#ifdef LIBCURL_FEATURE_SSL 1008#ifdef LIBCURL_FEATURE_SSL
974 if (workingState.use_ssl) { 1009 if (workingState.use_ssl) {
975 if (config.check_cert) { 1010 if (config.check_cert) {
@@ -992,7 +1027,7 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
992 1027
993 cert_ptr_union cert_ptr = {0}; 1028 cert_ptr_union cert_ptr = {0};
994 cert_ptr.to_info = NULL; 1029 cert_ptr.to_info = NULL;
995 res = curl_easy_getinfo(global_state.curl, CURLINFO_CERTINFO, &cert_ptr.to_info); 1030 res = curl_easy_getinfo(curl_state.curl, CURLINFO_CERTINFO, &cert_ptr.to_info);
996 if (!res && cert_ptr.to_info) { 1031 if (!res && cert_ptr.to_info) {
997# ifdef USE_OPENSSL 1032# ifdef USE_OPENSSL
998 /* We have no OpenSSL in libcurl, but we can use OpenSSL for X509 cert 1033 /* We have no OpenSSL in libcurl, but we can use OpenSSL for X509 cert
@@ -1066,54 +1101,55 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
1066 */ 1101 */
1067 double total_time; 1102 double total_time;
1068 handle_curl_option_return_code( 1103 handle_curl_option_return_code(
1069 curl_easy_getinfo(global_state.curl, CURLINFO_TOTAL_TIME, &total_time), 1104 curl_easy_getinfo(curl_state.curl, CURLINFO_TOTAL_TIME, &total_time),
1070 "CURLINFO_TOTAL_TIME"); 1105 "CURLINFO_TOTAL_TIME");
1071 size_t page_len = get_content_length(&global_state.header_buf, &global_state.body_buf); 1106 size_t page_len = get_content_length(&curl_state.header_buf, &curl_state.body_buf);
1072 char perfstring[DEFAULT_BUFFER_SIZE]; 1107 char perfstring[DEFAULT_BUFFER_SIZE];
1073 if (config.show_extended_perfdata) { 1108 if (config.show_extended_perfdata) {
1074 double time_connect; 1109 double time_connect;
1075 handle_curl_option_return_code( 1110 handle_curl_option_return_code(
1076 curl_easy_getinfo(global_state.curl, CURLINFO_CONNECT_TIME, &time_connect), 1111 curl_easy_getinfo(curl_state.curl, CURLINFO_CONNECT_TIME, &time_connect),
1077 "CURLINFO_CONNECT_TIME"); 1112 "CURLINFO_CONNECT_TIME");
1078 1113
1079 double time_appconnect; 1114 double time_appconnect;
1080 handle_curl_option_return_code( 1115 handle_curl_option_return_code(
1081 curl_easy_getinfo(global_state.curl, CURLINFO_APPCONNECT_TIME, &time_appconnect), 1116 curl_easy_getinfo(curl_state.curl, CURLINFO_APPCONNECT_TIME, &time_appconnect),
1082 "CURLINFO_APPCONNECT_TIME"); 1117 "CURLINFO_APPCONNECT_TIME");
1083 1118
1084 double time_headers; 1119 double time_headers;
1085 handle_curl_option_return_code( 1120 handle_curl_option_return_code(
1086 curl_easy_getinfo(global_state.curl, CURLINFO_PRETRANSFER_TIME, &time_headers), 1121 curl_easy_getinfo(curl_state.curl, CURLINFO_PRETRANSFER_TIME, &time_headers),
1087 "CURLINFO_PRETRANSFER_TIME"); 1122 "CURLINFO_PRETRANSFER_TIME");
1088 1123
1089 double time_firstbyte; 1124 double time_firstbyte;
1090 handle_curl_option_return_code( 1125 handle_curl_option_return_code(
1091 curl_easy_getinfo(global_state.curl, CURLINFO_STARTTRANSFER_TIME, &time_firstbyte), 1126 curl_easy_getinfo(curl_state.curl, CURLINFO_STARTTRANSFER_TIME, &time_firstbyte),
1092 "CURLINFO_STARTTRANSFER_TIME"); 1127 "CURLINFO_STARTTRANSFER_TIME");
1093 1128
1094 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s %s %s %s %s %s", 1129 snprintf(
1095 perfd_time(total_time, config.thlds, config.socket_timeout), 1130 perfstring, DEFAULT_BUFFER_SIZE, "%s %s %s %s %s %s %s",
1096 perfd_size(page_len, config.min_page_len), 1131 perfd_time(total_time, config.thlds, config.curl_config.socket_timeout),
1097 perfd_time_connect(time_connect, config.socket_timeout), 1132 perfd_size(page_len, config.min_page_len),
1098 workingState.use_ssl 1133 perfd_time_connect(time_connect, config.curl_config.socket_timeout),
1099 ? perfd_time_ssl(time_appconnect - time_connect, config.socket_timeout) 1134 workingState.use_ssl
1100 : "", 1135 ? perfd_time_ssl(time_appconnect - time_connect, config.curl_config.socket_timeout)
1101 perfd_time_headers(time_headers - time_appconnect, config.socket_timeout), 1136 : "",
1102 perfd_time_firstbyte(time_firstbyte - time_headers, config.socket_timeout), 1137 perfd_time_headers(time_headers - time_appconnect, config.curl_config.socket_timeout),
1103 perfd_time_transfer(total_time - time_firstbyte, config.socket_timeout)); 1138 perfd_time_firstbyte(time_firstbyte - time_headers, config.curl_config.socket_timeout),
1139 perfd_time_transfer(total_time - time_firstbyte, config.curl_config.socket_timeout));
1104 } else { 1140 } else {
1105 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s", 1141 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s",
1106 perfd_time(total_time, config.thlds, config.socket_timeout), 1142 perfd_time(total_time, config.thlds, config.curl_config.socket_timeout),
1107 perfd_size(page_len, config.min_page_len)); 1143 perfd_size(page_len, config.min_page_len));
1108 } 1144 }
1109 1145
1110 /* return a CRITICAL status if we couldn't read any data */ 1146 /* return a CRITICAL status if we couldn't read any data */
1111 if (strlen(global_state.header_buf.buf) == 0 && strlen(global_state.body_buf.buf) == 0) { 1147 if (strlen(curl_state.header_buf.buf) == 0 && strlen(curl_state.body_buf.buf) == 0) {
1112 die(STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n")); 1148 die(STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n"));
1113 } 1149 }
1114 1150
1115 /* get status line of answer, check sanity of HTTP code */ 1151 /* get status line of answer, check sanity of HTTP code */
1116 if (curlhelp_parse_statusline(global_state.header_buf.buf, &global_state.status_line) < 0) { 1152 if (curlhelp_parse_statusline(curl_state.header_buf.buf, &curl_state.status_line) < 0) {
1117 snprintf(msg, DEFAULT_BUFFER_SIZE, 1153 snprintf(msg, DEFAULT_BUFFER_SIZE,
1118 "Unparsable status line in %.3g seconds response time|%s\n", total_time, 1154 "Unparsable status line in %.3g seconds response time|%s\n", total_time,
1119 perfstring); 1155 perfstring);
@@ -1121,12 +1157,12 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
1121 * line */ 1157 * line */
1122 die(STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x unknown - %s", msg); 1158 die(STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x unknown - %s", msg);
1123 } 1159 }
1124 global_state.status_line_initialized = true; 1160 curl_state.status_line_initialized = true;
1125 1161
1126 /* get result code from cURL */ 1162 /* get result code from cURL */
1127 long httpReturnCode; 1163 long httpReturnCode;
1128 handle_curl_option_return_code( 1164 handle_curl_option_return_code(
1129 curl_easy_getinfo(global_state.curl, CURLINFO_RESPONSE_CODE, &httpReturnCode), 1165 curl_easy_getinfo(curl_state.curl, CURLINFO_RESPONSE_CODE, &httpReturnCode),
1130 "CURLINFO_RESPONSE_CODE"); 1166 "CURLINFO_RESPONSE_CODE");
1131 if (verbose >= 2) { 1167 if (verbose >= 2) {
1132 printf("* curl CURLINFO_RESPONSE_CODE is %ld\n", httpReturnCode); 1168 printf("* curl CURLINFO_RESPONSE_CODE is %ld\n", httpReturnCode);
@@ -1134,28 +1170,28 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
1134 1170
1135 /* print status line, header, body if verbose */ 1171 /* print status line, header, body if verbose */
1136 if (verbose >= 2) { 1172 if (verbose >= 2) {
1137 printf("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", global_state.header_buf.buf, 1173 printf("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", curl_state.header_buf.buf,
1138 (workingState.no_body ? " [[ skipped ]]" : global_state.body_buf.buf)); 1174 (workingState.no_body ? " [[ skipped ]]" : curl_state.body_buf.buf));
1139 } 1175 }
1140 1176
1141 /* make sure the status line matches the response we are looking for */ 1177 /* make sure the status line matches the response we are looking for */
1142 if (!expected_statuscode(global_state.status_line.first_line, config.server_expect.string)) { 1178 if (!expected_statuscode(curl_state.status_line.first_line, config.server_expect.string)) {
1143 if (workingState.serverPort == HTTP_PORT) { 1179 if (workingState.serverPort == HTTP_PORT) {
1144 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"), 1180 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"),
1145 global_state.status_line.first_line); 1181 curl_state.status_line.first_line);
1146 } else { 1182 } else {
1147 snprintf(msg, DEFAULT_BUFFER_SIZE, 1183 snprintf(msg, DEFAULT_BUFFER_SIZE,
1148 _("Invalid HTTP response received from host on port %d: %s\n"), 1184 _("Invalid HTTP response received from host on port %d: %s\n"),
1149 workingState.serverPort, global_state.status_line.first_line); 1185 workingState.serverPort, curl_state.status_line.first_line);
1150 } 1186 }
1151 die(STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg, config.show_body ? "\n" : "", 1187 die(STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg, config.show_body ? "\n" : "",
1152 config.show_body ? global_state.body_buf.buf : ""); 1188 config.show_body ? curl_state.body_buf.buf : "");
1153 } 1189 }
1154 1190
1155 mp_state_enum result = STATE_OK; 1191 mp_state_enum result = STATE_OK;
1156 if (config.server_expect.is_present) { 1192 if (config.server_expect.is_present) {
1157 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Status line output matched \"%s\" - "), 1193 snprintf(msg, DEFAULT_BUFFER_SIZE, _("Status line output matched \"%s\" - "),
1158 config.server_expect); 1194 config.server_expect.string);
1159 if (verbose) { 1195 if (verbose) {
1160 printf("%s\n", msg); 1196 printf("%s\n", msg);
1161 } 1197 }
@@ -1164,7 +1200,7 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
1164 /* illegal return codes result in a critical state */ 1200 /* illegal return codes result in a critical state */
1165 if (httpReturnCode >= 600 || httpReturnCode < 100) { 1201 if (httpReturnCode >= 600 || httpReturnCode < 100) {
1166 die(STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"), 1202 die(STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"),
1167 global_state.status_line.http_code, global_state.status_line.msg); 1203 curl_state.status_line.http_code, curl_state.status_line.msg);
1168 /* server errors result in a critical state */ 1204 /* server errors result in a critical state */
1169 } else if (httpReturnCode >= 500) { 1205 } else if (httpReturnCode >= 500) {
1170 result = STATE_CRITICAL; 1206 result = STATE_CRITICAL;
@@ -1173,25 +1209,25 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
1173 result = STATE_WARNING; 1209 result = STATE_WARNING;
1174 /* check redirected page if specified */ 1210 /* check redirected page if specified */
1175 } else if (httpReturnCode >= 300) { 1211 } else if (httpReturnCode >= 300) {
1176 if (config.onredirect == STATE_DEPENDENT) { 1212 if (config.on_redirect_dependent) {
1177 if (config.followmethod == FOLLOW_LIBCURL) { 1213 if (config.followmethod == FOLLOW_LIBCURL) {
1178 httpReturnCode = global_state.status_line.http_code; 1214 httpReturnCode = curl_state.status_line.http_code;
1179 } else { 1215 } else {
1180 /* old check_http style redirection, if we come 1216 /* old check_http style redirection, if we come
1181 * back here, we are in the same status as with 1217 * back here, we are in the same status as with
1182 * the libcurl method 1218 * the libcurl method
1183 */ 1219 */
1184 redir_wrapper redir_result = redir(&global_state.header_buf, config, 1220 redir_wrapper redir_result =
1185 redir_depth, workingState, global_state); 1221 redir(&curl_state.header_buf, config, redir_depth, workingState);
1186 check_http(config, redir_result.working_state, redir_result.redir_depth, 1222 cleanup(curl_state);
1187 header_list, redir_result.curl_state); 1223 check_http(config, redir_result.working_state, redir_result.redir_depth);
1188 } 1224 }
1189 } else { 1225 } else {
1190 /* this is a specific code in the command line to 1226 /* this is a specific code in the command line to
1191 * be returned when a redirection is encountered 1227 * be returned when a redirection is encountered
1192 */ 1228 */
1193 } 1229 }
1194 result = max_state_alt(config.onredirect, result); 1230 result = max_state_alt(config.on_redirect_result_state, result);
1195 /* all other codes are considered ok */ 1231 /* all other codes are considered ok */
1196 } else { 1232 } else {
1197 result = STATE_OK; 1233 result = STATE_OK;
@@ -1201,7 +1237,7 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
1201 /* libcurl redirection internally, handle error states here */ 1237 /* libcurl redirection internally, handle error states here */
1202 if (config.followmethod == FOLLOW_LIBCURL) { 1238 if (config.followmethod == FOLLOW_LIBCURL) {
1203 handle_curl_option_return_code( 1239 handle_curl_option_return_code(
1204 curl_easy_getinfo(global_state.curl, CURLINFO_REDIRECT_COUNT, &redir_depth), 1240 curl_easy_getinfo(curl_state.curl, CURLINFO_REDIRECT_COUNT, &redir_depth),
1205 "CURLINFO_REDIRECT_COUNT"); 1241 "CURLINFO_REDIRECT_COUNT");
1206 1242
1207 if (verbose >= 2) { 1243 if (verbose >= 2) {
@@ -1216,22 +1252,21 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
1216 } 1252 }
1217 1253
1218 /* check status codes, set exit status accordingly */ 1254 /* check status codes, set exit status accordingly */
1219 if (global_state.status_line.http_code != httpReturnCode) { 1255 if (curl_state.status_line.http_code != httpReturnCode) {
1220 die(STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"), 1256 die(STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"),
1221 string_statuscode(global_state.status_line.http_major, 1257 string_statuscode(curl_state.status_line.http_major, curl_state.status_line.http_minor),
1222 global_state.status_line.http_minor), 1258 curl_state.status_line.http_code, curl_state.status_line.msg, httpReturnCode);
1223 global_state.status_line.http_code, global_state.status_line.msg, httpReturnCode);
1224 } 1259 }
1225 1260
1226 if (config.maximum_age >= 0) { 1261 if (config.maximum_age >= 0) {
1227 result = max_state_alt( 1262 result = max_state_alt(
1228 check_document_dates(&global_state.header_buf, &msg, config.maximum_age), result); 1263 check_document_dates(&curl_state.header_buf, &msg, config.maximum_age), result);
1229 } 1264 }
1230 1265
1231 /* Page and Header content checks go here */ 1266 /* Page and Header content checks go here */
1232 1267
1233 if (strlen(config.header_expect)) { 1268 if (strlen(config.header_expect)) {
1234 if (!strstr(global_state.header_buf.buf, config.header_expect)) { 1269 if (!strstr(curl_state.header_buf.buf, config.header_expect)) {
1235 1270
1236 char output_header_search[30] = ""; 1271 char output_header_search[30] = "";
1237 strncpy(&output_header_search[0], config.header_expect, sizeof(output_header_search)); 1272 strncpy(&output_header_search[0], config.header_expect, sizeof(output_header_search));
@@ -1254,7 +1289,7 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
1254 } 1289 }
1255 1290
1256 if (strlen(config.string_expect)) { 1291 if (strlen(config.string_expect)) {
1257 if (!strstr(global_state.body_buf.buf, config.string_expect)) { 1292 if (!strstr(curl_state.body_buf.buf, config.string_expect)) {
1258 1293
1259 char output_string_search[30] = ""; 1294 char output_string_search[30] = "";
1260 strncpy(&output_string_search[0], config.string_expect, sizeof(output_string_search)); 1295 strncpy(&output_string_search[0], config.string_expect, sizeof(output_string_search));
@@ -1278,7 +1313,7 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
1278 1313
1279 if (strlen(config.regexp)) { 1314 if (strlen(config.regexp)) {
1280 regmatch_t pmatch[REGS]; 1315 regmatch_t pmatch[REGS];
1281 int errcode = regexec(&config.compiled_regex, global_state.body_buf.buf, REGS, pmatch, 0); 1316 int errcode = regexec(&config.compiled_regex, curl_state.body_buf.buf, REGS, pmatch, 0);
1282 if ((errcode == 0 && !config.invert_regex) || 1317 if ((errcode == 0 && !config.invert_regex) ||
1283 (errcode == REG_NOMATCH && config.invert_regex)) { 1318 (errcode == REG_NOMATCH && config.invert_regex)) {
1284 /* OK - No-op to avoid changing the logic around it */ 1319 /* OK - No-op to avoid changing the logic around it */
@@ -1344,11 +1379,10 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat
1344 die((int)max_state_alt(result, result_ssl), 1379 die((int)max_state_alt(result, result_ssl),
1345 "HTTP %s: %s %d %s%s%s - %zu bytes in %.3f second response time %s|%s\n%s%s", 1380 "HTTP %s: %s %d %s%s%s - %zu bytes in %.3f second response time %s|%s\n%s%s",
1346 state_text(result), 1381 state_text(result),
1347 string_statuscode(global_state.status_line.http_major, global_state.status_line.http_minor), 1382 string_statuscode(curl_state.status_line.http_major, curl_state.status_line.http_minor),
1348 global_state.status_line.http_code, global_state.status_line.msg, 1383 curl_state.status_line.http_code, curl_state.status_line.msg, strlen(msg) > 0 ? " - " : "",
1349 strlen(msg) > 0 ? " - " : "", msg, page_len, total_time, 1384 msg, page_len, total_time, (config.display_html ? "</A>" : ""), perfstring,
1350 (config.display_html ? "</A>" : ""), perfstring, 1385 (config.show_body ? curl_state.body_buf.buf : ""), (config.show_body ? "\n" : ""));
1351 (config.show_body ? global_state.body_buf.buf : ""), (config.show_body ? "\n" : ""));
1352 1386
1353 return max_state_alt(result, result_ssl); 1387 return max_state_alt(result, result_ssl);
1354} 1388}
@@ -1375,8 +1409,7 @@ char *uri_string(const UriTextRangeA range, char *buf, size_t buflen) {
1375} 1409}
1376 1410
1377redir_wrapper redir(curlhelp_write_curlbuf *header_buf, const check_curl_config config, 1411redir_wrapper redir(curlhelp_write_curlbuf *header_buf, const check_curl_config config,
1378 int redir_depth, check_curl_working_state working_state, 1412 int redir_depth, check_curl_working_state working_state) {
1379 check_curl_global_state global_state) {
1380 curlhelp_statusline status_line; 1413 curlhelp_statusline status_line;
1381 struct phr_header headers[255]; 1414 struct phr_header headers[255];
1382 size_t msglen; 1415 size_t msglen;
@@ -1533,8 +1566,6 @@ redir_wrapper redir(curlhelp_write_curlbuf *header_buf, const check_curl_config
1533 * attached to the URL in Location 1566 * attached to the URL in Location
1534 */ 1567 */
1535 1568
1536 cleanup(global_state);
1537
1538 redir_wrapper result = { 1569 redir_wrapper result = {
1539 .redir_depth = redir_depth, 1570 .redir_depth = redir_depth,
1540 .working_state = working_state, 1571 .working_state = working_state,
@@ -1673,7 +1704,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1673 if (!is_intnonneg(optarg)) { 1704 if (!is_intnonneg(optarg)) {
1674 usage2(_("Timeout interval must be a positive integer"), optarg); 1705 usage2(_("Timeout interval must be a positive integer"), optarg);
1675 } else { 1706 } else {
1676 result.config.socket_timeout = (int)strtol(optarg, NULL, 10); 1707 result.config.curl_config.socket_timeout = (int)strtol(optarg, NULL, 10);
1677 } 1708 }
1678 break; 1709 break;
1679 case 'c': /* critical time threshold */ 1710 case 'c': /* critical time threshold */
@@ -1724,12 +1755,12 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1724 } 1755 }
1725 break; 1756 break;
1726 case 'a': /* authorization info */ 1757 case 'a': /* authorization info */
1727 strncpy(result.config.user_auth, optarg, MAX_INPUT_BUFFER - 1); 1758 strncpy(result.config.curl_config.user_auth, optarg, MAX_INPUT_BUFFER - 1);
1728 result.config.user_auth[MAX_INPUT_BUFFER - 1] = 0; 1759 result.config.curl_config.user_auth[MAX_INPUT_BUFFER - 1] = 0;
1729 break; 1760 break;
1730 case 'b': /* proxy-authorization info */ 1761 case 'b': /* proxy-authorization info */
1731 strncpy(result.config.proxy_auth, optarg, MAX_INPUT_BUFFER - 1); 1762 strncpy(result.config.curl_config.proxy_auth, optarg, MAX_INPUT_BUFFER - 1);
1732 result.config.proxy_auth[MAX_INPUT_BUFFER - 1] = 0; 1763 result.config.curl_config.proxy_auth[MAX_INPUT_BUFFER - 1] = 0;
1733 break; 1764 break;
1734 case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */ 1765 case 'P': /* HTTP POST data in URL encoded format; ignored if settings already */
1735 if (!result.config.initial_config.http_post_data) { 1766 if (!result.config.initial_config.http_post_data) {
@@ -1746,19 +1777,20 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1746 result.config.initial_config.http_method = strdup(optarg); 1777 result.config.initial_config.http_method = strdup(optarg);
1747 break; 1778 break;
1748 case 'A': /* useragent */ 1779 case 'A': /* useragent */
1749 strncpy(result.config.user_agent, optarg, DEFAULT_BUFFER_SIZE); 1780 strncpy(result.config.curl_config.user_agent, optarg, DEFAULT_BUFFER_SIZE);
1750 result.config.user_agent[DEFAULT_BUFFER_SIZE - 1] = '\0'; 1781 result.config.curl_config.user_agent[DEFAULT_BUFFER_SIZE - 1] = '\0';
1751 break; 1782 break;
1752 case 'k': /* Additional headers */ 1783 case 'k': /* Additional headers */
1753 if (result.config.http_opt_headers_count == 0) { 1784 if (result.config.curl_config.http_opt_headers_count == 0) {
1754 result.config.http_opt_headers = 1785 result.config.curl_config.http_opt_headers =
1755 malloc(sizeof(char *) * (++result.config.http_opt_headers_count)); 1786 malloc(sizeof(char *) * (++result.config.curl_config.http_opt_headers_count));
1756 } else { 1787 } else {
1757 result.config.http_opt_headers = 1788 result.config.curl_config.http_opt_headers =
1758 realloc(result.config.http_opt_headers, 1789 realloc(result.config.curl_config.http_opt_headers,
1759 sizeof(char *) * (++result.config.http_opt_headers_count)); 1790 sizeof(char *) * (++result.config.curl_config.http_opt_headers_count));
1760 } 1791 }
1761 result.config.http_opt_headers[result.config.http_opt_headers_count - 1] = optarg; 1792 result.config.curl_config
1793 .http_opt_headers[result.config.curl_config.http_opt_headers_count - 1] = optarg;
1762 break; 1794 break;
1763 case 'L': /* show html link */ 1795 case 'L': /* show html link */
1764 result.config.display_html = true; 1796 result.config.display_html = true;
@@ -1805,7 +1837,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1805 usage4(_("Invalid option - SSL is not available")); 1837 usage4(_("Invalid option - SSL is not available"));
1806#endif 1838#endif
1807 test_file(optarg); 1839 test_file(optarg);
1808 result.config.client_cert = optarg; 1840 result.config.curl_config.client_cert = optarg;
1809 enable_tls = true; 1841 enable_tls = true;
1810 break; 1842 break;
1811 case 'K': /* use client private key */ 1843 case 'K': /* use client private key */
@@ -1813,7 +1845,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1813 usage4(_("Invalid option - SSL is not available")); 1845 usage4(_("Invalid option - SSL is not available"));
1814#endif 1846#endif
1815 test_file(optarg); 1847 test_file(optarg);
1816 result.config.client_privkey = optarg; 1848 result.config.curl_config.client_privkey = optarg;
1817 enable_tls = true; 1849 enable_tls = true;
1818 break; 1850 break;
1819 case CA_CERT_OPTION: /* use CA chain file */ 1851 case CA_CERT_OPTION: /* use CA chain file */
@@ -1821,14 +1853,14 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1821 usage4(_("Invalid option - SSL is not available")); 1853 usage4(_("Invalid option - SSL is not available"));
1822#endif 1854#endif
1823 test_file(optarg); 1855 test_file(optarg);
1824 result.config.ca_cert = optarg; 1856 result.config.curl_config.ca_cert = optarg;
1825 enable_tls = true; 1857 enable_tls = true;
1826 break; 1858 break;
1827 case 'D': /* verify peer certificate & host */ 1859 case 'D': /* verify peer certificate & host */
1828#ifndef LIBCURL_FEATURE_SSL 1860#ifndef LIBCURL_FEATURE_SSL
1829 usage4(_("Invalid option - SSL is not available")); 1861 usage4(_("Invalid option - SSL is not available"));
1830#endif 1862#endif
1831 result.config.verify_peer_and_host = true; 1863 result.config.curl_config.verify_peer_and_host = true;
1832 enable_tls = true; 1864 enable_tls = true;
1833 break; 1865 break;
1834 case 'S': /* use SSL */ 1866 case 'S': /* use SSL */
@@ -1852,36 +1884,44 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1852 break; 1884 break;
1853 case 'f': /* onredirect */ 1885 case 'f': /* onredirect */
1854 if (!strcmp(optarg, "ok")) { 1886 if (!strcmp(optarg, "ok")) {
1855 result.config.onredirect = STATE_OK; 1887 result.config.on_redirect_result_state = STATE_OK;
1888 result.config.on_redirect_dependent = false;
1856 } else if (!strcmp(optarg, "warning")) { 1889 } else if (!strcmp(optarg, "warning")) {
1857 result.config.onredirect = STATE_WARNING; 1890 result.config.on_redirect_result_state = STATE_WARNING;
1891 result.config.on_redirect_dependent = false;
1858 } else if (!strcmp(optarg, "critical")) { 1892 } else if (!strcmp(optarg, "critical")) {
1859 result.config.onredirect = STATE_CRITICAL; 1893 result.config.on_redirect_result_state = STATE_CRITICAL;
1894 result.config.on_redirect_dependent = false;
1860 } else if (!strcmp(optarg, "unknown")) { 1895 } else if (!strcmp(optarg, "unknown")) {
1861 result.config.onredirect = STATE_UNKNOWN; 1896 result.config.on_redirect_result_state = STATE_UNKNOWN;
1897 result.config.on_redirect_dependent = false;
1862 } else if (!strcmp(optarg, "follow")) { 1898 } else if (!strcmp(optarg, "follow")) {
1863 result.config.onredirect = STATE_DEPENDENT; 1899 result.config.on_redirect_dependent = true;
1864 } else if (!strcmp(optarg, "stickyport")) { 1900 } else if (!strcmp(optarg, "stickyport")) {
1865 result.config.onredirect = STATE_DEPENDENT, 1901 result.config.on_redirect_dependent = true;
1866 result.config.followmethod = FOLLOW_HTTP_CURL, 1902 result.config.followmethod = FOLLOW_HTTP_CURL,
1867 result.config.followsticky = STICKY_HOST | STICKY_PORT; 1903 result.config.followsticky = STICKY_HOST | STICKY_PORT;
1868 } else if (!strcmp(optarg, "sticky")) { 1904 } else if (!strcmp(optarg, "sticky")) {
1869 result.config.onredirect = STATE_DEPENDENT, 1905 result.config.on_redirect_dependent = true;
1870 result.config.followmethod = FOLLOW_HTTP_CURL, 1906 result.config.followmethod = FOLLOW_HTTP_CURL,
1871 result.config.followsticky = STICKY_HOST; 1907 result.config.followsticky = STICKY_HOST;
1872 } else if (!strcmp(optarg, "follow")) { 1908 } else if (!strcmp(optarg, "follow")) {
1873 result.config.onredirect = STATE_DEPENDENT, 1909 result.config.on_redirect_dependent = true;
1874 result.config.followmethod = FOLLOW_HTTP_CURL, 1910 result.config.followmethod = FOLLOW_HTTP_CURL,
1875 result.config.followsticky = STICKY_NONE; 1911 result.config.followsticky = STICKY_NONE;
1876 } else if (!strcmp(optarg, "curl")) { 1912 } else if (!strcmp(optarg, "curl")) {
1877 result.config.onredirect = STATE_DEPENDENT, 1913 result.config.on_redirect_dependent = true;
1878 result.config.followmethod = FOLLOW_LIBCURL; 1914 result.config.followmethod = FOLLOW_LIBCURL;
1879 } else { 1915 } else {
1880 usage2(_("Invalid onredirect option"), optarg); 1916 usage2(_("Invalid onredirect option"), optarg);
1881 } 1917 }
1882 if (verbose >= 2) { 1918 if (verbose >= 2) {
1883 printf(_("* Following redirects set to %s\n"), 1919 if (result.config.on_redirect_dependent) {
1884 state_text(result.config.onredirect)); 1920 printf(_("* Following redirects\n"));
1921 } else {
1922 printf(_("* Following redirects set to state %s\n"),
1923 state_text(result.config.on_redirect_result_state));
1924 }
1885 } 1925 }
1886 break; 1926 break;
1887 case 'd': /* string or substring */ 1927 case 'd': /* string or substring */
@@ -1898,7 +1938,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1898 result.config.server_expect.is_present = true; 1938 result.config.server_expect.is_present = true;
1899 break; 1939 break;
1900 case 'T': /* Content-type */ 1940 case 'T': /* Content-type */
1901 result.config.http_content_type = strdup(optarg); 1941 result.config.curl_config.http_content_type = strdup(optarg);
1902 break; 1942 break;
1903 case 'l': /* linespan */ 1943 case 'l': /* linespan */
1904 cflags &= ~REG_NEWLINE; 1944 cflags &= ~REG_NEWLINE;
@@ -1933,11 +1973,11 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1933 } 1973 }
1934 break; 1974 break;
1935 case '4': 1975 case '4':
1936 result.config.sin_family = AF_INET; 1976 result.config.curl_config.sin_family = AF_INET;
1937 break; 1977 break;
1938 case '6': 1978 case '6':
1939#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6) 1979#if defined(USE_IPV6) && defined(LIBCURL_FEATURE_IPV6)
1940 result.config.sin_family = AF_INET6; 1980 result.config.curl_config.sin_family = AF_INET6;
1941#else 1981#else
1942 usage4(_("IPv6 support not available")); 1982 usage4(_("IPv6 support not available"));
1943#endif 1983#endif
@@ -1997,30 +2037,33 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
1997 result.config.show_body = true; 2037 result.config.show_body = true;
1998 break; 2038 break;
1999 case HTTP_VERSION_OPTION: 2039 case HTTP_VERSION_OPTION:
2000 result.config.curl_http_version = CURL_HTTP_VERSION_NONE; 2040 result.config.curl_config.curl_http_version = CURL_HTTP_VERSION_NONE;
2001 if (strcmp(optarg, "1.0") == 0) { 2041 if (strcmp(optarg, "1.0") == 0) {
2002 result.config.curl_http_version = CURL_HTTP_VERSION_1_0; 2042 result.config.curl_config.curl_http_version = CURL_HTTP_VERSION_1_0;
2003 } else if (strcmp(optarg, "1.1") == 0) { 2043 } else if (strcmp(optarg, "1.1") == 0) {
2004 result.config.curl_http_version = CURL_HTTP_VERSION_1_1; 2044 result.config.curl_config.curl_http_version = CURL_HTTP_VERSION_1_1;
2005 } else if ((strcmp(optarg, "2.0") == 0) || (strcmp(optarg, "2") == 0)) { 2045 } else if ((strcmp(optarg, "2.0") == 0) || (strcmp(optarg, "2") == 0)) {
2006#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) 2046#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0)
2007 result.config.curl_http_version = CURL_HTTP_VERSION_2_0; 2047 result.config.curl_config.curl_http_version = CURL_HTTP_VERSION_2_0;
2008#else 2048#else
2009 result.config.curl_http_version = CURL_HTTP_VERSION_NONE; 2049 result.config.curl_http_version = CURL_HTTP_VERSION_NONE;
2010#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) */ 2050#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 33, 0) */
2051 } else if ((strcmp(optarg, "3") == 0)) {
2052 // TODO find out which libcurl version starts supporting HTTP 3
2053 result.config.curl_config.curl_http_version = CURL_HTTP_VERSION_3;
2011 } else { 2054 } else {
2012 fprintf(stderr, "unknown http-version parameter: %s\n", optarg); 2055 fprintf(stderr, "unknown http-version parameter: %s\n", optarg);
2013 exit(STATE_WARNING); 2056 exit(STATE_WARNING);
2014 } 2057 }
2015 break; 2058 break;
2016 case AUTOMATIC_DECOMPRESSION: 2059 case AUTOMATIC_DECOMPRESSION:
2017 result.config.automatic_decompression = true; 2060 result.config.curl_config.automatic_decompression = true;
2018 break; 2061 break;
2019 case COOKIE_JAR: 2062 case COOKIE_JAR:
2020 result.config.cookie_jar_file = optarg; 2063 result.config.curl_config.cookie_jar_file = optarg;
2021 break; 2064 break;
2022 case HAPROXY_PROTOCOL: 2065 case HAPROXY_PROTOCOL:
2023 result.config.haproxy_protocol = true; 2066 result.config.curl_config.haproxy_protocol = true;
2024 break; 2067 break;
2025 case '?': 2068 case '?':
2026 /* print short usage statement if args not parsable */ 2069 /* print short usage statement if args not parsable */
@@ -2035,7 +2078,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
2035 /* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default. 2078 /* ssl_version initialized to CURL_SSLVERSION_DEFAULT as a default.
2036 * Only set if it's non-zero. This helps when we include multiple 2079 * Only set if it's non-zero. This helps when we include multiple
2037 * parameters, like -S and -C combinations */ 2080 * parameters, like -S and -C combinations */
2038 result.config.ssl_version = CURL_SSLVERSION_DEFAULT; 2081 result.config.curl_config.ssl_version = CURL_SSLVERSION_DEFAULT;
2039 if (tls_option_optarg != NULL) { 2082 if (tls_option_optarg != NULL) {
2040 char *plus_ptr = strchr(optarg, '+'); 2083 char *plus_ptr = strchr(optarg, '+');
2041 if (plus_ptr) { 2084 if (plus_ptr) {
@@ -2044,30 +2087,30 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
2044 } 2087 }
2045 2088
2046 if (optarg[0] == '2') { 2089 if (optarg[0] == '2') {
2047 result.config.ssl_version = CURL_SSLVERSION_SSLv2; 2090 result.config.curl_config.ssl_version = CURL_SSLVERSION_SSLv2;
2048 } else if (optarg[0] == '3') { 2091 } else if (optarg[0] == '3') {
2049 result.config.ssl_version = CURL_SSLVERSION_SSLv3; 2092 result.config.curl_config.ssl_version = CURL_SSLVERSION_SSLv3;
2050 } else if (!strcmp(optarg, "1") || !strcmp(optarg, "1.0")) { 2093 } else if (!strcmp(optarg, "1") || !strcmp(optarg, "1.0")) {
2051#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 2094#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
2052 result.config.ssl_version = CURL_SSLVERSION_TLSv1_0; 2095 result.config.curl_config.ssl_version = CURL_SSLVERSION_TLSv1_0;
2053#else 2096#else
2054 result.config.ssl_version = CURL_SSLVERSION_DEFAULT; 2097 result.config.ssl_version = CURL_SSLVERSION_DEFAULT;
2055#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 2098#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
2056 } else if (!strcmp(optarg, "1.1")) { 2099 } else if (!strcmp(optarg, "1.1")) {
2057#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 2100#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
2058 result.config.ssl_version = CURL_SSLVERSION_TLSv1_1; 2101 result.config.curl_config.ssl_version = CURL_SSLVERSION_TLSv1_1;
2059#else 2102#else
2060 result.config.ssl_version = CURL_SSLVERSION_DEFAULT; 2103 result.config.ssl_version = CURL_SSLVERSION_DEFAULT;
2061#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 2104#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
2062 } else if (!strcmp(optarg, "1.2")) { 2105 } else if (!strcmp(optarg, "1.2")) {
2063#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) 2106#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0)
2064 result.config.ssl_version = CURL_SSLVERSION_TLSv1_2; 2107 result.config.curl_config.ssl_version = CURL_SSLVERSION_TLSv1_2;
2065#else 2108#else
2066 result.config.ssl_version = CURL_SSLVERSION_DEFAULT; 2109 result.config.ssl_version = CURL_SSLVERSION_DEFAULT;
2067#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */ 2110#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 34, 0) */
2068 } else if (!strcmp(optarg, "1.3")) { 2111 } else if (!strcmp(optarg, "1.3")) {
2069#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) 2112#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0)
2070 result.config.ssl_version = CURL_SSLVERSION_TLSv1_3; 2113 result.config.curl_config.ssl_version = CURL_SSLVERSION_TLSv1_3;
2071#else 2114#else
2072 result.config.ssl_version = CURL_SSLVERSION_DEFAULT; 2115 result.config.ssl_version = CURL_SSLVERSION_DEFAULT;
2073#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */ 2116#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 52, 0) */
@@ -2078,35 +2121,35 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
2078 } 2121 }
2079#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) 2122#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0)
2080 if (got_plus) { 2123 if (got_plus) {
2081 switch (result.config.ssl_version) { 2124 switch (result.config.curl_config.ssl_version) {
2082 case CURL_SSLVERSION_TLSv1_3: 2125 case CURL_SSLVERSION_TLSv1_3:
2083 result.config.ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3; 2126 result.config.curl_config.ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3;
2084 break; 2127 break;
2085 case CURL_SSLVERSION_TLSv1_2: 2128 case CURL_SSLVERSION_TLSv1_2:
2086 case CURL_SSLVERSION_TLSv1_1: 2129 case CURL_SSLVERSION_TLSv1_1:
2087 case CURL_SSLVERSION_TLSv1_0: 2130 case CURL_SSLVERSION_TLSv1_0:
2088 result.config.ssl_version |= CURL_SSLVERSION_MAX_DEFAULT; 2131 result.config.curl_config.ssl_version |= CURL_SSLVERSION_MAX_DEFAULT;
2089 break; 2132 break;
2090 } 2133 }
2091 } else { 2134 } else {
2092 switch (result.config.ssl_version) { 2135 switch (result.config.curl_config.ssl_version) {
2093 case CURL_SSLVERSION_TLSv1_3: 2136 case CURL_SSLVERSION_TLSv1_3:
2094 result.config.ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3; 2137 result.config.curl_config.ssl_version |= CURL_SSLVERSION_MAX_TLSv1_3;
2095 break; 2138 break;
2096 case CURL_SSLVERSION_TLSv1_2: 2139 case CURL_SSLVERSION_TLSv1_2:
2097 result.config.ssl_version |= CURL_SSLVERSION_MAX_TLSv1_2; 2140 result.config.curl_config.ssl_version |= CURL_SSLVERSION_MAX_TLSv1_2;
2098 break; 2141 break;
2099 case CURL_SSLVERSION_TLSv1_1: 2142 case CURL_SSLVERSION_TLSv1_1:
2100 result.config.ssl_version |= CURL_SSLVERSION_MAX_TLSv1_1; 2143 result.config.curl_config.ssl_version |= CURL_SSLVERSION_MAX_TLSv1_1;
2101 break; 2144 break;
2102 case CURL_SSLVERSION_TLSv1_0: 2145 case CURL_SSLVERSION_TLSv1_0:
2103 result.config.ssl_version |= CURL_SSLVERSION_MAX_TLSv1_0; 2146 result.config.curl_config.ssl_version |= CURL_SSLVERSION_MAX_TLSv1_0;
2104 break; 2147 break;
2105 } 2148 }
2106 } 2149 }
2107#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) */ 2150#endif /* LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 54, 0) */
2108 if (verbose >= 2) { 2151 if (verbose >= 2) {
2109 printf(_("* Set SSL/TLS version to %d\n"), result.config.ssl_version); 2152 printf(_("* Set SSL/TLS version to %d\n"), result.config.curl_config.ssl_version);
2110 } 2153 }
2111 if (!specify_port) { 2154 if (!specify_port) {
2112 result.config.initial_config.serverPort = HTTPS_PORT; 2155 result.config.initial_config.serverPort = HTTPS_PORT;
@@ -2135,18 +2178,18 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
2135 set_thresholds(&result.config.thlds, warning_thresholds, critical_thresholds); 2178 set_thresholds(&result.config.thlds, warning_thresholds, critical_thresholds);
2136 2179
2137 if (critical_thresholds && 2180 if (critical_thresholds &&
2138 result.config.thlds->critical->end > (double)result.config.socket_timeout) { 2181 result.config.thlds->critical->end > (double)result.config.curl_config.socket_timeout) {
2139 result.config.socket_timeout = (int)result.config.thlds->critical->end + 1; 2182 result.config.curl_config.socket_timeout = (int)result.config.thlds->critical->end + 1;
2140 } 2183 }
2141 if (verbose >= 2) { 2184 if (verbose >= 2) {
2142 printf("* Socket timeout set to %ld seconds\n", result.config.socket_timeout); 2185 printf("* Socket timeout set to %ld seconds\n", result.config.curl_config.socket_timeout);
2143 } 2186 }
2144 2187
2145 if (result.config.initial_config.http_method == NULL) { 2188 if (result.config.initial_config.http_method == NULL) {
2146 result.config.initial_config.http_method = strdup("GET"); 2189 result.config.initial_config.http_method = strdup("GET");
2147 } 2190 }
2148 2191
2149 if (result.config.client_cert && !result.config.client_privkey) { 2192 if (result.config.curl_config.client_cert && !result.config.curl_config.client_privkey) {
2150 usage4(_("If you use a client certificate you must also specify a private key file")); 2193 usage4(_("If you use a client certificate you must also specify a private key file"));
2151 } 2194 }
2152 2195
diff --git a/plugins/check_curl.d/config.h b/plugins/check_curl.d/config.h
index 7566b19c..be25d1bb 100644
--- a/plugins/check_curl.d/config.h
+++ b/plugins/check_curl.d/config.h
@@ -65,27 +65,32 @@ check_curl_working_state check_curl_working_state_init() {
65} 65}
66 66
67typedef struct { 67typedef struct {
68 check_curl_working_state initial_config;
69 sa_family_t sin_family;
70
71 bool automatic_decompression; 68 bool automatic_decompression;
72 bool haproxy_protocol; 69 bool haproxy_protocol;
70 long socket_timeout;
71 sa_family_t sin_family;
72 int curl_http_version;
73 char **http_opt_headers;
74 size_t http_opt_headers_count;
75 int ssl_version;
73 char *client_cert; 76 char *client_cert;
74 char *client_privkey; 77 char *client_privkey;
75 char *ca_cert; 78 char *ca_cert;
76 int ssl_version; 79 bool verify_peer_and_host;
77 char user_agent[DEFAULT_BUFFER_SIZE]; 80 char user_agent[DEFAULT_BUFFER_SIZE];
78 char **http_opt_headers;
79 size_t http_opt_headers_count;
80 int max_depth;
81 char *http_content_type;
82 long socket_timeout;
83 char user_auth[MAX_INPUT_BUFFER];
84 char proxy_auth[MAX_INPUT_BUFFER]; 81 char proxy_auth[MAX_INPUT_BUFFER];
82 char user_auth[MAX_INPUT_BUFFER];
83 char *http_content_type;
84 char *cookie_jar_file;
85} check_curl_static_curl_config;
86
87typedef struct {
88 check_curl_working_state initial_config;
89
90 check_curl_static_curl_config curl_config;
91 int max_depth;
85 int followmethod; 92 int followmethod;
86 int followsticky; 93 int followsticky;
87 int curl_http_version;
88 char *cookie_jar_file;
89 94
90 int maximum_age; 95 int maximum_age;
91 96
@@ -97,7 +102,6 @@ typedef struct {
97 102
98 mp_state_enum state_regex; 103 mp_state_enum state_regex;
99 bool invert_regex; 104 bool invert_regex;
100 bool verify_peer_and_host;
101 bool check_cert; 105 bool check_cert;
102 bool continue_after_check_cert; 106 bool continue_after_check_cert;
103 int days_till_exp_warn; 107 int days_till_exp_warn;
@@ -111,7 +115,8 @@ typedef struct {
111 } server_expect; 115 } server_expect;
112 char string_expect[MAX_INPUT_BUFFER]; 116 char string_expect[MAX_INPUT_BUFFER];
113 char header_expect[MAX_INPUT_BUFFER]; 117 char header_expect[MAX_INPUT_BUFFER];
114 mp_state_enum onredirect; 118 mp_state_enum on_redirect_result_state;
119 bool on_redirect_dependent;
115 120
116 bool show_extended_perfdata; 121 bool show_extended_perfdata;
117 bool show_body; 122 bool show_body;
@@ -122,33 +127,35 @@ check_curl_config check_curl_config_init() {
122 check_curl_config tmp = { 127 check_curl_config tmp = {
123 .initial_config = check_curl_working_state_init(), 128 .initial_config = check_curl_working_state_init(),
124 129
125 .sin_family = AF_UNSPEC, 130 .curl_config =
126 131 {
127 .automatic_decompression = false, 132 .automatic_decompression = false,
128 .haproxy_protocol = false, 133 .socket_timeout = DEFAULT_SOCKET_TIMEOUT,
129 .client_cert = NULL, 134 .haproxy_protocol = false,
130 .client_privkey = NULL, 135 .sin_family = AF_UNSPEC,
131 .ca_cert = NULL, 136 .curl_http_version = CURL_HTTP_VERSION_NONE,
132 .ssl_version = CURL_SSLVERSION_DEFAULT, 137 .http_opt_headers = NULL,
133 .user_agent = {'\0'}, 138 .http_opt_headers_count = 0,
134 .http_opt_headers = NULL, 139 .ssl_version = CURL_SSLVERSION_DEFAULT,
135 .http_opt_headers_count = 0, 140 .client_cert = NULL,
141 .client_privkey = NULL,
142 .ca_cert = NULL,
143 .verify_peer_and_host = false,
144 .user_agent = {'\0'},
145 .proxy_auth = "",
146 .user_auth = "",
147 .http_content_type = NULL,
148 .cookie_jar_file = NULL,
149 },
136 .max_depth = DEFAULT_MAX_REDIRS, 150 .max_depth = DEFAULT_MAX_REDIRS,
137 .http_content_type = NULL,
138 .socket_timeout = DEFAULT_SOCKET_TIMEOUT,
139 .user_auth = "",
140 .proxy_auth = "",
141 .followmethod = FOLLOW_HTTP_CURL, 151 .followmethod = FOLLOW_HTTP_CURL,
142 .followsticky = STICKY_NONE, 152 .followsticky = STICKY_NONE,
143 .curl_http_version = CURL_HTTP_VERSION_NONE,
144 .cookie_jar_file = NULL,
145 153
146 .maximum_age = -1, 154 .maximum_age = -1,
147 .regexp = {}, 155 .regexp = {},
148 .compiled_regex = {}, 156 .compiled_regex = {},
149 .state_regex = STATE_CRITICAL, 157 .state_regex = STATE_CRITICAL,
150 .invert_regex = false, 158 .invert_regex = false,
151 .verify_peer_and_host = false,
152 .check_cert = false, 159 .check_cert = false,
153 .continue_after_check_cert = false, 160 .continue_after_check_cert = false,
154 .days_till_exp_warn = 0, 161 .days_till_exp_warn = 0,
@@ -163,11 +170,16 @@ check_curl_config check_curl_config_init() {
163 }, 170 },
164 .string_expect = "", 171 .string_expect = "",
165 .header_expect = "", 172 .header_expect = "",
166 .onredirect = STATE_OK, 173 .on_redirect_result_state = STATE_OK,
174 .on_redirect_dependent = true,
167 175
168 .show_extended_perfdata = false, 176 .show_extended_perfdata = false,
169 .show_body = false, 177 .show_body = false,
170 .display_html = false, 178 .display_html = false,
171 }; 179 };
180
181 snprintf(tmp.curl_config.user_agent, DEFAULT_BUFFER_SIZE, "%s/v%s (monitoring-plugins %s, %s)",
182 "check_curl", NP_VERSION, VERSION, curl_version());
183
172 return tmp; 184 return tmp;
173} 185}