summaryrefslogtreecommitdiffstats
path: root/plugins/check_tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_tcp.c')
-rw-r--r--plugins/check_tcp.c600
1 files changed, 281 insertions, 319 deletions
diff --git a/plugins/check_tcp.c b/plugins/check_tcp.c
index 01dd35e..49ad096 100644
--- a/plugins/check_tcp.c
+++ b/plugins/check_tcp.c
@@ -1,35 +1,35 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_tcp plugin 3 * Monitoring check_tcp plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2013 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_tcp plugin 10 * This file contains the check_tcp plugin
11* 11 *
12* 12 *
13* This program is free software: you can redistribute it and/or modify 13 * This program is free software: you can redistribute it and/or modify
14* it under the terms of the GNU General Public License as published by 14 * it under the terms of the GNU General Public License as published by
15* the Free Software Foundation, either version 3 of the License, or 15 * the Free Software Foundation, either version 3 of the License, or
16* (at your option) any later version. 16 * (at your option) any later version.
17* 17 *
18* This program is distributed in the hope that it will be useful, 18 * This program is distributed in the hope that it will be useful,
19* but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21* GNU General Public License for more details. 21 * GNU General Public License for more details.
22* 22 *
23* You should have received a copy of the GNU General Public License 23 * You should have received a copy of the GNU General Public License
24* along with this program. If not, see <http://www.gnu.org/licenses/>. 24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25* 25 *
26* $Id$ 26 * $Id$
27* 27 *
28*****************************************************************************/ 28 *****************************************************************************/
29 29
30/* progname "check_tcp" changes depending on symlink called */ 30/* progname "check_tcp" changes depending on symlink called */
31char *progname; 31char *progname;
32const char *copyright = "1999-2008"; 32const char *copyright = "1999-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
@@ -43,17 +43,17 @@ const char *email = "devel@monitoring-plugins.org";
43#ifdef HAVE_SSL 43#ifdef HAVE_SSL
44static bool check_cert = false; 44static bool check_cert = false;
45static int days_till_exp_warn, days_till_exp_crit; 45static int days_till_exp_warn, days_till_exp_crit;
46# define my_recv(buf, len) ((flags & FLAG_SSL) ? np_net_ssl_read(buf, len) : read(sd, buf, len)) 46# define my_recv(buf, len) ((flags & FLAG_SSL) ? np_net_ssl_read(buf, len) : read(sd, buf, len))
47# define my_send(buf, len) ((flags & FLAG_SSL) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0)) 47# define my_send(buf, len) ((flags & FLAG_SSL) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0))
48#else 48#else
49# define my_recv(buf, len) read(sd, buf, len) 49# define my_recv(buf, len) read(sd, buf, len)
50# define my_send(buf, len) send(sd, buf, len, 0) 50# define my_send(buf, len) send(sd, buf, len, 0)
51#endif 51#endif
52 52
53/* int my_recv(char *, size_t); */ 53/* int my_recv(char *, size_t); */
54static int process_arguments (int, char **); 54static int process_arguments(int /*argc*/, char ** /*argv*/);
55void print_help (void); 55static void print_help(void);
56void print_usage (void); 56void print_usage(void);
57 57
58#define EXPECT server_expect[0] 58#define EXPECT server_expect[0]
59static char *SERVICE = "TCP"; 59static char *SERVICE = "TCP";
@@ -91,65 +91,52 @@ static char *sni = NULL;
91static bool sni_specified = false; 91static bool sni_specified = false;
92#endif 92#endif
93 93
94#define FLAG_SSL 0x01 94#define FLAG_SSL 0x01
95#define FLAG_VERBOSE 0x02 95#define FLAG_VERBOSE 0x02
96#define FLAG_TIME_WARN 0x04 96#define FLAG_TIME_WARN 0x04
97#define FLAG_TIME_CRIT 0x08 97#define FLAG_TIME_CRIT 0x08
98#define FLAG_HIDE_OUTPUT 0x10 98#define FLAG_HIDE_OUTPUT 0x10
99static size_t flags; 99static size_t flags;
100 100
101int 101int main(int argc, char **argv) {
102main (int argc, char **argv) 102 setlocale(LC_ALL, "");
103{ 103 bindtextdomain(PACKAGE, LOCALEDIR);
104 int result = STATE_UNKNOWN; 104 textdomain(PACKAGE);
105 char *status = NULL;
106 struct timeval tv;
107 struct timeval timeout;
108 int match = -1;
109 fd_set rfds;
110
111 FD_ZERO(&rfds);
112
113 setlocale (LC_ALL, "");
114 bindtextdomain (PACKAGE, LOCALEDIR);
115 textdomain (PACKAGE);
116 105
117 /* determine program- and service-name quickly */ 106 /* determine program- and service-name quickly */
118 progname = strrchr(argv[0], '/'); 107 progname = strrchr(argv[0], '/');
119 if(progname != NULL) progname++; 108 if (progname != NULL)
120 else progname = argv[0]; 109 progname++;
110 else
111 progname = argv[0];
121 112
122 size_t prog_name_len = strlen(progname); 113 size_t prog_name_len = strlen(progname);
123 if(prog_name_len > 6 && !memcmp(progname, "check_", 6)) { 114 if (prog_name_len > 6 && !memcmp(progname, "check_", 6)) {
124 SERVICE = strdup(progname + 6); 115 SERVICE = strdup(progname + 6);
125 for(size_t i = 0; i < prog_name_len - 6; i++) 116 for (size_t i = 0; i < prog_name_len - 6; i++)
126 SERVICE[i] = toupper(SERVICE[i]); 117 SERVICE[i] = toupper(SERVICE[i]);
127 } 118 }
128 119
129 /* set up a reasonable buffer at first (will be realloc()'ed if 120 /* set up a reasonable buffer at first (will be realloc()'ed if
130 * user specifies other options) */ 121 * user specifies other options) */
131 server_expect = calloc(sizeof(char *), 2); 122 server_expect = calloc(2, sizeof(char *));
132 123
133 /* determine defaults for this service's protocol */ 124 /* determine defaults for this service's protocol */
134 if (!strncmp(SERVICE, "UDP", 3)) { 125 if (!strncmp(SERVICE, "UDP", 3)) {
135 PROTOCOL = IPPROTO_UDP; 126 PROTOCOL = IPPROTO_UDP;
136 } 127 } else if (!strncmp(SERVICE, "FTP", 3)) {
137 else if (!strncmp(SERVICE, "FTP", 3)) {
138 EXPECT = "220"; 128 EXPECT = "220";
139 QUIT = "QUIT\r\n"; 129 QUIT = "QUIT\r\n";
140 PORT = 21; 130 PORT = 21;
141 } 131 } else if (!strncmp(SERVICE, "POP", 3) || !strncmp(SERVICE, "POP3", 4)) {
142 else if (!strncmp(SERVICE, "POP", 3) || !strncmp(SERVICE, "POP3", 4)) {
143 EXPECT = "+OK"; 132 EXPECT = "+OK";
144 QUIT = "QUIT\r\n"; 133 QUIT = "QUIT\r\n";
145 PORT = 110; 134 PORT = 110;
146 } 135 } else if (!strncmp(SERVICE, "SMTP", 4)) {
147 else if (!strncmp(SERVICE, "SMTP", 4)) {
148 EXPECT = "220"; 136 EXPECT = "220";
149 QUIT = "QUIT\r\n"; 137 QUIT = "QUIT\r\n";
150 PORT = 25; 138 PORT = 25;
151 } 139 } else if (!strncmp(SERVICE, "IMAP", 4)) {
152 else if (!strncmp(SERVICE, "IMAP", 4)) {
153 EXPECT = "* OK"; 140 EXPECT = "* OK";
154 QUIT = "a1 LOGOUT\r\n"; 141 QUIT = "a1 LOGOUT\r\n";
155 PORT = 143; 142 PORT = 143;
@@ -160,27 +147,23 @@ main (int argc, char **argv)
160 QUIT = "a1 LOGOUT\r\n"; 147 QUIT = "a1 LOGOUT\r\n";
161 flags |= FLAG_SSL; 148 flags |= FLAG_SSL;
162 PORT = 993; 149 PORT = 993;
163 } 150 } else if (!strncmp(SERVICE, "SPOP", 4)) {
164 else if (!strncmp(SERVICE, "SPOP", 4)) {
165 EXPECT = "+OK"; 151 EXPECT = "+OK";
166 QUIT = "QUIT\r\n"; 152 QUIT = "QUIT\r\n";
167 flags |= FLAG_SSL; 153 flags |= FLAG_SSL;
168 PORT = 995; 154 PORT = 995;
169 } 155 } else if (!strncmp(SERVICE, "SSMTP", 5)) {
170 else if (!strncmp(SERVICE, "SSMTP", 5)) {
171 EXPECT = "220"; 156 EXPECT = "220";
172 QUIT = "QUIT\r\n"; 157 QUIT = "QUIT\r\n";
173 flags |= FLAG_SSL; 158 flags |= FLAG_SSL;
174 PORT = 465; 159 PORT = 465;
175 } 160 } else if (!strncmp(SERVICE, "JABBER", 6)) {
176 else if (!strncmp(SERVICE, "JABBER", 6)) {
177 SEND = "<stream:stream to=\'host\' xmlns=\'jabber:client\' xmlns:stream=\'http://etherx.jabber.org/streams\'>\n"; 161 SEND = "<stream:stream to=\'host\' xmlns=\'jabber:client\' xmlns:stream=\'http://etherx.jabber.org/streams\'>\n";
178 EXPECT = "<?xml version=\'1.0\'"; 162 EXPECT = "<?xml version=\'1.0\'";
179 QUIT = "</stream:stream>\n"; 163 QUIT = "</stream:stream>\n";
180 flags |= FLAG_HIDE_OUTPUT; 164 flags |= FLAG_HIDE_OUTPUT;
181 PORT = 5222; 165 PORT = 5222;
182 } 166 } else if (!strncmp(SERVICE, "NNTPS", 5)) {
183 else if (!strncmp (SERVICE, "NNTPS", 5)) {
184 server_expect_count = 2; 167 server_expect_count = 2;
185 server_expect[0] = "200"; 168 server_expect[0] = "200";
186 server_expect[1] = "201"; 169 server_expect[1] = "201";
@@ -189,83 +172,86 @@ main (int argc, char **argv)
189 PORT = 563; 172 PORT = 563;
190 } 173 }
191#endif 174#endif
192 else if (!strncmp (SERVICE, "NNTP", 4)) { 175 else if (!strncmp(SERVICE, "NNTP", 4)) {
193 server_expect_count = 2; 176 server_expect_count = 2;
194 server_expect = malloc(sizeof(char *) * server_expect_count); 177 server_expect = malloc(sizeof(char *) * server_expect_count);
195 server_expect[0] = strdup("200"); 178 server_expect[0] = strdup("200");
196 server_expect[1] = strdup("201"); 179 server_expect[1] = strdup("201");
197 QUIT = "QUIT\r\n"; 180 QUIT = "QUIT\r\n";
198 PORT = 119; 181 PORT = 119;
199 } 182 } else if (!strncmp(SERVICE, "CLAMD", 5)) {
200 else if (!strncmp(SERVICE, "CLAMD", 5)) {
201 SEND = "PING"; 183 SEND = "PING";
202 EXPECT = "PONG"; 184 EXPECT = "PONG";
203 QUIT = NULL; 185 QUIT = NULL;
204 PORT = 3310; 186 PORT = 3310;
205 } 187 }
206 /* fallthrough check, so it's supposed to use reverse matching */ 188 /* fallthrough check, so it's supposed to use reverse matching */
207 else if (strcmp (SERVICE, "TCP")) 189 else if (strcmp(SERVICE, "TCP"))
208 usage (_("CRITICAL - Generic check_tcp called with unknown service\n")); 190 usage(_("CRITICAL - Generic check_tcp called with unknown service\n"));
209 191
210 server_address = "127.0.0.1"; 192 server_address = "127.0.0.1";
211 server_port = PORT; 193 server_port = PORT;
212 server_send = SEND; 194 server_send = SEND;
213 server_quit = QUIT; 195 server_quit = QUIT;
214 status = NULL; 196 char *status = NULL;
215 197
216 /* Parse extra opts if any */ 198 /* Parse extra opts if any */
217 argv=np_extra_opts (&argc, argv, progname); 199 argv = np_extra_opts(&argc, argv, progname);
218 200
219 if (process_arguments (argc, argv) == ERROR) 201 if (process_arguments(argc, argv) == ERROR)
220 usage4 (_("Could not parse arguments")); 202 usage4(_("Could not parse arguments"));
221 203
222 if(flags & FLAG_VERBOSE) { 204 if (flags & FLAG_VERBOSE) {
223 printf("Using service %s\n", SERVICE); 205 printf("Using service %s\n", SERVICE);
224 printf("Port: %d\n", server_port); 206 printf("Port: %d\n", server_port);
225 printf("flags: 0x%x\n", (int)flags); 207 printf("flags: 0x%x\n", (int)flags);
226 } 208 }
227 209
228 if(EXPECT && !server_expect_count) 210 if (EXPECT && !server_expect_count)
229 server_expect_count++; 211 server_expect_count++;
230 212
231 if(PROTOCOL==IPPROTO_UDP && !(server_expect_count && server_send)){ 213 if (PROTOCOL == IPPROTO_UDP && !(server_expect_count && server_send)) {
232 usage(_("With UDP checks, a send/expect string must be specified.")); 214 usage(_("With UDP checks, a send/expect string must be specified."));
233 } 215 }
234 216
235 /* set up the timer */ 217 /* set up the timer */
236 signal (SIGALRM, socket_timeout_alarm_handler); 218 signal(SIGALRM, socket_timeout_alarm_handler);
237 alarm (socket_timeout); 219 alarm(socket_timeout);
238 220
239 /* try to connect to the host at the given port number */ 221 /* try to connect to the host at the given port number */
240 gettimeofday (&tv, NULL); 222 struct timeval tv;
223 gettimeofday(&tv, NULL);
241 224
242 result = np_net_connect (server_address, server_port, &sd, PROTOCOL); 225 int result = STATE_UNKNOWN;
243 if (result == STATE_CRITICAL) return econn_refuse_state; 226 result = np_net_connect(server_address, server_port, &sd, PROTOCOL);
227 if (result == STATE_CRITICAL)
228 return econn_refuse_state;
244 229
245#ifdef HAVE_SSL 230#ifdef HAVE_SSL
246 if (flags & FLAG_SSL){ 231 if (flags & FLAG_SSL) {
247 result = np_net_ssl_init_with_hostname(sd, (sni_specified ? sni : NULL)); 232 result = np_net_ssl_init_with_hostname(sd, (sni_specified ? sni : NULL));
248 if (result == STATE_OK && check_cert) { 233 if (result == STATE_OK && check_cert) {
249 result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit); 234 result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit);
250 } 235 }
251 } 236 }
252 if(result != STATE_OK){ 237 if (result != STATE_OK) {
253 if(sd) close(sd); 238 if (sd)
239 close(sd);
254 np_net_ssl_cleanup(); 240 np_net_ssl_cleanup();
255 return result; 241 return result;
256 } 242 }
257#endif /* HAVE_SSL */ 243#endif /* HAVE_SSL */
258 244
259 if (server_send != NULL) { /* Something to send? */ 245 if (server_send != NULL) { /* Something to send? */
260 my_send(server_send, strlen(server_send)); 246 my_send(server_send, strlen(server_send));
261 } 247 }
262 248
263 if (delay > 0) { 249 if (delay > 0) {
264 tv.tv_sec += delay; 250 tv.tv_sec += delay;
265 sleep (delay); 251 sleep(delay);
266 } 252 }
267 253
268 if(flags & FLAG_VERBOSE) { 254 if (flags & FLAG_VERBOSE) {
269 if (server_send) { 255 if (server_send) {
270 printf("Send string: %s\n", server_send); 256 printf("Send string: %s\n", server_send);
271 } 257 }
@@ -273,13 +259,17 @@ main (int argc, char **argv)
273 printf("Quit string: %s\n", server_quit); 259 printf("Quit string: %s\n", server_quit);
274 } 260 }
275 printf("server_expect_count: %d\n", (int)server_expect_count); 261 printf("server_expect_count: %d\n", (int)server_expect_count);
276 for(size_t i = 0; i < server_expect_count; i++) 262 for (size_t i = 0; i < server_expect_count; i++)
277 printf("\t%zd: %s\n", i, server_expect[i]); 263 printf("\t%zd: %s\n", i, server_expect[i]);
278 } 264 }
279 265
280 /* if(len) later on, we know we have a non-NULL response */ 266 /* if(len) later on, we know we have a non-NULL response */
281 ssize_t len = 0; 267 ssize_t len = 0;
282 268
269 int match = -1;
270 struct timeval timeout;
271 fd_set rfds;
272 FD_ZERO(&rfds);
283 if (server_expect_count) { 273 if (server_expect_count) {
284 ssize_t received = 0; 274 ssize_t received = 0;
285 275
@@ -294,17 +284,14 @@ main (int argc, char **argv)
294 if (maxbytes && len >= maxbytes) 284 if (maxbytes && len >= maxbytes)
295 break; 285 break;
296 286
297 if ((match = np_expect_match(status, 287 if ((match = np_expect_match(status, server_expect, server_expect_count, match_flags)) != NP_MATCH_RETRY)
298 server_expect,
299 server_expect_count,
300 match_flags)) != NP_MATCH_RETRY)
301 break; 288 break;
302 289
303 /* some protocols wait for further input, so make sure we don't wait forever */ 290 /* some protocols wait for further input, so make sure we don't wait forever */
304 FD_SET(sd, &rfds); 291 FD_SET(sd, &rfds);
305 timeout.tv_sec = READ_TIMEOUT; 292 timeout.tv_sec = READ_TIMEOUT;
306 timeout.tv_usec = 0; 293 timeout.tv_usec = 0;
307 if(select(sd + 1, &rfds, NULL, NULL, &timeout) <= 0) 294 if (select(sd + 1, &rfds, NULL, NULL, &timeout) <= 0)
308 break; 295 break;
309 } 296 }
310 297
@@ -313,26 +300,26 @@ main (int argc, char **argv)
313 300
314 /* no data when expected, so return critical */ 301 /* no data when expected, so return critical */
315 if (len == 0) 302 if (len == 0)
316 die (STATE_CRITICAL, _("No data received from host\n")); 303 die(STATE_CRITICAL, _("No data received from host\n"));
317 304
318 /* print raw output if we're debugging */ 305 /* print raw output if we're debugging */
319 if(flags & FLAG_VERBOSE) 306 if (flags & FLAG_VERBOSE)
320 printf("received %d bytes from host\n#-raw-recv-------#\n%s\n#-raw-recv-------#\n", 307 printf("received %d bytes from host\n#-raw-recv-------#\n%s\n#-raw-recv-------#\n", (int)len + 1, status);
321 (int)len + 1, status);
322 /* strip whitespace from end of output */ 308 /* strip whitespace from end of output */
323 while(--len > 0 && isspace(status[len])) 309 while (--len > 0 && isspace(status[len]))
324 status[len] = '\0'; 310 status[len] = '\0';
325 } 311 }
326 312
327 if (server_quit != NULL) { 313 if (server_quit != NULL) {
328 my_send(server_quit, strlen(server_quit)); 314 my_send(server_quit, strlen(server_quit));
329 } 315 }
330 if (sd) close (sd); 316 if (sd)
317 close(sd);
331#ifdef HAVE_SSL 318#ifdef HAVE_SSL
332 np_net_ssl_cleanup(); 319 np_net_ssl_cleanup();
333#endif 320#endif
334 321
335 microsec = deltime (tv); 322 microsec = deltime(tv);
336 elapsed_time = (double)microsec / 1.0e6; 323 elapsed_time = (double)microsec / 1.0e6;
337 324
338 if (flags & FLAG_TIME_CRIT && elapsed_time > critical_time) 325 if (flags & FLAG_TIME_CRIT && elapsed_time > critical_time)
@@ -341,142 +328,123 @@ main (int argc, char **argv)
341 result = STATE_WARNING; 328 result = STATE_WARNING;
342 329
343 /* did we get the response we hoped? */ 330 /* did we get the response we hoped? */
344 if(match == NP_MATCH_FAILURE && result != STATE_CRITICAL) 331 if (match == NP_MATCH_FAILURE && result != STATE_CRITICAL)
345 result = expect_mismatch_state; 332 result = expect_mismatch_state;
346 333
347 /* reset the alarm */ 334 /* reset the alarm */
348 alarm (0); 335 alarm(0);
349 336
350 /* this is a bit stupid, because we don't want to print the 337 /* this is a bit stupid, because we don't want to print the
351 * response time (which can look ok to the user) if we didn't get 338 * response time (which can look ok to the user) if we didn't get
352 * the response we were looking for. if-else */ 339 * the response we were looking for. if-else */
353 printf("%s %s - ", SERVICE, state_text(result)); 340 printf("%s %s - ", SERVICE, state_text(result));
354 341
355 if(match == NP_MATCH_FAILURE && len && !(flags & FLAG_HIDE_OUTPUT)) 342 if (match == NP_MATCH_FAILURE && len && !(flags & FLAG_HIDE_OUTPUT))
356 printf("Unexpected response from host/socket: %s", status); 343 printf("Unexpected response from host/socket: %s", status);
357 else { 344 else {
358 if(match == NP_MATCH_FAILURE) 345 if (match == NP_MATCH_FAILURE)
359 printf("Unexpected response from host/socket on "); 346 printf("Unexpected response from host/socket on ");
360 else 347 else
361 printf("%.3f second response time on ", elapsed_time); 348 printf("%.3f second response time on ", elapsed_time);
362 if(server_address[0] != '/') { 349 if (server_address[0] != '/') {
363 if (host_specified) 350 if (host_specified)
364 printf("%s port %d", 351 printf("%s port %d", server_address, server_port);
365 server_address, server_port);
366 else 352 else
367 printf("port %d", server_port); 353 printf("port %d", server_port);
368 } 354 } else
369 else
370 printf("socket %s", server_address); 355 printf("socket %s", server_address);
371 } 356 }
372 357
373 if (match != NP_MATCH_FAILURE && !(flags & FLAG_HIDE_OUTPUT) && len) 358 if (match != NP_MATCH_FAILURE && !(flags & FLAG_HIDE_OUTPUT) && len)
374 printf (" [%s]", status); 359 printf(" [%s]", status);
375 360
376 /* perf-data doesn't apply when server doesn't talk properly, 361 /* perf-data doesn't apply when server doesn't talk properly,
377 * so print all zeroes on warn and crit. Use fperfdata since 362 * so print all zeroes on warn and crit. Use fperfdata since
378 * localisation settings can make different outputs */ 363 * localisation settings can make different outputs */
379 if(match == NP_MATCH_FAILURE) 364 if (match == NP_MATCH_FAILURE)
380 printf ("|%s", 365 printf("|%s", fperfdata("time", elapsed_time, "s", (flags & FLAG_TIME_WARN ? true : false), 0,
381 fperfdata ("time", elapsed_time, "s", 366 (flags & FLAG_TIME_CRIT ? true : false), 0, true, 0, true, socket_timeout));
382 (flags & FLAG_TIME_WARN ? true : false), 0,
383 (flags & FLAG_TIME_CRIT ? true : false), 0,
384 true, 0,
385 true, socket_timeout)
386 );
387 else 367 else
388 printf("|%s", 368 printf("|%s", fperfdata("time", elapsed_time, "s", (flags & FLAG_TIME_WARN ? true : false), warning_time,
389 fperfdata ("time", elapsed_time, "s", 369 (flags & FLAG_TIME_CRIT ? true : false), critical_time, true, 0, true, socket_timeout));
390 (flags & FLAG_TIME_WARN ? true : false), warning_time,
391 (flags & FLAG_TIME_CRIT ? true : false), critical_time,
392 true, 0,
393 true, socket_timeout)
394 );
395 370
396 putchar('\n'); 371 putchar('\n');
397 return result; 372 return result;
398} 373}
399 374
400
401
402/* process command-line arguments */ 375/* process command-line arguments */
403static int process_arguments (int argc, char **argv) { 376static int process_arguments(int argc, char **argv) {
404 int c;
405 bool escape = false;
406 char *temp;
407
408 enum { 377 enum {
409 SNI_OPTION = CHAR_MAX + 1 378 SNI_OPTION = CHAR_MAX + 1
410 }; 379 };
411 380
412 int option = 0; 381 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
413 static struct option longopts[] = { 382 {"critical", required_argument, 0, 'c'},
414 {"hostname", required_argument, 0, 'H'}, 383 {"warning", required_argument, 0, 'w'},
415 {"critical", required_argument, 0, 'c'}, 384 {"critical-codes", required_argument, 0, 'C'},
416 {"warning", required_argument, 0, 'w'}, 385 {"warning-codes", required_argument, 0, 'W'},
417 {"critical-codes", required_argument, 0, 'C'}, 386 {"timeout", required_argument, 0, 't'},
418 {"warning-codes", required_argument, 0, 'W'}, 387 {"protocol", required_argument, 0, 'P'}, /* FIXME: Unhandled */
419 {"timeout", required_argument, 0, 't'}, 388 {"port", required_argument, 0, 'p'},
420 {"protocol", required_argument, 0, 'P'}, /* FIXME: Unhandled */ 389 {"escape", no_argument, 0, 'E'},
421 {"port", required_argument, 0, 'p'}, 390 {"all", no_argument, 0, 'A'},
422 {"escape", no_argument, 0, 'E'}, 391 {"send", required_argument, 0, 's'},
423 {"all", no_argument, 0, 'A'}, 392 {"expect", required_argument, 0, 'e'},
424 {"send", required_argument, 0, 's'}, 393 {"maxbytes", required_argument, 0, 'm'},
425 {"expect", required_argument, 0, 'e'}, 394 {"quit", required_argument, 0, 'q'},
426 {"maxbytes", required_argument, 0, 'm'}, 395 {"jail", no_argument, 0, 'j'},
427 {"quit", required_argument, 0, 'q'}, 396 {"delay", required_argument, 0, 'd'},
428 {"jail", no_argument, 0, 'j'}, 397 {"refuse", required_argument, 0, 'r'},
429 {"delay", required_argument, 0, 'd'}, 398 {"mismatch", required_argument, 0, 'M'},
430 {"refuse", required_argument, 0, 'r'}, 399 {"use-ipv4", no_argument, 0, '4'},
431 {"mismatch", required_argument, 0, 'M'}, 400 {"use-ipv6", no_argument, 0, '6'},
432 {"use-ipv4", no_argument, 0, '4'}, 401 {"verbose", no_argument, 0, 'v'},
433 {"use-ipv6", no_argument, 0, '6'}, 402 {"version", no_argument, 0, 'V'},
434 {"verbose", no_argument, 0, 'v'}, 403 {"help", no_argument, 0, 'h'},
435 {"version", no_argument, 0, 'V'}, 404 {"ssl", no_argument, 0, 'S'},
436 {"help", no_argument, 0, 'h'}, 405 {"sni", required_argument, 0, SNI_OPTION},
437 {"ssl", no_argument, 0, 'S'}, 406 {"certificate", required_argument, 0, 'D'},
438 {"sni", required_argument, 0, SNI_OPTION}, 407 {0, 0, 0, 0}};
439 {"certificate", required_argument, 0, 'D'},
440 {0, 0, 0, 0}
441 };
442 408
443 if (argc < 2) 409 if (argc < 2)
444 usage4 (_("No arguments found")); 410 usage4(_("No arguments found"));
445 411
446 /* backwards compatibility */ 412 /* backwards compatibility */
447 for (c = 1; c < argc; c++) { 413 for (int i = 1; i < argc; i++) {
448 if (strcmp ("-to", argv[c]) == 0) 414 if (strcmp("-to", argv[i]) == 0)
449 strcpy (argv[c], "-t"); 415 strcpy(argv[i], "-t");
450 else if (strcmp ("-wt", argv[c]) == 0) 416 else if (strcmp("-wt", argv[i]) == 0)
451 strcpy (argv[c], "-w"); 417 strcpy(argv[i], "-w");
452 else if (strcmp ("-ct", argv[c]) == 0) 418 else if (strcmp("-ct", argv[i]) == 0)
453 strcpy (argv[c], "-c"); 419 strcpy(argv[i], "-c");
454 } 420 }
455 421
456 if (!is_option (argv[1])) { 422 if (!is_option(argv[1])) {
457 server_address = argv[1]; 423 server_address = argv[1];
458 argv[1] = argv[0]; 424 argv[1] = argv[0];
459 argv = &argv[1]; 425 argv = &argv[1];
460 argc--; 426 argc--;
461 } 427 }
462 428
463 while (1) { 429 int option_char;
464 c = getopt_long (argc, argv, "+hVv46EAH:s:e:q:m:c:w:t:p:C:W:d:Sr:jD:M:", 430 bool escape = false;
465 longopts, &option); 431 while (true) {
432 int option = 0;
433 option_char = getopt_long(argc, argv, "+hVv46EAH:s:e:q:m:c:w:t:p:C:W:d:Sr:jD:M:", longopts, &option);
466 434
467 if (c == -1 || c == EOF || c == 1) 435 if (option_char == -1 || option_char == EOF || option_char == 1)
468 break; 436 break;
469 437
470 switch (c) { 438 switch (option_char) {
471 case '?': /* print short usage statement if args not parsable */ 439 case '?': /* print short usage statement if args not parsable */
472 usage5 (); 440 usage5();
473 case 'h': /* help */ 441 case 'h': /* help */
474 print_help (); 442 print_help();
475 exit (STATE_UNKNOWN); 443 exit(STATE_UNKNOWN);
476 case 'V': /* version */ 444 case 'V': /* version */
477 print_revision (progname, NP_VERSION); 445 print_revision(progname, NP_VERSION);
478 exit (STATE_UNKNOWN); 446 exit(STATE_UNKNOWN);
479 case 'v': /* verbose mode */ 447 case 'v': /* verbose mode */
480 flags |= FLAG_VERBOSE; 448 flags |= FLAG_VERBOSE;
481 match_flags |= NP_MATCH_VERBOSE; 449 match_flags |= NP_MATCH_VERBOSE;
482 break; 450 break;
@@ -487,43 +455,43 @@ static int process_arguments (int argc, char **argv) {
487#ifdef USE_IPV6 455#ifdef USE_IPV6
488 address_family = AF_INET6; 456 address_family = AF_INET6;
489#else 457#else
490 usage4 (_("IPv6 support not available")); 458 usage4(_("IPv6 support not available"));
491#endif 459#endif
492 break; 460 break;
493 case 'H': /* hostname */ 461 case 'H': /* hostname */
494 host_specified = true; 462 host_specified = true;
495 server_address = optarg; 463 server_address = optarg;
496 break; 464 break;
497 case 'c': /* critical */ 465 case 'c': /* critical */
498 critical_time = strtod (optarg, NULL); 466 critical_time = strtod(optarg, NULL);
499 flags |= FLAG_TIME_CRIT; 467 flags |= FLAG_TIME_CRIT;
500 break; 468 break;
501 case 'j': /* hide output */ 469 case 'j': /* hide output */
502 flags |= FLAG_HIDE_OUTPUT; 470 flags |= FLAG_HIDE_OUTPUT;
503 break; 471 break;
504 case 'w': /* warning */ 472 case 'w': /* warning */
505 warning_time = strtod (optarg, NULL); 473 warning_time = strtod(optarg, NULL);
506 flags |= FLAG_TIME_WARN; 474 flags |= FLAG_TIME_WARN;
507 break; 475 break;
508 case 'C': 476 case 'C':
509 crit_codes = realloc (crit_codes, ++crit_codes_count); 477 crit_codes = realloc(crit_codes, ++crit_codes_count);
510 crit_codes[crit_codes_count - 1] = optarg; 478 crit_codes[crit_codes_count - 1] = optarg;
511 break; 479 break;
512 case 'W': 480 case 'W':
513 warn_codes = realloc (warn_codes, ++warn_codes_count); 481 warn_codes = realloc(warn_codes, ++warn_codes_count);
514 warn_codes[warn_codes_count - 1] = optarg; 482 warn_codes[warn_codes_count - 1] = optarg;
515 break; 483 break;
516 case 't': /* timeout */ 484 case 't': /* timeout */
517 if (!is_intpos (optarg)) 485 if (!is_intpos(optarg))
518 usage4 (_("Timeout interval must be a positive integer")); 486 usage4(_("Timeout interval must be a positive integer"));
519 else 487 else
520 socket_timeout = atoi (optarg); 488 socket_timeout = atoi(optarg);
521 break; 489 break;
522 case 'p': /* port */ 490 case 'p': /* port */
523 if (!is_intpos (optarg)) 491 if (!is_intpos(optarg))
524 usage4 (_("Port must be a positive integer")); 492 usage4(_("Port must be a positive integer"));
525 else 493 else
526 server_port = atoi (optarg); 494 server_port = atoi(optarg);
527 break; 495 break;
528 case 'E': 496 case 'E':
529 escape = true; 497 escape = true;
@@ -537,16 +505,16 @@ static int process_arguments (int argc, char **argv) {
537 case 'e': /* expect string (may be repeated) */ 505 case 'e': /* expect string (may be repeated) */
538 match_flags &= ~NP_MATCH_EXACT; 506 match_flags &= ~NP_MATCH_EXACT;
539 if (server_expect_count == 0) 507 if (server_expect_count == 0)
540 server_expect = malloc (sizeof (char *) * (++server_expect_count)); 508 server_expect = malloc(sizeof(char *) * (++server_expect_count));
541 else 509 else
542 server_expect = realloc (server_expect, sizeof (char *) * (++server_expect_count)); 510 server_expect = realloc(server_expect, sizeof(char *) * (++server_expect_count));
543 server_expect[server_expect_count - 1] = optarg; 511 server_expect[server_expect_count - 1] = optarg;
544 break; 512 break;
545 case 'm': 513 case 'm':
546 if (!is_intpos (optarg)) 514 if (!is_intpos(optarg))
547 usage4 (_("Maxbytes must be a positive integer")); 515 usage4(_("Maxbytes must be a positive integer"));
548 else 516 else
549 maxbytes = strtol (optarg, NULL, 0); 517 maxbytes = strtol(optarg, NULL, 0);
550 break; 518 break;
551 case 'q': 519 case 'q':
552 if (escape) 520 if (escape)
@@ -555,62 +523,62 @@ static int process_arguments (int argc, char **argv) {
555 xasprintf(&server_quit, "%s\r\n", optarg); 523 xasprintf(&server_quit, "%s\r\n", optarg);
556 break; 524 break;
557 case 'r': 525 case 'r':
558 if (!strncmp(optarg,"ok",2)) 526 if (!strncmp(optarg, "ok", 2))
559 econn_refuse_state = STATE_OK; 527 econn_refuse_state = STATE_OK;
560 else if (!strncmp(optarg,"warn",4)) 528 else if (!strncmp(optarg, "warn", 4))
561 econn_refuse_state = STATE_WARNING; 529 econn_refuse_state = STATE_WARNING;
562 else if (!strncmp(optarg,"crit",4)) 530 else if (!strncmp(optarg, "crit", 4))
563 econn_refuse_state = STATE_CRITICAL; 531 econn_refuse_state = STATE_CRITICAL;
564 else 532 else
565 usage4 (_("Refuse must be one of ok, warn, crit")); 533 usage4(_("Refuse must be one of ok, warn, crit"));
566 break; 534 break;
567 case 'M': 535 case 'M':
568 if (!strncmp(optarg,"ok",2)) 536 if (!strncmp(optarg, "ok", 2))
569 expect_mismatch_state = STATE_OK; 537 expect_mismatch_state = STATE_OK;
570 else if (!strncmp(optarg,"warn",4)) 538 else if (!strncmp(optarg, "warn", 4))
571 expect_mismatch_state = STATE_WARNING; 539 expect_mismatch_state = STATE_WARNING;
572 else if (!strncmp(optarg,"crit",4)) 540 else if (!strncmp(optarg, "crit", 4))
573 expect_mismatch_state = STATE_CRITICAL; 541 expect_mismatch_state = STATE_CRITICAL;
574 else 542 else
575 usage4 (_("Mismatch must be one of ok, warn, crit")); 543 usage4(_("Mismatch must be one of ok, warn, crit"));
576 break; 544 break;
577 case 'd': 545 case 'd':
578 if (is_intpos (optarg)) 546 if (is_intpos(optarg))
579 delay = atoi (optarg); 547 delay = atoi(optarg);
580 else 548 else
581 usage4 (_("Delay must be a positive integer")); 549 usage4(_("Delay must be a positive integer"));
582 break; 550 break;
583 case 'D': /* Check SSL cert validity - days 'til certificate expiration */ 551 case 'D': { /* Check SSL cert validity - days 'til certificate expiration */
584#ifdef HAVE_SSL 552#ifdef HAVE_SSL
585# ifdef USE_OPENSSL /* XXX */ 553# ifdef USE_OPENSSL /* XXX */
586 if ((temp=strchr(optarg,','))!=NULL) { 554 char *temp;
587 *temp='\0'; 555 if ((temp = strchr(optarg, ',')) != NULL) {
588 if (!is_intnonneg (optarg)) 556 *temp = '\0';
589 usage2 (_("Invalid certificate expiration period"), optarg); 557 if (!is_intnonneg(optarg))
590 days_till_exp_warn = atoi (optarg); 558 usage2(_("Invalid certificate expiration period"), optarg);
591 *temp=','; 559 days_till_exp_warn = atoi(optarg);
592 temp++; 560 *temp = ',';
593 if (!is_intnonneg (temp)) 561 temp++;
594 usage2 (_("Invalid certificate expiration period"), temp); 562 if (!is_intnonneg(temp))
595 days_till_exp_crit = atoi (temp); 563 usage2(_("Invalid certificate expiration period"), temp);
596 } 564 days_till_exp_crit = atoi(temp);
597 else { 565 } else {
598 days_till_exp_crit=0; 566 days_till_exp_crit = 0;
599 if (!is_intnonneg (optarg)) 567 if (!is_intnonneg(optarg))
600 usage2 (_("Invalid certificate expiration period"), optarg); 568 usage2(_("Invalid certificate expiration period"), optarg);
601 days_till_exp_warn = atoi (optarg); 569 days_till_exp_warn = atoi(optarg);
602 } 570 }
603 check_cert = true; 571 check_cert = true;
604 flags |= FLAG_SSL; 572 flags |= FLAG_SSL;
605 break; 573 } break;
606# endif /* USE_OPENSSL */ 574# endif /* USE_OPENSSL */
607#endif 575#endif
608 /* fallthrough if we don't have ssl */ 576 /* fallthrough if we don't have ssl */
609 case 'S': 577 case 'S':
610#ifdef HAVE_SSL 578#ifdef HAVE_SSL
611 flags |= FLAG_SSL; 579 flags |= FLAG_SSL;
612#else 580#else
613 die (STATE_UNKNOWN, _("Invalid option - SSL is not available")); 581 die(STATE_UNKNOWN, _("Invalid option - SSL is not available"));
614#endif 582#endif
615 break; 583 break;
616 case SNI_OPTION: 584 case SNI_OPTION:
@@ -619,7 +587,7 @@ static int process_arguments (int argc, char **argv) {
619 sni_specified = true; 587 sni_specified = true;
620 sni = optarg; 588 sni = optarg;
621#else 589#else
622 die (STATE_UNKNOWN, _("Invalid option - SSL is not available")); 590 die(STATE_UNKNOWN, _("Invalid option - SSL is not available"));
623#endif 591#endif
624 break; 592 break;
625 case 'A': 593 case 'A':
@@ -628,87 +596,81 @@ static int process_arguments (int argc, char **argv) {
628 } 596 }
629 } 597 }
630 598
631 c = optind; 599 option_char = optind;
632 if(!host_specified && c < argc) 600 if (!host_specified && option_char < argc)
633 server_address = strdup (argv[c++]); 601 server_address = strdup(argv[option_char++]);
634 602
635 if (server_address == NULL) 603 if (server_address == NULL)
636 usage4 (_("You must provide a server address")); 604 usage4(_("You must provide a server address"));
637 else if (server_address[0] != '/' && !is_host(server_address)) 605 else if (server_address[0] != '/' && !is_host(server_address))
638 die (STATE_CRITICAL, "%s %s - %s: %s\n", SERVICE, state_text(STATE_CRITICAL), _("Invalid hostname, address or socket"), server_address); 606 die(STATE_CRITICAL, "%s %s - %s: %s\n", SERVICE, state_text(STATE_CRITICAL), _("Invalid hostname, address or socket"),
607 server_address);
639 608
640 return OK; 609 return OK;
641} 610}
642 611
643 612void print_help(void) {
644void 613 print_revision(progname, NP_VERSION);
645print_help (void) 614
646{ 615 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
647 print_revision (progname, NP_VERSION); 616 printf(COPYRIGHT, copyright, email);
648 617
649 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 618 printf(_("This plugin tests %s connections with the specified host (or unix socket).\n\n"), SERVICE);
650 printf (COPYRIGHT, copyright, email); 619
651 620 print_usage();
652 printf (_("This plugin tests %s connections with the specified host (or unix socket).\n\n"), 621
653 SERVICE); 622 printf(UT_HELP_VRSN);
654 623 printf(UT_EXTRA_OPTS);
655 print_usage (); 624
656 625 printf(UT_HOST_PORT, 'p', "none");
657 printf (UT_HELP_VRSN); 626
658 printf (UT_EXTRA_OPTS); 627 printf(UT_IPv46);
659 628
660 printf (UT_HOST_PORT, 'p', "none"); 629 printf(" %s\n", "-E, --escape");
661 630 printf(" %s\n", _("Can use \\n, \\r, \\t or \\\\ in send or quit string. Must come before send or quit option"));
662 printf (UT_IPv46); 631 printf(" %s\n", _("Default: nothing added to send, \\r\\n added to end of quit"));
663 632 printf(" %s\n", "-s, --send=STRING");
664 printf (" %s\n", "-E, --escape"); 633 printf(" %s\n", _("String to send to the server"));
665 printf (" %s\n", _("Can use \\n, \\r, \\t or \\\\ in send or quit string. Must come before send or quit option")); 634 printf(" %s\n", "-e, --expect=STRING");
666 printf (" %s\n", _("Default: nothing added to send, \\r\\n added to end of quit")); 635 printf(" %s %s\n", _("String to expect in server response"), _("(may be repeated)"));
667 printf (" %s\n", "-s, --send=STRING"); 636 printf(" %s\n", "-A, --all");
668 printf (" %s\n", _("String to send to the server")); 637 printf(" %s\n", _("All expect strings need to occur in server response. Default is any"));
669 printf (" %s\n", "-e, --expect=STRING"); 638 printf(" %s\n", "-q, --quit=STRING");
670 printf (" %s %s\n", _("String to expect in server response"), _("(may be repeated)")); 639 printf(" %s\n", _("String to send server to initiate a clean close of the connection"));
671 printf (" %s\n", "-A, --all"); 640 printf(" %s\n", "-r, --refuse=ok|warn|crit");
672 printf (" %s\n", _("All expect strings need to occur in server response. Default is any")); 641 printf(" %s\n", _("Accept TCP refusals with states ok, warn, crit (default: crit)"));
673 printf (" %s\n", "-q, --quit=STRING"); 642 printf(" %s\n", "-M, --mismatch=ok|warn|crit");
674 printf (" %s\n", _("String to send server to initiate a clean close of the connection")); 643 printf(" %s\n", _("Accept expected string mismatches with states ok, warn, crit (default: warn)"));
675 printf (" %s\n", "-r, --refuse=ok|warn|crit"); 644 printf(" %s\n", "-j, --jail");
676 printf (" %s\n", _("Accept TCP refusals with states ok, warn, crit (default: crit)")); 645 printf(" %s\n", _("Hide output from TCP socket"));
677 printf (" %s\n", "-M, --mismatch=ok|warn|crit"); 646 printf(" %s\n", "-m, --maxbytes=INTEGER");
678 printf (" %s\n", _("Accept expected string mismatches with states ok, warn, crit (default: warn)")); 647 printf(" %s\n", _("Close connection once more than this number of bytes are received"));
679 printf (" %s\n", "-j, --jail"); 648 printf(" %s\n", "-d, --delay=INTEGER");
680 printf (" %s\n", _("Hide output from TCP socket")); 649 printf(" %s\n", _("Seconds to wait between sending string and polling for response"));
681 printf (" %s\n", "-m, --maxbytes=INTEGER");
682 printf (" %s\n", _("Close connection once more than this number of bytes are received"));
683 printf (" %s\n", "-d, --delay=INTEGER");
684 printf (" %s\n", _("Seconds to wait between sending string and polling for response"));
685 650
686#ifdef HAVE_SSL 651#ifdef HAVE_SSL
687 printf (" %s\n", "-D, --certificate=INTEGER[,INTEGER]"); 652 printf(" %s\n", "-D, --certificate=INTEGER[,INTEGER]");
688 printf (" %s\n", _("Minimum number of days a certificate has to be valid.")); 653 printf(" %s\n", _("Minimum number of days a certificate has to be valid."));
689 printf (" %s\n", _("1st is #days for warning, 2nd is critical (if not specified - 0).")); 654 printf(" %s\n", _("1st is #days for warning, 2nd is critical (if not specified - 0)."));
690 printf (" %s\n", "-S, --ssl"); 655 printf(" %s\n", "-S, --ssl");
691 printf (" %s\n", _("Use SSL for the connection.")); 656 printf(" %s\n", _("Use SSL for the connection."));
692 printf (" %s\n", "--sni=STRING"); 657 printf(" %s\n", "--sni=STRING");
693 printf (" %s\n", _("SSL server_name")); 658 printf(" %s\n", _("SSL server_name"));
694#endif 659#endif
695 660
696 printf (UT_WARN_CRIT); 661 printf(UT_WARN_CRIT);
697 662
698 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 663 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
699 664
700 printf (UT_VERBOSE); 665 printf(UT_VERBOSE);
701 666
702 printf (UT_SUPPORT); 667 printf(UT_SUPPORT);
703} 668}
704 669
705 670void print_usage(void) {
706void 671 printf("%s\n", _("Usage:"));
707print_usage (void) 672 printf("%s -H host -p port [-w <warning time>] [-c <critical time>] [-s <send string>]\n", progname);
708{ 673 printf("[-e <expect string>] [-q <quit string>][-m <maximum bytes>] [-d <delay>]\n");
709 printf ("%s\n", _("Usage:")); 674 printf("[-t <timeout seconds>] [-r <refuse state>] [-M <mismatch state>] [-v] [-4|-6] [-j]\n");
710 printf ("%s -H host -p port [-w <warning time>] [-c <critical time>] [-s <send string>]\n",progname); 675 printf("[-D <warn days cert expire>[,<crit days cert expire>]] [-S <use SSL>] [-E]\n");
711 printf ("[-e <expect string>] [-q <quit string>][-m <maximum bytes>] [-d <delay>]\n");
712 printf ("[-t <timeout seconds>] [-r <refuse state>] [-M <mismatch state>] [-v] [-4|-6] [-j]\n");
713 printf ("[-D <warn days cert expire>[,<crit days cert expire>]] [-S <use SSL>] [-E]\n");
714} 676}