summaryrefslogtreecommitdiffstats
path: root/plugins/check_curl.c
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2017-04-18 21:14:54 +0200
committerSven Nierlein <sven@nierlein.de>2018-10-22 16:30:31 +0200
commit304e04a3849e00aa78327eb694e79487a3c8eaac (patch)
treeab32956feaa52009480d2769a593420474b4242c /plugins/check_curl.c
parent54c8f76c72ce73a9e0e23dbce26d09aa15e002ad (diff)
downloadmonitoring-plugins-304e04a3849e00aa78327eb694e79487a3c8eaac.tar.gz
some cleanup and added error handling around curl_easy_getinfo/curl_easy_setopt
Diffstat (limited to 'plugins/check_curl.c')
-rw-r--r--plugins/check_curl.c123
1 files changed, 64 insertions, 59 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index 5d3df9ee..f8c8832b 100644
--- a/plugins/check_curl.c
+++ b/plugins/check_curl.c
@@ -159,6 +159,7 @@ int maximum_age = -1;
159int address_family = AF_UNSPEC; 159int address_family = AF_UNSPEC;
160 160
161int process_arguments (int, char**); 161int process_arguments (int, char**);
162void handle_curl_option_return_code (CURLcode res, const char* option);
162int check_http (void); 163int check_http (void);
163void print_help (void); 164void print_help (void);
164void print_usage (void); 165void print_usage (void);
@@ -242,6 +243,16 @@ expected_statuscode (const char *reply, const char *statuscodes)
242 return result; 243 return result;
243} 244}
244 245
246void
247handle_curl_option_return_code (CURLcode res, const char* option)
248{
249 if (res != CURLE_OK) {
250 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Error while setting cURL option '%s': cURL returned %d - %s"),
251 res, curl_easy_strerror(res));
252 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
253 }
254}
255
245int 256int
246check_http (void) 257check_http (void)
247{ 258{
@@ -256,50 +267,50 @@ check_http (void)
256 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n"); 267 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n");
257 268
258 if (verbose >= 1) 269 if (verbose >= 1)
259 curl_easy_setopt (curl, CURLOPT_VERBOSE, TRUE); 270 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_VERBOSE, TRUE), "CURLOPT_VERBOSE");
260 271
261 /* print everything on stdout like check_http would do */ 272 /* print everything on stdout like check_http would do */
262 curl_easy_setopt(curl, CURLOPT_STDERR, stdout); 273 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_STDERR, stdout), "CURLOPT_STDERR");
263 274
264 /* initialize buffer for body of the answer */ 275 /* initialize buffer for body of the answer */
265 if (curlhelp_initwritebuffer(&body_buf) < 0) 276 if (curlhelp_initwritebuffer(&body_buf) < 0)
266 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n"); 277 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n");
267 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback); 278 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback), "CURLOPT_WRITEFUNCTION");
268 curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)&body_buf); 279 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)&body_buf), "CURLOPT_WRITEDATA");
269 280
270 /* initialize buffer for header of the answer */ 281 /* initialize buffer for header of the answer */
271 if (curlhelp_initwritebuffer( &header_buf ) < 0) 282 if (curlhelp_initwritebuffer( &header_buf ) < 0)
272 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n" ); 283 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n" );
273 curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback); 284 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, (curl_write_callback)curlhelp_buffer_write_callback), "CURLOPT_HEADERFUNCTION");
274 curl_easy_setopt (curl, CURLOPT_WRITEHEADER, (void *)&header_buf); 285 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_WRITEHEADER, (void *)&header_buf), "CURLOPT_WRITEHEADER");
275 286
276 /* set the error buffer */ 287 /* set the error buffer */
277 curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, errbuf); 288 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, errbuf), "CURLOPT_ERRORBUFFER");
278 289
279 /* set timeouts */ 290 /* set timeouts */
280 curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, socket_timeout); 291 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, socket_timeout), "CURLOPT_CONNECTTIMEOUT");
281 curl_easy_setopt (curl, CURLOPT_TIMEOUT, socket_timeout); 292 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_TIMEOUT, socket_timeout), "CURLOPT_TIMEOUT");
282 293
283 /* compose URL */ 294 /* compose URL */
284 snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s%s", use_ssl ? "https" : "http", 295 snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s%s", use_ssl ? "https" : "http",
285 server_address, server_url); 296 server_address, server_url);
286 curl_easy_setopt (curl, CURLOPT_URL, url); 297 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_URL, url), "CURLOPT_URL");
287 298
288 /* set port */ 299 /* set port */
289 curl_easy_setopt (curl, CURLOPT_PORT, server_port); 300 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_PORT, server_port), "CURLOPT_PORT");
290 301
291 /* set HTTP method */ 302 /* set HTTP method */
292 if (http_method) { 303 if (http_method) {
293 if (!strcmp(http_method, "POST")) 304 if (!strcmp(http_method, "POST"))
294 curl_easy_setopt (curl, CURLOPT_POST, 1); 305 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_POST, 1), "CURLOPT_POST");
295 else if (!strcmp(http_method, "PUT")) 306 else if (!strcmp(http_method, "PUT"))
296#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 12, 1) 307#if LIBCURL_VERSION_NUM >= MAKE_LIBCURL_VERSION(7, 12, 1)
297 curl_easy_setopt (curl, CURLOPT_UPLOAD, 1); 308 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_UPLOAD, 1), "CURLOPT_UPLOAD");
298#else 309#else
299 curl_easy_setopt (curl, CURLOPT_PUT, 1); 310 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_PUT, 1), "CURLOPT_PUT");
300#endif 311#endif
301 else 312 else
302 curl_easy_setopt (curl, CURLOPT_CUSTOMREQUEST, http_method); 313 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CUSTOMREQUEST, http_method), "CURLOPT_CUSTOMREQUEST");
303 } 314 }
304 315
305 /* set hostname (virtual hosts) */ 316 /* set hostname (virtual hosts) */
@@ -317,44 +328,44 @@ check_http (void)
317 header_list = curl_slist_append (header_list, http_header); 328 header_list = curl_slist_append (header_list, http_header);
318 329
319 /* set HTTP headers */ 330 /* set HTTP headers */
320 curl_easy_setopt( curl, CURLOPT_HTTPHEADER, header_list ); 331 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_HTTPHEADER, header_list ), "CURLOPT_HTTPHEADER");
321 332
322 /* set SSL version, warn about unsecure or unsupported versions */ 333 /* set SSL version, warn about unsecure or unsupported versions */
323 if (use_ssl) { 334 if (use_ssl) {
324 curl_easy_setopt (curl, CURLOPT_SSLVERSION, ssl_version); 335 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLVERSION, ssl_version), "CURLOPT_SSLVERSION");
325 } 336 }
326 337
327 /* client certificate and key to present to server (SSL) */ 338 /* client certificate and key to present to server (SSL) */
328 if (client_cert) 339 if (client_cert)
329 curl_easy_setopt (curl, CURLOPT_SSLCERT, client_cert); 340 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLCERT, client_cert), "CURLOPT_SSLCERT");
330 if (client_privkey) 341 if (client_privkey)
331 curl_easy_setopt (curl, CURLOPT_SSLKEY, client_privkey); 342 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSLKEY, client_privkey), "CURLOPT_SSLKEY");
332 if (ca_cert) 343 if (ca_cert) {
333 curl_easy_setopt (curl, CURLOPT_CAINFO, ca_cert); 344 /* per default if we have a CA verify both the peer and the
334 345 * hostname in the certificate, can be switched off later */
335 /* per default if we have a CA verify both the peer and the 346 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_CAINFO, ca_cert), "CURLOPT_CAINFO");
336 * hostname in the certificate, can be switched off later */ 347 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 2), "CURLOPT_SSL_VERIFYPEER");
337 curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 2); 348 handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_SSL_VERIFYHOST, 2), "CURLOPT_SSL_VERIFYHOST");
338 curl_easy_setopt( curl, CURLOPT_SSL_VERIFYHOST, 2); 349 } else {
339 350 /* backward-compatible behaviour, be tolerant in checks
340 /* backward-compatible behaviour, be tolerant in checks 351 * TODO: depending on more options have aspects we want
341 * TODO: depending on more options have aspects we want 352 * to be less tolerant about ssl verfications
342 * to be less tolerant about ssl verfications 353 */
343 */ 354 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0), "CURLOPT_SSL_VERIFYPEER");
344 curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0); 355 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0), "CURLOPT_SSL_VERIFYHOST");
345 curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0); 356 }
346 357
347 /* set callback to extract certificate */ 358 /* set callback to extract certificate */
348 if(check_cert) { 359 if(check_cert) {
349 curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun); 360 handle_curl_option_return_code (curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun), "CURLOPT_SSL_CTX_FUNCTION");
350 } 361 }
351 362
352 /* set default or user-given user agent identification */ 363 /* set default or user-given user agent identification */
353 curl_easy_setopt (curl, CURLOPT_USERAGENT, user_agent); 364 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_USERAGENT, user_agent), "CURLOPT_USERAGENT");
354 365
355 /* authentication */ 366 /* authentication */
356 if (strcmp(user_auth, "")) 367 if (strcmp(user_auth, ""))
357 curl_easy_setopt (curl, CURLOPT_USERPWD, user_auth); 368 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_USERPWD, user_auth), "CURLOPT_USERPWD");
358 369
359 /* TODO: parameter auth method, bitfield of following methods: 370 /* TODO: parameter auth method, bitfield of following methods:
360 * CURLAUTH_BASIC (default) 371 * CURLAUTH_BASIC (default)
@@ -368,17 +379,12 @@ check_http (void)
368 * CURLAUTH_ANYSAFE: most secure, without BASIC 379 * CURLAUTH_ANYSAFE: most secure, without BASIC
369 * or CURLAUTH_ANY: most secure, even BASIC if necessary 380 * or CURLAUTH_ANY: most secure, even BASIC if necessary
370 * 381 *
371 * curl_easy_setopt( curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_DIGEST ); 382 * handle_curl_option_return_code (curl_easy_setopt( curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_DIGEST ), "CURLOPT_HTTPAUTH");
372 */ 383 */
373 384
374 /* TODO: --cacert: CA certificate file to verify SSL connection against (SSL) */
375 /* if( args_info.cacert_given ) {
376 curl_easy_setopt( curl, CURLOPT_CAINFO, args_info.cacert_arg );
377 } */
378
379 /* handle redirections */ 385 /* handle redirections */
380 if (onredirect == STATE_DEPENDENT) { 386 if (onredirect == STATE_DEPENDENT) {
381 curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1); 387 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1), "CURLOPT_FOLLOWLOCATION");
382 /* TODO: handle the following aspects of redirection 388 /* TODO: handle the following aspects of redirection
383 CURLOPT_POSTREDIR: method switch 389 CURLOPT_POSTREDIR: method switch
384 CURLINFO_REDIRECT_URL: custom redirect option 390 CURLINFO_REDIRECT_URL: custom redirect option
@@ -389,15 +395,15 @@ check_http (void)
389 395
390 /* no-body */ 396 /* no-body */
391 if (no_body) 397 if (no_body)
392 curl_easy_setopt (curl, CURLOPT_NOBODY, 1); 398 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_NOBODY, 1), "CURLOPT_NOBODY");
393 399
394 /* IPv4 or IPv6 forced DNS resolution */ 400 /* IPv4 or IPv6 forced DNS resolution */
395 if (address_family == AF_UNSPEC) 401 if (address_family == AF_UNSPEC)
396 curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER); 402 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_WHATEVER), "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_WHATEVER)");
397 else if (address_family == AF_INET) 403 else if (address_family == AF_INET)
398 curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); 404 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4), "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V4)");
399 else if (address_family == AF_INET6) 405 else if (address_family == AF_INET6)
400 curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); 406 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6), "CURLOPT_IPRESOLVE(CURL_IPRESOLVE_V6)");
401 407
402 /* either send http POST data (any data, not only POST)*/ 408 /* either send http POST data (any data, not only POST)*/
403 if (!strcmp(http_method, "POST") ||!strcmp(http_method, "PUT")) { 409 if (!strcmp(http_method, "POST") ||!strcmp(http_method, "PUT")) {
@@ -412,12 +418,12 @@ check_http (void)
412 http_post_data = ""; 418 http_post_data = "";
413 if (!strcmp(http_method, "POST")) { 419 if (!strcmp(http_method, "POST")) {
414 /* POST method, set payload with CURLOPT_POSTFIELDS */ 420 /* POST method, set payload with CURLOPT_POSTFIELDS */
415 curl_easy_setopt (curl, CURLOPT_POSTFIELDS, http_post_data); 421 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_POSTFIELDS, http_post_data), "CURLOPT_POSTFIELDS");
416 } else if (!strcmp(http_method, "PUT")) { 422 } else if (!strcmp(http_method, "PUT")) {
417 curl_easy_setopt (curl, CURLOPT_READFUNCTION, (curl_read_callback)curlhelp_buffer_read_callback); 423 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_READFUNCTION, (curl_read_callback)curlhelp_buffer_read_callback), "CURLOPT_READFUNCTION");
418 curlhelp_initreadbuffer (&put_buf, http_post_data, strlen (http_post_data)); 424 curlhelp_initreadbuffer (&put_buf, http_post_data, strlen (http_post_data));
419 curl_easy_setopt (curl, CURLOPT_READDATA, (void *)&put_buf); 425 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_READDATA, (void *)&put_buf), "CURLOPT_READDATA");
420 curl_easy_setopt (curl, CURLOPT_INFILESIZE, (curl_off_t)strlen (http_post_data)); 426 handle_curl_option_return_code (curl_easy_setopt (curl, CURLOPT_INFILESIZE, (curl_off_t)strlen (http_post_data)), "CURLOPT_INFILESIZE");
421 } 427 }
422 } 428 }
423 429
@@ -432,7 +438,6 @@ check_http (void)
432 438
433 /* Curl errors, result in critical Nagios state */ 439 /* Curl errors, result in critical Nagios state */
434 if (res != CURLE_OK) { 440 if (res != CURLE_OK) {
435 remove_newlines (errbuf);
436 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"), 441 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: cURL returned %d - %s"),
437 server_port, res, curl_easy_strerror(res)); 442 server_port, res, curl_easy_strerror(res));
438 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 443 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
@@ -451,12 +456,12 @@ check_http (void)
451 /* we got the data and we executed the request in a given time, so we can append 456 /* we got the data and we executed the request in a given time, so we can append
452 * performance data to the answer always 457 * performance data to the answer always
453 */ 458 */
454 curl_easy_getinfo (curl, CURLINFO_TOTAL_TIME, &total_time); 459 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_TOTAL_TIME, &total_time), "CURLINFO_TOTAL_TIME");
455 if(show_extended_perfdata) { 460 if(show_extended_perfdata) {
456 curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &time_connect); 461 handle_curl_option_return_code (curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &time_connect), "CURLINFO_CONNECT_TIME");
457 curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, &time_appconnect); 462 handle_curl_option_return_code (curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, &time_appconnect), "CURLINFO_APPCONNECT_TIME");
458 curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &time_headers); 463 handle_curl_option_return_code (curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &time_headers), "CURLINFO_PRETRANSFER_TIME");
459 curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &time_firstbyte); 464 handle_curl_option_return_code (curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &time_firstbyte), "CURLINFO_STARTTRANSFER_TIME");
460 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "time=%.6gs;%.6g;%.6g;; size=%dB;;; time_connect=%.6gs;;;; %s time_headers=%.6gs;;;; time_firstbyte=%.6gs;;;; time_transfer=%.6gs;;;;", 465 snprintf(perfstring, DEFAULT_BUFFER_SIZE, "time=%.6gs;%.6g;%.6g;; size=%dB;;; time_connect=%.6gs;;;; %s time_headers=%.6gs;;;; time_firstbyte=%.6gs;;;; time_transfer=%.6gs;;;;",
461 total_time, 466 total_time,
462 warning_thresholds != NULL ? (double)thlds->warning->end : 0.0, 467 warning_thresholds != NULL ? (double)thlds->warning->end : 0.0,
@@ -489,7 +494,7 @@ check_http (void)
489 } 494 }
490 495
491 /* get result code from cURL */ 496 /* get result code from cURL */
492 curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &code); 497 handle_curl_option_return_code (curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &code), "CURLINFO_RESPONSE_CODE");
493 if (verbose>=2) 498 if (verbose>=2)
494 printf ("* curl CURLINFO_RESPONSE_CODE is %d\n", code); 499 printf ("* curl CURLINFO_RESPONSE_CODE is %d\n", code);
495 500