diff options
author | Andreas Baumann <abaumann@yahoo.com> | 2008-09-27 17:52:05 +0000 |
---|---|---|
committer | Andreas Baumann <abaumann@yahoo.com> | 2008-09-27 17:52:05 +0000 |
commit | 6b1b9863d8fccfe09c2f72c68e1ebfeea54efbe8 (patch) | |
tree | 0c4e761c5b5aad7010c210a4519a2a72760af55d /src/check_curl.c | |
parent | eedc9cd68aef078e4584e43d8055d70e1fa07351 (diff) | |
download | nagios-plugin-curl-6b1b9863d8fccfe09c2f72c68e1ebfeea54efbe8.tar.gz nagios-plugin-curl-6b1b9863d8fccfe09c2f72c68e1ebfeea54efbe8.tar.bz2 |
- added first runnig version
Diffstat (limited to 'src/check_curl.c')
-rw-r--r-- | src/check_curl.c | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/src/check_curl.c b/src/check_curl.c new file mode 100644 index 0000000..556cd92 --- /dev/null +++ b/src/check_curl.c @@ -0,0 +1,274 @@ +/* + check_curl - Nagios Curl-based check plugin + Copyright (C) 2008 Andreas Baumann + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <curl/curl.h> +#include <curl/types.h> +#include <curl/easy.h> + +#include "cmdline.h" + +#include "common.h" +#include "curlhelper.h" + +#define DEFAULT_TIMEOUT (double)10.0 + +int main( int argc, char *argv[] ) { + struct gengetopt_args_info args_info; + curlhelp_curlbuf body_buf; + curlhelp_curlbuf header_buf; + CURL *curl; + char b[2048]; + CURLcode res; + char errbuf[CURL_ERROR_SIZE+1]; + struct curl_slist *header_list = NULL; + long code; + double total_time; + const char *level_str = "OK"; + int exit_state = STATE_OK; + char perfstring[1024]; + curlhelp_statusline status_line; + + cmdline_parser_init( &args_info ); + + /* read command line arguments (to get the name of the configuration file, + * do it without checking for required arguments + */ + if( cmdline_parser2( argc, argv, &args_info, 0, 0, 0 ) != 0 ) { + printf( "HTTP CRITICAL - unable to parse arguments\n" ); + fprintf( stderr, "\n%s\n", gengetopt_args_info_usage ); + cmdline_parser_free( &args_info ); + exit( STATE_UNKNOWN ); + } + + if( args_info.config_file_given ) { + /* read command line options from file, allow override of configuration + * options from the command line and check for required options + */ + if( cmdline_parser_configfile( args_info.config_file_arg, &args_info, 1, 0, 1 ) != 0 ) { + printf( "HTTP CRITICAL - unable to read '%s'\n", args_info.config_file_arg ); + fprintf( stderr, "\n%s\n", gengetopt_args_info_usage ); + cmdline_parser_free( &args_info ); + exit( STATE_UNKNOWN ); + } + } else { + /* read command line options again, this time checking for required options */ + if( cmdline_parser2( argc, argv, &args_info, 1, 0, 1 ) != 0 ) { + printf( "HTTP CRITICAL - illegal arguments, check help page\n" ); + fprintf( stderr, "\n%s\n", gengetopt_args_info_usage ); + cmdline_parser_free( &args_info ); + exit( STATE_UNKNOWN ); + } + } + + /* start up curl */ + if( curl_global_init( CURL_GLOBAL_ALL ) != CURLE_OK ) { + printf( "HTTP CRITICAL - curl_global_init failed!\n" ); + cmdline_parser_free( &args_info ); + exit( STATE_UNKNOWN ); + } + if( ( curl = curl_easy_init( ) ) == NULL ) { + printf( "HTTP CRITICAL - curl_easy_init failed!\n" ); + cmdline_parser_free( &args_info ); + curl_global_cleanup( ); + exit( STATE_UNKNOWN ); + } + + /* -v: verbosity */ + curl_easy_setopt( curl, CURLOPT_VERBOSE, args_info.verbose_given ); + + /* initialize buffer for body of the answer */ + if( curlhelp_initbuffer( &body_buf ) < 0 ) { + printf( "HTTP CRITICAL - out of memory allocating a buffer\n" ); + cmdline_parser_free( &args_info ); + curl_global_cleanup( ); + exit( STATE_UNKNOWN ); + } + curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, curlhelp_buffer_callback ); + curl_easy_setopt( curl, CURLOPT_WRITEDATA, (void *)&body_buf ); + + /* initialize buffer for header of the answer */ + if( curlhelp_initbuffer( &header_buf ) < 0 ) { + printf( "HTTP CRITICAL - out of memory allocating a buffer\n" ); + curlhelp_freebuffer( &body_buf ); + cmdline_parser_free( &args_info ); + curl_global_cleanup( ); + exit( STATE_UNKNOWN ); + } + curl_easy_setopt( curl, CURLOPT_HEADERFUNCTION, curlhelp_buffer_callback ); + curl_easy_setopt( curl, CURLOPT_WRITEHEADER , (void *)&header_buf ); + + /* authentication */ + if( args_info.authorization_given ) + curl_easy_setopt( curl, CURLOPT_USERPWD, args_info.authorization_arg ); + + /* compose URL */ + snprintf( b, 2048, "http%s://%s%s", + args_info.ssl_given ? "s" : "", + args_info.ip_arg, + args_info.url_given ? args_info.url_arg : "/" ); + curl_easy_setopt( curl, CURLOPT_URL, b ); + + /* set port */ + if( args_info.port_given ) + curl_easy_setopt( curl, CURLOPT_PORT, args_info.port_arg ); + + /* compose HTTP headers */ +#if 0 /* FIXME: doesn't work with curl 7.15.2 (Centos 5.2)!! Check out why */ + if( args_info.host_given ) { + snprintf( b, 2048, "Host: %s", args_info.host_arg ); + header_list = curl_slist_append( header_list, b ); + } + curl_easy_setopt( curl, CURLOPT_HTTPHEADER, header_list ); +#endif + + /* set the error buffer */ + curl_easy_setopt( curl, CURLOPT_ERRORBUFFER, errbuf ); + + /* set timeouts */ + { + long timeout; + + if( args_info.timeout_given ) + timeout = args_info.timeout_arg; + else + timeout = DEFAULT_TIMEOUT; + + curl_easy_setopt( curl, CURLOPT_CONNECTTIMEOUT, timeout ); + curl_easy_setopt( curl, CURLOPT_TIMEOUT, timeout ); + } + + /* do the request */ + res = curl_easy_perform( curl ); + + /* terminate buffer, print it if verbose */ + if( args_info.verbose_given ) { + puts( "--- HEADER ---" ); + puts( header_buf.buf ); + } + if( args_info.verbose_given ) { + puts( "--- BODY ---" ); + puts( body_buf.buf ); + } + + /* free header list, we don't need it anymore */ + curl_slist_free_all( header_list ); + + /* Curl errors, result in critical Nagios state */ + if( res != CURLE_OK ) { + printf( "HTTP CRITICAL - %s (error: %d)\n", errbuf, res ); + curlhelp_freebuffer( &body_buf ); + curlhelp_freebuffer( &header_buf ); + curl_easy_cleanup( curl ); + curl_global_cleanup( ); + exit( STATE_CRITICAL ); + } + + /* we got the data and we executed the request in a given time, so we can append + * performance data to the answer always + */ + curl_easy_getinfo( curl, CURLINFO_TOTAL_TIME, &total_time ); + snprintf( perfstring, 1024, "time=%.6gs;%.6g;%.6g;%.6g size=%dB;;;0", + total_time, + args_info.warning_given ? args_info.warning_arg : 0.0, + args_info.critical_given ? args_info.critical_arg : 0.0, + 0.0, + body_buf.buflen ); + + /* -s: check if the excepted string matches */ + if( args_info.string_given ) { + if( strstr( body_buf.buf, args_info.string_arg ) == NULL ) { + printf( "HTTP CRITICAL - string not found|%s\n", perfstring ); + curlhelp_freebuffer( &body_buf ); + curlhelp_freebuffer( &header_buf ); + curl_easy_cleanup( curl ); + curl_global_cleanup( ); + exit( STATE_CRITICAL ); + } + } + + /* -w, -c: check warning and critical level */ + if( args_info.critical_given && ( total_time > args_info.critical_arg ) ) { + level_str = "CRITICAL"; + exit_state = STATE_CRITICAL; + } + if( !( exit_state == STATE_CRITICAL ) && args_info.warning_given && ( total_time > args_info.warning_arg ) ) { + level_str = "WARNING"; + exit_state = STATE_WARNING; + } + + /* get status line of answer, check sanity of HTTP code */ + if( curlhelp_parse_statusline( header_buf.buf, &status_line ) < 0 ) { + printf( "HTTP CRITICAL HTTP/1.x %ld unknown - Unparseable status line in %.3g seconds response time|%s\n", + code, total_time, perfstring ); + curlhelp_freebuffer( &body_buf ); + curlhelp_freebuffer( &header_buf ); + curl_easy_cleanup( curl ); + curl_global_cleanup( ); + exit( STATE_CRITICAL ); + } + curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &code ); + if( status_line.http_code != code ) { + printf( "HTTP CRITICAL HTTP/%d.%d %d %s - different HTTP codes (cUrl has %ld) in %.3g seconds response time|%s\n", + status_line.http_major, status_line.http_minor, + status_line.http_code, status_line.msg, code, + total_time, perfstring ); + curlhelp_free_statusline( &status_line ); + curlhelp_freebuffer( &body_buf ); + curlhelp_freebuffer( &header_buf ); + curl_easy_cleanup( curl ); + curl_global_cleanup( ); + exit( STATE_CRITICAL ); + } + + /* check status codes, set exit status accordingly */ + if( code >= 600 || code <= 100 ) { + printf( "HTTP CRITICAL HTTP/%d.%d %d %s - Illegal status code (status line: %.40s)\n", + status_line.http_major, status_line.http_minor, + status_line.http_code, status_line.msg, + status_line.first_line ); + curlhelp_free_statusline( &status_line ); + curlhelp_freebuffer( &body_buf ); + curlhelp_freebuffer( &header_buf ); + curl_easy_cleanup( curl ); + curl_global_cleanup( ); + exit( STATE_CRITICAL ); + } + if( code >= 500 ) { + level_str = "CRITICAL"; + exit_state = STATE_CRITICAL; + } else if( code >= 400 ) { + level_str = "WARNING"; + exit_state = STATE_WARNING; + } + + printf( "HTTP %s HTTP/%d.%d %d %s - %.3g seconds response time|%s\n", + level_str, status_line.http_major, status_line.http_minor, + status_line.http_code, status_line.msg, + total_time, perfstring ); + + curlhelp_free_statusline( &status_line ); + curlhelp_freebuffer( &body_buf ); + curlhelp_freebuffer( &header_buf ); + curl_easy_cleanup( curl ); + curl_global_cleanup( ); + exit( exit_state ); +} |