diff options
Diffstat (limited to 'plugins/check_http.c')
-rw-r--r-- | plugins/check_http.c | 138 |
1 files changed, 115 insertions, 23 deletions
diff --git a/plugins/check_http.c b/plugins/check_http.c index 9231a55..ea7a673 100644 --- a/plugins/check_http.c +++ b/plugins/check_http.c | |||
@@ -1,40 +1,40 @@ | |||
1 | /***************************************************************************** | 1 | /***************************************************************************** |
2 | * | 2 | * |
3 | * Nagios check_http plugin | 3 | * Nagios check_http plugin |
4 | * | 4 | * |
5 | * License: GPL | 5 | * License: GPL |
6 | * Copyright (c) 1999-2008 Nagios Plugins Development Team | 6 | * Copyright (c) 1999-2013 Nagios Plugins Development Team |
7 | * | 7 | * |
8 | * Description: | 8 | * Description: |
9 | * | 9 | * |
10 | * This file contains the check_http plugin | 10 | * This file contains the check_http plugin |
11 | * | 11 | * |
12 | * This plugin tests the HTTP service on the specified host. It can test | 12 | * This plugin tests the HTTP service on the specified host. It can test |
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 | * | 17 | * |
18 | * This program is free software: you can redistribute it and/or modify | 18 | * This program is free software: you can redistribute it and/or modify |
19 | * it under the terms of the GNU General Public License as published by | 19 | * it under the terms of the GNU General Public License as published by |
20 | * the Free Software Foundation, either version 3 of the License, or | 20 | * the Free Software Foundation, either version 3 of the License, or |
21 | * (at your option) any later version. | 21 | * (at your option) any later version. |
22 | * | 22 | * |
23 | * This program is distributed in the hope that it will be useful, | 23 | * This program is distributed in the hope that it will be useful, |
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
26 | * GNU General Public License for more details. | 26 | * GNU General Public License for more details. |
27 | * | 27 | * |
28 | * You should have received a copy of the GNU General Public License | 28 | * You should have received a copy of the GNU General Public License |
29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 29 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
30 | * | 30 | * |
31 | * | 31 | * |
32 | *****************************************************************************/ | 32 | *****************************************************************************/ |
33 | 33 | ||
34 | /* splint -I. -I../../plugins -I../../lib/ -I/usr/kerberos/include/ ../../plugins/check_http.c */ | 34 | /* splint -I. -I../../plugins -I../../lib/ -I/usr/kerberos/include/ ../../plugins/check_http.c */ |
35 | 35 | ||
36 | const char *progname = "check_http"; | 36 | const char *progname = "check_http"; |
37 | const char *copyright = "1999-2011"; | 37 | const char *copyright = "1999-2013"; |
38 | const char *email = "nagiosplug-devel@lists.sourceforge.net"; | 38 | const char *email = "nagiosplug-devel@lists.sourceforge.net"; |
39 | 39 | ||
40 | #include "common.h" | 40 | #include "common.h" |
@@ -43,7 +43,6 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; | |||
43 | #include "base64.h" | 43 | #include "base64.h" |
44 | #include <ctype.h> | 44 | #include <ctype.h> |
45 | 45 | ||
46 | #define INPUT_DELIMITER ";" | ||
47 | #define STICKY_NONE 0 | 46 | #define STICKY_NONE 0 |
48 | #define STICKY_HOST 1 | 47 | #define STICKY_HOST 1 |
49 | #define STICKY_PORT 2 | 48 | #define STICKY_PORT 2 |
@@ -85,6 +84,7 @@ int errcode; | |||
85 | int invert_regex = 0; | 84 | int invert_regex = 0; |
86 | 85 | ||
87 | struct timeval tv; | 86 | struct timeval tv; |
87 | struct timeval tv_temp; | ||
88 | 88 | ||
89 | #define HTTP_URL "/" | 89 | #define HTTP_URL "/" |
90 | #define CRLF "\r\n" | 90 | #define CRLF "\r\n" |
@@ -100,7 +100,9 @@ char *user_agent; | |||
100 | int server_url_length; | 100 | int server_url_length; |
101 | int server_expect_yn = 0; | 101 | int server_expect_yn = 0; |
102 | char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT; | 102 | char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT; |
103 | char header_expect[MAX_INPUT_BUFFER] = ""; | ||
103 | char string_expect[MAX_INPUT_BUFFER] = ""; | 104 | char string_expect[MAX_INPUT_BUFFER] = ""; |
105 | char output_header_search[30] = ""; | ||
104 | char output_string_search[30] = ""; | 106 | char output_string_search[30] = ""; |
105 | char *warning_thresholds = NULL; | 107 | char *warning_thresholds = NULL; |
106 | char *critical_thresholds = NULL; | 108 | char *critical_thresholds = NULL; |
@@ -115,6 +117,7 @@ int followsticky = STICKY_NONE; | |||
115 | int use_ssl = FALSE; | 117 | int use_ssl = FALSE; |
116 | int use_sni = FALSE; | 118 | int use_sni = FALSE; |
117 | int verbose = FALSE; | 119 | int verbose = FALSE; |
120 | int show_extended_perfdata = FALSE; | ||
118 | int sd; | 121 | int sd; |
119 | int min_page_len = 0; | 122 | int min_page_len = 0; |
120 | int max_page_len = 0; | 123 | int max_page_len = 0; |
@@ -131,6 +134,11 @@ void redir (char *pos, char *status_line); | |||
131 | int server_type_check(const char *type); | 134 | int server_type_check(const char *type); |
132 | int server_port_check(int ssl_flag); | 135 | int server_port_check(int ssl_flag); |
133 | char *perfd_time (double microsec); | 136 | char *perfd_time (double microsec); |
137 | char *perfd_time_connect (double microsec); | ||
138 | char *perfd_time_ssl (double microsec); | ||
139 | char *perfd_time_firstbyte (double microsec); | ||
140 | char *perfd_time_headers (double microsec); | ||
141 | char *perfd_time_transfer (double microsec); | ||
134 | char *perfd_size (int page_len); | 142 | char *perfd_size (int page_len); |
135 | void print_help (void); | 143 | void print_help (void); |
136 | void print_usage (void); | 144 | void print_usage (void); |
@@ -199,6 +207,7 @@ process_arguments (int argc, char **argv) | |||
199 | {"port", required_argument, 0, 'p'}, | 207 | {"port", required_argument, 0, 'p'}, |
200 | {"authorization", required_argument, 0, 'a'}, | 208 | {"authorization", required_argument, 0, 'a'}, |
201 | {"proxy_authorization", required_argument, 0, 'b'}, | 209 | {"proxy_authorization", required_argument, 0, 'b'}, |
210 | {"header-string", required_argument, 0, 'd'}, | ||
202 | {"string", required_argument, 0, 's'}, | 211 | {"string", required_argument, 0, 's'}, |
203 | {"expect", required_argument, 0, 'e'}, | 212 | {"expect", required_argument, 0, 'e'}, |
204 | {"regex", required_argument, 0, 'r'}, | 213 | {"regex", required_argument, 0, 'r'}, |
@@ -216,6 +225,7 @@ process_arguments (int argc, char **argv) | |||
216 | {"invert-regex", no_argument, NULL, INVERT_REGEX}, | 225 | {"invert-regex", no_argument, NULL, INVERT_REGEX}, |
217 | {"use-ipv4", no_argument, 0, '4'}, | 226 | {"use-ipv4", no_argument, 0, '4'}, |
218 | {"use-ipv6", no_argument, 0, '6'}, | 227 | {"use-ipv6", no_argument, 0, '6'}, |
228 | {"extended-perfdata", no_argument, 0, 'E'}, | ||
219 | {0, 0, 0, 0} | 229 | {0, 0, 0, 0} |
220 | }; | 230 | }; |
221 | 231 | ||
@@ -236,7 +246,7 @@ process_arguments (int argc, char **argv) | |||
236 | } | 246 | } |
237 | 247 | ||
238 | while (1) { | 248 | while (1) { |
239 | c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:e:p:s:R:r:u:f:C:nlLS::m:M:N", longopts, &option); | 249 | c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:d:e:p:s:R:r:u:f:C:nlLS::m:M:N:E", longopts, &option); |
240 | if (c == -1 || c == EOF) | 250 | if (c == -1 || c == EOF) |
241 | break; | 251 | break; |
242 | 252 | ||
@@ -385,6 +395,10 @@ process_arguments (int argc, char **argv) | |||
385 | free(http_method); | 395 | free(http_method); |
386 | http_method = strdup (optarg); | 396 | http_method = strdup (optarg); |
387 | break; | 397 | break; |
398 | case 'd': /* string or substring */ | ||
399 | strncpy (header_expect, optarg, MAX_INPUT_BUFFER - 1); | ||
400 | header_expect[MAX_INPUT_BUFFER - 1] = 0; | ||
401 | break; | ||
388 | case 's': /* string or substring */ | 402 | case 's': /* string or substring */ |
389 | strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1); | 403 | strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1); |
390 | string_expect[MAX_INPUT_BUFFER - 1] = 0; | 404 | string_expect[MAX_INPUT_BUFFER - 1] = 0; |
@@ -471,6 +485,9 @@ process_arguments (int argc, char **argv) | |||
471 | } | 485 | } |
472 | } | 486 | } |
473 | break; | 487 | break; |
488 | case 'E': /* show extended perfdata */ | ||
489 | show_extended_perfdata = TRUE; | ||
490 | break; | ||
474 | } | 491 | } |
475 | } | 492 | } |
476 | 493 | ||
@@ -812,17 +829,33 @@ check_http (void) | |||
812 | char *pos; | 829 | char *pos; |
813 | long microsec; | 830 | long microsec; |
814 | double elapsed_time; | 831 | double elapsed_time; |
832 | long microsec_connect; | ||
833 | double elapsed_time_connect; | ||
834 | long microsec_ssl; | ||
835 | double elapsed_time_ssl; | ||
836 | long microsec_firstbyte; | ||
837 | double elapsed_time_firstbyte; | ||
838 | long microsec_headers; | ||
839 | double elapsed_time_headers; | ||
840 | long microsec_transfer; | ||
841 | double elapsed_time_transfer; | ||
815 | int page_len = 0; | 842 | int page_len = 0; |
816 | int result = STATE_OK; | 843 | int result = STATE_OK; |
817 | 844 | ||
818 | /* try to connect to the host at the given port number */ | 845 | /* try to connect to the host at the given port number */ |
846 | gettimeofday (&tv_temp, NULL); | ||
819 | if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK) | 847 | if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK) |
820 | die (STATE_CRITICAL, _("HTTP CRITICAL - Unable to open TCP socket\n")); | 848 | die (STATE_CRITICAL, _("HTTP CRITICAL - Unable to open TCP socket\n")); |
849 | microsec_connect = deltime (tv_temp); | ||
821 | #ifdef HAVE_SSL | 850 | #ifdef HAVE_SSL |
851 | elapsed_time_connect = (double)microsec_connect / 1.0e6; | ||
822 | if (use_ssl == TRUE) { | 852 | if (use_ssl == TRUE) { |
853 | gettimeofday (&tv_temp, NULL); | ||
823 | result = np_net_ssl_init_with_hostname_and_version(sd, (use_sni ? host_name : NULL), ssl_version); | 854 | result = np_net_ssl_init_with_hostname_and_version(sd, (use_sni ? host_name : NULL), ssl_version); |
824 | if (result != STATE_OK) | 855 | if (result != STATE_OK) |
825 | return result; | 856 | return result; |
857 | microsec_ssl = deltime (tv_temp); | ||
858 | elapsed_time_ssl = (double)microsec_ssl / 1.0e6; | ||
826 | if (check_cert == TRUE) { | 859 | if (check_cert == TRUE) { |
827 | result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit); | 860 | result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit); |
828 | np_net_ssl_cleanup(); | 861 | np_net_ssl_cleanup(); |
@@ -854,8 +887,7 @@ check_http (void) | |||
854 | /* optionally send any other header tag */ | 887 | /* optionally send any other header tag */ |
855 | if (http_opt_headers_count) { | 888 | if (http_opt_headers_count) { |
856 | for (i = 0; i < http_opt_headers_count ; i++) { | 889 | for (i = 0; i < http_opt_headers_count ; i++) { |
857 | for ((pos = strtok(http_opt_headers[i], INPUT_DELIMITER)); pos; (pos = strtok(NULL, INPUT_DELIMITER))) | 890 | xasprintf (&buf, "%s%s\r\n", buf, http_opt_headers[i]); |
858 | xasprintf (&buf, "%s%s\r\n", buf, pos); | ||
859 | } | 891 | } |
860 | /* This cannot be free'd here because a redirection will then try to access this and segfault */ | 892 | /* This cannot be free'd here because a redirection will then try to access this and segfault */ |
861 | /* Covered in a testcase in tests/check_http.t */ | 893 | /* Covered in a testcase in tests/check_http.t */ |
@@ -891,11 +923,19 @@ check_http (void) | |||
891 | } | 923 | } |
892 | 924 | ||
893 | if (verbose) printf ("%s\n", buf); | 925 | if (verbose) printf ("%s\n", buf); |
926 | gettimeofday (&tv_temp, NULL); | ||
894 | my_send (buf, strlen (buf)); | 927 | my_send (buf, strlen (buf)); |
928 | microsec_headers = deltime (tv_temp); | ||
929 | elapsed_time_headers = (double)microsec_headers / 1.0e6; | ||
895 | 930 | ||
896 | /* fetch the page */ | 931 | /* fetch the page */ |
897 | full_page = strdup(""); | 932 | full_page = strdup(""); |
933 | gettimeofday (&tv_temp, NULL); | ||
898 | while ((i = my_recv (buffer, MAX_INPUT_BUFFER-1)) > 0) { | 934 | while ((i = my_recv (buffer, MAX_INPUT_BUFFER-1)) > 0) { |
935 | if ((i >= 1) && (elapsed_time_firstbyte <= 0.000001)) { | ||
936 | microsec_firstbyte = deltime (tv_temp); | ||
937 | elapsed_time_firstbyte = (double)microsec_firstbyte / 1.0e6; | ||
938 | } | ||
899 | buffer[i] = '\0'; | 939 | buffer[i] = '\0'; |
900 | xasprintf (&full_page_new, "%s%s", full_page, buffer); | 940 | xasprintf (&full_page_new, "%s%s", full_page, buffer); |
901 | free (full_page); | 941 | free (full_page); |
@@ -907,6 +947,8 @@ check_http (void) | |||
907 | break; | 947 | break; |
908 | } | 948 | } |
909 | } | 949 | } |
950 | microsec_transfer = deltime (tv_temp); | ||
951 | elapsed_time_transfer = (double)microsec_transfer / 1.0e6; | ||
910 | 952 | ||
911 | if (i < 0 && errno != ECONNRESET) { | 953 | if (i < 0 && errno != ECONNRESET) { |
912 | #ifdef HAVE_SSL | 954 | #ifdef HAVE_SSL |
@@ -1050,6 +1092,17 @@ check_http (void) | |||
1050 | } | 1092 | } |
1051 | 1093 | ||
1052 | /* Page and Header content checks go here */ | 1094 | /* Page and Header content checks go here */ |
1095 | if (strlen (header_expect)) { | ||
1096 | if (!strstr (header, header_expect)) { | ||
1097 | strncpy(&output_header_search[0],header_expect,sizeof(output_header_search)); | ||
1098 | if(output_header_search[sizeof(output_header_search)-1]!='\0') { | ||
1099 | bcopy("...",&output_header_search[sizeof(output_header_search)-4],4); | ||
1100 | } | ||
1101 | xasprintf (&msg, _("%sheader '%s' not found on '%s://%s:%d%s', "), msg, output_header_search, use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url); | ||
1102 | result = STATE_CRITICAL; | ||
1103 | } | ||
1104 | } | ||
1105 | |||
1053 | 1106 | ||
1054 | if (strlen (string_expect)) { | 1107 | if (strlen (string_expect)) { |
1055 | if (!strstr (page, string_expect)) { | 1108 | if (!strstr (page, string_expect)) { |
@@ -1108,11 +1161,25 @@ check_http (void) | |||
1108 | msg[strlen(msg)-3] = '\0'; | 1161 | msg[strlen(msg)-3] = '\0'; |
1109 | 1162 | ||
1110 | /* check elapsed time */ | 1163 | /* check elapsed time */ |
1111 | xasprintf (&msg, | 1164 | if (show_extended_perfdata) |
1112 | _("%s - %d bytes in %.3f second response time %s|%s %s"), | 1165 | xasprintf (&msg, |
1113 | msg, page_len, elapsed_time, | 1166 | _("%s - %d bytes in %.3f second response time %s|%s %s %s %s %s %s %s"), |
1114 | (display_html ? "</A>" : ""), | 1167 | msg, page_len, elapsed_time, |
1115 | perfd_time (elapsed_time), perfd_size (page_len)); | 1168 | (display_html ? "</A>" : ""), |
1169 | perfd_time (elapsed_time), | ||
1170 | perfd_size (page_len), | ||
1171 | perfd_time_connect (elapsed_time_connect), | ||
1172 | use_ssl == TRUE ? perfd_time_ssl (elapsed_time_ssl) : "", | ||
1173 | perfd_time_headers (elapsed_time_headers), | ||
1174 | perfd_time_firstbyte (elapsed_time_firstbyte), | ||
1175 | perfd_time_transfer (elapsed_time_transfer)); | ||
1176 | else | ||
1177 | xasprintf (&msg, | ||
1178 | _("%s - %d bytes in %.3f second response time %s|%s %s"), | ||
1179 | msg, page_len, elapsed_time, | ||
1180 | (display_html ? "</A>" : ""), | ||
1181 | perfd_time (elapsed_time), | ||
1182 | perfd_size (page_len)); | ||
1116 | 1183 | ||
1117 | result = max_state_alt(get_status(elapsed_time, thlds), result); | 1184 | result = max_state_alt(get_status(elapsed_time, thlds), result); |
1118 | 1185 | ||
@@ -1301,7 +1368,30 @@ char *perfd_time (double elapsed_time) | |||
1301 | TRUE, 0, FALSE, 0); | 1368 | TRUE, 0, FALSE, 0); |
1302 | } | 1369 | } |
1303 | 1370 | ||
1371 | char *perfd_time_connect (double elapsed_time_connect) | ||
1372 | { | ||
1373 | return fperfdata ("time_connect", elapsed_time_connect, "s", FALSE, 0, FALSE, 0, FALSE, 0, FALSE, 0); | ||
1374 | } | ||
1375 | |||
1376 | char *perfd_time_ssl (double elapsed_time_ssl) | ||
1377 | { | ||
1378 | return fperfdata ("time_ssl", elapsed_time_ssl, "s", FALSE, 0, FALSE, 0, FALSE, 0, FALSE, 0); | ||
1379 | } | ||
1380 | |||
1381 | char *perfd_time_headers (double elapsed_time_headers) | ||
1382 | { | ||
1383 | return fperfdata ("time_headers", elapsed_time_headers, "s", FALSE, 0, FALSE, 0, FALSE, 0, FALSE, 0); | ||
1384 | } | ||
1385 | |||
1386 | char *perfd_time_firstbyte (double elapsed_time_firstbyte) | ||
1387 | { | ||
1388 | return fperfdata ("time_firstbyte", elapsed_time_firstbyte, "s", FALSE, 0, FALSE, 0, FALSE, 0, FALSE, 0); | ||
1389 | } | ||
1304 | 1390 | ||
1391 | char *perfd_time_transfer (double elapsed_time_transfer) | ||
1392 | { | ||
1393 | return fperfdata ("time_transfer", elapsed_time_transfer, "s", FALSE, 0, FALSE, 0, FALSE, 0, FALSE, 0); | ||
1394 | } | ||
1305 | 1395 | ||
1306 | char *perfd_size (int page_len) | 1396 | char *perfd_size (int page_len) |
1307 | { | 1397 | { |
@@ -1362,6 +1452,8 @@ print_help (void) | |||
1362 | printf (" %s", _("the first (status) line of the server response (default: ")); | 1452 | printf (" %s", _("the first (status) line of the server response (default: ")); |
1363 | printf ("%s)\n", HTTP_EXPECT); | 1453 | printf ("%s)\n", HTTP_EXPECT); |
1364 | printf (" %s\n", _("If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)")); | 1454 | printf (" %s\n", _("If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)")); |
1455 | printf (" %s\n", "-d, --header-string=STRING"); | ||
1456 | printf (" %s\n", _("String to expect in the response headers")); | ||
1365 | printf (" %s\n", "-s, --string=STRING"); | 1457 | printf (" %s\n", "-s, --string=STRING"); |
1366 | printf (" %s\n", _("String to expect in the content")); | 1458 | printf (" %s\n", _("String to expect in the content")); |
1367 | printf (" %s\n", "-u, --url=PATH"); | 1459 | printf (" %s\n", "-u, --url=PATH"); |
@@ -1463,7 +1555,7 @@ print_usage (void) | |||
1463 | printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname); | 1555 | printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname); |
1464 | printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-a auth]\n"); | 1556 | printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-a auth]\n"); |
1465 | printf (" [-b proxy_auth] [-f <ok|warning|critcal|follow|sticky|stickyport>]\n"); | 1557 | printf (" [-b proxy_auth] [-f <ok|warning|critcal|follow|sticky|stickyport>]\n"); |
1466 | printf (" [-e <expect>] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n"); | 1558 | printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n"); |
1467 | printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n"); | 1559 | printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n"); |
1468 | printf (" [-A string] [-k string] [-S <version>] [--sni] [-C <warn_age>[,<crit_age>]]\n"); | 1560 | printf (" [-A string] [-k string] [-S <version>] [--sni] [-C <warn_age>[,<crit_age>]]\n"); |
1469 | printf (" [-T <content-type>] [-j method]\n"); | 1561 | printf (" [-T <content-type>] [-j method]\n"); |