summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/check_curl.c1162
1 files changed, 574 insertions, 588 deletions
diff --git a/plugins/check_curl.c b/plugins/check_curl.c
index 8ef48d0..8ed1aee 100644
--- a/plugins/check_curl.c
+++ b/plugins/check_curl.c
@@ -13,7 +13,7 @@
13* normal (http) and secure (https) servers, follow redirects, search for 13* normal (http) and secure (https) servers, follow redirects, search for
14* strings and regular expressions, check connection times, and report on 14* strings and regular expressions, check connection times, and report on
15* certificate expiration times. 15* certificate expiration times.
16* 16*
17* This plugin uses functions from the curl library, see 17* This plugin uses functions from the curl library, see
18* http://curl.haxx.se 18* http://curl.haxx.se
19* 19*
@@ -40,20 +40,6 @@ const char *email = "devel@monitoring-plugins.org";
40#include "common.h" 40#include "common.h"
41#include "utils.h" 41#include "utils.h"
42 42
43#ifdef HAVE_SYS_TYPES_H
44#include <sys/types.h>
45#else
46#define unsigned int size_t
47#endif
48
49#ifdef HAVE_STRING_H
50#include <string.h>
51#endif
52
53#ifdef HAVE_STDLIB_H
54#include <stdlib.h>
55#endif
56
57#ifndef LIBCURL_PROTOCOL_HTTP 43#ifndef LIBCURL_PROTOCOL_HTTP
58#error libcurl compiled without HTTP support, compiling check_curl plugin makes not much sense 44#error libcurl compiled without HTTP support, compiling check_curl plugin makes not much sense
59#endif 45#endif
@@ -69,21 +55,21 @@ const char *email = "devel@monitoring-plugins.org";
69 55
70/* for buffers for header and body */ 56/* for buffers for header and body */
71typedef struct { 57typedef struct {
72 char *buf; 58 char *buf;
73 size_t buflen; 59 size_t buflen;
74 size_t bufsize; 60 size_t bufsize;
75} curlhelp_curlbuf; 61} curlhelp_curlbuf;
76 62
77/* for parsing the HTTP status line */ 63/* for parsing the HTTP status line */
78typedef struct { 64typedef struct {
79 int http_major; /* major version of the protocol, always 1 (HTTP/0.9 65 int http_major; /* major version of the protocol, always 1 (HTTP/0.9
80 * never reached the big internet most likely) */ 66 * never reached the big internet most likely) */
81 int http_minor; /* minor version of the protocol, usually 0 or 1 */ 67 int http_minor; /* minor version of the protocol, usually 0 or 1 */
82 int http_code; /* HTTP return code as in RFC 2145 */ 68 int http_code; /* HTTP return code as in RFC 2145 */
83 int http_subcode; /* Microsoft IIS extension, HTTP subcodes, see 69 int http_subcode; /* Microsoft IIS extension, HTTP subcodes, see
84 * http://support.microsoft.com/kb/318380/en-us */ 70 * http://support.microsoft.com/kb/318380/en-us */
85 char *msg; /* the human readable message */ 71 char *msg; /* the human readable message */
86 char *first_line; /* a copy of the first line */ 72 char *first_line; /* a copy of the first line */
87} curlhelp_statusline; 73} curlhelp_statusline;
88 74
89char *server_address; 75char *server_address;
@@ -137,587 +123,587 @@ void test_file (char *);
137int 123int
138main (int argc, char **argv) 124main (int argc, char **argv)
139{ 125{
140 int result = STATE_OK; 126 int result = STATE_OK;
141 127
142 setlocale (LC_ALL, ""); 128 setlocale (LC_ALL, "");
143 bindtextdomain (PACKAGE, LOCALEDIR); 129 bindtextdomain (PACKAGE, LOCALEDIR);
144 textdomain (PACKAGE); 130 textdomain (PACKAGE);
145 131
146 /* Parse extra opts if any */ 132 /* Parse extra opts if any */
147 argv = np_extra_opts (&argc, argv, progname); 133 argv = np_extra_opts (&argc, argv, progname);
148 134
149 /* set defaults */ 135 /* set defaults */
150 snprintf( user_agent, DEFAULT_BUFFER_SIZE, "%s/v%s (monitoring-plugins %s)", 136 snprintf( user_agent, DEFAULT_BUFFER_SIZE, "%s/v%s (monitoring-plugins %s)",
151 progname, NP_VERSION, VERSION); 137 progname, NP_VERSION, VERSION);
152 138
153 /* parse arguments */ 139 /* parse arguments */
154 if (process_arguments (argc, argv) == ERROR) 140 if (process_arguments (argc, argv) == ERROR)
155 usage4 (_("Could not parse arguments")); 141 usage4 (_("Could not parse arguments"));
156 142
157 /* initialize curl */ 143 /* initialize curl */
158 if (curl_global_init (CURL_GLOBAL_DEFAULT) != CURLE_OK) 144 if (curl_global_init (CURL_GLOBAL_DEFAULT) != CURLE_OK)
159 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n"); 145 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_global_init failed\n");
160 146
161 if ((curl = curl_easy_init()) == NULL) 147 if ((curl = curl_easy_init()) == NULL)
162 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n"); 148 die (STATE_UNKNOWN, "HTTP UNKNOWN - curl_easy_init failed\n");
163 149
164 if (verbose >= 3) 150 if (verbose >= 3)
165 curl_easy_setopt (curl, CURLOPT_VERBOSE, TRUE); 151 curl_easy_setopt (curl, CURLOPT_VERBOSE, TRUE);
166 152
167 /* initialize buffer for body of the answer */ 153 /* initialize buffer for body of the answer */
168 if (curlhelp_initbuffer(&body_buf) < 0) 154 if (curlhelp_initbuffer(&body_buf) < 0)
169 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n"); 155 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for body\n");
170 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, curlhelp_buffer_callback); 156 curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, curlhelp_buffer_callback);
171 curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)&body_buf); 157 curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)&body_buf);
172 158
173 /* initialize buffer for header of the answer */ 159 /* initialize buffer for header of the answer */
174 if (curlhelp_initbuffer( &header_buf ) < 0) 160 if (curlhelp_initbuffer( &header_buf ) < 0)
175 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n" ); 161 die (STATE_UNKNOWN, "HTTP CRITICAL - out of memory allocating buffer for header\n" );
176 curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, curlhelp_buffer_callback); 162 curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, curlhelp_buffer_callback);
177 curl_easy_setopt (curl, CURLOPT_WRITEHEADER, (void *)&header_buf); 163 curl_easy_setopt (curl, CURLOPT_WRITEHEADER, (void *)&header_buf);
178 164
179 /* set the error buffer */ 165 /* set the error buffer */
180 curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, errbuf); 166 curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, errbuf);
181 167
182 /* set timeouts */ 168 /* set timeouts */
183 curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, socket_timeout); 169 curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, socket_timeout);
184 curl_easy_setopt (curl, CURLOPT_TIMEOUT, socket_timeout); 170 curl_easy_setopt (curl, CURLOPT_TIMEOUT, socket_timeout);
185 171
186 /* compose URL */ 172 /* compose URL */
187 snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s%s", use_ssl ? "https" : "http", 173 snprintf (url, DEFAULT_BUFFER_SIZE, "%s://%s%s", use_ssl ? "https" : "http",
188 server_address, server_url); 174 server_address, server_url);
189 curl_easy_setopt (curl, CURLOPT_URL, url); 175 curl_easy_setopt (curl, CURLOPT_URL, url);
190 176
191 /* set port */ 177 /* set port */
192 curl_easy_setopt (curl, CURLOPT_PORT, server_port); 178 curl_easy_setopt (curl, CURLOPT_PORT, server_port);
193 179
194 /* compose HTTP headers */ 180 /* compose HTTP headers */
195 snprintf (http_header, DEFAULT_BUFFER_SIZE, "Host: %s", host_name); 181 snprintf (http_header, DEFAULT_BUFFER_SIZE, "Host: %s", host_name);
196 header_list = curl_slist_append (header_list, http_header); 182 header_list = curl_slist_append (header_list, http_header);
197 curl_easy_setopt( curl, CURLOPT_HTTPHEADER, header_list ); 183 curl_easy_setopt( curl, CURLOPT_HTTPHEADER, header_list );
198 184
199 /* set SSL version, warn about unsecure or unsupported versions */ 185 /* set SSL version, warn about unsecure or unsupported versions */
200 if (use_ssl) { 186 if (use_ssl) {
201 curl_easy_setopt (curl, CURLOPT_SSLVERSION, ssl_version); 187 curl_easy_setopt (curl, CURLOPT_SSLVERSION, ssl_version);
202 } 188 }
203 189
204 /* client certificate and key to present to server (SSL) */ 190 /* client certificate and key to present to server (SSL) */
205 if (client_cert) 191 if (client_cert)
206 curl_easy_setopt (curl, CURLOPT_SSLCERT, client_cert); 192 curl_easy_setopt (curl, CURLOPT_SSLCERT, client_cert);
207 if (client_privkey) 193 if (client_privkey)
208 curl_easy_setopt (curl, CURLOPT_SSLKEY, client_privkey); 194 curl_easy_setopt (curl, CURLOPT_SSLKEY, client_privkey);
209 195
210 /* per default if we have a CA verify both the peer and the 196 /* per default if we have a CA verify both the peer and the
211 * hostname in the certificate, can be switched off later */ 197 * hostname in the certificate, can be switched off later */
212 curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 2); 198 curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 2);
213 curl_easy_setopt( curl, CURLOPT_SSL_VERIFYHOST, 2); 199 curl_easy_setopt( curl, CURLOPT_SSL_VERIFYHOST, 2);
214 200
215 /* backward-compatible behaviour, be tolerant in checks */ 201 /* backward-compatible behaviour, be tolerant in checks */
216 if (!check_cert) { 202 if (!check_cert) {
217 //TODO: depending on more options have aspects we want 203 //TODO: depending on more options have aspects we want
218 //to be tolerant about 204 //to be tolerant about
219 //curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 1 ); 205 //curl_easy_setopt( curl, CURLOPT_SSL_VERIFYPEER, 1 );
220 curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0); 206 curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 0);
221 curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0); 207 curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 0);
222 } 208 }
223 209
224 /* set default or user-given user agent identification */ 210 /* set default or user-given user agent identification */
225 curl_easy_setopt (curl, CURLOPT_USERAGENT, user_agent); 211 curl_easy_setopt (curl, CURLOPT_USERAGENT, user_agent);
226 212
227 /* authentication */ 213 /* authentication */
228 if (strcmp(user_auth, "")) 214 if (strcmp(user_auth, ""))
229 curl_easy_setopt (curl, CURLOPT_USERPWD, user_auth); 215 curl_easy_setopt (curl, CURLOPT_USERPWD, user_auth);
230 216
231 /* TODO: parameter auth method, bitfield of following methods: 217 /* TODO: parameter auth method, bitfield of following methods:
232 * CURLAUTH_BASIC (default) 218 * CURLAUTH_BASIC (default)
233 * CURLAUTH_DIGEST 219 * CURLAUTH_DIGEST
234 * CURLAUTH_DIGEST_IE 220 * CURLAUTH_DIGEST_IE
235 * CURLAUTH_NEGOTIATE 221 * CURLAUTH_NEGOTIATE
236 * CURLAUTH_NTLM 222 * CURLAUTH_NTLM
237 * CURLAUTH_NTLM_WB 223 * CURLAUTH_NTLM_WB
238 * 224 *
239 * convenience tokens for typical sets of methods: 225 * convenience tokens for typical sets of methods:
240 * CURLAUTH_ANYSAFE: most secure, without BASIC 226 * CURLAUTH_ANYSAFE: most secure, without BASIC
241 * or CURLAUTH_ANY: most secure, even BASIC if necessary 227 * or CURLAUTH_ANY: most secure, even BASIC if necessary
242 * 228 *
243 * curl_easy_setopt( curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_DIGEST ); 229 * curl_easy_setopt( curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_DIGEST );
244 */ 230 */
245 231
246 /* TODO: --cacert: CA certificate file to verify SSL connection against (SSL) */ 232 /* TODO: --cacert: CA certificate file to verify SSL connection against (SSL) */
247 //~ if( args_info.cacert_given ) { 233 //~ if( args_info.cacert_given ) {
248 //~ curl_easy_setopt( curl, CURLOPT_CAINFO, args_info.cacert_arg ); 234 //~ curl_easy_setopt( curl, CURLOPT_CAINFO, args_info.cacert_arg );
249 //~ } 235 //~ }
250 236
251 /* handle redirections */ 237 /* handle redirections */
252 if (onredirect == STATE_DEPENDENT) { 238 if (onredirect == STATE_DEPENDENT) {
253 curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1); 239 curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1);
254 /* TODO: handle the following aspects of redirection 240 /* TODO: handle the following aspects of redirection
255 CURLOPT_POSTREDIR: method switch 241 CURLOPT_POSTREDIR: method switch
256 CURLINFO_REDIRECT_URL: custom redirect option 242 CURLINFO_REDIRECT_URL: custom redirect option
257 CURLOPT_REDIRECT_PROTOCOLS 243 CURLOPT_REDIRECT_PROTOCOLS
258 CURLINFO_REDIRECT_COUNT 244 CURLINFO_REDIRECT_COUNT
259 */ 245 */
260 } 246 }
261 247
262 /* do the request */ 248 /* do the request */
263 res = curl_easy_perform(curl); 249 res = curl_easy_perform(curl);
264 250
265 /* free header list, we don't need it anymore */ 251 /* free header list, we don't need it anymore */
266 curl_slist_free_all (header_list); 252 curl_slist_free_all (header_list);
267 253
268 /* Curl errors, result in critical Nagios state */ 254 /* Curl errors, result in critical Nagios state */
269 if (res != CURLE_OK) { 255 if (res != CURLE_OK) {
270 remove_newlines (errbuf); 256 remove_newlines (errbuf);
271 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: cURL returned %d - %s\n"), 257 snprintf (msg, DEFAULT_BUFFER_SIZE, _("Invalid HTTP response received from host on port %d: cURL returned %d - %s\n"),
272 server_port, res, curl_easy_strerror(res)); 258 server_port, res, curl_easy_strerror(res));
273 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg); 259 die (STATE_CRITICAL, "HTTP CRITICAL - %s\n", msg);
274 } 260 }
275 261
276 /* we got the data and we executed the request in a given time, so we can append 262 /* we got the data and we executed the request in a given time, so we can append
277 * performance data to the answer always 263 * performance data to the answer always
278 */ 264 */
279 curl_easy_getinfo (curl, CURLINFO_TOTAL_TIME, &total_time); 265 curl_easy_getinfo (curl, CURLINFO_TOTAL_TIME, &total_time);
280 snprintf (perfstring, DEFAULT_BUFFER_SIZE, "time=%.6gs;%.6g;%.6g;%.6g size=%dB;;;0", 266 snprintf (perfstring, DEFAULT_BUFFER_SIZE, "time=%.6gs;%.6g;%.6g;%.6g size=%dB;;;0",
281 total_time, 267 total_time,
282 0.0, 0.0, 268 0.0, 0.0,
283 //~ args_info.warning_given ? args_info.warning_arg : 0.0, 269 //~ args_info.warning_given ? args_info.warning_arg : 0.0,
284 //~ args_info.critical_given ? args_info.critical_arg : 0.0, 270 //~ args_info.critical_given ? args_info.critical_arg : 0.0,
285 0.0, 271 0.0,
286 (int)body_buf.buflen); 272 (int)body_buf.buflen);
287 273
288 /* return a CRITICAL status if we couldn't read any data */ 274 /* return a CRITICAL status if we couldn't read any data */
289 if (strlen(header_buf.buf) == 0 && strlen(body_buf.buf) == 0) 275 if (strlen(header_buf.buf) == 0 && strlen(body_buf.buf) == 0)
290 die (STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n")); 276 die (STATE_CRITICAL, _("HTTP CRITICAL - No header received from host\n"));
291 277
292 /* get status line of answer, check sanity of HTTP code */ 278 /* get status line of answer, check sanity of HTTP code */
293 if (curlhelp_parse_statusline (header_buf.buf, &status_line) < 0) { 279 if (curlhelp_parse_statusline (header_buf.buf, &status_line) < 0) {
294 snprintf (msg, DEFAULT_BUFFER_SIZE, "Unparseable status line in %.3g seconds response time|%s\n", 280 snprintf (msg, DEFAULT_BUFFER_SIZE, "Unparseable status line in %.3g seconds response time|%s\n",
295 code, total_time, perfstring); 281 code, total_time, perfstring);
296 die (STATE_CRITICAL, "HTTP CRITICAL HTTP/1.x %d unknown - %s", code, msg); 282 die (STATE_CRITICAL, "HTTP CRITICAL HTTP/1.x %d unknown - %s", code, msg);
297 } 283 }
298 284
299 /* get result code from cURL */ 285 /* get result code from cURL */
300 curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &code); 286 curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &code);
301 if (verbose>=2) 287 if (verbose>=2)
302 printf ("* curl CURLINFO_RESPONSE_CODE is %d\n", code); 288 printf ("* curl CURLINFO_RESPONSE_CODE is %d\n", code);
303 289
304 /* print status line, header, body if verbose */ 290 /* print status line, header, body if verbose */
305 if (verbose >= 2) { 291 if (verbose >= 2) {
306 puts ("--- HEADER ---"); 292 puts ("--- HEADER ---");
307 puts (header_buf.buf); 293 puts (header_buf.buf);
308 puts ("--- BODY ---"); 294 puts ("--- BODY ---");
309 puts (body_buf.buf); 295 puts (body_buf.buf);
310 } 296 }
311 297
312 /* illegal return codes result in a critical state */ 298 /* illegal return codes result in a critical state */
313 if (code >= 600 || code < 100) { 299 if (code >= 600 || code < 100) {
314 die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"), status_line.http_code, status_line.msg); 300 die (STATE_CRITICAL, _("HTTP CRITICAL: Invalid Status (%d, %.40s)\n"), status_line.http_code, status_line.msg);
315 /* server errors result in a critical state */ 301 /* server errors result in a critical state */
316 } else if (code >= 500) { 302 } else if (code >= 500) {
317 result = STATE_CRITICAL; 303 result = STATE_CRITICAL;
318 /* client errors result in a warning state */ 304 /* client errors result in a warning state */
319 } else if (code >= 400) { 305 } else if (code >= 400) {
320 result = STATE_WARNING; 306 result = STATE_WARNING;
321 /* check redirected page if specified */ 307 /* check redirected page if specified */
322 } else if (code >= 300) { 308 } else if (code >= 300) {
323 if (onredirect == STATE_DEPENDENT) { 309 if (onredirect == STATE_DEPENDENT) {
324 code = status_line.http_code; 310 code = status_line.http_code;
325 } 311 }
326 result = max_state_alt (onredirect, result); 312 result = max_state_alt (onredirect, result);
327 /* TODO: make sure the last status line has been 313 /* TODO: make sure the last status line has been
328 parsed into the status_line structure 314 parsed into the status_line structure
329 */ 315 */
330 /* all other codes are considered ok */ 316 /* all other codes are considered ok */
331 } else { 317 } else {
332 result = STATE_OK; 318 result = STATE_OK;
333 } 319 }
334 320
335 /* check status codes, set exit status accordingly */ 321 /* check status codes, set exit status accordingly */
336 if( status_line.http_code != code ) { 322 if( status_line.http_code != code ) {
337 die (STATE_CRITICAL, _("HTTP CRITICAL HTTP/%d.%d %d %s - different HTTP codes (cUrl has %ld)\n"), 323 die (STATE_CRITICAL, _("HTTP CRITICAL HTTP/%d.%d %d %s - different HTTP codes (cUrl has %ld)\n"),
338 status_line.http_major, status_line.http_minor, 324 status_line.http_major, status_line.http_minor,
339 status_line.http_code, status_line.msg, code); 325 status_line.http_code, status_line.msg, code);
340 } 326 }
341 327
342 /* Page and Header content checks go here */ 328 /* Page and Header content checks go here */
343 if (strlen (string_expect)) { 329 if (strlen (string_expect)) {
344 if (!strstr (body_buf.buf, string_expect)) { 330 if (!strstr (body_buf.buf, string_expect)) {
345 strncpy(&output_string_search[0],string_expect,sizeof(output_string_search)); 331 strncpy(&output_string_search[0],string_expect,sizeof(output_string_search));
346 if(output_string_search[sizeof(output_string_search)-1]!='\0') { 332 if(output_string_search[sizeof(output_string_search)-1]!='\0') {
347 bcopy("...",&output_string_search[sizeof(output_string_search)-4],4); 333 bcopy("...",&output_string_search[sizeof(output_string_search)-4],4);
348 } 334 }
349 snprintf (msg, DEFAULT_BUFFER_SIZE, _("%sstring '%s' not found on '%s://%s:%d%s', "), msg, output_string_search, use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url); 335 snprintf (msg, DEFAULT_BUFFER_SIZE, _("%sstring '%s' not found on '%s://%s:%d%s', "), msg, output_string_search, use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url);
350 result = STATE_CRITICAL; 336 result = STATE_CRITICAL;
351 } 337 }
352 } 338 }
353 339
354 /* -w, -c: check warning and critical level */ 340 /* -w, -c: check warning and critical level */
355 result = max_state_alt(get_status(total_time, thlds), result); 341 result = max_state_alt(get_status(total_time, thlds), result);
356 342
357 //~ die (result, "HTTP %s: %s\n", state_text(result), msg); 343 //~ die (result, "HTTP %s: %s\n", state_text(result), msg);
358 die (result, "HTTP %s HTTP/%d.%d %d %s - %s - %.3g seconds response time|%s\n", 344 die (result, "HTTP %s HTTP/%d.%d %d %s - %s - %.3g seconds response time|%s\n",
359 state_text(result), status_line.http_major, status_line.http_minor, 345 state_text(result), status_line.http_major, status_line.http_minor,
360 status_line.http_code, status_line.msg, msg, 346 status_line.http_code, status_line.msg, msg,
361 total_time, perfstring); 347 total_time, perfstring);
362 348
363 /* proper cleanup after die? */ 349 /* proper cleanup after die? */
364 curlhelp_free_statusline(&status_line); 350 curlhelp_free_statusline(&status_line);
365 curl_easy_cleanup (curl); 351 curl_easy_cleanup (curl);
366 curl_global_cleanup (); 352 curl_global_cleanup ();
367 curlhelp_freebuffer(&body_buf); 353 curlhelp_freebuffer(&body_buf);
368 curlhelp_freebuffer(&header_buf); 354 curlhelp_freebuffer(&header_buf);
369 355
370 return result; 356 return result;
371} 357}
372 358
373/* check whether a file exists */ 359/* check whether a file exists */
374void 360void
375test_file (char *path) 361test_file (char *path)
376{ 362{
377 if (access(path, R_OK) == 0) 363 if (access(path, R_OK) == 0)
378 return; 364 return;
379 usage2 (_("file does not exist or is not readable"), path); 365 usage2 (_("file does not exist or is not readable"), path);
380} 366}
381 367
382int 368int
383process_arguments (int argc, char **argv) 369process_arguments (int argc, char **argv)
384{ 370{
385 int c; 371 int c;
386 372
387 enum { 373 enum {
388 SNI_OPTION 374 SNI_OPTION
389 }; 375 };
390 376
391 int option=0; 377 int option=0;
392 static struct option longopts[] = { 378 static struct option longopts[] = {
393 {"ssl", optional_argument, 0, 'S'}, 379 {"ssl", optional_argument, 0, 'S'},
394 {"sni", no_argument, 0, SNI_OPTION}, 380 {"sni", no_argument, 0, SNI_OPTION},
395 {"IP-address", required_argument, 0, 'I'}, 381 {"IP-address", required_argument, 0, 'I'},
396 {"url", required_argument, 0, 'u'}, 382 {"url", required_argument, 0, 'u'},
397 {"port", required_argument, 0, 'p'}, 383 {"port", required_argument, 0, 'p'},
398 {"authorization", required_argument, 0, 'a'}, 384 {"authorization", required_argument, 0, 'a'},
399 {"string", required_argument, 0, 's'}, 385 {"string", required_argument, 0, 's'},
400 {"onredirect", required_argument, 0, 'f'}, 386 {"onredirect", required_argument, 0, 'f'},
401 {"client-cert", required_argument, 0, 'J'}, 387 {"client-cert", required_argument, 0, 'J'},
402 {"private-key", required_argument, 0, 'K'}, 388 {"private-key", required_argument, 0, 'K'},
403 {"useragent", required_argument, 0, 'A'}, 389 {"useragent", required_argument, 0, 'A'},
404 {"certificate", required_argument, 0, 'C'}, 390 {"certificate", required_argument, 0, 'C'},
405 {0, 0, 0, 0} 391 {0, 0, 0, 0}
406 }; 392 };
407 393
408 if (argc < 2) 394 if (argc < 2)
409 usage ("\n"); 395 usage ("\n");
410 396
411 while (1) { 397 while (1) {
412 c = getopt_long (argc, argv, "Vvht:c:w:A:H:I:a:p:s:u:f:C:J:K:S::", longopts, &option); 398 c = getopt_long (argc, argv, "Vvht:c:w:A:H:I:a:p:s:u:f:C:J:K:S::", longopts, &option);
413 if (c == -1 || c == EOF || c == 1) 399 if (c == -1 || c == EOF || c == 1)
414 break; 400 break;
415 401
416 switch (c) { 402 switch (c) {
417 case 'h': 403 case 'h':
418 print_help(); 404 print_help();
419 exit(STATE_UNKNOWN); 405 exit(STATE_UNKNOWN);
420 break; 406 break;
421 case 'V': 407 case 'V':
422 print_revision(progname, NP_VERSION); 408 print_revision(progname, NP_VERSION);
423 print_curl_version(); 409 print_curl_version();
424 exit(STATE_UNKNOWN); 410 exit(STATE_UNKNOWN);
425 break; 411 break;
426 case 'v': 412 case 'v':
427 verbose++; 413 verbose++;
428 break; 414 break;
429 case 't': /* timeout period */ 415 case 't': /* timeout period */
430 if (!is_intnonneg (optarg)) 416 if (!is_intnonneg (optarg))
431 usage2 (_("Timeout interval must be a positive integer"), optarg); 417 usage2 (_("Timeout interval must be a positive integer"), optarg);
432 else 418 else
433 socket_timeout = (int)strtol (optarg, NULL, 10); 419 socket_timeout = (int)strtol (optarg, NULL, 10);
434 break; 420 break;
435 case 'c': /* critical time threshold */ 421 case 'c': /* critical time threshold */
436 critical_thresholds = optarg; 422 critical_thresholds = optarg;
437 break; 423 break;
438 case 'w': /* warning time threshold */ 424 case 'w': /* warning time threshold */
439 warning_thresholds = optarg; 425 warning_thresholds = optarg;
440 break; 426 break;
441 case 'H': /* virtual host */ 427 case 'H': /* virtual host */
442 host_name = strdup (optarg); 428 host_name = strdup (optarg);
443 break; 429 break;
444 case 'I': /* internet address */ 430 case 'I': /* internet address */
445 server_address = strdup (optarg); 431 server_address = strdup (optarg);
446 break; 432 break;
447 case 'u': /* URL path */ 433 case 'u': /* URL path */
448 server_url = strdup (optarg); 434 server_url = strdup (optarg);
449 break; 435 break;
450 case 'p': /* Server port */ 436 case 'p': /* Server port */
451 if (!is_intnonneg (optarg)) 437 if (!is_intnonneg (optarg))
452 usage2 (_("Invalid port number, expecting a non-negative number"), optarg); 438 usage2 (_("Invalid port number, expecting a non-negative number"), optarg);
453 else { 439 else {
454 if( strtol(optarg, NULL, 10) > MAX_PORT) 440 if( strtol(optarg, NULL, 10) > MAX_PORT)
455 usage2 (_("Invalid port number, supplied port number is too big"), optarg); 441 usage2 (_("Invalid port number, supplied port number is too big"), optarg);
456 server_port = (unsigned short)strtol(optarg, NULL, 10); 442 server_port = (unsigned short)strtol(optarg, NULL, 10);
457 } 443 }
458 break; 444 break;
459 case 'a': /* authorization info */ 445 case 'a': /* authorization info */
460 strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1); 446 strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1);
461 user_auth[MAX_INPUT_BUFFER - 1] = 0; 447 user_auth[MAX_INPUT_BUFFER - 1] = 0;
462 break; 448 break;
463 case 'A': /* useragent */ 449 case 'A': /* useragent */
464 snprintf (user_agent, DEFAULT_BUFFER_SIZE, optarg); 450 snprintf (user_agent, DEFAULT_BUFFER_SIZE, optarg);
465 break; 451 break;
466 case 'C': /* Check SSL cert validity */ 452 case 'C': /* Check SSL cert validity */
467#ifdef LIBCURL_FEATURE_SSL 453#ifdef LIBCURL_FEATURE_SSL
468 /* TODO: C:, check age of certificate for backward compatible 454 /* TODO: C:, check age of certificate for backward compatible
469 * behaviour, but we would later add more check conditions */ 455 * behaviour, but we would later add more check conditions */
470 check_cert = TRUE; 456 check_cert = TRUE;
471 goto enable_ssl; 457 goto enable_ssl;
472#endif 458#endif
473 case 'J': /* use client certificate */ 459 case 'J': /* use client certificate */
474#ifdef LIBCURL_FEATURE_SSL 460#ifdef LIBCURL_FEATURE_SSL
475 test_file(optarg); 461 test_file(optarg);
476 client_cert = optarg; 462 client_cert = optarg;
477 goto enable_ssl; 463 goto enable_ssl;
478#endif 464#endif
479 case 'K': /* use client private key */ 465 case 'K': /* use client private key */
480#ifdef LIBCURL_FEATURE_SSL 466#ifdef LIBCURL_FEATURE_SSL
481 test_file(optarg); 467 test_file(optarg);
482 client_privkey = optarg; 468 client_privkey = optarg;
483 goto enable_ssl; 469 goto enable_ssl;
484#endif 470#endif
485 case 'S': /* use SSL */ 471 case 'S': /* use SSL */
486#ifdef LIBCURL_FEATURE_SSL 472#ifdef LIBCURL_FEATURE_SSL
487 enable_ssl: 473 enable_ssl:
488 use_ssl = TRUE; 474 use_ssl = TRUE;
489 /* ssl_version initialized to CURL_SSLVERSION_TLSv1_0 as a default. Only set if it's non-zero. This helps when we include multiple 475 /* ssl_version initialized to CURL_SSLVERSION_TLSv1_0 as a default. Only set if it's non-zero. This helps when we include multiple
490 parameters, like -S and -C combinations */ 476 parameters, like -S and -C combinations */
491 ssl_version = CURL_SSLVERSION_TLSv1_0; 477 ssl_version = CURL_SSLVERSION_TLSv1_0;
492 if (c=='S' && optarg != NULL) { 478 if (c=='S' && optarg != NULL) {
493 int got_plus = strchr(optarg, '+') != NULL; 479 int got_plus = strchr(optarg, '+') != NULL;
494 480
495 if (!strncmp (optarg, "1.2", 3)) 481 if (!strncmp (optarg, "1.2", 3))
496 ssl_version = CURL_SSLVERSION_TLSv1_2; 482 ssl_version = CURL_SSLVERSION_TLSv1_2;
497 else if (!strncmp (optarg, "1.1", 3)) 483 else if (!strncmp (optarg, "1.1", 3))
498 ssl_version = CURL_SSLVERSION_TLSv1_1; 484 ssl_version = CURL_SSLVERSION_TLSv1_1;
499 else if (optarg[0] == '1') 485 else if (optarg[0] == '1')
500 ssl_version = CURL_SSLVERSION_TLSv1_0; 486 ssl_version = CURL_SSLVERSION_TLSv1_0;
501 else if (optarg[0] == '3') 487 else if (optarg[0] == '3')
502 ssl_version = CURL_SSLVERSION_SSLv3; 488 ssl_version = CURL_SSLVERSION_SSLv3;
503 else if (optarg[0] == '2') 489 else if (optarg[0] == '2')
504 ssl_version = CURL_SSLVERSION_SSLv2; 490 ssl_version = CURL_SSLVERSION_SSLv2;
505 else 491 else
506 usage4 (_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2 (with optional '+' suffix)")); 492 usage4 (_("Invalid option - Valid SSL/TLS versions: 2, 3, 1, 1.1, 1.2 (with optional '+' suffix)"));
507 } 493 }
508 if (server_port == DEFAULT_HTTP_PORT) 494 if (server_port == DEFAULT_HTTP_PORT)
509 server_port = DEFAULT_HTTPS_PORT; 495 server_port = DEFAULT_HTTPS_PORT;
510#else 496#else
511 /* -C -J and -K fall through to here without SSL */ 497 /* -C -J and -K fall through to here without SSL */
512 usage4 (_("Invalid option - SSL is not available")); 498 usage4 (_("Invalid option - SSL is not available"));
513#endif 499#endif
514 break; 500 break;
515 case SNI_OPTION: /* --sni is parsed, but ignored, the default is TRUE with libcurl */ 501 case SNI_OPTION: /* --sni is parsed, but ignored, the default is TRUE with libcurl */
516 use_sni = TRUE; 502 use_sni = TRUE;
517 break; 503 break;
518 case 'f': /* onredirect */ 504 case 'f': /* onredirect */
519 if (!strcmp (optarg, "ok")) 505 if (!strcmp (optarg, "ok"))
520 onredirect = STATE_OK; 506 onredirect = STATE_OK;
521 else if (!strcmp (optarg, "warning")) 507 else if (!strcmp (optarg, "warning"))
522 onredirect = STATE_WARNING; 508 onredirect = STATE_WARNING;
523 else if (!strcmp (optarg, "critical")) 509 else if (!strcmp (optarg, "critical"))
524 onredirect = STATE_CRITICAL; 510 onredirect = STATE_CRITICAL;
525 else if (!strcmp (optarg, "unknown")) 511 else if (!strcmp (optarg, "unknown"))
526 onredirect = STATE_UNKNOWN; 512 onredirect = STATE_UNKNOWN;
527 else if (!strcmp (optarg, "follow")) 513 else if (!strcmp (optarg, "follow"))
528 onredirect = STATE_DEPENDENT; 514 onredirect = STATE_DEPENDENT;
529 else usage2 (_("Invalid onredirect option"), optarg); 515 else usage2 (_("Invalid onredirect option"), optarg);
530 //~ if (!strcmp (optarg, "stickyport")) 516 //~ if (!strcmp (optarg, "stickyport"))
531 //~ onredirect = STATE_DEPENDENT, followsticky = STICKY_HOST|STICKY_PORT; 517 //~ onredirect = STATE_DEPENDENT, followsticky = STICKY_HOST|STICKY_PORT;
532 //~ else if (!strcmp (optarg, "sticky")) 518 //~ else if (!strcmp (optarg, "sticky"))
533 //~ onredirect = STATE_DEPENDENT, followsticky = STICKY_HOST; 519 //~ onredirect = STATE_DEPENDENT, followsticky = STICKY_HOST;
534 //~ else if (!strcmp (optarg, "follow")) 520 //~ else if (!strcmp (optarg, "follow"))
535 //~ onredirect = STATE_DEPENDENT, followsticky = STICKY_NONE; 521 //~ onredirect = STATE_DEPENDENT, followsticky = STICKY_NONE;
536 if (verbose >= 2) 522 if (verbose >= 2)
537 printf(_("* Following redirects set to %s\n"), state_text(onredirect)); 523 printf(_("* Following redirects set to %s\n"), state_text(onredirect));
538 break; 524 break;
539 case 's': /* string or substring */ 525 case 's': /* string or substring */
540 strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1); 526 strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1);
541 string_expect[MAX_INPUT_BUFFER - 1] = 0; 527 string_expect[MAX_INPUT_BUFFER - 1] = 0;
542 break; 528 break;
543 case '?': 529 case '?':
544 /* print short usage statement if args not parsable */ 530 /* print short usage statement if args not parsable */
545 usage5 (); 531 usage5 ();
546 break; 532 break;
547 } 533 }
548 } 534 }
549 535
550 c = optind; 536 c = optind;
551 537
552 if (server_address == NULL && c < argc) 538 if (server_address == NULL && c < argc)
553 server_address = strdup (argv[c++]); 539 server_address = strdup (argv[c++]);
554 540
555 if (host_name == NULL && c < argc) 541 if (host_name == NULL && c < argc)
556 host_name = strdup (argv[c++]); 542 host_name = strdup (argv[c++]);
557 543
558 if (server_address == NULL) { 544 if (server_address == NULL) {
559 if (host_name == NULL) 545 if (host_name == NULL)
560 usage4 (_("You must specify a server address or host name")); 546 usage4 (_("You must specify a server address or host name"));
561 else 547 else
562 server_address = strdup (host_name); 548 server_address = strdup (host_name);
563 } 549 }
564 550
565 set_thresholds(&thlds, warning_thresholds, critical_thresholds); 551 set_thresholds(&thlds, warning_thresholds, critical_thresholds);
566 552
567 if (critical_thresholds && thlds->critical->end>(double)socket_timeout) 553 if (critical_thresholds && thlds->critical->end>(double)socket_timeout)
568 socket_timeout = (int)thlds->critical->end + 1; 554 socket_timeout = (int)thlds->critical->end + 1;
569 if (verbose >= 2) 555 if (verbose >= 2)
570 printf ("* Socket timeout set to %d seconds\n", socket_timeout); 556 printf ("* Socket timeout set to %d seconds\n", socket_timeout);
571 557
572 //~ if (http_method == NULL) 558 //~ if (http_method == NULL)
573 //~ http_method = strdup ("GET"); 559 //~ http_method = strdup ("GET");
574 560
575 if (client_cert && !client_privkey) 561 if (client_cert && !client_privkey)
576 usage4 (_("If you use a client certificate you must also specify a private key file")); 562 usage4 (_("If you use a client certificate you must also specify a private key file"));
577 563
578 //~ if (virtual_port == 0) 564 //~ if (virtual_port == 0)
579 //~ virtual_port = server_port; 565 //~ virtual_port = server_port;
580 566
581 return TRUE; 567 return TRUE;
582} 568}
583 569
584void 570void
585print_help (void) 571print_help (void)
586{ 572{
587 print_revision(progname, NP_VERSION); 573 print_revision(progname, NP_VERSION);
574
575 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
576 printf ("Copyright (c) 2017 Andreas Baumann <abaumann@yahoo.com>\n");
577 printf (COPYRIGHT, copyright, email);
588 578
589 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 579 printf ("%s\n", _("This plugin tests the HTTP service on the specified host. It can test"));
590 printf ("Copyright (c) 2017 Andreas Baumann <abaumann@yahoo.com>\n"); 580 printf ("%s\n", _("normal (http) and secure (https) servers, follow redirects, search for"));
591 printf (COPYRIGHT, copyright, email); 581 printf ("%s\n", _("strings and regular expressions, check connection times, and report on"));
582 printf ("%s\n", _("certificate expiration times."));
583 printf ("\n");
584 printf ("%s\n", _("It makes use of libcurl to do so. It tries to be as compatible to check_http"));
585 printf ("%s\n", _("as possible."));
592 586
593 printf ("%s\n", _("This plugin tests the HTTP service on the specified host. It can test")); 587 printf ("\n\n");
594 printf ("%s\n", _("normal (http) and secure (https) servers, follow redirects, search for"));
595 printf ("%s\n", _("strings and regular expressions, check connection times, and report on"));
596 printf ("%s\n", _("certificate expiration times."));
597 printf ("\n");
598 printf ("%s\n", _("It makes use of libcurl to do so. It tries to be as compatible to check_http"));
599 printf ("%s\n", _("as possible."));
600 588
601 printf ("\n\n"); 589 print_usage();
602 590
603 print_usage(); 591 printf (_("NOTE: One or both of -H and -I must be specified"));
604
605 printf (_("NOTE: One or both of -H and -I must be specified"));
606 592
607 printf ("\n"); 593 printf ("\n");
608 594
609 printf (UT_HELP_VRSN); 595 printf (UT_HELP_VRSN);
610 printf (UT_EXTRA_OPTS); 596 printf (UT_EXTRA_OPTS);
611 597
612 printf (" %s\n", "-H, --hostname=ADDRESS"); 598 printf (" %s\n", "-H, --hostname=ADDRESS");
613 printf (" %s\n", _("Host name argument for servers using host headers (virtual host)")); 599 printf (" %s\n", _("Host name argument for servers using host headers (virtual host)"));
614 printf (" %s\n", _("Append a port to include it in the header (eg: example.com:5000)")); 600 printf (" %s\n", _("Append a port to include it in the header (eg: example.com:5000)"));
615 printf (" %s\n", "-I, --IP-address=ADDRESS"); 601 printf (" %s\n", "-I, --IP-address=ADDRESS");
616 printf (" %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup).")); 602 printf (" %s\n", _("IP address or name (use numeric address if possible to bypass DNS lookup)."));
617 printf (" %s\n", "-p, --port=INTEGER"); 603 printf (" %s\n", "-p, --port=INTEGER");
618 printf (" %s", _("Port number (default: ")); 604 printf (" %s", _("Port number (default: "));
619 printf ("%d)\n", DEFAULT_HTTP_PORT); 605 printf ("%d)\n", DEFAULT_HTTP_PORT);
620 606
621#ifdef LIBCURL_FEATURE_SSL 607#ifdef LIBCURL_FEATURE_SSL
622 printf (" %s\n", "-S, --ssl=VERSION[+]"); 608 printf (" %s\n", "-S, --ssl=VERSION[+]");
623 printf (" %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents")); 609 printf (" %s\n", _("Connect via SSL. Port defaults to 443. VERSION is optional, and prevents"));
624 printf (" %s\n", _("auto-negotiation (2 = SSLv2, 3 = SSLv3, 1 = TLSv1, 1.1 = TLSv1.1,")); 610 printf (" %s\n", _("auto-negotiation (2 = SSLv2, 3 = SSLv3, 1 = TLSv1, 1.1 = TLSv1.1,"));
625 printf (" %s\n", _("1.2 = TLSv1.2). With a '+' suffix, newer versions are also accepted.")); 611 printf (" %s\n", _("1.2 = TLSv1.2). With a '+' suffix, newer versions are also accepted."));
626 printf (" %s\n", _("Note: SSLv2 and SSLv3 are deprecated and are usually disabled in libcurl")); 612 printf (" %s\n", _("Note: SSLv2 and SSLv3 are deprecated and are usually disabled in libcurl"));
627 printf (" %s\n", "--sni"); 613 printf (" %s\n", "--sni");
628 printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)")); 614 printf (" %s\n", _("Enable SSL/TLS hostname extension support (SNI)"));
629#if LIBCURL_VERSION_NUM >= 0x071801 615#if LIBCURL_VERSION_NUM >= 0x071801
630 printf (" %s\n", _("Note: --sni is the default in libcurl as SSLv2 and SSLV3 are deprecated and")); 616 printf (" %s\n", _("Note: --sni is the default in libcurl as SSLv2 and SSLV3 are deprecated and"));
631 printf (" %s\n", _(" SNI only really works since TLSv1.0")); 617 printf (" %s\n", _(" SNI only really works since TLSv1.0"));
632#else 618#else
633 printf (" %s\n", _("Note: SNI is not supported in libcurl before 7.18.1")); 619 printf (" %s\n", _("Note: SNI is not supported in libcurl before 7.18.1"));
634#endif 620#endif
635 printf (" %s\n", "-C, --certificate"); 621 printf (" %s\n", "-C, --certificate");
636 printf (" %s\n", _("Check validity of certificate")); 622 printf (" %s\n", _("Check validity of certificate"));
637 printf (" %s\n", "-J, --client-cert=FILE"); 623 printf (" %s\n", "-J, --client-cert=FILE");
638 printf (" %s\n", _("Name of file that contains the client certificate (PEM format)")); 624 printf (" %s\n", _("Name of file that contains the client certificate (PEM format)"));
639 printf (" %s\n", _("to be used in establishing the SSL session")); 625 printf (" %s\n", _("to be used in establishing the SSL session"));
640 printf (" %s\n", "-K, --private-key=FILE"); 626 printf (" %s\n", "-K, --private-key=FILE");
641 printf (" %s\n", _("Name of file containing the private key (PEM format)")); 627 printf (" %s\n", _("Name of file containing the private key (PEM format)"));
642 printf (" %s\n", _("matching the client certificate")); 628 printf (" %s\n", _("matching the client certificate"));
643#endif 629#endif
644 630
645 printf (" %s\n", "-s, --string=STRING"); 631 printf (" %s\n", "-s, --string=STRING");
646 printf (" %s\n", _("String to expect in the content")); 632 printf (" %s\n", _("String to expect in the content"));
647 printf (" %s\n", "-u, --url=PATH"); 633 printf (" %s\n", "-u, --url=PATH");
648 printf (" %s\n", _("URL to GET or POST (default: /)")); 634 printf (" %s\n", _("URL to GET or POST (default: /)"));
649 635
650 printf (" %s\n", "-a, --authorization=AUTH_PAIR"); 636 printf (" %s\n", "-a, --authorization=AUTH_PAIR");
651 printf (" %s\n", _("Username:password on sites with basic authentication")); 637 printf (" %s\n", _("Username:password on sites with basic authentication"));
652 printf (" %s\n", "-A, --useragent=STRING"); 638 printf (" %s\n", "-A, --useragent=STRING");
653 printf (" %s\n", _("String to be sent in http header as \"User Agent\"")); 639 printf (" %s\n", _("String to be sent in http header as \"User Agent\""));
654 printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport>"); 640 printf (" %s\n", "-f, --onredirect=<ok|warning|critical|follow|sticky|stickyport>");
655 printf (" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the")); 641 printf (" %s\n", _("How to handle redirected pages. sticky is like follow but stick to the"));
656 printf (" %s\n", _("specified IP address. stickyport also ensures port stays the same.")); 642 printf (" %s\n", _("specified IP address. stickyport also ensures port stays the same."));
657 643
658 printf (UT_WARN_CRIT); 644 printf (UT_WARN_CRIT);
659 645
660 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 646 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
661 647
662 printf (UT_VERBOSE); 648 printf (UT_VERBOSE);
663 649
664 printf (UT_SUPPORT); 650 printf (UT_SUPPORT);
665} 651}
666 652
667void 653void
668print_usage (void) 654print_usage (void)
669{ 655{
670 printf ("%s\n", _("Usage:")); 656 printf ("%s\n", _("Usage:"));
671 printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname); 657 printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname);
672 printf (" [-J <client certificate file>] [-K <private key>]\n"); 658 printf (" [-J <client certificate file>] [-K <private key>]\n");
673 printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-a auth]\n"); 659 printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-a auth]\n");
674 printf (" [-f <ok|warning|critcal|follow>]\n"); 660 printf (" [-f <ok|warning|critcal|follow>]\n");
675 printf (" [-A string] [-S <version>] [-C]\n"); 661 printf (" [-A string] [-S <version>] [-C]\n");
676 printf (" [-v verbose]\n", progname); 662 printf (" [-v verbose]\n", progname);
677 printf ("\n"); 663 printf ("\n");
678 printf ("%s\n", _("WARNING: check_curl is experimental. Please use")); 664 printf ("%s\n", _("WARNING: check_curl is experimental. Please use"));
679 printf ("%s\n\n", _("check_http if you need a stable version.")); 665 printf ("%s\n\n", _("check_http if you need a stable version."));
680} 666}
681 667
682void 668void
683print_curl_version (void) 669print_curl_version (void)
684{ 670{
685 printf( "%s\n", curl_version()); 671 printf( "%s\n", curl_version());
686} 672}
687 673
688int 674int
689curlhelp_initbuffer (curlhelp_curlbuf *buf) 675curlhelp_initbuffer (curlhelp_curlbuf *buf)
690{ 676{
691 buf->bufsize = DEFAULT_BUFFER_SIZE; 677 buf->bufsize = DEFAULT_BUFFER_SIZE;
692 buf->buflen = 0; 678 buf->buflen = 0;
693 buf->buf = (char *)malloc ((size_t)buf->bufsize); 679 buf->buf = (char *)malloc ((size_t)buf->bufsize);
694 if (buf->buf == NULL) return -1; 680 if (buf->buf == NULL) return -1;
695 return 0; 681 return 0;
696} 682}
697 683
698int 684int
699curlhelp_buffer_callback (void *buffer, size_t size, size_t nmemb, void *stream) 685curlhelp_buffer_callback (void *buffer, size_t size, size_t nmemb, void *stream)
700{ 686{
701 curlhelp_curlbuf *buf = (curlhelp_curlbuf *)stream; 687 curlhelp_curlbuf *buf = (curlhelp_curlbuf *)stream;
702 688
703 while (buf->bufsize < buf->buflen + size * nmemb + 1) { 689 while (buf->bufsize < buf->buflen + size * nmemb + 1) {
704 buf->bufsize *= buf->bufsize * 2; 690 buf->bufsize *= buf->bufsize * 2;
705 buf->buf = (char *)realloc (buf->buf, buf->bufsize); 691 buf->buf = (char *)realloc (buf->buf, buf->bufsize);
706 if (buf->buf == NULL) return -1; 692 if (buf->buf == NULL) return -1;
707 } 693 }
708 694
709 memcpy (buf->buf + buf->buflen, buffer, size * nmemb); 695 memcpy (buf->buf + buf->buflen, buffer, size * nmemb);
710 buf->buflen += size * nmemb; 696 buf->buflen += size * nmemb;
711 buf->buf[buf->buflen] = '\0'; 697 buf->buf[buf->buflen] = '\0';
712 698
713 return (int)(size * nmemb); 699 return (int)(size * nmemb);
714} 700}
715 701
716void 702void
717curlhelp_freebuffer (curlhelp_curlbuf *buf) 703curlhelp_freebuffer (curlhelp_curlbuf *buf)
718{ 704{
719 free (buf->buf); 705 free (buf->buf);
720 buf->buf = NULL; 706 buf->buf = NULL;
721} 707}
722 708
723/* TODO: when redirecting we get more than one HTTP header, make sure 709/* TODO: when redirecting we get more than one HTTP header, make sure
@@ -726,76 +712,76 @@ curlhelp_freebuffer (curlhelp_curlbuf *buf)
726int 712int
727curlhelp_parse_statusline (char *buf, curlhelp_statusline *status_line) 713curlhelp_parse_statusline (char *buf, curlhelp_statusline *status_line)
728{ 714{
729 char *first_line_end; 715 char *first_line_end;
730 char *p; 716 char *p;
731 size_t first_line_len; 717 size_t first_line_len;
732 char *pp; 718 char *pp;
733 719
734 first_line_end = strstr(buf, "\r\n"); 720 first_line_end = strstr(buf, "\r\n");
735 if (first_line_end == NULL) return -1; 721 if (first_line_end == NULL) return -1;
736 722
737 first_line_len = (size_t)(first_line_end - buf); 723 first_line_len = (size_t)(first_line_end - buf);
738 status_line->first_line = (char *)malloc (first_line_len + 1); 724 status_line->first_line = (char *)malloc (first_line_len + 1);
739 if (status_line->first_line == NULL) return -1; 725 if (status_line->first_line == NULL) return -1;
740 memcpy (status_line->first_line, buf, first_line_len); 726 memcpy (status_line->first_line, buf, first_line_len);
741 status_line->first_line[first_line_len] = '\0'; 727 status_line->first_line[first_line_len] = '\0';
742 728
743 /* protocol and version: "HTTP/x.x" SP */ 729 /* protocol and version: "HTTP/x.x" SP */
744 730
745 p = strtok(status_line->first_line, "/"); 731 p = strtok(status_line->first_line, "/");
746 if( p == NULL ) { free( status_line->first_line ); return -1; } 732 if( p == NULL ) { free( status_line->first_line ); return -1; }
747 if( strcmp( p, "HTTP" ) != 0 ) { free( status_line->first_line ); return -1; } 733 if( strcmp( p, "HTTP" ) != 0 ) { free( status_line->first_line ); return -1; }
748 734
749 p = strtok( NULL, "." ); 735 p = strtok( NULL, "." );
750 if( p == NULL ) { free( status_line->first_line ); return -1; } 736 if( p == NULL ) { free( status_line->first_line ); return -1; }
751 status_line->http_major = (int)strtol( p, &pp, 10 ); 737 status_line->http_major = (int)strtol( p, &pp, 10 );
752 if( *pp != '\0' ) { free( status_line->first_line ); return -1; } 738 if( *pp != '\0' ) { free( status_line->first_line ); return -1; }
753 739
754 p = strtok( NULL, " " ); 740 p = strtok( NULL, " " );
755 if( p == NULL ) { free( status_line->first_line ); return -1; } 741 if( p == NULL ) { free( status_line->first_line ); return -1; }
756 status_line->http_minor = (int)strtol( p, &pp, 10 ); 742 status_line->http_minor = (int)strtol( p, &pp, 10 );
757 if( *pp != '\0' ) { free( status_line->first_line ); return -1; } 743 if( *pp != '\0' ) { free( status_line->first_line ); return -1; }
758 744
759 /* status code: "404" or "404.1", then SP */ 745 /* status code: "404" or "404.1", then SP */
760 746
761 p = strtok( NULL, " ." ); 747 p = strtok( NULL, " ." );
762 if( p == NULL ) { free( status_line->first_line ); return -1; } 748 if( p == NULL ) { free( status_line->first_line ); return -1; }
763 if( strchr( p, '.' ) != NULL ) { 749 if( strchr( p, '.' ) != NULL ) {
764 char *ppp; 750 char *ppp;
765 ppp = strtok( p, "." ); 751 ppp = strtok( p, "." );
766 status_line->http_code = (int)strtol( ppp, &pp, 10 ); 752 status_line->http_code = (int)strtol( ppp, &pp, 10 );
767 if( *pp != '\0' ) { free( status_line->first_line ); return -1; } 753 if( *pp != '\0' ) { free( status_line->first_line ); return -1; }
768 754
769 ppp = strtok( NULL, "" ); 755 ppp = strtok( NULL, "" );
770 status_line->http_subcode = (int)strtol( ppp, &pp, 10 ); 756 status_line->http_subcode = (int)strtol( ppp, &pp, 10 );
771 if( *pp != '\0' ) { free( status_line->first_line ); return -1; } 757 if( *pp != '\0' ) { free( status_line->first_line ); return -1; }
772 } else { 758 } else {
773 status_line->http_code = (int)strtol( p, &pp, 10 ); 759 status_line->http_code = (int)strtol( p, &pp, 10 );
774 status_line->http_subcode = -1; 760 status_line->http_subcode = -1;
775 if( *pp != '\0' ) { free( status_line->first_line ); return -1; } 761 if( *pp != '\0' ) { free( status_line->first_line ); return -1; }
776 } 762 }
777 763
778 /* Human readable message: "Not Found" CRLF */ 764 /* Human readable message: "Not Found" CRLF */
779 765
780 p = strtok( NULL, "" ); 766 p = strtok( NULL, "" );
781 if( p == NULL ) { free( status_line->first_line ); return -1; } 767 if( p == NULL ) { free( status_line->first_line ); return -1; }
782 status_line->msg = p; 768 status_line->msg = p;
783 769
784 return 0; 770 return 0;
785} 771}
786 772
787void 773void
788curlhelp_free_statusline (curlhelp_statusline *status_line) 774curlhelp_free_statusline (curlhelp_statusline *status_line)
789{ 775{
790 free (status_line->first_line); 776 free (status_line->first_line);
791} 777}
792 778
793void 779void
794remove_newlines (char *s) 780remove_newlines (char *s)
795{ 781{
796 char *p; 782 char *p;
797 783
798 for (p = s; *p != '\0'; p++) 784 for (p = s; *p != '\0'; p++)
799 if (*p == '\r' || *p == '\n') 785 if (*p == '\r' || *p == '\n')
800 *p = ' '; 786 *p = ' ';
801} 787}