diff options
author | Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> | 2025-09-12 16:37:24 +0200 |
---|---|---|
committer | Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> | 2025-09-12 16:37:24 +0200 |
commit | 44b2a25a6b9fb0791ec7150100a4d51e5f129611 (patch) | |
tree | 4fb13f9effac32bf156cc6eaefe22f6deea6d7ea | |
parent | aaff3aa9da27ff7666d2a776d524c784b76eb3d7 (diff) | |
download | monitoring-plugins-44b2a25a6b9fb0791ec7150100a4d51e5f129611.tar.gz |
check_curl: implement new output mechanism
-rw-r--r-- | plugins/check_curl.c | 562 | ||||
-rw-r--r-- | plugins/check_curl.d/check_curl_helpers.c | 251 | ||||
-rw-r--r-- | plugins/check_curl.d/check_curl_helpers.h | 21 | ||||
-rw-r--r-- | plugins/check_curl.d/config.h | 7 |
4 files changed, 443 insertions, 398 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c index b0dde1eb..722666dd 100644 --- a/plugins/check_curl.c +++ b/plugins/check_curl.c | |||
@@ -42,7 +42,10 @@ const char *email = "devel@monitoring-plugins.org"; | |||
42 | #include "thresholds.h" | 42 | #include "thresholds.h" |
43 | #include <stdbool.h> | 43 | #include <stdbool.h> |
44 | #include <ctype.h> | 44 | #include <ctype.h> |
45 | #include "output.h" | ||
46 | #include "perfdata.h" | ||
45 | 47 | ||
48 | #include <assert.h> | ||
46 | #include "common.h" | 49 | #include "common.h" |
47 | #include "utils.h" | 50 | #include "utils.h" |
48 | #include "./check_curl.d/check_curl_helpers.h" | 51 | #include "./check_curl.d/check_curl_helpers.h" |
@@ -78,7 +81,6 @@ enum { | |||
78 | // Globals | 81 | // Globals |
79 | int verbose = 0; | 82 | int verbose = 0; |
80 | 83 | ||
81 | extern char msg[DEFAULT_BUFFER_SIZE]; | ||
82 | extern char errbuf[MAX_INPUT_BUFFER]; | 84 | extern char errbuf[MAX_INPUT_BUFFER]; |
83 | extern bool is_openssl_callback; | 85 | extern bool is_openssl_callback; |
84 | extern bool add_sslctx_verify_fun; | 86 | extern bool add_sslctx_verify_fun; |
@@ -93,8 +95,8 @@ typedef struct { | |||
93 | } check_curl_config_wrapper; | 95 | } check_curl_config_wrapper; |
94 | static check_curl_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); | 96 | static check_curl_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); |
95 | 97 | ||
96 | static mp_state_enum check_http(check_curl_config /*config*/, check_curl_working_state workingState, | 98 | static mp_subcheck check_http(check_curl_config /*config*/, check_curl_working_state workingState, |
97 | int redir_depth); | 99 | int redir_depth); |
98 | 100 | ||
99 | typedef struct { | 101 | typedef struct { |
100 | int redir_depth; | 102 | int redir_depth; |
@@ -149,7 +151,12 @@ int main(int argc, char **argv) { | |||
149 | 151 | ||
150 | check_curl_working_state working_state = config.initial_config; | 152 | check_curl_working_state working_state = config.initial_config; |
151 | 153 | ||
152 | exit((int)check_http(config, working_state, 0)); | 154 | mp_check overall = mp_check_init(); |
155 | mp_subcheck sc_test = check_http(config, working_state, 0); | ||
156 | |||
157 | mp_add_subcheck_to_check(&overall, sc_test); | ||
158 | |||
159 | mp_exit(overall); | ||
153 | } | 160 | } |
154 | 161 | ||
155 | #ifdef HAVE_SSL | 162 | #ifdef HAVE_SSL |
@@ -200,8 +207,8 @@ CURLcode sslctxfun(CURL *curl, SSL_CTX *sslctx, void *parm) { | |||
200 | # endif /* USE_OPENSSL */ | 207 | # endif /* USE_OPENSSL */ |
201 | #endif /* HAVE_SSL */ | 208 | #endif /* HAVE_SSL */ |
202 | 209 | ||
203 | mp_state_enum check_http(const check_curl_config config, check_curl_working_state workingState, | 210 | mp_subcheck check_http(const check_curl_config config, check_curl_working_state workingState, |
204 | int redir_depth) { | 211 | int redir_depth) { |
205 | 212 | ||
206 | // ======================= | 213 | // ======================= |
207 | // Initialisation for curl | 214 | // Initialisation for curl |
@@ -213,6 +220,13 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat | |||
213 | check_curl_global_state curl_state = conf_curl_struct.curl_state; | 220 | check_curl_global_state curl_state = conf_curl_struct.curl_state; |
214 | workingState = conf_curl_struct.working_state; | 221 | workingState = conf_curl_struct.working_state; |
215 | 222 | ||
223 | mp_subcheck sc_result = mp_subcheck_init(); | ||
224 | |||
225 | char *url = fmt_url(workingState); | ||
226 | xasprintf(&sc_result.output, "Testing %s", url); | ||
227 | // TODO add some output here URL or something | ||
228 | free(url); | ||
229 | |||
216 | // ============== | 230 | // ============== |
217 | // do the request | 231 | // do the request |
218 | // ============== | 232 | // ============== |
@@ -222,172 +236,149 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat | |||
222 | printf("**** REQUEST CONTENT ****\n%s\n", workingState.http_post_data); | 236 | printf("**** REQUEST CONTENT ****\n%s\n", workingState.http_post_data); |
223 | } | 237 | } |
224 | 238 | ||
239 | mp_subcheck sc_curl = mp_subcheck_init(); | ||
240 | |||
225 | /* Curl errors, result in critical Nagios state */ | 241 | /* Curl errors, result in critical Nagios state */ |
226 | if (res != CURLE_OK) { | 242 | if (res != CURLE_OK) { |
227 | snprintf(msg, DEFAULT_BUFFER_SIZE, | 243 | xasprintf(&sc_curl.output, |
228 | _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"), | 244 | _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"), |
229 | workingState.serverPort, res, errbuf[0] ? errbuf : curl_easy_strerror(res)); | 245 | workingState.serverPort, res, errbuf[0] ? errbuf : curl_easy_strerror(res)); |
230 | die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); | 246 | sc_curl = mp_set_subcheck_state(sc_curl, STATE_CRITICAL); |
247 | mp_add_subcheck_to_subcheck(&sc_result, sc_curl); | ||
248 | return sc_result; | ||
231 | } | 249 | } |
232 | 250 | ||
251 | xasprintf(&sc_curl.output, "cURL performed query"); | ||
252 | sc_curl = mp_set_subcheck_state(sc_curl, STATE_OK); | ||
253 | mp_add_subcheck_to_subcheck(&sc_result, sc_curl); | ||
254 | |||
233 | // ========== | 255 | // ========== |
234 | // Evaluation | 256 | // Evaluation |
235 | // ========== | 257 | // ========== |
236 | 258 | ||
237 | mp_state_enum result_ssl = STATE_OK; | ||
238 | /* certificate checks */ | ||
239 | #ifdef LIBCURL_FEATURE_SSL | 259 | #ifdef LIBCURL_FEATURE_SSL |
240 | if (workingState.use_ssl) { | 260 | if (workingState.use_ssl && config.check_cert) { |
241 | if (config.check_cert) { | 261 | mp_subcheck sc_certificate = check_curl_certificate_checks( |
242 | if (is_openssl_callback) { | 262 | curl_state.curl, cert, config.days_till_exp_warn, config.days_till_exp_crit); |
243 | # ifdef USE_OPENSSL | ||
244 | /* check certificate with OpenSSL functions, curl has been built against OpenSSL | ||
245 | * and we actually have OpenSSL in the monitoring tools | ||
246 | */ | ||
247 | result_ssl = np_net_ssl_check_certificate(cert, config.days_till_exp_warn, | ||
248 | config.days_till_exp_crit); | ||
249 | if (!config.continue_after_check_cert) { | ||
250 | return result_ssl; | ||
251 | } | ||
252 | # else /* USE_OPENSSL */ | ||
253 | die(STATE_CRITICAL, "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL " | ||
254 | "callback used and not linked against OpenSSL\n"); | ||
255 | # endif /* USE_OPENSSL */ | ||
256 | } else { | ||
257 | struct curl_slist *slist; | ||
258 | 263 | ||
259 | cert_ptr_union cert_ptr = {0}; | 264 | mp_add_subcheck_to_subcheck(&sc_result, sc_certificate); |
260 | cert_ptr.to_info = NULL; | 265 | if (!config.continue_after_check_cert) { |
261 | res = curl_easy_getinfo(curl_state.curl, CURLINFO_CERTINFO, &cert_ptr.to_info); | 266 | // TODO finish here then |
262 | if (!res && cert_ptr.to_info) { | ||
263 | # ifdef USE_OPENSSL | ||
264 | /* We have no OpenSSL in libcurl, but we can use OpenSSL for X509 cert | ||
265 | * parsing We only check the first certificate and assume it's the one of | ||
266 | * the server | ||
267 | */ | ||
268 | char *raw_cert = NULL; | ||
269 | bool got_first_cert = false; | ||
270 | for (int i = 0; i < cert_ptr.to_certinfo->num_of_certs; i++) { | ||
271 | if (got_first_cert) { | ||
272 | break; | ||
273 | } | ||
274 | |||
275 | for (slist = cert_ptr.to_certinfo->certinfo[i]; slist; | ||
276 | slist = slist->next) { | ||
277 | if (verbose >= 2) { | ||
278 | printf("%d ** %s\n", i, slist->data); | ||
279 | } | ||
280 | if (strncmp(slist->data, "Cert:", 5) == 0) { | ||
281 | raw_cert = &slist->data[5]; | ||
282 | got_first_cert = true; | ||
283 | break; | ||
284 | } | ||
285 | } | ||
286 | } | ||
287 | |||
288 | if (!raw_cert) { | ||
289 | snprintf(msg, DEFAULT_BUFFER_SIZE, | ||
290 | _("Cannot retrieve certificates from CERTINFO information - " | ||
291 | "certificate data was empty")); | ||
292 | die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); | ||
293 | } | ||
294 | BIO *cert_BIO = BIO_new(BIO_s_mem()); | ||
295 | BIO_write(cert_BIO, raw_cert, (int)strlen(raw_cert)); | ||
296 | cert = PEM_read_bio_X509(cert_BIO, NULL, NULL, NULL); | ||
297 | if (!cert) { | ||
298 | snprintf( | ||
299 | msg, DEFAULT_BUFFER_SIZE, | ||
300 | _("Cannot read certificate from CERTINFO information - BIO error")); | ||
301 | die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); | ||
302 | } | ||
303 | BIO_free(cert_BIO); | ||
304 | result_ssl = np_net_ssl_check_certificate(cert, config.days_till_exp_warn, | ||
305 | config.days_till_exp_crit); | ||
306 | if (!config.continue_after_check_cert) { | ||
307 | return result_ssl; | ||
308 | } | ||
309 | # else /* USE_OPENSSL */ | ||
310 | /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our | ||
311 | * disposal, so we use the libcurl CURLINFO data | ||
312 | */ | ||
313 | result_ssl = net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, | ||
314 | days_till_exp_crit); | ||
315 | if (!continue_after_check_cert) { | ||
316 | return result_ssl; | ||
317 | } | ||
318 | # endif /* USE_OPENSSL */ | ||
319 | } else { | ||
320 | snprintf(msg, DEFAULT_BUFFER_SIZE, | ||
321 | _("Cannot retrieve certificates - cURL returned %d - %s"), res, | ||
322 | curl_easy_strerror(res)); | ||
323 | die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); | ||
324 | } | ||
325 | } | ||
326 | } | 267 | } |
327 | } | 268 | } |
328 | #endif /* LIBCURL_FEATURE_SSL */ | 269 | #endif |
329 | 270 | ||
330 | /* we got the data and we executed the request in a given time, so we can append | 271 | /* we got the data and we executed the request in a given time, so we can append |
331 | * performance data to the answer always | 272 | * performance data to the answer always |
332 | */ | 273 | */ |
274 | |||
275 | // total time the query took | ||
276 | mp_perfdata pd_total_time = perfdata_init(); | ||
333 | double total_time; | 277 | double total_time; |
334 | handle_curl_option_return_code( | 278 | handle_curl_option_return_code( |
335 | curl_easy_getinfo(curl_state.curl, CURLINFO_TOTAL_TIME, &total_time), | 279 | curl_easy_getinfo(curl_state.curl, CURLINFO_TOTAL_TIME, &total_time), |
336 | "CURLINFO_TOTAL_TIME"); | 280 | "CURLINFO_TOTAL_TIME"); |
337 | size_t page_len = get_content_length(curl_state.header_buf, curl_state.body_buf); | 281 | mp_perfdata_value pd_val_total_time = mp_create_pd_value(total_time); |
338 | char perfstring[DEFAULT_BUFFER_SIZE]; | 282 | pd_total_time.value = pd_val_total_time; |
283 | pd_total_time = mp_pd_set_thresholds(pd_total_time, config.thlds); | ||
284 | pd_total_time.label = "time"; | ||
285 | pd_total_time.uom = "s"; | ||
286 | |||
287 | mp_subcheck sc_total_time = mp_subcheck_init(); | ||
288 | sc_total_time = mp_set_subcheck_state(sc_total_time, mp_get_pd_status(pd_total_time)); | ||
289 | xasprintf(&sc_total_time.output, "Total connection time: %fs", total_time); | ||
290 | mp_add_perfdata_to_subcheck(&sc_total_time, pd_total_time); | ||
291 | |||
292 | mp_add_subcheck_to_subcheck(&sc_result, sc_total_time); | ||
293 | |||
339 | if (config.show_extended_perfdata) { | 294 | if (config.show_extended_perfdata) { |
295 | // overall connection time | ||
296 | mp_perfdata pd_time_connect = perfdata_init(); | ||
340 | double time_connect; | 297 | double time_connect; |
341 | handle_curl_option_return_code( | 298 | handle_curl_option_return_code( |
342 | curl_easy_getinfo(curl_state.curl, CURLINFO_CONNECT_TIME, &time_connect), | 299 | curl_easy_getinfo(curl_state.curl, CURLINFO_CONNECT_TIME, &time_connect), |
343 | "CURLINFO_CONNECT_TIME"); | 300 | "CURLINFO_CONNECT_TIME"); |
344 | 301 | ||
302 | mp_perfdata_value pd_val_time_connect = mp_create_pd_value(time_connect); | ||
303 | pd_time_connect.value = pd_val_time_connect; | ||
304 | pd_time_connect.label = "time"; | ||
305 | pd_time_connect.uom = "s"; | ||
306 | pd_time_connect = mp_set_pd_max_value( | ||
307 | pd_time_connect, mp_create_pd_value(config.curl_config.socket_timeout)); | ||
308 | |||
309 | pd_time_connect = mp_pd_set_thresholds(pd_time_connect, config.thlds); | ||
310 | mp_add_perfdata_to_subcheck(&sc_result, pd_time_connect); | ||
311 | |||
312 | // application connection time, used to compute other timings | ||
345 | double time_appconnect; | 313 | double time_appconnect; |
346 | handle_curl_option_return_code( | 314 | handle_curl_option_return_code( |
347 | curl_easy_getinfo(curl_state.curl, CURLINFO_APPCONNECT_TIME, &time_appconnect), | 315 | curl_easy_getinfo(curl_state.curl, CURLINFO_APPCONNECT_TIME, &time_appconnect), |
348 | "CURLINFO_APPCONNECT_TIME"); | 316 | "CURLINFO_APPCONNECT_TIME"); |
349 | 317 | ||
350 | double time_headers; | 318 | if (workingState.use_ssl) { |
351 | handle_curl_option_return_code( | 319 | mp_perfdata pd_time_tls = perfdata_init(); |
352 | curl_easy_getinfo(curl_state.curl, CURLINFO_PRETRANSFER_TIME, &time_headers), | 320 | { |
353 | "CURLINFO_PRETRANSFER_TIME"); | 321 | mp_perfdata_value pd_val_time_tls = |
322 | mp_create_pd_value(time_appconnect - time_connect); | ||
323 | |||
324 | pd_time_tls.value = pd_val_time_tls; | ||
325 | } | ||
326 | pd_time_tls.label = "time_tls"; | ||
327 | pd_time_tls.uom = "s"; | ||
328 | mp_add_perfdata_to_subcheck(&sc_result, pd_time_tls); | ||
329 | } | ||
330 | |||
331 | mp_perfdata pd_time_headers = perfdata_init(); | ||
332 | { | ||
333 | double time_headers; | ||
334 | handle_curl_option_return_code( | ||
335 | curl_easy_getinfo(curl_state.curl, CURLINFO_PRETRANSFER_TIME, &time_headers), | ||
336 | "CURLINFO_PRETRANSFER_TIME"); | ||
337 | |||
338 | mp_perfdata_value pd_val_time_headers = | ||
339 | mp_create_pd_value(time_headers - time_appconnect); | ||
340 | |||
341 | pd_time_headers.value = pd_val_time_headers; | ||
342 | } | ||
343 | pd_time_headers.label = "time_headers"; | ||
344 | pd_time_headers.uom = "s"; | ||
345 | mp_add_perfdata_to_subcheck(&sc_result, pd_time_headers); | ||
354 | 346 | ||
347 | mp_perfdata pd_time_firstbyte = perfdata_init(); | ||
355 | double time_firstbyte; | 348 | double time_firstbyte; |
356 | handle_curl_option_return_code( | 349 | handle_curl_option_return_code( |
357 | curl_easy_getinfo(curl_state.curl, CURLINFO_STARTTRANSFER_TIME, &time_firstbyte), | 350 | curl_easy_getinfo(curl_state.curl, CURLINFO_STARTTRANSFER_TIME, &time_firstbyte), |
358 | "CURLINFO_STARTTRANSFER_TIME"); | 351 | "CURLINFO_STARTTRANSFER_TIME"); |
359 | 352 | ||
360 | snprintf( | 353 | mp_perfdata_value pd_val_time_firstbyte = mp_create_pd_value(time_firstbyte); |
361 | perfstring, DEFAULT_BUFFER_SIZE, "%s %s %s %s %s %s %s", | 354 | pd_time_firstbyte.value = pd_val_time_firstbyte; |
362 | perfd_time(total_time, config.thlds, config.curl_config.socket_timeout), | 355 | pd_time_firstbyte.label = "time_firstbyte"; |
363 | perfd_size(page_len, config.min_page_len), | 356 | pd_time_firstbyte.uom = "s"; |
364 | perfd_time_connect(time_connect, config.curl_config.socket_timeout), | 357 | mp_add_perfdata_to_subcheck(&sc_result, pd_time_firstbyte); |
365 | workingState.use_ssl | 358 | |
366 | ? perfd_time_ssl(time_appconnect - time_connect, config.curl_config.socket_timeout) | 359 | mp_perfdata pd_time_transfer = perfdata_init(); |
367 | : "", | 360 | pd_time_transfer.value = mp_create_pd_value(total_time - time_firstbyte); |
368 | perfd_time_headers(time_headers - time_appconnect, config.curl_config.socket_timeout), | 361 | pd_time_transfer.label = "time_transfer"; |
369 | perfd_time_firstbyte(time_firstbyte - time_headers, config.curl_config.socket_timeout), | 362 | pd_time_transfer.uom = "s"; |
370 | perfd_time_transfer(total_time - time_firstbyte, config.curl_config.socket_timeout)); | 363 | mp_add_perfdata_to_subcheck(&sc_result, pd_time_transfer); |
371 | } else { | ||
372 | snprintf(perfstring, DEFAULT_BUFFER_SIZE, "%s %s", | ||
373 | perfd_time(total_time, config.thlds, config.curl_config.socket_timeout), | ||
374 | perfd_size(page_len, config.min_page_len)); | ||
375 | } | 364 | } |
376 | 365 | ||
377 | /* return a CRITICAL status if we couldn't read any data */ | 366 | /* return a CRITICAL status if we couldn't read any data */ |
378 | if (strlen(curl_state.header_buf->buf) == 0 && strlen(curl_state.body_buf->buf) == 0) { | 367 | if (strlen(curl_state.header_buf->buf) == 0 && strlen(curl_state.body_buf->buf) == 0) { |
379 | die(STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n")); | 368 | sc_result = mp_set_subcheck_state(sc_result, STATE_CRITICAL); |
369 | xasprintf(&sc_result.output, "No header received from host"); | ||
370 | return sc_result; | ||
380 | } | 371 | } |
381 | 372 | ||
382 | /* get status line of answer, check sanity of HTTP code */ | 373 | /* get status line of answer, check sanity of HTTP code */ |
383 | if (curlhelp_parse_statusline(curl_state.header_buf->buf, curl_state.status_line) < 0) { | 374 | if (curlhelp_parse_statusline(curl_state.header_buf->buf, curl_state.status_line) < 0) { |
384 | snprintf(msg, DEFAULT_BUFFER_SIZE, | 375 | sc_result = mp_set_subcheck_state(sc_result, STATE_CRITICAL); |
385 | "Unparsable status line in %.3g seconds response time|%s\n", total_time, | ||
386 | perfstring); | ||
387 | /* we cannot know the major/minor version here for sure as we cannot parse the first | 376 | /* we cannot know the major/minor version here for sure as we cannot parse the first |
388 | * line */ | 377 | * line */ |
389 | die(STATE_CRITICAL, "HTTP CRITICAL HTTP/x.x unknown - %s", msg); | 378 | xasprintf(&sc_result.output, "HTTP/x.x unknown - Unparsable status line"); |
379 | return sc_result; | ||
390 | } | 380 | } |
381 | |||
391 | curl_state.status_line_initialized = true; | 382 | curl_state.status_line_initialized = true; |
392 | 383 | ||
393 | /* get result code from cURL */ | 384 | /* get result code from cURL */ |
@@ -406,43 +397,71 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat | |||
406 | } | 397 | } |
407 | 398 | ||
408 | /* make sure the status line matches the response we are looking for */ | 399 | /* make sure the status line matches the response we are looking for */ |
400 | mp_subcheck sc_expect = mp_subcheck_init(); | ||
401 | sc_expect = mp_set_subcheck_default_state(sc_expect, STATE_OK); | ||
409 | if (!expected_statuscode(curl_state.status_line->first_line, config.server_expect.string)) { | 402 | if (!expected_statuscode(curl_state.status_line->first_line, config.server_expect.string)) { |
410 | if (workingState.serverPort == HTTP_PORT) { | 403 | if (workingState.serverPort == HTTP_PORT) { |
411 | snprintf(msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host: %s\n"), | 404 | xasprintf(&sc_expect.output, _("Invalid HTTP response received from host: %s\n"), |
412 | curl_state.status_line->first_line); | 405 | curl_state.status_line->first_line); |
413 | } else { | 406 | } else { |
414 | snprintf(msg, DEFAULT_BUFFER_SIZE, | 407 | xasprintf(&sc_expect.output, |
415 | _("Invalid HTTP response received from host on port %d: %s\n"), | 408 | _("Invalid HTTP response received from host on port %d: %s\n"), |
416 | workingState.serverPort, curl_state.status_line->first_line); | 409 | workingState.serverPort, curl_state.status_line->first_line); |
417 | } | 410 | } |
418 | die(STATE_CRITICAL, "HTTP CRITICAL - %s%s%s", msg, config.show_body ? "\n" : "", | 411 | sc_expect = mp_set_subcheck_default_state(sc_expect, STATE_CRITICAL); |
419 | config.show_body ? curl_state.body_buf->buf : ""); | 412 | } else { |
413 | xasprintf(&sc_expect.output, _("Status line output matched \"%s\""), | ||
414 | config.server_expect.string); | ||
420 | } | 415 | } |
416 | mp_add_subcheck_to_subcheck(&sc_result, sc_expect); | ||
421 | 417 | ||
422 | mp_state_enum result = STATE_OK; | 418 | if (!config.server_expect.is_present) { |
423 | if (config.server_expect.is_present) { | ||
424 | snprintf(msg, DEFAULT_BUFFER_SIZE, _("Status line output matched \"%s\" - "), | ||
425 | config.server_expect.string); | ||
426 | if (verbose) { | ||
427 | printf("%s\n", msg); | ||
428 | } | ||
429 | result = STATE_OK; | ||
430 | } else { | ||
431 | /* illegal return codes result in a critical state */ | 419 | /* illegal return codes result in a critical state */ |
420 | mp_subcheck sc_return_code = mp_subcheck_init(); | ||
421 | sc_return_code = mp_set_subcheck_default_state(sc_return_code, STATE_OK); | ||
422 | xasprintf(&sc_return_code.output, "HTTP return code: %d", | ||
423 | curl_state.status_line->http_code); | ||
424 | |||
432 | if (httpReturnCode >= 600 || httpReturnCode < 100) { | 425 | if (httpReturnCode >= 600 || httpReturnCode < 100) { |
433 | die(STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"), | 426 | sc_return_code = mp_set_subcheck_state(sc_return_code, STATE_CRITICAL); |
434 | curl_state.status_line->http_code, curl_state.status_line->msg); | 427 | xasprintf(&sc_return_code.output, _("Invalid Status (%d, %.40s)"), |
435 | /* server errors result in a critical state */ | 428 | curl_state.status_line->http_code, curl_state.status_line->msg); |
436 | } else if (httpReturnCode >= 500) { | 429 | mp_add_subcheck_to_subcheck(&sc_result, sc_return_code); |
437 | result = STATE_CRITICAL; | 430 | return sc_result; |
431 | } | ||
432 | |||
433 | // server errors result in a critical state | ||
434 | if (httpReturnCode >= 500) { | ||
435 | sc_return_code = mp_set_subcheck_state(sc_return_code, STATE_CRITICAL); | ||
438 | /* client errors result in a warning state */ | 436 | /* client errors result in a warning state */ |
439 | } else if (httpReturnCode >= 400) { | 437 | } else if (httpReturnCode >= 400) { |
440 | result = STATE_WARNING; | 438 | sc_return_code = mp_set_subcheck_state(sc_return_code, STATE_WARNING); |
441 | /* check redirected page if specified */ | 439 | /* check redirected page if specified */ |
442 | } else if (httpReturnCode >= 300) { | 440 | } else if (httpReturnCode >= 300) { |
443 | if (config.on_redirect_dependent) { | 441 | if (config.on_redirect_dependent) { |
444 | if (config.followmethod == FOLLOW_LIBCURL) { | 442 | if (config.followmethod == FOLLOW_LIBCURL) { |
445 | httpReturnCode = curl_state.status_line->http_code; | 443 | httpReturnCode = curl_state.status_line->http_code; |
444 | handle_curl_option_return_code( | ||
445 | curl_easy_getinfo(curl_state.curl, CURLINFO_REDIRECT_COUNT, &redir_depth), | ||
446 | "CURLINFO_REDIRECT_COUNT"); | ||
447 | |||
448 | if (verbose >= 2) { | ||
449 | printf(_("* curl LIBINFO_REDIRECT_COUNT is %d\n"), redir_depth); | ||
450 | } | ||
451 | |||
452 | mp_subcheck sc_redir_depth = mp_subcheck_init(); | ||
453 | if (redir_depth > config.max_depth) { | ||
454 | xasprintf(&sc_redir_depth.output, | ||
455 | "maximum redirection depth %d exceeded in libcurl", | ||
456 | config.max_depth); | ||
457 | sc_redir_depth = mp_set_subcheck_state(sc_redir_depth, STATE_CRITICAL); | ||
458 | mp_add_subcheck_to_subcheck(&sc_result, sc_redir_depth); | ||
459 | return sc_result; | ||
460 | } | ||
461 | xasprintf(&sc_redir_depth.output, "redirection depth %d (of a maximum %d)", | ||
462 | redir_depth, config.max_depth); | ||
463 | mp_add_subcheck_to_subcheck(&sc_result, sc_redir_depth); | ||
464 | |||
446 | } else { | 465 | } else { |
447 | /* old check_http style redirection, if we come | 466 | /* old check_http style redirection, if we come |
448 | * back here, we are in the same status as with | 467 | * back here, we are in the same status as with |
@@ -451,54 +470,53 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat | |||
451 | redir_wrapper redir_result = | 470 | redir_wrapper redir_result = |
452 | redir(curl_state.header_buf, config, redir_depth, workingState); | 471 | redir(curl_state.header_buf, config, redir_depth, workingState); |
453 | cleanup(curl_state); | 472 | cleanup(curl_state); |
454 | check_http(config, redir_result.working_state, redir_result.redir_depth); | 473 | mp_subcheck sc_redir = |
474 | check_http(config, redir_result.working_state, redir_result.redir_depth); | ||
475 | mp_add_subcheck_to_subcheck(&sc_result, sc_redir); | ||
476 | |||
477 | return sc_result; | ||
455 | } | 478 | } |
456 | } else { | 479 | } else { |
457 | /* this is a specific code in the command line to | 480 | /* this is a specific code in the command line to |
458 | * be returned when a redirection is encountered | 481 | * be returned when a redirection is encountered |
459 | */ | 482 | */ |
483 | sc_return_code = | ||
484 | mp_set_subcheck_state(sc_return_code, config.on_redirect_result_state); | ||
460 | } | 485 | } |
461 | result = max_state_alt(config.on_redirect_result_state, result); | ||
462 | /* all other codes are considered ok */ | ||
463 | } else { | 486 | } else { |
464 | result = STATE_OK; | 487 | sc_return_code = mp_set_subcheck_state(sc_return_code, STATE_OK); |
465 | } | ||
466 | } | ||
467 | |||
468 | /* libcurl redirection internally, handle error states here */ | ||
469 | if (config.followmethod == FOLLOW_LIBCURL) { | ||
470 | handle_curl_option_return_code( | ||
471 | curl_easy_getinfo(curl_state.curl, CURLINFO_REDIRECT_COUNT, &redir_depth), | ||
472 | "CURLINFO_REDIRECT_COUNT"); | ||
473 | |||
474 | if (verbose >= 2) { | ||
475 | printf(_("* curl LIBINFO_REDIRECT_COUNT is %d\n"), redir_depth); | ||
476 | } | 488 | } |
477 | 489 | ||
478 | if (redir_depth > config.max_depth) { | 490 | mp_add_subcheck_to_subcheck(&sc_result, sc_return_code); |
479 | snprintf(msg, DEFAULT_BUFFER_SIZE, "maximum redirection depth %d exceeded in libcurl", | ||
480 | config.max_depth); | ||
481 | die(STATE_WARNING, "HTTP WARNING - %s", msg); | ||
482 | } | ||
483 | } | 491 | } |
484 | 492 | ||
485 | /* check status codes, set exit status accordingly */ | 493 | /* check status codes, set exit status accordingly */ |
486 | if (curl_state.status_line->http_code != httpReturnCode) { | 494 | if (curl_state.status_line->http_code != httpReturnCode) { |
487 | die(STATE_CRITICAL, _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"), | 495 | mp_subcheck sc_http_return_code_sanity = mp_subcheck_init(); |
488 | string_statuscode(curl_state.status_line->http_major, curl_state.status_line->http_minor), | 496 | sc_http_return_code_sanity = |
489 | curl_state.status_line->http_code, curl_state.status_line->msg, httpReturnCode); | 497 | mp_set_subcheck_state(sc_http_return_code_sanity, STATE_CRITICAL); |
498 | xasprintf(&sc_http_return_code_sanity.output, | ||
499 | _("HTTP CRITICAL %s %d %s - different HTTP codes (cUrl has %ld)\n"), | ||
500 | string_statuscode(curl_state.status_line->http_major, | ||
501 | curl_state.status_line->http_minor), | ||
502 | curl_state.status_line->http_code, curl_state.status_line->msg, httpReturnCode); | ||
503 | |||
504 | mp_add_subcheck_to_subcheck(&sc_result, sc_http_return_code_sanity); | ||
505 | return sc_result; | ||
490 | } | 506 | } |
491 | 507 | ||
492 | if (config.maximum_age >= 0) { | 508 | if (config.maximum_age >= 0) { |
493 | result = max_state_alt( | 509 | mp_subcheck sc_max_age = check_document_dates(curl_state.header_buf, config.maximum_age); |
494 | check_document_dates(curl_state.header_buf, msg, config.maximum_age), result); | 510 | mp_add_subcheck_to_subcheck(&sc_result, sc_max_age); |
495 | } | 511 | } |
496 | 512 | ||
497 | /* Page and Header content checks go here */ | 513 | /* Page and Header content checks go here */ |
498 | |||
499 | if (strlen(config.header_expect)) { | 514 | if (strlen(config.header_expect)) { |
500 | if (!strstr(curl_state.header_buf->buf, config.header_expect)) { | 515 | mp_subcheck sc_header_expect = mp_subcheck_init(); |
516 | sc_header_expect = mp_set_subcheck_default_state(sc_header_expect, STATE_OK); | ||
517 | xasprintf(&sc_header_expect.output, "Expect %s in header", config.header_expect); | ||
501 | 518 | ||
519 | if (!strstr(curl_state.header_buf->buf, config.header_expect)) { | ||
502 | char output_header_search[30] = ""; | 520 | char output_header_search[30] = ""; |
503 | strncpy(&output_header_search[0], config.header_expect, sizeof(output_header_search)); | 521 | strncpy(&output_header_search[0], config.header_expect, sizeof(output_header_search)); |
504 | 522 | ||
@@ -506,22 +524,23 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat | |||
506 | bcopy("...", &output_header_search[sizeof(output_header_search) - 4], 4); | 524 | bcopy("...", &output_header_search[sizeof(output_header_search) - 4], 4); |
507 | } | 525 | } |
508 | 526 | ||
509 | char tmp[DEFAULT_BUFFER_SIZE]; | 527 | xasprintf(&sc_header_expect.output, _("header '%s' not found on '%s://%s:%d%s', "), |
510 | 528 | output_header_search, workingState.use_ssl ? "https" : "http", | |
511 | snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sheader '%s' not found on '%s://%s:%d%s', "), | 529 | workingState.host_name ? workingState.host_name : workingState.server_address, |
512 | msg, output_header_search, workingState.use_ssl ? "https" : "http", | 530 | workingState.serverPort, workingState.server_url); |
513 | workingState.host_name ? workingState.host_name : workingState.server_address, | ||
514 | workingState.serverPort, workingState.server_url); | ||
515 | |||
516 | strcpy(msg, tmp); | ||
517 | 531 | ||
518 | result = STATE_CRITICAL; | 532 | sc_header_expect = mp_set_subcheck_state(sc_header_expect, STATE_CRITICAL); |
519 | } | 533 | } |
534 | |||
535 | mp_add_subcheck_to_subcheck(&sc_result, sc_header_expect); | ||
520 | } | 536 | } |
521 | 537 | ||
522 | if (strlen(config.string_expect)) { | 538 | if (strlen(config.string_expect)) { |
523 | if (!strstr(curl_state.body_buf->buf, config.string_expect)) { | 539 | mp_subcheck sc_string_expect = mp_subcheck_init(); |
540 | sc_string_expect = mp_set_subcheck_default_state(sc_string_expect, STATE_OK); | ||
541 | xasprintf(&sc_string_expect.output, "Expect string \"%s\" in body", config.string_expect); | ||
524 | 542 | ||
543 | if (!strstr(curl_state.body_buf->buf, config.string_expect)) { | ||
525 | char output_string_search[30] = ""; | 544 | char output_string_search[30] = ""; |
526 | strncpy(&output_string_search[0], config.string_expect, sizeof(output_string_search)); | 545 | strncpy(&output_string_search[0], config.string_expect, sizeof(output_string_search)); |
527 | 546 | ||
@@ -529,93 +548,86 @@ mp_state_enum check_http(const check_curl_config config, check_curl_working_stat | |||
529 | bcopy("...", &output_string_search[sizeof(output_string_search) - 4], 4); | 548 | bcopy("...", &output_string_search[sizeof(output_string_search) - 4], 4); |
530 | } | 549 | } |
531 | 550 | ||
532 | char tmp[DEFAULT_BUFFER_SIZE]; | 551 | xasprintf(&sc_string_expect.output, _("string '%s' not found on '%s://%s:%d%s', "), |
533 | 552 | output_string_search, workingState.use_ssl ? "https" : "http", | |
534 | snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sstring '%s' not found on '%s://%s:%d%s', "), | 553 | workingState.host_name ? workingState.host_name : workingState.server_address, |
535 | msg, output_string_search, workingState.use_ssl ? "https" : "http", | 554 | workingState.serverPort, workingState.server_url); |
536 | workingState.host_name ? workingState.host_name : workingState.server_address, | ||
537 | workingState.serverPort, workingState.server_url); | ||
538 | 555 | ||
539 | strcpy(msg, tmp); | 556 | sc_string_expect = mp_set_subcheck_state(sc_string_expect, STATE_CRITICAL); |
540 | |||
541 | result = STATE_CRITICAL; | ||
542 | } | 557 | } |
558 | |||
559 | mp_add_subcheck_to_subcheck(&sc_result, sc_string_expect); | ||
543 | } | 560 | } |
544 | 561 | ||
545 | if (strlen(config.regexp)) { | 562 | if (strlen(config.regexp)) { |
563 | mp_subcheck sc_body_regex = mp_subcheck_init(); | ||
564 | xasprintf(&sc_body_regex.output, "Regex \"%s\" in body matched", config.regexp); | ||
546 | regmatch_t pmatch[REGS]; | 565 | regmatch_t pmatch[REGS]; |
566 | |||
547 | int errcode = regexec(&config.compiled_regex, curl_state.body_buf->buf, REGS, pmatch, 0); | 567 | int errcode = regexec(&config.compiled_regex, curl_state.body_buf->buf, REGS, pmatch, 0); |
548 | if ((errcode == 0 && !config.invert_regex) || | ||
549 | (errcode == REG_NOMATCH && config.invert_regex)) { | ||
550 | /* OK - No-op to avoid changing the logic around it */ | ||
551 | result = max_state_alt(STATE_OK, result); | ||
552 | } else if ((errcode == REG_NOMATCH && !config.invert_regex) || | ||
553 | (errcode == 0 && config.invert_regex)) { | ||
554 | if (!config.invert_regex) { | ||
555 | char tmp[DEFAULT_BUFFER_SIZE]; | ||
556 | |||
557 | snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spattern not found, "), msg); | ||
558 | strcpy(msg, tmp); | ||
559 | 568 | ||
569 | if (errcode == 0) { | ||
570 | // got a match | ||
571 | if (config.invert_regex) { | ||
572 | sc_body_regex = mp_set_subcheck_state(sc_body_regex, STATE_OK); | ||
560 | } else { | 573 | } else { |
561 | char tmp[DEFAULT_BUFFER_SIZE]; | 574 | sc_body_regex = mp_set_subcheck_state(sc_body_regex, config.state_regex); |
562 | |||
563 | snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spattern found, "), msg); | ||
564 | strcpy(msg, tmp); | ||
565 | } | 575 | } |
566 | result = config.state_regex; | ||
567 | } else { | 576 | } else { |
568 | regerror(errcode, &config.compiled_regex, errbuf, MAX_INPUT_BUFFER); | 577 | xasprintf(&sc_body_regex.output, "%s not", sc_body_regex.output); |
569 | 578 | // got no match | |
570 | char tmp[DEFAULT_BUFFER_SIZE]; | 579 | if (config.invert_regex) { |
571 | 580 | sc_body_regex = mp_set_subcheck_state(sc_body_regex, config.state_regex); | |
572 | snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sExecute Error: %s, "), msg, errbuf); | 581 | } else { |
573 | strcpy(msg, tmp); | 582 | sc_body_regex = mp_set_subcheck_state(sc_body_regex, STATE_OK); |
574 | result = STATE_UNKNOWN; | 583 | } |
575 | } | 584 | } |
576 | } | ||
577 | 585 | ||
578 | /* make sure the page is of an appropriate size */ | 586 | mp_add_subcheck_to_subcheck(&sc_result, sc_body_regex); |
579 | if ((config.max_page_len > 0) && (page_len > config.max_page_len)) { | 587 | } |
580 | char tmp[DEFAULT_BUFFER_SIZE]; | ||
581 | 588 | ||
582 | snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spage size %zu too large, "), msg, page_len); | 589 | // size a.k.a. page length |
590 | mp_perfdata pd_page_length = perfdata_init(); | ||
591 | size_t page_len = get_content_length(curl_state.header_buf, curl_state.body_buf); | ||
592 | mp_perfdata_value pd_val_page_length = mp_create_pd_value(page_len); | ||
593 | pd_page_length.value = pd_val_page_length; | ||
594 | pd_page_length.label = "size"; | ||
595 | pd_page_length.uom = "B"; | ||
596 | pd_page_length.min = mp_create_pd_value(0); | ||
597 | pd_page_length.warn = config.page_length_limits; | ||
598 | pd_page_length.warn_present = true; | ||
583 | 599 | ||
584 | strcpy(msg, tmp); | 600 | /* make sure the page is of an appropriate size */ |
601 | if (config.page_length_limits_is_set) { | ||
602 | mp_thresholds page_length_threshold = mp_thresholds_init(); | ||
603 | page_length_threshold.warning = config.page_length_limits; | ||
604 | page_length_threshold.warning_is_set = true; | ||
585 | 605 | ||
586 | result = max_state_alt(STATE_WARNING, result); | 606 | pd_page_length = mp_pd_set_thresholds(pd_page_length, page_length_threshold); |
587 | 607 | ||
588 | } else if ((config.min_page_len > 0) && (page_len < config.min_page_len)) { | 608 | mp_subcheck sc_page_length = mp_subcheck_init(); |
589 | char tmp[DEFAULT_BUFFER_SIZE]; | ||
590 | 609 | ||
591 | snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%spage size %zu too small, "), msg, page_len); | 610 | mp_add_perfdata_to_subcheck(&sc_page_length, pd_page_length); |
592 | strcpy(msg, tmp); | ||
593 | result = max_state_alt(STATE_WARNING, result); | ||
594 | } | ||
595 | 611 | ||
596 | /* -w, -c: check warning and critical level */ | 612 | mp_state_enum tmp_state = mp_get_pd_status(pd_page_length); |
597 | result = max_state_alt(get_status(total_time, config.thlds), result); | 613 | sc_page_length = mp_set_subcheck_state(sc_page_length, tmp_state); |
598 | 614 | ||
599 | /* Cut-off trailing characters */ | 615 | switch (tmp_state) { |
600 | if (strlen(msg) >= 2) { | 616 | case STATE_CRITICAL: |
601 | if (msg[strlen(msg) - 2] == ',') { | 617 | case STATE_WARNING: |
602 | msg[strlen(msg) - 2] = '\0'; | 618 | xasprintf(&sc_page_length.output, _("page size %zu violates threshold"), page_len); |
603 | } else { | 619 | break; |
604 | msg[strlen(msg) - 3] = '\0'; | 620 | case STATE_OK: |
621 | xasprintf(&sc_page_length.output, _("page size %zu is OK"), page_len); | ||
622 | break; | ||
623 | default: | ||
624 | assert(false); | ||
605 | } | 625 | } |
626 | |||
627 | mp_add_subcheck_to_subcheck(&sc_result, sc_page_length); | ||
606 | } | 628 | } |
607 | 629 | ||
608 | /* TODO: separate _() msg and status code: die (result, "HTTP %s: %s\n", state_text(result), | 630 | return sc_result; |
609 | * msg); */ | ||
610 | die((int)max_state_alt(result, result_ssl), | ||
611 | "HTTP %s: %s %d %s%s%s - %zu bytes in %.3f second response time %s|%s\n%s%s", | ||
612 | state_text(result), | ||
613 | string_statuscode(curl_state.status_line->http_major, curl_state.status_line->http_minor), | ||
614 | curl_state.status_line->http_code, curl_state.status_line->msg, strlen(msg) > 0 ? " - " : "", | ||
615 | msg, page_len, total_time, (config.display_html ? "</A>" : ""), perfstring, | ||
616 | (config.show_body ? curl_state.body_buf->buf : ""), (config.show_body ? "\n" : "")); | ||
617 | |||
618 | return max_state_alt(result, result_ssl); | ||
619 | } | 631 | } |
620 | 632 | ||
621 | int uri_strcmp(const UriTextRangeA range, const char *stringToCompare) { | 633 | int uri_strcmp(const UriTextRangeA range, const char *stringToCompare) { |
@@ -895,8 +907,6 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) { | |||
895 | } | 907 | } |
896 | 908 | ||
897 | int option = 0; | 909 | int option = 0; |
898 | char *warning_thresholds = NULL; | ||
899 | char *critical_thresholds = NULL; | ||
900 | int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE; | 910 | int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE; |
901 | bool specify_port = false; | 911 | bool specify_port = false; |
902 | bool enable_tls = false; | 912 | bool enable_tls = false; |
@@ -931,11 +941,22 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) { | |||
931 | } | 941 | } |
932 | break; | 942 | break; |
933 | case 'c': /* critical time threshold */ | 943 | case 'c': /* critical time threshold */ |
934 | critical_thresholds = optarg; | 944 | { |
935 | break; | 945 | mp_range_parsed critical_range = mp_parse_range_string(optarg); |
946 | if (critical_range.error != MP_PARSING_SUCCES) { | ||
947 | die(STATE_UNKNOWN, "failed to parse critical threshold: %s", optarg); | ||
948 | } | ||
949 | result.config.thlds = mp_thresholds_set_crit(result.config.thlds, critical_range.range); | ||
950 | } break; | ||
936 | case 'w': /* warning time threshold */ | 951 | case 'w': /* warning time threshold */ |
937 | warning_thresholds = optarg; | 952 | { |
938 | break; | 953 | mp_range_parsed warning_range = mp_parse_range_string(optarg); |
954 | |||
955 | if (warning_range.error != MP_PARSING_SUCCES) { | ||
956 | die(STATE_UNKNOWN, "failed to parse warning threshold: %s", optarg); | ||
957 | } | ||
958 | result.config.thlds = mp_thresholds_set_warn(result.config.thlds, warning_range.range); | ||
959 | } break; | ||
939 | case 'H': /* virtual host */ | 960 | case 'H': /* virtual host */ |
940 | result.config.initial_config.host_name = strdup(optarg); | 961 | result.config.initial_config.host_name = strdup(optarg); |
941 | char *tmp_string; | 962 | char *tmp_string; |
@@ -1207,27 +1228,14 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) { | |||
1207 | break; | 1228 | break; |
1208 | case 'm': /* min_page_length */ | 1229 | case 'm': /* min_page_length */ |
1209 | { | 1230 | { |
1210 | char *tmp; | 1231 | mp_range_parsed foo = mp_parse_range_string(optarg); |
1211 | if (strchr(optarg, ':') != (char *)NULL) { | ||
1212 | /* range, so get two values, min:max */ | ||
1213 | tmp = strtok(optarg, ":"); | ||
1214 | if (tmp == NULL) { | ||
1215 | printf("Bad format: try \"-m min:max\"\n"); | ||
1216 | exit(STATE_WARNING); | ||
1217 | } else { | ||
1218 | result.config.min_page_len = atol(tmp); | ||
1219 | } | ||
1220 | 1232 | ||
1221 | tmp = strtok(NULL, ":"); | 1233 | if (foo.error != MP_PARSING_SUCCES) { |
1222 | if (tmp == NULL) { | 1234 | die(STATE_CRITICAL, "failed to parse page size limits: %s", optarg); |
1223 | printf("Bad format: try \"-m min:max\"\n"); | ||
1224 | exit(STATE_WARNING); | ||
1225 | } else { | ||
1226 | result.config.max_page_len = atol(tmp); | ||
1227 | } | ||
1228 | } else { | ||
1229 | result.config.min_page_len = atol(optarg); | ||
1230 | } | 1235 | } |
1236 | |||
1237 | result.config.page_length_limits = foo.range; | ||
1238 | result.config.page_length_limits_is_set = true; | ||
1231 | break; | 1239 | break; |
1232 | } | 1240 | } |
1233 | case 'N': /* no-body */ | 1241 | case 'N': /* no-body */ |
@@ -1401,16 +1409,6 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) { | |||
1401 | } | 1409 | } |
1402 | } | 1410 | } |
1403 | 1411 | ||
1404 | set_thresholds(&result.config.thlds, warning_thresholds, critical_thresholds); | ||
1405 | |||
1406 | if (critical_thresholds && | ||
1407 | result.config.thlds->critical->end > (double)result.config.curl_config.socket_timeout) { | ||
1408 | result.config.curl_config.socket_timeout = (int)result.config.thlds->critical->end + 1; | ||
1409 | } | ||
1410 | if (verbose >= 2) { | ||
1411 | printf("* Socket timeout set to %ld seconds\n", result.config.curl_config.socket_timeout); | ||
1412 | } | ||
1413 | |||
1414 | if (result.config.initial_config.http_method == NULL) { | 1412 | if (result.config.initial_config.http_method == NULL) { |
1415 | result.config.initial_config.http_method = strdup("GET"); | 1413 | result.config.initial_config.http_method = strdup("GET"); |
1416 | } | 1414 | } |
diff --git a/plugins/check_curl.d/check_curl_helpers.c b/plugins/check_curl.d/check_curl_helpers.c index e33f2aa9..49949ccb 100644 --- a/plugins/check_curl.d/check_curl_helpers.c +++ b/plugins/check_curl.d/check_curl_helpers.c | |||
@@ -5,9 +5,12 @@ | |||
5 | #include <netdb.h> | 5 | #include <netdb.h> |
6 | #include <stdlib.h> | 6 | #include <stdlib.h> |
7 | #include "../utils.h" | 7 | #include "../utils.h" |
8 | #include "check_curl.d/config.h" | ||
9 | #include "output.h" | ||
10 | #include "perfdata.h" | ||
11 | #include "states.h" | ||
8 | 12 | ||
9 | extern int verbose; | 13 | extern int verbose; |
10 | char msg[DEFAULT_BUFFER_SIZE]; | ||
11 | char errbuf[MAX_INPUT_BUFFER]; | 14 | char errbuf[MAX_INPUT_BUFFER]; |
12 | bool is_openssl_callback = false; | 15 | bool is_openssl_callback = false; |
13 | bool add_sslctx_verify_fun = false; | 16 | bool add_sslctx_verify_fun = false; |
@@ -127,10 +130,9 @@ check_curl_configure_curl(const check_curl_static_curl_config config, | |||
127 | int res; | 130 | int res; |
128 | if ((res = lookup_host(working_state.server_address, addrstr, DEFAULT_BUFFER_SIZE / 2, | 131 | if ((res = lookup_host(working_state.server_address, addrstr, DEFAULT_BUFFER_SIZE / 2, |
129 | config.sin_family)) != 0) { | 132 | config.sin_family)) != 0) { |
130 | snprintf(msg, DEFAULT_BUFFER_SIZE, | 133 | die(STATE_CRITICAL, |
131 | _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"), | 134 | _("Unable to lookup IP address for '%s': getaddrinfo returned %d - %s"), |
132 | working_state.server_address, res, gai_strerror(res)); | 135 | working_state.server_address, res, gai_strerror(res)); |
133 | die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); | ||
134 | } | 136 | } |
135 | snprintf(dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", working_state.host_name, | 137 | snprintf(dnscache, DEFAULT_BUFFER_SIZE, "%s:%d:%s", working_state.host_name, |
136 | working_state.serverPort, addrstr); | 138 | working_state.serverPort, addrstr); |
@@ -154,12 +156,7 @@ check_curl_configure_curl(const check_curl_static_curl_config config, | |||
154 | } | 156 | } |
155 | 157 | ||
156 | /* compose URL: use the address we want to connect to, set Host: header later */ | 158 | /* compose URL: use the address we want to connect to, set Host: header later */ |
157 | char url[DEFAULT_BUFFER_SIZE]; | 159 | char *url = fmt_url(working_state); |
158 | snprintf(url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", working_state.use_ssl ? "https" : "http", | ||
159 | (working_state.use_ssl & (working_state.host_name != NULL)) | ||
160 | ? working_state.host_name | ||
161 | : working_state.server_address, | ||
162 | working_state.serverPort, working_state.server_url); | ||
163 | 160 | ||
164 | if (verbose >= 1) { | 161 | if (verbose >= 1) { |
165 | printf("* curl CURLOPT_URL: %s\n", url); | 162 | printf("* curl CURLOPT_URL: %s\n", url); |
@@ -167,6 +164,8 @@ check_curl_configure_curl(const check_curl_static_curl_config config, | |||
167 | handle_curl_option_return_code(curl_easy_setopt(result.curl_state.curl, CURLOPT_URL, url), | 164 | handle_curl_option_return_code(curl_easy_setopt(result.curl_state.curl, CURLOPT_URL, url), |
168 | "CURLOPT_URL"); | 165 | "CURLOPT_URL"); |
169 | 166 | ||
167 | free(url); | ||
168 | |||
170 | /* extract proxy information for legacy proxy https requests */ | 169 | /* extract proxy information for legacy proxy https requests */ |
171 | if (!strcmp(working_state.http_method, "CONNECT") || | 170 | if (!strcmp(working_state.http_method, "CONNECT") || |
172 | strstr(working_state.server_url, "http") == working_state.server_url) { | 171 | strstr(working_state.server_url, "http") == working_state.server_url) { |
@@ -548,10 +547,8 @@ check_curl_configure_curl(const check_curl_static_curl_config config, | |||
548 | 547 | ||
549 | void handle_curl_option_return_code(CURLcode res, const char *option) { | 548 | void handle_curl_option_return_code(CURLcode res, const char *option) { |
550 | if (res != CURLE_OK) { | 549 | if (res != CURLE_OK) { |
551 | snprintf(msg, DEFAULT_BUFFER_SIZE, | 550 | die(STATE_CRITICAL, _("Error while setting cURL option '%s': cURL returned %d - %s"), |
552 | _("Error while setting cURL option '%s': cURL returned %d - %s"), option, res, | 551 | option, res, curl_easy_strerror(res)); |
553 | curl_easy_strerror(res)); | ||
554 | die(STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); | ||
555 | } | 552 | } |
556 | } | 553 | } |
557 | 554 | ||
@@ -618,9 +615,9 @@ check_curl_config check_curl_config_init() { | |||
618 | .continue_after_check_cert = false, | 615 | .continue_after_check_cert = false, |
619 | .days_till_exp_warn = 0, | 616 | .days_till_exp_warn = 0, |
620 | .days_till_exp_crit = 0, | 617 | .days_till_exp_crit = 0, |
621 | .thlds = NULL, | 618 | .thlds = mp_thresholds_init(), |
622 | .min_page_len = 0, | 619 | .page_length_limits = mp_range_init(), |
623 | .max_page_len = 0, | 620 | .page_length_limits_is_set = false, |
624 | .server_expect = | 621 | .server_expect = |
625 | { | 622 | { |
626 | .string = HTTP_EXPECT, | 623 | .string = HTTP_EXPECT, |
@@ -729,9 +726,7 @@ size_t get_content_length(const curlhelp_write_curlbuf *header_buf, | |||
729 | return header_buf->buflen + body_buf->buflen; | 726 | return header_buf->buflen + body_buf->buflen; |
730 | } | 727 | } |
731 | 728 | ||
732 | mp_state_enum check_document_dates(const curlhelp_write_curlbuf *header_buf, | 729 | mp_subcheck check_document_dates(const curlhelp_write_curlbuf *header_buf, const int maximum_age) { |
733 | const char msg[static DEFAULT_BUFFER_SIZE], | ||
734 | const int maximum_age) { | ||
735 | struct phr_header headers[255]; | 730 | struct phr_header headers[255]; |
736 | size_t nof_headers = 255; | 731 | size_t nof_headers = 255; |
737 | curlhelp_statusline status_line; | 732 | curlhelp_statusline status_line; |
@@ -747,73 +742,54 @@ mp_state_enum check_document_dates(const curlhelp_write_curlbuf *header_buf, | |||
747 | char *server_date = get_header_value(headers, nof_headers, "date"); | 742 | char *server_date = get_header_value(headers, nof_headers, "date"); |
748 | char *document_date = get_header_value(headers, nof_headers, "last-modified"); | 743 | char *document_date = get_header_value(headers, nof_headers, "last-modified"); |
749 | 744 | ||
750 | mp_state_enum date_result = STATE_OK; | 745 | mp_subcheck sc_document_dates = mp_subcheck_init(); |
751 | if (!server_date || !*server_date) { | 746 | if (!server_date || !*server_date) { |
752 | char tmp[DEFAULT_BUFFER_SIZE]; | 747 | xasprintf(&sc_document_dates.output, _("Server date unknown")); |
753 | 748 | sc_document_dates = mp_set_subcheck_state(sc_document_dates, STATE_UNKNOWN); | |
754 | snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sServer date unknown, "), msg); | ||
755 | strcpy(msg, tmp); | ||
756 | |||
757 | date_result = max_state_alt(STATE_UNKNOWN, date_result); | ||
758 | |||
759 | } else if (!document_date || !*document_date) { | 749 | } else if (!document_date || !*document_date) { |
760 | char tmp[DEFAULT_BUFFER_SIZE]; | 750 | xasprintf(&sc_document_dates.output, _("Document modification date unknown, ")); |
761 | 751 | sc_document_dates = mp_set_subcheck_state(sc_document_dates, STATE_CRITICAL); | |
762 | snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sDocument modification date unknown, "), msg); | ||
763 | strcpy(msg, tmp); | ||
764 | |||
765 | date_result = max_state_alt(STATE_CRITICAL, date_result); | ||
766 | |||
767 | } else { | 752 | } else { |
768 | time_t srv_data = curl_getdate(server_date, NULL); | 753 | time_t srv_data = curl_getdate(server_date, NULL); |
769 | time_t doc_data = curl_getdate(document_date, NULL); | 754 | time_t doc_data = curl_getdate(document_date, NULL); |
755 | |||
770 | if (verbose >= 2) { | 756 | if (verbose >= 2) { |
771 | printf("* server date: '%s' (%d), doc_date: '%s' (%d)\n", server_date, (int)srv_data, | 757 | printf("* server date: '%s' (%d), doc_date: '%s' (%d)\n", server_date, (int)srv_data, |
772 | document_date, (int)doc_data); | 758 | document_date, (int)doc_data); |
773 | } | 759 | } |
774 | if (srv_data <= 0) { | ||
775 | char tmp[DEFAULT_BUFFER_SIZE]; | ||
776 | 760 | ||
777 | snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sServer date \"%100s\" unparsable, "), msg, | 761 | if (srv_data <= 0) { |
778 | server_date); | 762 | xasprintf(&sc_document_dates.output, _("Server date \"%100s\" unparsable"), |
779 | strcpy(msg, tmp); | 763 | server_date); |
780 | 764 | sc_document_dates = mp_set_subcheck_state(sc_document_dates, STATE_CRITICAL); | |
781 | date_result = max_state_alt(STATE_CRITICAL, date_result); | ||
782 | } else if (doc_data <= 0) { | 765 | } else if (doc_data <= 0) { |
783 | char tmp[DEFAULT_BUFFER_SIZE]; | ||
784 | |||
785 | snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sDocument date \"%100s\" unparsable, "), msg, | ||
786 | document_date); | ||
787 | strcpy(msg, tmp); | ||
788 | 766 | ||
789 | date_result = max_state_alt(STATE_CRITICAL, date_result); | 767 | xasprintf(&sc_document_dates.output, _("Document date \"%100s\" unparsable"), |
768 | document_date); | ||
769 | sc_document_dates = mp_set_subcheck_state(sc_document_dates, STATE_CRITICAL); | ||
790 | } else if (doc_data > srv_data + 30) { | 770 | } else if (doc_data > srv_data + 30) { |
791 | char tmp[DEFAULT_BUFFER_SIZE]; | ||
792 | 771 | ||
793 | snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sDocument is %d seconds in the future, "), msg, | 772 | xasprintf(&sc_document_dates.output, _("Document is %d seconds in the future"), |
794 | (int)doc_data - (int)srv_data); | 773 | (int)doc_data - (int)srv_data); |
795 | strcpy(msg, tmp); | ||
796 | 774 | ||
797 | date_result = max_state_alt(STATE_CRITICAL, date_result); | 775 | sc_document_dates = mp_set_subcheck_state(sc_document_dates, STATE_CRITICAL); |
798 | } else if (doc_data < srv_data - maximum_age) { | 776 | } else if (doc_data < srv_data - maximum_age) { |
799 | time_t last_modified = (srv_data - doc_data); | 777 | time_t last_modified = (srv_data - doc_data); |
800 | if (last_modified > (60 * 60 * 24 * 2)) { | 778 | if (last_modified > (60 * 60 * 24 * 2)) { // two days hardcoded? |
801 | char tmp[DEFAULT_BUFFER_SIZE]; | 779 | xasprintf(&sc_document_dates.output, _("Last modified %.1f days ago"), |
802 | 780 | ((float)last_modified) / (60 * 60 * 24)); | |
803 | snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sLast modified %.1f days ago, "), msg, | 781 | sc_document_dates = mp_set_subcheck_state(sc_document_dates, STATE_CRITICAL); |
804 | ((float)last_modified) / (60 * 60 * 24)); | ||
805 | strcpy(msg, tmp); | ||
806 | |||
807 | date_result = max_state_alt(STATE_CRITICAL, date_result); | ||
808 | } else { | 782 | } else { |
809 | char tmp[DEFAULT_BUFFER_SIZE]; | 783 | xasprintf(&sc_document_dates.output, _("Last modified %ld:%02ld:%02ld ago"), |
810 | 784 | last_modified / (60 * 60), (last_modified / 60) % 60, last_modified % 60); | |
811 | snprintf(tmp, DEFAULT_BUFFER_SIZE, _("%sLast modified %ld:%02ld:%02ld ago, "), msg, | 785 | sc_document_dates = mp_set_subcheck_state(sc_document_dates, STATE_CRITICAL); |
812 | last_modified / (60 * 60), (last_modified / 60) % 60, last_modified % 60); | ||
813 | strcpy(msg, tmp); | ||
814 | |||
815 | date_result = max_state_alt(STATE_CRITICAL, date_result); | ||
816 | } | 786 | } |
787 | } else { | ||
788 | // TODO is this the OK case? | ||
789 | time_t last_modified = (srv_data - doc_data); | ||
790 | xasprintf(&sc_document_dates.output, _("Last modified %ld:%02ld:%02ld ago"), | ||
791 | last_modified / (60 * 60), (last_modified / 60) % 60, last_modified % 60); | ||
792 | sc_document_dates = mp_set_subcheck_state(sc_document_dates, STATE_OK); | ||
817 | } | 793 | } |
818 | } | 794 | } |
819 | 795 | ||
@@ -824,7 +800,7 @@ mp_state_enum check_document_dates(const curlhelp_write_curlbuf *header_buf, | |||
824 | free(document_date); | 800 | free(document_date); |
825 | } | 801 | } |
826 | 802 | ||
827 | return date_result; | 803 | return sc_document_dates; |
828 | } | 804 | } |
829 | 805 | ||
830 | void curlhelp_free_statusline(curlhelp_statusline *status_line) { free(status_line->first_line); } | 806 | void curlhelp_free_statusline(curlhelp_statusline *status_line) { free(status_line->first_line); } |
@@ -1172,46 +1148,117 @@ char *string_statuscode(int major, int minor) { | |||
1172 | return buf; | 1148 | return buf; |
1173 | } | 1149 | } |
1174 | 1150 | ||
1175 | char *perfd_time(double elapsed_time, thresholds *thlds, long socket_timeout) { | 1151 | /* check whether a file exists */ |
1176 | return fperfdata("time", elapsed_time, "s", (thlds->warning != NULL), | 1152 | void test_file(char *path) { |
1177 | thlds->warning ? thlds->warning->end : 0, (thlds->critical != NULL), | 1153 | if (access(path, R_OK) == 0) { |
1178 | thlds->critical ? thlds->critical->end : 0, true, 0, true, socket_timeout); | 1154 | return; |
1155 | } | ||
1156 | usage2(_("file does not exist or is not readable"), path); | ||
1179 | } | 1157 | } |
1180 | 1158 | ||
1181 | char *perfd_time_connect(double elapsed_time_connect, long socket_timeout) { | 1159 | mp_subcheck np_net_ssl_check_certificate(X509 *certificate, int days_till_exp_warn, |
1182 | return fperfdata("time_connect", elapsed_time_connect, "s", false, 0, false, 0, false, 0, true, | 1160 | int days_till_exp_crit); |
1183 | socket_timeout); | ||
1184 | } | ||
1185 | 1161 | ||
1186 | char *perfd_time_ssl(double elapsed_time_ssl, long socket_timeout) { | 1162 | mp_subcheck check_curl_certificate_checks(CURL *curl, X509 *cert, int warn_days_till_exp, |
1187 | return fperfdata("time_ssl", elapsed_time_ssl, "s", false, 0, false, 0, false, 0, true, | 1163 | int crit_days_till_exp) { |
1188 | socket_timeout); | 1164 | mp_subcheck sc_cert_result = mp_subcheck_init(); |
1189 | } | 1165 | sc_cert_result = mp_set_subcheck_default_state(sc_cert_result, STATE_OK); |
1190 | 1166 | ||
1191 | char *perfd_time_headers(double elapsed_time_headers, long socket_timeout) { | 1167 | #ifdef LIBCURL_FEATURE_SSL |
1192 | return fperfdata("time_headers", elapsed_time_headers, "s", false, 0, false, 0, false, 0, true, | 1168 | if (is_openssl_callback) { |
1193 | socket_timeout); | 1169 | # ifdef USE_OPENSSL |
1194 | } | 1170 | /* check certificate with OpenSSL functions, curl has been built against OpenSSL |
1171 | * and we actually have OpenSSL in the monitoring tools | ||
1172 | */ | ||
1173 | return np_net_ssl_check_certificate(cert, warn_days_till_exp, crit_days_till_exp); | ||
1174 | # else /* USE_OPENSSL */ | ||
1175 | xasprintf(&result.output, "HTTP CRITICAL - Cannot retrieve certificates - OpenSSL " | ||
1176 | "callback used and not linked against OpenSSL\n"); | ||
1177 | mp_set_subcheck_state(result, STATE_CRITICAL); | ||
1178 | # endif /* USE_OPENSSL */ | ||
1179 | } else { | ||
1180 | struct curl_slist *slist; | ||
1181 | |||
1182 | cert_ptr_union cert_ptr = {0}; | ||
1183 | cert_ptr.to_info = NULL; | ||
1184 | CURLcode res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &cert_ptr.to_info); | ||
1185 | if (!res && cert_ptr.to_info) { | ||
1186 | # ifdef USE_OPENSSL | ||
1187 | /* We have no OpenSSL in libcurl, but we can use OpenSSL for X509 cert | ||
1188 | * parsing We only check the first certificate and assume it's the one of | ||
1189 | * the server | ||
1190 | */ | ||
1191 | char *raw_cert = NULL; | ||
1192 | bool got_first_cert = false; | ||
1193 | for (int i = 0; i < cert_ptr.to_certinfo->num_of_certs; i++) { | ||
1194 | if (got_first_cert) { | ||
1195 | break; | ||
1196 | } | ||
1197 | |||
1198 | for (slist = cert_ptr.to_certinfo->certinfo[i]; slist; slist = slist->next) { | ||
1199 | if (verbose >= 2) { | ||
1200 | printf("%d ** %s\n", i, slist->data); | ||
1201 | } | ||
1202 | if (strncmp(slist->data, "Cert:", 5) == 0) { | ||
1203 | raw_cert = &slist->data[5]; | ||
1204 | got_first_cert = true; | ||
1205 | break; | ||
1206 | } | ||
1207 | } | ||
1208 | } | ||
1195 | 1209 | ||
1196 | char *perfd_time_firstbyte(double elapsed_time_firstbyte, long socket_timeout) { | 1210 | if (!raw_cert) { |
1197 | return fperfdata("time_firstbyte", elapsed_time_firstbyte, "s", false, 0, false, 0, false, 0, | ||
1198 | true, socket_timeout); | ||
1199 | } | ||
1200 | 1211 | ||
1201 | char *perfd_time_transfer(double elapsed_time_transfer, long socket_timeout) { | 1212 | xasprintf(&sc_cert_result.output, |
1202 | return fperfdata("time_transfer", elapsed_time_transfer, "s", false, 0, false, 0, false, 0, | 1213 | _("Cannot retrieve certificates from CERTINFO information - " |
1203 | true, socket_timeout); | 1214 | "certificate data was empty")); |
1204 | } | 1215 | sc_cert_result = mp_set_subcheck_state(sc_cert_result, STATE_CRITICAL); |
1216 | return sc_cert_result; | ||
1217 | } | ||
1218 | |||
1219 | BIO *cert_BIO = BIO_new(BIO_s_mem()); | ||
1220 | BIO_write(cert_BIO, raw_cert, (int)strlen(raw_cert)); | ||
1221 | |||
1222 | cert = PEM_read_bio_X509(cert_BIO, NULL, NULL, NULL); | ||
1223 | if (!cert) { | ||
1224 | xasprintf(&sc_cert_result.output, | ||
1225 | _("Cannot read certificate from CERTINFO information - BIO error")); | ||
1226 | sc_cert_result = mp_set_subcheck_state(sc_cert_result, STATE_CRITICAL); | ||
1227 | return sc_cert_result; | ||
1228 | } | ||
1205 | 1229 | ||
1206 | char *perfd_size(size_t page_len, int min_page_len) { | 1230 | BIO_free(cert_BIO); |
1207 | return perfdata("size", page_len, "B", (min_page_len > 0), min_page_len, (min_page_len > 0), 0, | 1231 | return np_net_ssl_check_certificate(cert, warn_days_till_exp, crit_days_till_exp); |
1208 | true, 0, false, 0); | 1232 | # else /* USE_OPENSSL */ |
1233 | /* We assume we don't have OpenSSL and np_net_ssl_check_certificate at our | ||
1234 | * disposal, so we use the libcurl CURLINFO data | ||
1235 | */ | ||
1236 | return net_noopenssl_check_certificate(&cert_ptr, days_till_exp_warn, | ||
1237 | days_till_exp_crit); | ||
1238 | # endif /* USE_OPENSSL */ | ||
1239 | } else { | ||
1240 | xasprintf(&sc_cert_result.output, | ||
1241 | _("Cannot retrieve certificates - cURL returned %d - %s"), res, | ||
1242 | curl_easy_strerror(res)); | ||
1243 | mp_set_subcheck_state(sc_cert_result, STATE_CRITICAL); | ||
1244 | } | ||
1245 | } | ||
1246 | #endif /* LIBCURL_FEATURE_SSL */ | ||
1247 | |||
1248 | return sc_cert_result; | ||
1209 | } | 1249 | } |
1210 | 1250 | ||
1211 | /* check whether a file exists */ | 1251 | char *fmt_url(check_curl_working_state workingState) { |
1212 | void test_file(char *path) { | 1252 | char *url = calloc(DEFAULT_BUFFER_SIZE, sizeof(char)); |
1213 | if (access(path, R_OK) == 0) { | 1253 | if (url == NULL) { |
1214 | return; | 1254 | die(STATE_UNKNOWN, "memory allocation failed"); |
1215 | } | 1255 | } |
1216 | usage2(_("file does not exist or is not readable"), path); | 1256 | |
1257 | snprintf(url, DEFAULT_BUFFER_SIZE, "%s://%s:%d%s", workingState.use_ssl ? "https" : "http", | ||
1258 | (workingState.use_ssl & (workingState.host_name != NULL)) | ||
1259 | ? workingState.host_name | ||
1260 | : workingState.server_address, | ||
1261 | workingState.serverPort, workingState.server_url); | ||
1262 | |||
1263 | return url; | ||
1217 | } | 1264 | } |
diff --git a/plugins/check_curl.d/check_curl_helpers.h b/plugins/check_curl.d/check_curl_helpers.h index 0f43ab90..87e45a9d 100644 --- a/plugins/check_curl.d/check_curl_helpers.h +++ b/plugins/check_curl.d/check_curl_helpers.h | |||
@@ -1,7 +1,11 @@ | |||
1 | #include "./config.h" | 1 | #include "./config.h" |
2 | #include <curl/curl.h> | 2 | #include <curl/curl.h> |
3 | #include "../picohttpparser/picohttpparser.h" | 3 | #include "../picohttpparser/picohttpparser.h" |
4 | // #include "curl/easy.h" | 4 | #include "output.h" |
5 | |||
6 | #if defined(HAVE_SSL) && defined(USE_OPENSSL) | ||
7 | # include <openssl/opensslv.h> | ||
8 | #endif | ||
5 | 9 | ||
6 | /* for buffers for header and body */ | 10 | /* for buffers for header and body */ |
7 | typedef struct { | 11 | typedef struct { |
@@ -99,8 +103,8 @@ int curlhelp_parse_statusline(const char * /*buf*/, curlhelp_statusline * /*stat | |||
99 | void curlhelp_free_statusline(curlhelp_statusline * /*status_line*/); | 103 | void curlhelp_free_statusline(curlhelp_statusline * /*status_line*/); |
100 | 104 | ||
101 | char *get_header_value(const struct phr_header *headers, size_t nof_headers, const char *header); | 105 | char *get_header_value(const struct phr_header *headers, size_t nof_headers, const char *header); |
102 | mp_state_enum check_document_dates(const curlhelp_write_curlbuf * /*header_buf*/, | 106 | mp_subcheck check_document_dates(const curlhelp_write_curlbuf * /*header_buf*/, |
103 | const char msg[static DEFAULT_BUFFER_SIZE], int /*maximum_age*/); | 107 | int /*maximum_age*/); |
104 | size_t get_content_length(const curlhelp_write_curlbuf *header_buf, | 108 | size_t get_content_length(const curlhelp_write_curlbuf *header_buf, |
105 | const curlhelp_write_curlbuf *body_buf); | 109 | const curlhelp_write_curlbuf *body_buf); |
106 | int lookup_host(const char *host, char *buf, size_t buflen, sa_family_t addr_family); | 110 | int lookup_host(const char *host, char *buf, size_t buflen, sa_family_t addr_family); |
@@ -114,12 +118,7 @@ void cleanup(check_curl_global_state global_state); | |||
114 | bool expected_statuscode(const char *reply, const char *statuscodes); | 118 | bool expected_statuscode(const char *reply, const char *statuscodes); |
115 | char *string_statuscode(int major, int minor); | 119 | char *string_statuscode(int major, int minor); |
116 | 120 | ||
117 | char *perfd_time(double elapsed_time, thresholds * /*thlds*/, long /*socket_timeout*/); | ||
118 | char *perfd_time_connect(double elapsed_time_connect, long /*socket_timeout*/); | ||
119 | char *perfd_time_ssl(double elapsed_time_ssl, long /*socket_timeout*/); | ||
120 | char *perfd_time_firstbyte(double elapsed_time_firstbyte, long /*socket_timeout*/); | ||
121 | char *perfd_time_headers(double elapsed_time_headers, long /*socket_timeout*/); | ||
122 | char *perfd_time_transfer(double elapsed_time_transfer, long /*socket_timeout*/); | ||
123 | char *perfd_size(size_t page_len, int /*min_page_len*/); | ||
124 | |||
125 | void test_file(char *path); | 121 | void test_file(char *path); |
122 | mp_subcheck check_curl_certificate_checks(CURL *curl, X509 *cert, int warn_days_till_exp, | ||
123 | int crit_days_till_exp); | ||
124 | char *fmt_url(check_curl_working_state workingState); | ||
diff --git a/plugins/check_curl.d/config.h b/plugins/check_curl.d/config.h index a4b1eecf..32399b8a 100644 --- a/plugins/check_curl.d/config.h +++ b/plugins/check_curl.d/config.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <string.h> | 8 | #include <string.h> |
9 | #include <sys/socket.h> | 9 | #include <sys/socket.h> |
10 | #include "curl/curl.h" | 10 | #include "curl/curl.h" |
11 | #include "perfdata.h" | ||
11 | #include "regex.h" | 12 | #include "regex.h" |
12 | 13 | ||
13 | enum { | 14 | enum { |
@@ -93,9 +94,9 @@ typedef struct { | |||
93 | bool continue_after_check_cert; | 94 | bool continue_after_check_cert; |
94 | int days_till_exp_warn; | 95 | int days_till_exp_warn; |
95 | int days_till_exp_crit; | 96 | int days_till_exp_crit; |
96 | thresholds *thlds; | 97 | mp_thresholds thlds; |
97 | size_t min_page_len; | 98 | mp_range page_length_limits; |
98 | size_t max_page_len; | 99 | bool page_length_limits_is_set; |
99 | struct { | 100 | struct { |
100 | char string[MAX_INPUT_BUFFER]; | 101 | char string[MAX_INPUT_BUFFER]; |
101 | bool is_present; | 102 | bool is_present; |