diff options
author | M. Sean Finney <seanius@users.sourceforge.net> | 2005-06-05 17:43:58 +0000 |
---|---|---|
committer | M. Sean Finney <seanius@users.sourceforge.net> | 2005-06-05 17:43:58 +0000 |
commit | 45b373ebdad0c82296342f4ad774db2ff643e511 (patch) | |
tree | 848c9fc447b8fe00a0728183596545933cf351e4 /plugins/check_tcp.c | |
parent | f61bb07f9526444a26e930538ad4dba6ddcd2087 (diff) | |
download | monitoring-plugins-45b373ebdad0c82296342f4ad774db2ff643e511.tar.gz |
check_tcp code cleanup from andreas plus fix to andreas' patch from sean
git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@1189 f882894a-f735-0410-b71e-b25c423dba1c
Diffstat (limited to 'plugins/check_tcp.c')
-rw-r--r-- | plugins/check_tcp.c | 518 |
1 files changed, 242 insertions, 276 deletions
diff --git a/plugins/check_tcp.c b/plugins/check_tcp.c index 3087453a..ad8b0429 100644 --- a/plugins/check_tcp.c +++ b/plugins/check_tcp.c | |||
@@ -47,240 +47,206 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; | |||
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #ifdef HAVE_SSL | 49 | #ifdef HAVE_SSL |
50 | int check_cert = FALSE; | 50 | static int check_cert = FALSE; |
51 | int days_till_exp; | 51 | static int days_till_exp; |
52 | char *randbuff = ""; | 52 | static char *randbuff = ""; |
53 | SSL_CTX *ctx; | 53 | static SSL_CTX *ctx; |
54 | SSL *ssl; | 54 | static SSL *ssl; |
55 | X509 *server_cert; | 55 | static X509 *server_cert; |
56 | int connect_SSL (void); | 56 | static int connect_SSL (void); |
57 | int check_certificate (X509 **); | 57 | static int check_certificate (X509 **); |
58 | # define my_recv(buf, len) ((flags & FLAG_SSL) ? SSL_read(ssl, buf, len) : read(sd, buf, len)) | ||
59 | #else | ||
60 | # define my_recv(buf, len) read(sd, buf, len) | ||
58 | #endif | 61 | #endif |
59 | 62 | ||
60 | #define MAXBUF 1024 | ||
61 | 63 | ||
62 | int process_arguments (int, char **); | 64 | /* int my_recv(char *, size_t); */ |
63 | int my_recv (void); | 65 | static int process_arguments (int, char **); |
64 | void print_help (void); | 66 | void print_help (void); |
65 | void print_usage (void); | 67 | void print_usage (void); |
66 | 68 | ||
67 | char *SERVICE = NULL; | 69 | #define EXPECT server_expect[0] |
68 | char *SEND = NULL; | 70 | static char *SERVICE = "TCP"; |
69 | char *EXPECT = NULL; | 71 | static char *SEND = NULL; |
70 | char *QUIT = NULL; | 72 | static char *QUIT = NULL; |
71 | int PROTOCOL = 0; | 73 | static int PROTOCOL = IPPROTO_TCP; /* most common is default */ |
72 | int PORT = 0; | 74 | static int PORT = 0; |
73 | 75 | ||
74 | char timestamp[17] = ""; | 76 | static char timestamp[17] = ""; |
75 | int server_port = 0; | 77 | static int server_port = 0; |
76 | char *server_address = NULL; | 78 | static char *server_address = NULL; |
77 | char *server_send = NULL; | 79 | static char *server_send = NULL; |
78 | char *server_quit = NULL; | 80 | static char *server_quit = NULL; |
79 | char **server_expect = NULL; | 81 | static char **server_expect; |
80 | size_t server_expect_count = 0; | 82 | static size_t server_expect_count = 0; |
81 | int maxbytes = 0; | 83 | static size_t maxbytes = 0; |
82 | char **warn_codes = NULL; | 84 | static char **warn_codes = NULL; |
83 | size_t warn_codes_count = 0; | 85 | static size_t warn_codes_count = 0; |
84 | char **crit_codes = NULL; | 86 | static char **crit_codes = NULL; |
85 | size_t crit_codes_count = 0; | 87 | static size_t crit_codes_count = 0; |
86 | unsigned int delay = 0; | 88 | static unsigned int delay = 0; |
87 | double warning_time = 0; | 89 | static double warning_time = 0; |
88 | int check_warning_time = FALSE; | 90 | static double critical_time = 0; |
89 | double critical_time = 0; | 91 | static double elapsed_time = 0; |
90 | int check_critical_time = FALSE; | 92 | static long microsec; |
91 | int hide_output = FALSE; | 93 | static int sd = 0; |
92 | double elapsed_time = 0; | 94 | #define MAXBUF 1024 |
93 | long microsec; | 95 | static char buffer[MAXBUF]; |
94 | int verbose = FALSE; | 96 | static int expect_mismatch_state = STATE_WARNING; |
95 | int use_ssl = FALSE; | 97 | |
96 | int sd = 0; | 98 | #define FLAG_SSL 0x01 |
97 | char *buffer; | 99 | #define FLAG_VERBOSE 0x02 |
98 | int expect_mismatch_state = STATE_WARNING; | 100 | #define FLAG_EXACT_MATCH 0x04 |
99 | int exact_matching = TRUE; | 101 | #define FLAG_TIME_WARN 0x08 |
102 | #define FLAG_TIME_CRIT 0x10 | ||
103 | #define FLAG_HIDE_OUTPUT 0x20 | ||
104 | static size_t flags = FLAG_EXACT_MATCH; | ||
100 | 105 | ||
101 | int | 106 | int |
102 | main (int argc, char **argv) | 107 | main (int argc, char **argv) |
103 | { | 108 | { |
104 | int result = STATE_UNKNOWN; | 109 | int result = STATE_UNKNOWN; |
105 | int i; | 110 | int i; |
106 | char *status; | 111 | char *status = NULL; |
107 | struct timeval tv; | 112 | struct timeval tv; |
113 | size_t len, match = -1; | ||
108 | 114 | ||
109 | setlocale (LC_ALL, ""); | 115 | setlocale (LC_ALL, ""); |
110 | bindtextdomain (PACKAGE, LOCALEDIR); | 116 | bindtextdomain (PACKAGE, LOCALEDIR); |
111 | textdomain (PACKAGE); | 117 | textdomain (PACKAGE); |
112 | 118 | ||
113 | if (strstr (argv[0], "check_udp")) { | 119 | /* determine program- and service-name quickly */ |
114 | progname = strdup ("check_udp"); | 120 | progname = strrchr(argv[0], '/'); |
115 | SERVICE = strdup ("UDP"); | 121 | if(progname != NULL) progname++; |
116 | SEND = NULL; | 122 | else progname = argv[0]; |
117 | EXPECT = NULL; | 123 | |
118 | QUIT = NULL; | 124 | len = strlen(progname); |
119 | PROTOCOL = IPPROTO_UDP; | 125 | if(len > 6 && !memcmp(progname, "check_", 6)) { |
120 | PORT = 0; | 126 | SERVICE = progname + 6; |
127 | for(i = 0; i < len - 6; i++) | ||
128 | SERVICE[i] = toupper(SERVICE[i]); | ||
121 | } | 129 | } |
122 | else if (strstr (argv[0], "check_tcp")) { | 130 | |
123 | progname = strdup ("check_tcp"); | 131 | /* set up a resonable buffer at first (will be realloc()'ed if |
124 | SERVICE = strdup ("TCP"); | 132 | * user specifies other options) */ |
125 | SEND = NULL; | 133 | server_expect = calloc(sizeof(char *), 2); |
126 | EXPECT = NULL; | 134 | |
127 | QUIT = NULL; | 135 | /* determine defaults for this service's protocol */ |
128 | PROTOCOL = IPPROTO_TCP; | 136 | if (!strncmp(SERVICE, "UDP", 3)) { |
129 | PORT = 0; | 137 | PROTOCOL = IPPROTO_UDP; |
130 | } | 138 | } |
131 | else if (strstr (argv[0], "check_ftp")) { | 139 | else if (!strncmp(SERVICE, "FTP", 3)) { |
132 | progname = strdup ("check_ftp"); | 140 | EXPECT = "220"; |
133 | SERVICE = strdup ("FTP"); | 141 | QUIT = "QUIT\r\n"; |
134 | SEND = NULL; | ||
135 | EXPECT = strdup ("220"); | ||
136 | QUIT = strdup ("QUIT\r\n"); | ||
137 | PROTOCOL = IPPROTO_TCP; | ||
138 | PORT = 21; | 142 | PORT = 21; |
139 | } | 143 | } |
140 | else if (strstr (argv[0], "check_smtp")) { | 144 | else if (!strncmp(SERVICE, "POP", 3) || !strncmp(SERVICE, "POP3", 4)) { |
141 | progname = strdup ("check_smtp"); | 145 | EXPECT = "+OK"; |
142 | SERVICE = strdup ("SMTP"); | 146 | QUIT = "QUIT\r\n"; |
143 | SEND = NULL; | ||
144 | EXPECT = strdup ("220"); | ||
145 | QUIT = strdup ("QUIT\r\n"); | ||
146 | PROTOCOL = IPPROTO_TCP; | ||
147 | PORT = 25; | ||
148 | } | ||
149 | else if (strstr (argv[0], "check_pop")) { | ||
150 | progname = strdup ("check_pop"); | ||
151 | SERVICE = strdup ("POP"); | ||
152 | SEND = NULL; | ||
153 | EXPECT = strdup ("+OK"); | ||
154 | QUIT = strdup ("QUIT\r\n"); | ||
155 | PROTOCOL = IPPROTO_TCP; | ||
156 | PORT = 110; | 147 | PORT = 110; |
157 | } | 148 | } |
158 | else if (strstr (argv[0], "check_imap")) { | 149 | else if (!strncmp(SERVICE, "SMTP", 4)) { |
159 | progname = strdup ("check_imap"); | 150 | EXPECT = "220"; |
160 | SERVICE = strdup ("IMAP"); | 151 | QUIT = "QUIT\r\n"; |
161 | SEND = NULL; | 152 | PORT = 25; |
162 | EXPECT = strdup ("* OK"); | 153 | } |
163 | QUIT = strdup ("a1 LOGOUT\r\n"); | 154 | else if (!strncmp(SERVICE, "IMAP", 4)) { |
164 | PROTOCOL = IPPROTO_TCP; | 155 | EXPECT = "* OK"; |
156 | QUIT = "a1 LOGOUT\r\n"; | ||
165 | PORT = 143; | 157 | PORT = 143; |
166 | } | 158 | } |
167 | #ifdef HAVE_SSL | 159 | #ifdef HAVE_SSL |
168 | else if (strstr(argv[0],"check_simap")) { | 160 | else if (!strncmp(SERVICE, "SIMAP", 5)) { |
169 | progname = strdup ("check_simap"); | 161 | EXPECT = "* OK"; |
170 | SERVICE = strdup ("SIMAP"); | 162 | QUIT = "a1 LOGOUT\r\n"; |
171 | SEND=NULL; | 163 | flags |= FLAG_SSL; |
172 | EXPECT = strdup ("* OK"); | 164 | PORT = 993; |
173 | QUIT = strdup ("a1 LOGOUT\r\n"); | ||
174 | PROTOCOL=IPPROTO_TCP; | ||
175 | use_ssl=TRUE; | ||
176 | PORT=993; | ||
177 | } | 165 | } |
178 | else if (strstr(argv[0],"check_spop")) { | 166 | else if (!strncmp(SERVICE, "SPOP", 4)) { |
179 | progname = strdup ("check_spop"); | 167 | EXPECT = "+OK"; |
180 | SERVICE = strdup ("SPOP"); | 168 | QUIT = "QUIT\r\n"; |
181 | SEND=NULL; | 169 | flags |= FLAG_SSL; |
182 | EXPECT = strdup ("+OK"); | 170 | PORT = 995; |
183 | QUIT = strdup ("QUIT\r\n"); | ||
184 | PROTOCOL=IPPROTO_TCP; | ||
185 | use_ssl=TRUE; | ||
186 | PORT=995; | ||
187 | } | 171 | } |
188 | else if (strstr(argv[0],"check_ssmtp")) { | 172 | else if (!strncmp(SERVICE, "SSMTP", 5)) { |
189 | progname = strdup ("check_ssmtp"); | 173 | EXPECT = "220"; |
190 | SERVICE = strdup ("SSMTP"); | 174 | QUIT = "QUIT\r\n"; |
191 | SEND=NULL; | 175 | flags |= FLAG_SSL; |
192 | EXPECT = strdup ("220"); | 176 | PORT = 465; |
193 | QUIT = strdup ("QUIT\r\n"); | ||
194 | PROTOCOL=IPPROTO_TCP; | ||
195 | use_ssl=TRUE; | ||
196 | PORT=465; | ||
197 | } | 177 | } |
198 | else if (strstr(argv[0],"check_jabber")) { | 178 | else if (!strncmp(SERVICE, "JABBER", 6)) { |
199 | progname = strdup("check_jabber"); | 179 | SEND = "<stream:stream to=\'host\' xmlns=\'jabber:client\' xmlns:stream=\'http://etherx.jabber.org/streams\'>\n"; |
200 | SERVICE = strdup("JABBER"); | 180 | EXPECT = "<?xml version=\'1.0\'?><stream:stream xmlns:stream=\'http://etherx.jabber.org/streams\'"; |
201 | SEND = strdup("<stream:stream to=\'host\' xmlns=\'jabber:client\' xmlns:stream=\'http://etherx.jabber.org/streams\'>\n"); | 181 | QUIT = "</stream:stream>\n"; |
202 | EXPECT = strdup("<?xml version=\'1.0\'?><stream:stream xmlns:stream=\'http://etherx.jabber.org/streams\'"); | 182 | flags |= FLAG_SSL | FLAG_HIDE_OUTPUT; |
203 | QUIT = strdup("</stream:stream>\n"); | ||
204 | PROTOCOL=IPPROTO_TCP; | ||
205 | use_ssl=TRUE; | ||
206 | PORT = 5222; | 183 | PORT = 5222; |
207 | } | 184 | } |
208 | else if (strstr (argv[0], "check_nntps")) { | 185 | else if (!strncmp (SERVICE, "NNTPS", 5)) { |
209 | progname = strdup("check_nntps"); | 186 | server_expect_count = 2; |
210 | SERVICE = strdup("NNTPS"); | 187 | server_expect[0] = "200"; |
211 | SEND = NULL; | 188 | server_expect[1] = "201"; |
212 | EXPECT = NULL; | 189 | QUIT = "QUIT\r\n"; |
213 | server_expect = realloc (server_expect, ++server_expect_count); | 190 | flags |= FLAG_SSL; |
214 | asprintf (&server_expect[server_expect_count - 1], "200"); | ||
215 | server_expect = realloc (server_expect, ++server_expect_count); | ||
216 | asprintf (&server_expect[server_expect_count - 1], "201"); | ||
217 | QUIT = strdup("QUIT\r\n"); | ||
218 | PROTOCOL = IPPROTO_TCP; | ||
219 | use_ssl=TRUE; | ||
220 | PORT = 563; | 191 | PORT = 563; |
221 | } | 192 | } |
222 | |||
223 | #endif | 193 | #endif |
224 | else if (strstr (argv[0], "check_nntp")) { | 194 | else if (!strncmp (SERVICE, "NNTP", 4)) { |
225 | progname = strdup ("check_nntp"); | 195 | server_expect_count = 2; |
226 | SERVICE = strdup ("NNTP"); | 196 | server_expect = malloc(sizeof(char *) * server_expect_count); |
227 | SEND = NULL; | 197 | server_expect[0] = strdup("200"); |
228 | EXPECT = NULL; | 198 | server_expect[1] = strdup("201"); |
229 | server_expect = realloc (server_expect, sizeof (char *) * (++server_expect_count)); | 199 | QUIT = "QUIT\r\n"; |
230 | asprintf (&server_expect[server_expect_count - 1], "200"); | ||
231 | server_expect = realloc (server_expect, sizeof (char *) * (++server_expect_count)); | ||
232 | asprintf (&server_expect[server_expect_count - 1], "201"); | ||
233 | asprintf (&QUIT, "QUIT\r\n"); | ||
234 | PROTOCOL = IPPROTO_TCP; | ||
235 | PORT = 119; | 200 | PORT = 119; |
236 | } | 201 | } |
237 | else { | 202 | /* fallthrough check, so it's supposed to use reverse matching */ |
238 | progname = strdup ("check_tcp"); | 203 | else if (strcmp (SERVICE, "TCP")) |
239 | usage (_("CRITICAL - Generic check_tcp called with unknown service\n")); | 204 | usage (_("CRITICAL - Generic check_tcp called with unknown service\n")); |
240 | } | ||
241 | 205 | ||
242 | server_address = strdup ("127.0.0.1"); | 206 | server_address = "127.0.0.1"; |
243 | server_port = PORT; | 207 | server_port = PORT; |
244 | server_send = SEND; | 208 | server_send = SEND; |
245 | server_quit = QUIT; | 209 | server_quit = QUIT; |
246 | status = strdup (""); | 210 | status = NULL; |
247 | 211 | ||
248 | if (process_arguments (argc, argv) == ERROR) | 212 | if (process_arguments (argc, argv) == ERROR) |
249 | usage4 (_("Could not parse arguments")); | 213 | usage4 (_("Could not parse arguments")); |
250 | 214 | ||
251 | /* use default expect if none listed in process_arguments() */ | 215 | if(flags & FLAG_VERBOSE) { |
252 | if (EXPECT && server_expect_count == 0) { | 216 | printf("Using service %s\n", SERVICE); |
253 | server_expect = malloc (sizeof (char *) * (++server_expect_count)); | 217 | printf("Port: %d\n", PORT); |
254 | server_expect[server_expect_count - 1] = EXPECT; | 218 | printf("flags: 0x%x\n", flags); |
255 | } | 219 | } |
256 | 220 | ||
257 | /* initialize alarm signal handling */ | 221 | if(EXPECT && !server_expect_count) |
258 | signal (SIGALRM, socket_timeout_alarm_handler); | 222 | server_expect_count++; |
259 | 223 | ||
260 | /* set socket timeout */ | 224 | /* set up the timer */ |
225 | signal (SIGALRM, socket_timeout_alarm_handler); | ||
261 | alarm (socket_timeout); | 226 | alarm (socket_timeout); |
262 | 227 | ||
263 | /* try to connect to the host at the given port number */ | 228 | /* try to connect to the host at the given port number */ |
264 | gettimeofday (&tv, NULL); | 229 | gettimeofday (&tv, NULL); |
265 | #ifdef HAVE_SSL | 230 | #ifdef HAVE_SSL |
266 | if (use_ssl && check_cert == TRUE) { | 231 | if (flags & FLAG_SSL && check_cert == TRUE) { |
267 | if (connect_SSL () != OK) | 232 | if (connect_SSL () != OK) |
268 | die (STATE_CRITICAL,_("CRITICAL - Could not make SSL connection\n")); | 233 | die (STATE_CRITICAL,_("CRITICAL - Could not make SSL connection\n")); |
269 | if ((server_cert = SSL_get_peer_certificate (ssl)) != NULL) { | 234 | if ((server_cert = SSL_get_peer_certificate (ssl)) != NULL) { |
270 | result = check_certificate (&server_cert); | 235 | result = check_certificate (&server_cert); |
271 | X509_free(server_cert); | 236 | X509_free(server_cert); |
272 | } | 237 | } |
273 | else { | 238 | else { |
274 | printf(_("CRITICAL - Cannot retrieve server certificate.\n")); | 239 | printf(_("CRITICAL - Cannot retrieve server certificate.\n")); |
275 | result = STATE_CRITICAL; | 240 | result = STATE_CRITICAL; |
276 | } | 241 | } |
277 | SSL_shutdown (ssl); | 242 | |
278 | SSL_free (ssl); | 243 | SSL_shutdown (ssl); |
279 | SSL_CTX_free (ctx); | 244 | SSL_free (ssl); |
280 | close (sd); | 245 | SSL_CTX_free (ctx); |
281 | return result; | 246 | close (sd); |
247 | return result; | ||
282 | } | 248 | } |
283 | else if (use_ssl) | 249 | else if (flags & FLAG_SSL) |
284 | result = connect_SSL (); | 250 | result = connect_SSL (); |
285 | else | 251 | else |
286 | #endif | 252 | #endif |
@@ -290,9 +256,8 @@ main (int argc, char **argv) | |||
290 | return STATE_CRITICAL; | 256 | return STATE_CRITICAL; |
291 | 257 | ||
292 | if (server_send != NULL) { /* Something to send? */ | 258 | if (server_send != NULL) { /* Something to send? */ |
293 | asprintf (&server_send, "%s\r\n", server_send); | ||
294 | #ifdef HAVE_SSL | 259 | #ifdef HAVE_SSL |
295 | if (use_ssl) | 260 | if (flags & FLAG_SSL) |
296 | SSL_write(ssl, server_send, (int)strlen(server_send)); | 261 | SSL_write(ssl, server_send, (int)strlen(server_send)); |
297 | else | 262 | else |
298 | #endif | 263 | #endif |
@@ -304,63 +269,71 @@ main (int argc, char **argv) | |||
304 | sleep (delay); | 269 | sleep (delay); |
305 | } | 270 | } |
306 | 271 | ||
307 | if (server_send || server_expect_count > 0) { | 272 | if(flags & FLAG_VERBOSE) { |
273 | printf("server_expect_count: %d\n", server_expect_count); | ||
274 | for(i = 0; i < server_expect_count; i++) | ||
275 | printf("\t%d: %s\n", i, server_expect[i]); | ||
276 | } | ||
277 | |||
278 | /* if(len) later on, we know we have a non-NULL response */ | ||
279 | len = 0; | ||
280 | if (server_expect_count) { | ||
308 | 281 | ||
309 | buffer = malloc (MAXBUF); | ||
310 | memset (buffer, '\0', MAXBUF); | ||
311 | /* watch for the expect string */ | 282 | /* watch for the expect string */ |
312 | while ((i = my_recv ()) > 0) { | 283 | while ((i = my_recv(buffer, sizeof(buffer))) > 0) { |
313 | buffer[i] = '\0'; | 284 | status = realloc(status, len + i + 1); |
314 | asprintf (&status, "%s%s", status, buffer); | 285 | memcpy(&status[len], buffer, i); |
315 | if (buffer[i-1] == '\n') { | 286 | len += i; |
316 | if (buffer[i-2] == '\r' || i < MAXBUF-1) | 287 | |
317 | break; | 288 | /* stop reading if user-forced or data-starved */ |
318 | } | 289 | if(i < sizeof(buffer) || (maxbytes && len >= maxbytes)) |
319 | if (maxbytes>0 && strlen(status) >= (unsigned)maxbytes) | 290 | break; |
291 | |||
292 | if (maxbytes && len >= maxbytes) | ||
320 | break; | 293 | break; |
321 | } | 294 | } |
322 | 295 | ||
323 | /* return a CRITICAL status if we couldn't read any data */ | 296 | /* no data when expected, so return critical */ |
324 | if (strlen(status) == 0) | 297 | if (len == 0) |
325 | die (STATE_CRITICAL, _("No data received from host\n")); | 298 | die (STATE_CRITICAL, _("No data received from host\n")); |
326 | 299 | ||
327 | strip (status); | 300 | /* force null-termination and strip whitespace from end of output */ |
328 | 301 | status[len--] = '\0'; | |
329 | if (status && verbose) | 302 | /* print raw output if we're debugging */ |
330 | printf ("%s\n", status); | 303 | if(flags & FLAG_VERBOSE) |
331 | 304 | printf("received %d bytes from host\n#-raw-recv-------#\n%s\n#-raw-recv-------#\n", | |
332 | if (server_expect_count > 0) { | 305 | len + 1, status); |
333 | for (i = 0;; i++) { | 306 | while(isspace(status[len])) status[len--] = '\0'; |
334 | if (verbose) | 307 | |
335 | printf ("%d %d\n", i, (int)server_expect_count); | 308 | for (i = 0; i < server_expect_count; i++) { |
336 | if (i >= (int)server_expect_count) | 309 | match = -2; /* tag it so we know if we tried and failed */ |
337 | die (expect_mismatch_state, _("Unexpected response from host: %s\n"), status); | 310 | if (flags & FLAG_VERBOSE) |
338 | /* default expect gets exact matching */ | 311 | printf ("looking for [%s] %s [%s]\n", server_expect[i], |
339 | if (exact_matching) { | 312 | (flags & FLAG_EXACT_MATCH) ? "in beginning of" : "anywhere in", |
340 | if (strncmp(status, server_expect[i], strlen(server_expect[i])) == 0) | 313 | status); |
341 | break; | 314 | |
342 | } else { | 315 | /* match it. math first in short-circuit */ |
343 | if (strstr (status, server_expect[i])) | 316 | if ((flags & FLAG_EXACT_MATCH && !strncmp(status, server_expect[i], strlen(server_expect[i]))) || |
344 | break; | 317 | (!(flags & FLAG_EXACT_MATCH) && strstr(status, server_expect[i]))) |
345 | } | 318 | { |
319 | if(flags & FLAG_VERBOSE) puts("found it"); | ||
320 | match = i; | ||
321 | break; | ||
346 | } | 322 | } |
347 | } | 323 | } |
348 | } | 324 | } |
349 | 325 | ||
350 | if (server_quit != NULL) { | 326 | if (server_quit != NULL) { |
351 | #ifdef HAVE_SSL | 327 | #ifdef HAVE_SSL |
352 | if (use_ssl) { | 328 | if (flags & FLAG_SSL) { |
353 | SSL_write (ssl, server_quit, (int)strlen(server_quit)); | 329 | SSL_write (ssl, server_quit, (int)strlen(server_quit)); |
354 | SSL_shutdown (ssl); | 330 | SSL_shutdown (ssl); |
355 | SSL_free (ssl); | 331 | SSL_free (ssl); |
356 | SSL_CTX_free (ctx); | 332 | SSL_CTX_free (ctx); |
357 | } | 333 | } |
358 | else { | 334 | else |
359 | #endif | 335 | #endif |
360 | send (sd, server_quit, strlen (server_quit), 0); | 336 | send (sd, server_quit, strlen (server_quit), 0); |
361 | #ifdef HAVE_SSL | ||
362 | } | ||
363 | #endif | ||
364 | } | 337 | } |
365 | 338 | ||
366 | /* close the connection */ | 339 | /* close the connection */ |
@@ -370,37 +343,53 @@ main (int argc, char **argv) | |||
370 | microsec = deltime (tv); | 343 | microsec = deltime (tv); |
371 | elapsed_time = (double)microsec / 1.0e6; | 344 | elapsed_time = (double)microsec / 1.0e6; |
372 | 345 | ||
373 | if (check_critical_time == TRUE && elapsed_time > critical_time) | 346 | if (flags & FLAG_TIME_CRIT && elapsed_time > critical_time) |
374 | result = STATE_CRITICAL; | 347 | result = STATE_CRITICAL; |
375 | else if (check_warning_time == TRUE && elapsed_time > warning_time) | 348 | else if (flags & FLAG_TIME_WARN && elapsed_time > warning_time) |
349 | result = STATE_WARNING; | ||
350 | |||
351 | /* did we get the response we hoped? */ | ||
352 | if(match == -2 && result != STATE_CRITICAL) | ||
376 | result = STATE_WARNING; | 353 | result = STATE_WARNING; |
377 | 354 | ||
378 | /* reset the alarm */ | 355 | /* reset the alarm */ |
379 | alarm (0); | 356 | alarm (0); |
380 | 357 | ||
381 | printf | 358 | /* this is a bit stupid, because we don't want to print the |
382 | (_("%s %s%s - %.3f second response time on port %d"), | 359 | * response time (which can look ok to the user) if we didn't get |
383 | SERVICE, | 360 | * the response we were looking for. if-else */ |
384 | state_text (result), | 361 | printf(_("%s %s - "), SERVICE, state_text(result)); |
385 | (was_refused) ? " (refused)" : "", | ||
386 | elapsed_time, server_port); | ||
387 | 362 | ||
388 | if (hide_output == FALSE && status && strlen(status) > 0) | 363 | if(match == -2 && len && !(flags & FLAG_HIDE_OUTPUT)) |
389 | printf (" [%s]", status); | 364 | printf("Unexpected response from host: %s", status); |
365 | else | ||
366 | printf("%.3f second response time on port %d", | ||
367 | elapsed_time, server_port); | ||
390 | 368 | ||
391 | printf (" |%s\n", fperfdata ("time", elapsed_time, "s", | 369 | if (match != -2 && !(flags & FLAG_HIDE_OUTPUT) && len) |
392 | TRUE, warning_time, | 370 | printf (" [%s]", status); |
393 | TRUE, critical_time, | ||
394 | TRUE, 0, | ||
395 | TRUE, socket_timeout)); | ||
396 | 371 | ||
372 | /* perf-data doesn't apply when server doesn't talk properly, | ||
373 | * so print all zeroes on warn and crit */ | ||
374 | if(match == -2) | ||
375 | printf ("|time=%fs;0.0;0.0;0.0;0.0", elapsed_time); | ||
376 | else | ||
377 | printf("|%s", | ||
378 | fperfdata ("time", elapsed_time, "s", | ||
379 | TRUE, warning_time, | ||
380 | TRUE, critical_time, | ||
381 | TRUE, 0, | ||
382 | TRUE, socket_timeout) | ||
383 | ); | ||
384 | |||
385 | putchar('\n'); | ||
397 | return result; | 386 | return result; |
398 | } | 387 | } |
399 | 388 | ||
400 | 389 | ||
401 | 390 | ||
402 | /* process command-line arguments */ | 391 | /* process command-line arguments */ |
403 | int | 392 | static int |
404 | process_arguments (int argc, char **argv) | 393 | process_arguments (int argc, char **argv) |
405 | { | 394 | { |
406 | int c; | 395 | int c; |
@@ -472,7 +461,7 @@ process_arguments (int argc, char **argv) | |||
472 | print_revision (progname, revision); | 461 | print_revision (progname, revision); |
473 | exit (STATE_OK); | 462 | exit (STATE_OK); |
474 | case 'v': /* verbose mode */ | 463 | case 'v': /* verbose mode */ |
475 | verbose = TRUE; | 464 | flags |= FLAG_VERBOSE; |
476 | break; | 465 | break; |
477 | case '4': | 466 | case '4': |
478 | address_family = AF_INET; | 467 | address_family = AF_INET; |
@@ -494,17 +483,17 @@ process_arguments (int argc, char **argv) | |||
494 | usage4 (_("Critical threshold must be a positive integer")); | 483 | usage4 (_("Critical threshold must be a positive integer")); |
495 | else | 484 | else |
496 | critical_time = strtod (optarg, NULL); | 485 | critical_time = strtod (optarg, NULL); |
497 | check_critical_time = TRUE; | 486 | flags |= FLAG_TIME_CRIT; |
498 | break; | 487 | break; |
499 | case 'j': /* hide output */ | 488 | case 'j': /* hide output */ |
500 | hide_output = TRUE; | 489 | flags |= FLAG_HIDE_OUTPUT; |
501 | break; | 490 | break; |
502 | case 'w': /* warning */ | 491 | case 'w': /* warning */ |
503 | if (!is_intnonneg (optarg)) | 492 | if (!is_intnonneg (optarg)) |
504 | usage4 (_("Warning threshold must be a positive integer")); | 493 | usage4 (_("Warning threshold must be a positive integer")); |
505 | else | 494 | else |
506 | warning_time = strtod (optarg, NULL); | 495 | warning_time = strtod (optarg, NULL); |
507 | check_warning_time = TRUE; | 496 | flags |= FLAG_TIME_WARN; |
508 | break; | 497 | break; |
509 | case 'C': | 498 | case 'C': |
510 | crit_codes = realloc (crit_codes, ++crit_codes_count); | 499 | crit_codes = realloc (crit_codes, ++crit_codes_count); |
@@ -531,7 +520,7 @@ process_arguments (int argc, char **argv) | |||
531 | break; | 520 | break; |
532 | case 'e': /* expect string (may be repeated) */ | 521 | case 'e': /* expect string (may be repeated) */ |
533 | EXPECT = NULL; | 522 | EXPECT = NULL; |
534 | exact_matching = FALSE; | 523 | flags &= ~FLAG_EXACT_MATCH; |
535 | if (server_expect_count == 0) | 524 | if (server_expect_count == 0) |
536 | server_expect = malloc (sizeof (char *) * (++server_expect_count)); | 525 | server_expect = malloc (sizeof (char *) * (++server_expect_count)); |
537 | else | 526 | else |
@@ -542,7 +531,7 @@ process_arguments (int argc, char **argv) | |||
542 | if (!is_intpos (optarg)) | 531 | if (!is_intpos (optarg)) |
543 | usage4 (_("Maxbytes must be a positive integer")); | 532 | usage4 (_("Maxbytes must be a positive integer")); |
544 | else | 533 | else |
545 | maxbytes = atoi (optarg); | 534 | maxbytes = strtol (optarg, NULL, 0); |
546 | case 'q': | 535 | case 'q': |
547 | asprintf(&server_quit, "%s\r\n", optarg); | 536 | asprintf(&server_quit, "%s\r\n", optarg); |
548 | break; | 537 | break; |
@@ -572,16 +561,19 @@ process_arguments (int argc, char **argv) | |||
572 | else | 561 | else |
573 | usage4 (_("Delay must be a positive integer")); | 562 | usage4 (_("Delay must be a positive integer")); |
574 | break; | 563 | break; |
575 | case 'D': /* Check SSL cert validity - days 'til certificate expiration */ | 564 | case 'D': /* Check SSL cert validity - days 'til certificate expiration */ |
576 | #ifdef HAVE_SSL | 565 | #ifdef HAVE_SSL |
577 | if (!is_intnonneg (optarg)) | 566 | if (!is_intnonneg (optarg)) |
578 | usage2 (_("Invalid certificate expiration period"), optarg); | 567 | usage2 (_("Invalid certificate expiration period"), optarg); |
579 | days_till_exp = atoi (optarg); | 568 | days_till_exp = atoi (optarg); |
580 | check_cert = TRUE; | 569 | check_cert = TRUE; |
581 | use_ssl = TRUE; | 570 | flags |= FLAG_SSL; |
582 | break; | 571 | break; |
572 | #endif | ||
573 | /* fallthrough if we don't have ssl */ | ||
583 | case 'S': | 574 | case 'S': |
584 | use_ssl = TRUE; | 575 | #ifdef HAVE_SSL |
576 | flags |= FLAG_SSL; | ||
585 | #else | 577 | #else |
586 | die (STATE_UNKNOWN, _("Invalid option - SSL is not available")); | 578 | die (STATE_UNKNOWN, _("Invalid option - SSL is not available")); |
587 | #endif | 579 | #endif |
@@ -596,9 +588,9 @@ process_arguments (int argc, char **argv) | |||
596 | } | 588 | } |
597 | 589 | ||
598 | 590 | ||
599 | 591 | /* SSL-specific functions */ | |
600 | #ifdef HAVE_SSL | 592 | #ifdef HAVE_SSL |
601 | int | 593 | static int |
602 | connect_SSL (void) | 594 | connect_SSL (void) |
603 | { | 595 | { |
604 | SSL_METHOD *meth; | 596 | SSL_METHOD *meth; |
@@ -649,12 +641,8 @@ connect_SSL (void) | |||
649 | 641 | ||
650 | return STATE_CRITICAL; | 642 | return STATE_CRITICAL; |
651 | } | 643 | } |
652 | #endif | ||
653 | |||
654 | |||
655 | 644 | ||
656 | #ifdef HAVE_SSL | 645 | static int |
657 | int | ||
658 | check_certificate (X509 ** certificate) | 646 | check_certificate (X509 ** certificate) |
659 | { | 647 | { |
660 | ASN1_STRING *tm; | 648 | ASN1_STRING *tm; |
@@ -727,29 +715,7 @@ check_certificate (X509 ** certificate) | |||
727 | 715 | ||
728 | return STATE_OK; | 716 | return STATE_OK; |
729 | } | 717 | } |
730 | #endif | 718 | #endif /* HAVE_SSL */ |
731 | |||
732 | |||
733 | |||
734 | int | ||
735 | my_recv (void) | ||
736 | { | ||
737 | int i; | ||
738 | |||
739 | #ifdef HAVE_SSL | ||
740 | if (use_ssl) { | ||
741 | i = SSL_read (ssl, buffer, MAXBUF - 1); | ||
742 | } | ||
743 | else { | ||
744 | #endif | ||
745 | i = read (sd, buffer, MAXBUF - 1); | ||
746 | #ifdef HAVE_SSL | ||
747 | } | ||
748 | #endif | ||
749 | |||
750 | return i; | ||
751 | } | ||
752 | |||
753 | 719 | ||
754 | 720 | ||
755 | void | 721 | void |
@@ -809,7 +775,6 @@ print_help (void) | |||
809 | } | 775 | } |
810 | 776 | ||
811 | 777 | ||
812 | |||
813 | void | 778 | void |
814 | print_usage (void) | 779 | print_usage (void) |
815 | { | 780 | { |
@@ -818,5 +783,6 @@ Usage: %s -H host -p port [-w <warning time>] [-c <critical time>]\n\ | |||
818 | [-s <send string>] [-e <expect string>] [-q <quit string>]\n\ | 783 | [-s <send string>] [-e <expect string>] [-q <quit string>]\n\ |
819 | [-m <maximum bytes>] [-d <delay>] [-t <timeout seconds>]\n\ | 784 | [-m <maximum bytes>] [-d <delay>] [-t <timeout seconds>]\n\ |
820 | [-r <refuse state>] [-M <mismatch state>] [-v] [-4|-6] [-j]\n\ | 785 | [-r <refuse state>] [-M <mismatch state>] [-v] [-4|-6] [-j]\n\ |
821 | [-D <days to cert expiry>] [-S <use SSL>]\n", progname); | 786 | [-D <days to cert expiry>] [-S <use SSL>]\n", progname); |
822 | } | 787 | } |
788 | |||