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.c1124
1 files changed, 619 insertions, 505 deletions
diff --git a/plugins/check_tcp.c b/plugins/check_tcp.c
index 01dd35eb..09806373 100644
--- a/plugins/check_tcp.c
+++ b/plugins/check_tcp.c
@@ -1,415 +1,496 @@
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-2025 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-2025";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "./common.h"
36#include "netutils.h" 36#include "./netutils.h"
37#include "utils.h" 37#include "./utils.h"
38#include "utils_tcp.h" 38#include "./check_tcp.d/config.h"
39#include "output.h"
40#include "states.h"
39 41
42#include <sys/types.h>
40#include <ctype.h> 43#include <ctype.h>
41#include <sys/select.h> 44#include <sys/select.h>
42 45
46ssize_t my_recv(int socket_descriptor, char *buf, size_t len, bool use_tls) {
43#ifdef HAVE_SSL 47#ifdef HAVE_SSL
44static bool check_cert = false; 48 if (use_tls) {
45static int days_till_exp_warn, days_till_exp_crit; 49 return np_net_ssl_read(buf, (int)len);
46# define my_recv(buf, len) ((flags & FLAG_SSL) ? np_net_ssl_read(buf, len) : read(sd, buf, len)) 50 }
47# define my_send(buf, len) ((flags & FLAG_SSL) ? np_net_ssl_write(buf, len) : send(sd, buf, len, 0))
48#else
49# define my_recv(buf, len) read(sd, buf, len)
50# define my_send(buf, len) send(sd, buf, len, 0)
51#endif 51#endif
52 return read(socket_descriptor, buf, len);
53}
52 54
53/* int my_recv(char *, size_t); */ 55ssize_t my_send(int socket_descriptor, char *buf, size_t len, bool use_tls) {
54static int process_arguments (int, char **);
55void print_help (void);
56void print_usage (void);
57
58#define EXPECT server_expect[0]
59static char *SERVICE = "TCP";
60static char *SEND = NULL;
61static char *QUIT = NULL;
62static int PROTOCOL = IPPROTO_TCP; /* most common is default */
63static int PORT = 0;
64static int READ_TIMEOUT = 2;
65
66static int server_port = 0;
67static char *server_address = NULL;
68static bool host_specified = false;
69static char *server_send = NULL;
70static char *server_quit = NULL;
71static char **server_expect;
72static size_t server_expect_count = 0;
73static ssize_t maxbytes = 0;
74static char **warn_codes = NULL;
75static size_t warn_codes_count = 0;
76static char **crit_codes = NULL;
77static size_t crit_codes_count = 0;
78static unsigned int delay = 0;
79static double warning_time = 0;
80static double critical_time = 0;
81static double elapsed_time = 0;
82static long microsec;
83static int sd = 0;
84#define MAXBUF 1024
85static char buffer[MAXBUF];
86static int expect_mismatch_state = STATE_WARNING;
87static int match_flags = NP_MATCH_EXACT;
88
89#ifdef HAVE_SSL 56#ifdef HAVE_SSL
90static char *sni = NULL; 57 if (use_tls) {
91static bool sni_specified = false; 58 return np_net_ssl_write(buf, (int)len);
59 }
92#endif 60#endif
61 return write(socket_descriptor, buf, len);
62}
93 63
94#define FLAG_SSL 0x01 64typedef struct {
95#define FLAG_VERBOSE 0x02 65 int errorcode;
96#define FLAG_TIME_WARN 0x04 66 check_tcp_config config;
97#define FLAG_TIME_CRIT 0x08 67} check_tcp_config_wrapper;
98#define FLAG_HIDE_OUTPUT 0x10 68static check_tcp_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/,
99static size_t flags; 69 check_tcp_config /*config*/);
100 70void print_help(const char *service);
101int 71void print_usage(void);
102main (int argc, char **argv) 72
103{ 73int verbosity = 0;
104 int result = STATE_UNKNOWN; 74
105 char *status = NULL; 75static const int READ_TIMEOUT = 2;
106 struct timeval tv; 76
107 struct timeval timeout; 77const int MAXBUF = 1024;
108 int match = -1; 78
109 fd_set rfds; 79const int DEFAULT_FTP_PORT = 21;
110 80const int DEFAULT_POP_PORT = 110;
111 FD_ZERO(&rfds); 81const int DEFAULT_SPOP_PORT = 995;
112 82const int DEFAULT_SMTP_PORT = 25;
113 setlocale (LC_ALL, ""); 83const int DEFAULT_SSMTP_PORT = 465;
114 bindtextdomain (PACKAGE, LOCALEDIR); 84const int DEFAULT_IMAP_PORT = 143;
115 textdomain (PACKAGE); 85const int DEFAULT_SIMAP_PORT = 993;
86const int DEFAULT_XMPP_C2S_PORT = 5222;
87const int DEFAULT_NNTP_PORT = 119;
88const int DEFAULT_NNTPS_PORT = 563;
89const int DEFAULT_CLAMD_PORT = 3310;
90
91int main(int argc, char **argv) {
92 setlocale(LC_ALL, "");
93 bindtextdomain(PACKAGE, LOCALEDIR);
94 textdomain(PACKAGE);
116 95
117 /* determine program- and service-name quickly */ 96 /* determine program- and service-name quickly */
118 progname = strrchr(argv[0], '/'); 97 progname = strrchr(argv[0], '/');
119 if(progname != NULL) progname++; 98 if (progname != NULL) {
120 else progname = argv[0]; 99 progname++;
100 } else {
101 progname = argv[0];
102 }
103
104 // Initialize config here with values from above,
105 // might be changed by on disk config or cli commands
106 check_tcp_config config = check_tcp_config_init();
121 107
122 size_t prog_name_len = strlen(progname); 108 size_t prog_name_len = strlen(progname);
123 if(prog_name_len > 6 && !memcmp(progname, "check_", 6)) { 109 const size_t prefix_length = strlen("check_");
124 SERVICE = strdup(progname + 6); 110
125 for(size_t i = 0; i < prog_name_len - 6; i++) 111 if (prog_name_len <= prefix_length) {
126 SERVICE[i] = toupper(SERVICE[i]); 112 die(STATE_UNKNOWN, _("Weird progname"));
113 }
114
115 if (!memcmp(progname, "check_", prefix_length)) {
116 config.service = strdup(progname + prefix_length);
117 if (config.service == NULL) {
118 die(STATE_UNKNOWN, _("Allocation failed"));
119 }
120
121 for (size_t i = 0; i < prog_name_len - prefix_length; i++) {
122 config.service[i] = toupper(config.service[i]);
123 }
127 } 124 }
128 125
129 /* set up a reasonable buffer at first (will be realloc()'ed if 126 /* set up a reasonable buffer at first (will be realloc()'ed if
130 * user specifies other options) */ 127 * user specifies other options) */
131 server_expect = calloc(sizeof(char *), 2); 128 config.server_expect = calloc(2, sizeof(char *));
132 129
133 /* determine defaults for this service's protocol */ 130 if (config.server_expect == NULL) {
134 if (!strncmp(SERVICE, "UDP", 3)) { 131 die(STATE_UNKNOWN, _("Allocation failed"));
135 PROTOCOL = IPPROTO_UDP;
136 }
137 else if (!strncmp(SERVICE, "FTP", 3)) {
138 EXPECT = "220";
139 QUIT = "QUIT\r\n";
140 PORT = 21;
141 }
142 else if (!strncmp(SERVICE, "POP", 3) || !strncmp(SERVICE, "POP3", 4)) {
143 EXPECT = "+OK";
144 QUIT = "QUIT\r\n";
145 PORT = 110;
146 }
147 else if (!strncmp(SERVICE, "SMTP", 4)) {
148 EXPECT = "220";
149 QUIT = "QUIT\r\n";
150 PORT = 25;
151 } 132 }
152 else if (!strncmp(SERVICE, "IMAP", 4)) { 133
153 EXPECT = "* OK"; 134 /* determine defaults for this service's protocol */
154 QUIT = "a1 LOGOUT\r\n"; 135 if (!strncmp(config.service, "UDP", strlen("UDP"))) {
155 PORT = 143; 136 config.protocol = IPPROTO_UDP;
137 } else if (!strncmp(config.service, "FTP", strlen("FTP"))) {
138 config.server_expect[0] = "220";
139 config.quit = "QUIT\r\n";
140 config.server_port = DEFAULT_FTP_PORT;
141 } else if (!strncmp(config.service, "POP", strlen("POP")) ||
142 !strncmp(config.service, "POP3", strlen("POP3"))) {
143 config.server_expect[0] = "+OK";
144 config.quit = "QUIT\r\n";
145 config.server_port = DEFAULT_POP_PORT;
146 } else if (!strncmp(config.service, "SMTP", strlen("SMTP"))) {
147 config.server_expect[0] = "220";
148 config.quit = "QUIT\r\n";
149 config.server_port = DEFAULT_SMTP_PORT;
150 } else if (!strncmp(config.service, "IMAP", strlen("IMAP"))) {
151 config.server_expect[0] = "* OK";
152 config.quit = "a1 LOGOUT\r\n";
153 config.server_port = DEFAULT_IMAP_PORT;
156 } 154 }
157#ifdef HAVE_SSL 155#ifdef HAVE_SSL
158 else if (!strncmp(SERVICE, "SIMAP", 5)) { 156 else if (!strncmp(config.service, "SIMAP", strlen("SIMAP"))) {
159 EXPECT = "* OK"; 157 config.server_expect[0] = "* OK";
160 QUIT = "a1 LOGOUT\r\n"; 158 config.quit = "a1 LOGOUT\r\n";
161 flags |= FLAG_SSL; 159 config.use_tls = true;
162 PORT = 993; 160 config.server_port = DEFAULT_SIMAP_PORT;
163 } 161 } else if (!strncmp(config.service, "SPOP", strlen("SPOP"))) {
164 else if (!strncmp(SERVICE, "SPOP", 4)) { 162 config.server_expect[0] = "+OK";
165 EXPECT = "+OK"; 163 config.quit = "QUIT\r\n";
166 QUIT = "QUIT\r\n"; 164 config.use_tls = true;
167 flags |= FLAG_SSL; 165 config.server_port = DEFAULT_SPOP_PORT;
168 PORT = 995; 166 } else if (!strncmp(config.service, "SSMTP", strlen("SSMTP"))) {
169 } 167 config.server_expect[0] = "220";
170 else if (!strncmp(SERVICE, "SSMTP", 5)) { 168 config.quit = "QUIT\r\n";
171 EXPECT = "220"; 169 config.use_tls = true;
172 QUIT = "QUIT\r\n"; 170 config.server_port = DEFAULT_SSMTP_PORT;
173 flags |= FLAG_SSL; 171 } else if (!strncmp(config.service, "JABBER", strlen("JABBER"))) {
174 PORT = 465; 172 config.send = "<stream:stream to=\'host\' xmlns=\'jabber:client\' "
175 } 173 "xmlns:stream=\'http://etherx.jabber.org/streams\'>\n";
176 else if (!strncmp(SERVICE, "JABBER", 6)) { 174 config.server_expect[0] = "<?xml version=\'1.0\'";
177 SEND = "<stream:stream to=\'host\' xmlns=\'jabber:client\' xmlns:stream=\'http://etherx.jabber.org/streams\'>\n"; 175 config.quit = "</stream:stream>\n";
178 EXPECT = "<?xml version=\'1.0\'"; 176 config.hide_output = true;
179 QUIT = "</stream:stream>\n"; 177 config.server_port = DEFAULT_XMPP_C2S_PORT;
180 flags |= FLAG_HIDE_OUTPUT; 178 } else if (!strncmp(config.service, "NNTPS", strlen("NNTPS"))) {
181 PORT = 5222; 179 config.server_expect_count = 2;
182 } 180 config.server_expect[0] = "200";
183 else if (!strncmp (SERVICE, "NNTPS", 5)) { 181 config.server_expect[1] = "201";
184 server_expect_count = 2; 182 config.quit = "QUIT\r\n";
185 server_expect[0] = "200"; 183 config.use_tls = true;
186 server_expect[1] = "201"; 184 config.server_port = DEFAULT_NNTPS_PORT;
187 QUIT = "QUIT\r\n";
188 flags |= FLAG_SSL;
189 PORT = 563;
190 } 185 }
191#endif 186#endif
192 else if (!strncmp (SERVICE, "NNTP", 4)) { 187 else if (!strncmp(config.service, "NNTP", strlen("NNTP"))) {
193 server_expect_count = 2; 188 config.server_expect_count = 2;
194 server_expect = malloc(sizeof(char *) * server_expect_count); 189 char **tmp = realloc(config.server_expect, config.server_expect_count * sizeof(char *));
195 server_expect[0] = strdup("200"); 190 if (tmp == NULL) {
196 server_expect[1] = strdup("201"); 191 free(config.server_expect);
197 QUIT = "QUIT\r\n"; 192 die(STATE_UNKNOWN, _("Allocation failed"));
198 PORT = 119; 193 }
199 } 194 config.server_expect = tmp;
200 else if (!strncmp(SERVICE, "CLAMD", 5)) { 195
201 SEND = "PING"; 196 config.server_expect[0] = strdup("200");
202 EXPECT = "PONG"; 197 config.server_expect[1] = strdup("201");
203 QUIT = NULL; 198 config.quit = "QUIT\r\n";
204 PORT = 3310; 199 config.server_port = DEFAULT_NNTP_PORT;
200 } else if (!strncmp(config.service, "CLAMD", strlen("CLAMD"))) {
201 config.send = "PING";
202 config.server_expect[0] = "PONG";
203 config.quit = NULL;
204 config.server_port = DEFAULT_CLAMD_PORT;
205 } 205 }
206 /* fallthrough check, so it's supposed to use reverse matching */ 206 /* fallthrough check, so it's supposed to use reverse matching */
207 else if (strcmp (SERVICE, "TCP")) 207 else if (strcmp(config.service, "TCP")) {
208 usage (_("CRITICAL - Generic check_tcp called with unknown service\n")); 208 usage(_("CRITICAL - Generic check_tcp called with unknown service\n"));
209 209 }
210 server_address = "127.0.0.1";
211 server_port = PORT;
212 server_send = SEND;
213 server_quit = QUIT;
214 status = NULL;
215 210
216 /* Parse extra opts if any */ 211 /* Parse extra opts if any */
217 argv=np_extra_opts (&argc, argv, progname); 212 argv = np_extra_opts(&argc, argv, progname);
213
214 check_tcp_config_wrapper paw = process_arguments(argc, argv, config);
215 if (paw.errorcode == ERROR) {
216 usage4(_("Could not parse arguments"));
217 }
218 218
219 if (process_arguments (argc, argv) == ERROR) 219 config = paw.config;
220 usage4 (_("Could not parse arguments"));
221 220
222 if(flags & FLAG_VERBOSE) { 221 if (verbosity > 0) {
223 printf("Using service %s\n", SERVICE); 222 printf("Using service %s\n", config.service);
224 printf("Port: %d\n", server_port); 223 printf("Port: %d\n", config.server_port);
225 printf("flags: 0x%x\n", (int)flags);
226 } 224 }
227 225
228 if(EXPECT && !server_expect_count) 226 if ((config.server_expect_count == 0) && config.server_expect[0]) {
229 server_expect_count++; 227 config.server_expect_count++;
228 }
230 229
231 if(PROTOCOL==IPPROTO_UDP && !(server_expect_count && server_send)){ 230 if (config.protocol == IPPROTO_UDP && !(config.server_expect_count && config.send)) {
232 usage(_("With UDP checks, a send/expect string must be specified.")); 231 usage(_("With UDP checks, a send/expect string must be specified."));
233 } 232 }
234 233
234 // Initialize check stuff before setting timers
235 mp_check overall = mp_check_init();
236 if (config.output_format_set) {
237 mp_set_format(config.output_format);
238 }
239
235 /* set up the timer */ 240 /* set up the timer */
236 signal (SIGALRM, socket_timeout_alarm_handler); 241 signal(SIGALRM, socket_timeout_alarm_handler);
237 alarm (socket_timeout); 242 alarm(socket_timeout);
238 243
239 /* try to connect to the host at the given port number */ 244 /* try to connect to the host at the given port number */
240 gettimeofday (&tv, NULL); 245 struct timeval start_time;
241 246 gettimeofday(&start_time, NULL);
242 result = np_net_connect (server_address, server_port, &sd, PROTOCOL); 247
243 if (result == STATE_CRITICAL) return econn_refuse_state; 248 int socket_descriptor = 0;
249 mp_subcheck inital_connect_result = mp_subcheck_init();
250
251 // Try initial connection
252 if (np_net_connect(config.server_address, config.server_port, &socket_descriptor,
253 config.protocol) == STATE_CRITICAL) {
254 // Early exit here, we got connection refused
255 inital_connect_result =
256 mp_set_subcheck_state(inital_connect_result, config.econn_refuse_state);
257 xasprintf(&inital_connect_result.output, "Connection to %s on port %i was REFUSED",
258 config.server_address, config.server_port);
259 mp_add_subcheck_to_check(&overall, inital_connect_result);
260 mp_exit(overall);
261 } else {
262 inital_connect_result = mp_set_subcheck_state(inital_connect_result, STATE_OK);
263 xasprintf(&inital_connect_result.output, "Connection to %s on port %i was a SUCCESS",
264 config.server_address, config.server_port);
265 mp_add_subcheck_to_check(&overall, inital_connect_result);
266 }
244 267
245#ifdef HAVE_SSL 268#ifdef HAVE_SSL
246 if (flags & FLAG_SSL){ 269 if (config.use_tls) {
247 result = np_net_ssl_init_with_hostname(sd, (sni_specified ? sni : NULL)); 270 mp_subcheck tls_connection_result = mp_subcheck_init();
248 if (result == STATE_OK && check_cert) { 271 mp_state_enum result = np_net_ssl_init_with_hostname(
249 result = np_net_ssl_check_cert(days_till_exp_warn, days_till_exp_crit); 272 socket_descriptor, (config.sni_specified ? config.sni : NULL));
273 tls_connection_result = mp_set_subcheck_default_state(tls_connection_result, result);
274
275 if (result == STATE_OK) {
276 xasprintf(&tls_connection_result.output, "TLS connection succeeded");
277
278 if (config.check_cert) {
279 result =
280 np_net_ssl_check_cert(config.days_till_exp_warn, config.days_till_exp_crit);
281
282 mp_subcheck tls_certificate_lifetime_result = mp_subcheck_init();
283 tls_certificate_lifetime_result =
284 mp_set_subcheck_state(tls_certificate_lifetime_result, result);
285
286 if (result == STATE_OK) {
287 xasprintf(&tls_certificate_lifetime_result.output,
288 "Certificate lifetime is within thresholds");
289 } else if (result == STATE_WARNING) {
290 xasprintf(&tls_certificate_lifetime_result.output,
291 "Certificate lifetime is violating warning threshold (%i)",
292 config.days_till_exp_warn);
293 } else if (result == STATE_CRITICAL) {
294 xasprintf(&tls_certificate_lifetime_result.output,
295 "Certificate lifetime is violating critical threshold (%i)",
296 config.days_till_exp_crit);
297 } else {
298 xasprintf(&tls_certificate_lifetime_result.output,
299 "Certificate lifetime is somehow unknown");
300 }
301
302 mp_add_subcheck_to_subcheck(&tls_connection_result,
303 tls_certificate_lifetime_result);
304 }
305
306 mp_add_subcheck_to_check(&overall, tls_connection_result);
307 } else {
308 xasprintf(&tls_connection_result.output, "TLS connection failed");
309 mp_add_subcheck_to_check(&overall, tls_connection_result);
310
311 if (socket_descriptor) {
312 close(socket_descriptor);
313 }
314 np_net_ssl_cleanup();
315
316 mp_exit(overall);
250 } 317 }
251 } 318 }
252 if(result != STATE_OK){
253 if(sd) close(sd);
254 np_net_ssl_cleanup();
255 return result;
256 }
257#endif /* HAVE_SSL */ 319#endif /* HAVE_SSL */
258 320
259 if (server_send != NULL) { /* Something to send? */ 321 if (config.send != NULL) { /* Something to send? */
260 my_send(server_send, strlen(server_send)); 322 my_send(socket_descriptor, config.send, strlen(config.send), config.use_tls);
261 } 323 }
262 324
263 if (delay > 0) { 325 if (config.delay > 0) {
264 tv.tv_sec += delay; 326 start_time.tv_sec += config.delay;
265 sleep (delay); 327 sleep(config.delay);
266 } 328 }
267 329
268 if(flags & FLAG_VERBOSE) { 330 if (verbosity > 0) {
269 if (server_send) { 331 if (config.send) {
270 printf("Send string: %s\n", server_send); 332 printf("Send string: %s\n", config.send);
333 }
334 if (config.quit) {
335 printf("Quit string: %s\n", config.quit);
271 } 336 }
272 if (server_quit) { 337 printf("server_expect_count: %d\n", (int)config.server_expect_count);
273 printf("Quit string: %s\n", server_quit); 338 for (size_t i = 0; i < config.server_expect_count; i++) {
339 printf("\t%zd: %s\n", i, config.server_expect[i]);
274 } 340 }
275 printf("server_expect_count: %d\n", (int)server_expect_count);
276 for(size_t i = 0; i < server_expect_count; i++)
277 printf("\t%zd: %s\n", i, server_expect[i]);
278 } 341 }
279 342
280 /* if(len) later on, we know we have a non-NULL response */ 343 /* if(len) later on, we know we have a non-NULL response */
281 ssize_t len = 0; 344 ssize_t len = 0;
345 char *received_buffer = NULL;
346 enum np_match_result match = NP_MATCH_NONE;
347 mp_subcheck expected_data_result = mp_subcheck_init();
282 348
283 if (server_expect_count) { 349 if (config.server_expect_count) {
284 ssize_t received = 0; 350 ssize_t received = 0;
351 char buffer[MAXBUF];
285 352
286 /* watch for the expect string */ 353 /* watch for the expect string */
287 while ((received = my_recv(buffer, sizeof(buffer))) > 0) { 354 while ((received = my_recv(socket_descriptor, buffer, sizeof(buffer), config.use_tls)) >
288 status = realloc(status, len + received + 1); 355 0) {
289 memcpy(&status[len], buffer, received); 356 received_buffer = realloc(received_buffer, len + received + 1);
357
358 if (received_buffer == NULL) {
359 die(STATE_UNKNOWN, _("Allocation failed"));
360 }
361
362 memcpy(&received_buffer[len], buffer, received);
290 len += received; 363 len += received;
291 status[len] = '\0'; 364 received_buffer[len] = '\0';
292 365
293 /* stop reading if user-forced */ 366 /* stop reading if user-forced */
294 if (maxbytes && len >= maxbytes) 367 if (config.maxbytes && len >= config.maxbytes) {
295 break; 368 break;
369 }
296 370
297 if ((match = np_expect_match(status, 371 if ((match = np_expect_match(received_buffer, config.server_expect,
298 server_expect, 372 config.server_expect_count, config.match_flags)) !=
299 server_expect_count, 373 NP_MATCH_RETRY) {
300 match_flags)) != NP_MATCH_RETRY)
301 break; 374 break;
375 }
376
377 fd_set rfds;
378 FD_ZERO(&rfds);
379 FD_SET(socket_descriptor, &rfds);
302 380
303 /* some protocols wait for further input, so make sure we don't wait forever */ 381 /* some protocols wait for further input, so make sure we don't wait forever */
304 FD_SET(sd, &rfds); 382 struct timeval timeout;
305 timeout.tv_sec = READ_TIMEOUT; 383 timeout.tv_sec = READ_TIMEOUT;
306 timeout.tv_usec = 0; 384 timeout.tv_usec = 0;
307 if(select(sd + 1, &rfds, NULL, NULL, &timeout) <= 0) 385
386 if (select(socket_descriptor + 1, &rfds, NULL, NULL, &timeout) <= 0) {
308 break; 387 break;
388 }
309 } 389 }
310 390
311 if (match == NP_MATCH_RETRY) 391 if (match == NP_MATCH_RETRY) {
312 match = NP_MATCH_FAILURE; 392 match = NP_MATCH_FAILURE;
393 }
313 394
314 /* no data when expected, so return critical */ 395 /* no data when expected, so return critical */
315 if (len == 0) 396 if (len == 0) {
316 die (STATE_CRITICAL, _("No data received from host\n")); 397 xasprintf(&expected_data_result.output, "Received no data when some was expected");
398 expected_data_result = mp_set_subcheck_state(expected_data_result, STATE_CRITICAL);
399 mp_add_subcheck_to_check(&overall, expected_data_result);
400 mp_exit(overall);
401 }
317 402
318 /* print raw output if we're debugging */ 403 /* print raw output if we're debugging */
319 if(flags & FLAG_VERBOSE) 404 if (verbosity > 0) {
320 printf("received %d bytes from host\n#-raw-recv-------#\n%s\n#-raw-recv-------#\n", 405 printf("received %d bytes from host\n#-raw-recv-------#\n%s\n#-raw-recv-------#\n",
321 (int)len + 1, status); 406 (int)len + 1, received_buffer);
407 }
322 /* strip whitespace from end of output */ 408 /* strip whitespace from end of output */
323 while(--len > 0 && isspace(status[len])) 409 while (--len > 0 && isspace(received_buffer[len])) {
324 status[len] = '\0'; 410 received_buffer[len] = '\0';
411 }
325 } 412 }
326 413
327 if (server_quit != NULL) { 414 if (config.quit != NULL) {
328 my_send(server_quit, strlen(server_quit)); 415 my_send(socket_descriptor, config.quit, strlen(config.quit), config.use_tls);
416 }
417
418 if (socket_descriptor) {
419 close(socket_descriptor);
329 } 420 }
330 if (sd) close (sd);
331#ifdef HAVE_SSL 421#ifdef HAVE_SSL
332 np_net_ssl_cleanup(); 422 np_net_ssl_cleanup();
333#endif 423#endif
334 424
335 microsec = deltime (tv); 425 long microsec = deltime(start_time);
336 elapsed_time = (double)microsec / 1.0e6; 426 double elapsed_time = (double)microsec / 1.0e6;
427
428 mp_subcheck elapsed_time_result = mp_subcheck_init();
429
430 mp_perfdata time_pd = perfdata_init();
431 time_pd = mp_set_pd_value(time_pd, elapsed_time);
432 time_pd.label = "time";
433 time_pd.uom = "s";
434
435 if (config.critical_time_set && elapsed_time > config.critical_time) {
436 xasprintf(&elapsed_time_result.output,
437 "Connection time %fs exceeded critical threshold (%f)", elapsed_time,
438 config.critical_time);
439
440 elapsed_time_result = mp_set_subcheck_state(elapsed_time_result, STATE_CRITICAL);
441 time_pd.crit_present = true;
442 mp_range crit_val = mp_range_init();
443
444 crit_val.end = mp_create_pd_value(config.critical_time);
445 crit_val.end_infinity = false;
446
447 time_pd.crit = crit_val;
448 } else if (config.warning_time_set && elapsed_time > config.warning_time) {
449 xasprintf(&elapsed_time_result.output,
450 "Connection time %fs exceeded warning threshold (%f)", elapsed_time,
451 config.critical_time);
452
453 elapsed_time_result = mp_set_subcheck_state(elapsed_time_result, STATE_WARNING);
454 time_pd.warn_present = true;
455 mp_range warn_val = mp_range_init();
456 warn_val.end = mp_create_pd_value(config.critical_time);
457 warn_val.end_infinity = false;
458
459 time_pd.warn = warn_val;
460 } else {
461 elapsed_time_result = mp_set_subcheck_state(elapsed_time_result, STATE_OK);
462 xasprintf(&elapsed_time_result.output, "Connection time %fs is within thresholds",
463 elapsed_time);
464 }
337 465
338 if (flags & FLAG_TIME_CRIT && elapsed_time > critical_time) 466 mp_add_perfdata_to_subcheck(&elapsed_time_result, time_pd);
339 result = STATE_CRITICAL; 467 mp_add_subcheck_to_check(&overall, elapsed_time_result);
340 else if (flags & FLAG_TIME_WARN && elapsed_time > warning_time)
341 result = STATE_WARNING;
342 468
343 /* did we get the response we hoped? */ 469 /* did we get the response we hoped? */
344 if(match == NP_MATCH_FAILURE && result != STATE_CRITICAL) 470 if (match == NP_MATCH_FAILURE) {
345 result = expect_mismatch_state; 471 expected_data_result =
472 mp_set_subcheck_state(expected_data_result, config.expect_mismatch_state);
473 xasprintf(&expected_data_result.output, "Answer failed to match expectation");
474 mp_add_subcheck_to_check(&overall, expected_data_result);
475 } else if (match == NP_MATCH_SUCCESS) {
476 expected_data_result = mp_set_subcheck_state(expected_data_result, STATE_OK);
477 xasprintf(&expected_data_result.output, "The answer of the server matched the expectation");
478 mp_add_subcheck_to_check(&overall, expected_data_result);
479 }
346 480
347 /* reset the alarm */ 481 /* reset the alarm */
348 alarm (0); 482 alarm(0);
349
350 /* 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
352 * the response we were looking for. if-else */
353 printf("%s %s - ", SERVICE, state_text(result));
354
355 if(match == NP_MATCH_FAILURE && len && !(flags & FLAG_HIDE_OUTPUT))
356 printf("Unexpected response from host/socket: %s", status);
357 else {
358 if(match == NP_MATCH_FAILURE)
359 printf("Unexpected response from host/socket on ");
360 else
361 printf("%.3f second response time on ", elapsed_time);
362 if(server_address[0] != '/') {
363 if (host_specified)
364 printf("%s port %d",
365 server_address, server_port);
366 else
367 printf("port %d", server_port);
368 }
369 else
370 printf("socket %s", server_address);
371 }
372 483
373 if (match != NP_MATCH_FAILURE && !(flags & FLAG_HIDE_OUTPUT) && len) 484 mp_exit(overall);
374 printf (" [%s]", status);
375
376 /* perf-data doesn't apply when server doesn't talk properly,
377 * so print all zeroes on warn and crit. Use fperfdata since
378 * localisation settings can make different outputs */
379 if(match == NP_MATCH_FAILURE)
380 printf ("|%s",
381 fperfdata ("time", elapsed_time, "s",
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
388 printf("|%s",
389 fperfdata ("time", elapsed_time, "s",
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
396 putchar('\n');
397 return result;
398} 485}
399 486
400
401
402/* process command-line arguments */ 487/* process command-line arguments */
403static int process_arguments (int argc, char **argv) { 488static check_tcp_config_wrapper process_arguments(int argc, char **argv, check_tcp_config config) {
404 int c;
405 bool escape = false;
406 char *temp;
407
408 enum { 489 enum {
409 SNI_OPTION = CHAR_MAX + 1 490 SNI_OPTION = CHAR_MAX + 1,
491 output_format_index,
410 }; 492 };
411 493
412 int option = 0;
413 static struct option longopts[] = { 494 static struct option longopts[] = {
414 {"hostname", required_argument, 0, 'H'}, 495 {"hostname", required_argument, 0, 'H'},
415 {"critical", required_argument, 0, 'c'}, 496 {"critical", required_argument, 0, 'c'},
@@ -437,278 +518,311 @@ static int process_arguments (int argc, char **argv) {
437 {"ssl", no_argument, 0, 'S'}, 518 {"ssl", no_argument, 0, 'S'},
438 {"sni", required_argument, 0, SNI_OPTION}, 519 {"sni", required_argument, 0, SNI_OPTION},
439 {"certificate", required_argument, 0, 'D'}, 520 {"certificate", required_argument, 0, 'D'},
440 {0, 0, 0, 0} 521 {"output-format", required_argument, 0, output_format_index},
441 }; 522 {0, 0, 0, 0}};
442 523
443 if (argc < 2) 524 if (argc < 2) {
444 usage4 (_("No arguments found")); 525 usage4(_("No arguments found"));
526 }
445 527
446 /* backwards compatibility */ 528 /* backwards compatibility */
447 for (c = 1; c < argc; c++) { 529 for (int i = 1; i < argc; i++) {
448 if (strcmp ("-to", argv[c]) == 0) 530 if (strcmp("-to", argv[i]) == 0) {
449 strcpy (argv[c], "-t"); 531 strcpy(argv[i], "-t");
450 else if (strcmp ("-wt", argv[c]) == 0) 532 } else if (strcmp("-wt", argv[i]) == 0) {
451 strcpy (argv[c], "-w"); 533 strcpy(argv[i], "-w");
452 else if (strcmp ("-ct", argv[c]) == 0) 534 } else if (strcmp("-ct", argv[i]) == 0) {
453 strcpy (argv[c], "-c"); 535 strcpy(argv[i], "-c");
536 }
454 } 537 }
455 538
456 if (!is_option (argv[1])) { 539 if (!is_option(argv[1])) {
457 server_address = argv[1]; 540 config.server_address = argv[1];
458 argv[1] = argv[0]; 541 argv[1] = argv[0];
459 argv = &argv[1]; 542 argv = &argv[1];
460 argc--; 543 argc--;
461 } 544 }
462 545
463 while (1) { 546 bool escape = false;
464 c = getopt_long (argc, argv, "+hVv46EAH:s:e:q:m:c:w:t:p:C:W:d:Sr:jD:M:", 547
465 longopts, &option); 548 while (true) {
549 int option = 0;
550 int option_index =
551 getopt_long(argc, argv, "+hVv46EAH:s:e:q:m:c:w:t:p:C:W:d:Sr:jD:M:", longopts, &option);
466 552
467 if (c == -1 || c == EOF || c == 1) 553 if (option_index == -1 || option_index == EOF || option_index == 1) {
468 break; 554 break;
555 }
469 556
470 switch (c) { 557 switch (option_index) {
471 case '?': /* print short usage statement if args not parsable */ 558 case '?': /* print short usage statement if args not parsable */
472 usage5 (); 559 usage5();
473 case 'h': /* help */ 560 case 'h': /* help */
474 print_help (); 561 print_help(config.service);
475 exit (STATE_UNKNOWN); 562 exit(STATE_UNKNOWN);
476 case 'V': /* version */ 563 case 'V': /* version */
477 print_revision (progname, NP_VERSION); 564 print_revision(progname, NP_VERSION);
478 exit (STATE_UNKNOWN); 565 exit(STATE_UNKNOWN);
479 case 'v': /* verbose mode */ 566 case 'v': /* verbose mode */
480 flags |= FLAG_VERBOSE; 567 verbosity++;
481 match_flags |= NP_MATCH_VERBOSE; 568 config.match_flags |= NP_MATCH_VERBOSE;
482 break; 569 break;
483 case '4': 570 case '4': // Apparently unused TODO
484 address_family = AF_INET; 571 address_family = AF_INET;
485 break; 572 break;
486 case '6': 573 case '6': // Apparently unused TODO
487#ifdef USE_IPV6 574#ifdef USE_IPV6
488 address_family = AF_INET6; 575 address_family = AF_INET6;
489#else 576#else
490 usage4 (_("IPv6 support not available")); 577 usage4(_("IPv6 support not available"));
491#endif 578#endif
492 break; 579 break;
493 case 'H': /* hostname */ 580 case 'H': /* hostname */
494 host_specified = true; 581 config.host_specified = true;
495 server_address = optarg; 582 config.server_address = optarg;
496 break;
497 case 'c': /* critical */
498 critical_time = strtod (optarg, NULL);
499 flags |= FLAG_TIME_CRIT;
500 break; 583 break;
501 case 'j': /* hide output */ 584 case 'c': /* critical */
502 flags |= FLAG_HIDE_OUTPUT; 585 config.critical_time = strtod(optarg, NULL);
586 config.critical_time_set = true;
503 break; 587 break;
504 case 'w': /* warning */ 588 case 'j': /* hide output */
505 warning_time = strtod (optarg, NULL); 589 config.hide_output = true;
506 flags |= FLAG_TIME_WARN;
507 break; 590 break;
508 case 'C': 591 case 'w': /* warning */
509 crit_codes = realloc (crit_codes, ++crit_codes_count); 592 config.warning_time = strtod(optarg, NULL);
510 crit_codes[crit_codes_count - 1] = optarg; 593 config.warning_time_set = true;
511 break; 594 break;
512 case 'W': 595 case 't': /* timeout */
513 warn_codes = realloc (warn_codes, ++warn_codes_count); 596 if (!is_intpos(optarg)) {
514 warn_codes[warn_codes_count - 1] = optarg; 597 usage4(_("Timeout interval must be a positive integer"));
515 break; 598 } else {
516 case 't': /* timeout */ 599 socket_timeout = atoi(optarg);
517 if (!is_intpos (optarg)) 600 }
518 usage4 (_("Timeout interval must be a positive integer"));
519 else
520 socket_timeout = atoi (optarg);
521 break; 601 break;
522 case 'p': /* port */ 602 case 'p': /* port */
523 if (!is_intpos (optarg)) 603 if (!is_intpos(optarg)) {
524 usage4 (_("Port must be a positive integer")); 604 usage4(_("Port must be a positive integer"));
525 else 605 } else {
526 server_port = atoi (optarg); 606 config.server_port = atoi(optarg);
607 }
527 break; 608 break;
528 case 'E': 609 case 'E':
529 escape = true; 610 escape = true;
530 break; 611 break;
531 case 's': 612 case 's':
532 if (escape) 613 if (escape) {
533 server_send = np_escaped_string(optarg); 614 config.send = np_escaped_string(optarg);
534 else 615 } else {
535 xasprintf(&server_send, "%s", optarg); 616 xasprintf(&config.send, "%s", optarg);
617 }
536 break; 618 break;
537 case 'e': /* expect string (may be repeated) */ 619 case 'e': /* expect string (may be repeated) */
538 match_flags &= ~NP_MATCH_EXACT; 620 config.match_flags &= ~NP_MATCH_EXACT;
539 if (server_expect_count == 0) 621 if (config.server_expect_count == 0) {
540 server_expect = malloc (sizeof (char *) * (++server_expect_count)); 622 config.server_expect = malloc(sizeof(char *) * (++config.server_expect_count));
541 else 623 } else {
542 server_expect = realloc (server_expect, sizeof (char *) * (++server_expect_count)); 624 config.server_expect =
543 server_expect[server_expect_count - 1] = optarg; 625 realloc(config.server_expect, sizeof(char *) * (++config.server_expect_count));
626 }
627
628 if (config.server_expect == NULL) {
629 die(STATE_UNKNOWN, _("Allocation failed"));
630 }
631 config.server_expect[config.server_expect_count - 1] = optarg;
544 break; 632 break;
545 case 'm': 633 case 'm':
546 if (!is_intpos (optarg)) 634 if (!is_intpos(optarg)) {
547 usage4 (_("Maxbytes must be a positive integer")); 635 usage4(_("Maxbytes must be a positive integer"));
548 else 636 } else {
549 maxbytes = strtol (optarg, NULL, 0); 637 config.maxbytes = strtol(optarg, NULL, 0);
638 }
550 break; 639 break;
551 case 'q': 640 case 'q':
552 if (escape) 641 if (escape) {
553 server_quit = np_escaped_string(optarg); 642 config.quit = np_escaped_string(optarg);
554 else 643 } else {
555 xasprintf(&server_quit, "%s\r\n", optarg); 644 xasprintf(&config.quit, "%s\r\n", optarg);
645 }
556 break; 646 break;
557 case 'r': 647 case 'r':
558 if (!strncmp(optarg,"ok",2)) 648 if (!strncmp(optarg, "ok", 2)) {
559 econn_refuse_state = STATE_OK; 649 config.econn_refuse_state = STATE_OK;
560 else if (!strncmp(optarg,"warn",4)) 650 } else if (!strncmp(optarg, "warn", 4)) {
561 econn_refuse_state = STATE_WARNING; 651 config.econn_refuse_state = STATE_WARNING;
562 else if (!strncmp(optarg,"crit",4)) 652 } else if (!strncmp(optarg, "crit", 4)) {
563 econn_refuse_state = STATE_CRITICAL; 653 config.econn_refuse_state = STATE_CRITICAL;
564 else 654 } else {
565 usage4 (_("Refuse must be one of ok, warn, crit")); 655 usage4(_("Refuse must be one of ok, warn, crit"));
656 }
566 break; 657 break;
567 case 'M': 658 case 'M':
568 if (!strncmp(optarg,"ok",2)) 659 if (!strncmp(optarg, "ok", 2)) {
569 expect_mismatch_state = STATE_OK; 660 config.expect_mismatch_state = STATE_OK;
570 else if (!strncmp(optarg,"warn",4)) 661 } else if (!strncmp(optarg, "warn", 4)) {
571 expect_mismatch_state = STATE_WARNING; 662 config.expect_mismatch_state = STATE_WARNING;
572 else if (!strncmp(optarg,"crit",4)) 663 } else if (!strncmp(optarg, "crit", 4)) {
573 expect_mismatch_state = STATE_CRITICAL; 664 config.expect_mismatch_state = STATE_CRITICAL;
574 else 665 } else {
575 usage4 (_("Mismatch must be one of ok, warn, crit")); 666 usage4(_("Mismatch must be one of ok, warn, crit"));
667 }
576 break; 668 break;
577 case 'd': 669 case 'd':
578 if (is_intpos (optarg)) 670 if (is_intpos(optarg)) {
579 delay = atoi (optarg); 671 config.delay = atoi(optarg);
580 else 672 } else {
581 usage4 (_("Delay must be a positive integer")); 673 usage4(_("Delay must be a positive integer"));
674 }
582 break; 675 break;
583 case 'D': /* Check SSL cert validity - days 'til certificate expiration */ 676 case 'D': /* Check SSL cert validity - days 'til certificate expiration */
584#ifdef HAVE_SSL 677#ifdef HAVE_SSL
585# ifdef USE_OPENSSL /* XXX */ 678# ifdef USE_OPENSSL /* XXX */
586 if ((temp=strchr(optarg,','))!=NULL) { 679 {
587 *temp='\0'; 680 char *temp;
588 if (!is_intnonneg (optarg)) 681 if ((temp = strchr(optarg, ',')) != NULL) {
589 usage2 (_("Invalid certificate expiration period"), optarg); 682 *temp = '\0';
590 days_till_exp_warn = atoi (optarg); 683 if (!is_intnonneg(optarg)) {
591 *temp=','; 684 usage2(_("Invalid certificate expiration period"), optarg);
592 temp++; 685 }
593 if (!is_intnonneg (temp)) 686 config.days_till_exp_warn = atoi(optarg);
594 usage2 (_("Invalid certificate expiration period"), temp); 687 *temp = ',';
595 days_till_exp_crit = atoi (temp); 688 temp++;
689 if (!is_intnonneg(temp)) {
690 usage2(_("Invalid certificate expiration period"), temp);
691 }
692 config.days_till_exp_crit = atoi(temp);
693 } else {
694 config.days_till_exp_crit = 0;
695 if (!is_intnonneg(optarg)) {
696 usage2(_("Invalid certificate expiration period"), optarg);
697 }
698 config.days_till_exp_warn = atoi(optarg);
596 } 699 }
597 else { 700 config.check_cert = true;
598 days_till_exp_crit=0; 701 config.use_tls = true;
599 if (!is_intnonneg (optarg)) 702 } break;
600 usage2 (_("Invalid certificate expiration period"), optarg); 703# endif /* USE_OPENSSL */
601 days_till_exp_warn = atoi (optarg);
602 }
603 check_cert = true;
604 flags |= FLAG_SSL;
605 break;
606# endif /* USE_OPENSSL */
607#endif 704#endif
608 /* fallthrough if we don't have ssl */ 705 /* fallthrough if we don't have ssl */
609 case 'S': 706 case 'S':
610#ifdef HAVE_SSL 707#ifdef HAVE_SSL
611 flags |= FLAG_SSL; 708 config.use_tls = true;
612#else 709#else
613 die (STATE_UNKNOWN, _("Invalid option - SSL is not available")); 710 die(STATE_UNKNOWN, _("Invalid option - SSL is not available"));
614#endif 711#endif
615 break; 712 break;
616 case SNI_OPTION: 713 case SNI_OPTION:
617#ifdef HAVE_SSL 714#ifdef HAVE_SSL
618 flags |= FLAG_SSL; 715 config.use_tls = true;
619 sni_specified = true; 716 config.sni_specified = true;
620 sni = optarg; 717 config.sni = optarg;
621#else 718#else
622 die (STATE_UNKNOWN, _("Invalid option - SSL is not available")); 719 die(STATE_UNKNOWN, _("Invalid option - SSL is not available"));
623#endif 720#endif
624 break; 721 break;
625 case 'A': 722 case 'A':
626 match_flags |= NP_MATCH_ALL; 723 config.match_flags |= NP_MATCH_ALL;
724 break;
725 case output_format_index: {
726 parsed_output_format parser = mp_parse_output_format(optarg);
727 if (!parser.parsing_success) {
728 // TODO List all available formats here, maybe add anothoer usage function
729 printf("Invalid output format: %s\n", optarg);
730 exit(STATE_UNKNOWN);
731 }
732
733 config.output_format_set = true;
734 config.output_format = parser.output_format;
627 break; 735 break;
628 } 736 }
737 }
629 } 738 }
630 739
631 c = optind; 740 int index = optind;
632 if(!host_specified && c < argc) 741 if (!config.host_specified && index < argc) {
633 server_address = strdup (argv[c++]); 742 config.server_address = strdup(argv[index++]);
743 }
634 744
635 if (server_address == NULL) 745 if (config.server_address == NULL) {
636 usage4 (_("You must provide a server address")); 746 usage4(_("You must provide a server address"));
637 else if (server_address[0] != '/' && !is_host(server_address)) 747 } else if (config.server_address[0] != '/' && !is_host(config.server_address)) {
638 die (STATE_CRITICAL, "%s %s - %s: %s\n", SERVICE, state_text(STATE_CRITICAL), _("Invalid hostname, address or socket"), server_address); 748 die(STATE_CRITICAL, "%s %s - %s: %s\n", config.service, state_text(STATE_CRITICAL),
749 _("Invalid hostname, address or socket"), config.server_address);
750 }
639 751
640 return OK; 752 check_tcp_config_wrapper result = {
753 .config = config,
754 .errorcode = OK,
755 };
756 return result;
641} 757}
642 758
643 759void print_help(const char *service) {
644void 760 print_revision(progname, NP_VERSION);
645print_help (void) 761
646{ 762 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
647 print_revision (progname, NP_VERSION); 763 printf(COPYRIGHT, copyright, email);
648 764
649 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n"); 765 printf(_("This plugin tests %s connections with the specified host (or unix socket).\n\n"),
650 printf (COPYRIGHT, copyright, email); 766 service);
651 767
652 printf (_("This plugin tests %s connections with the specified host (or unix socket).\n\n"), 768 print_usage();
653 SERVICE); 769
654 770 printf(UT_HELP_VRSN);
655 print_usage (); 771 printf(UT_EXTRA_OPTS);
656 772
657 printf (UT_HELP_VRSN); 773 printf(UT_HOST_PORT, 'p', "none");
658 printf (UT_EXTRA_OPTS); 774
659 775 printf(UT_IPv46);
660 printf (UT_HOST_PORT, 'p', "none"); 776
661 777 printf(" %s\n", "-E, --escape");
662 printf (UT_IPv46); 778 printf(" %s\n", _("Can use \\n, \\r, \\t or \\\\ in send or quit string. Must come before "
663 779 "send or quit option"));
664 printf (" %s\n", "-E, --escape"); 780 printf(" %s\n", _("Default: nothing added to send, \\r\\n added to end of quit"));
665 printf (" %s\n", _("Can use \\n, \\r, \\t or \\\\ in send or quit string. Must come before send or quit option")); 781 printf(" %s\n", "-s, --send=STRING");
666 printf (" %s\n", _("Default: nothing added to send, \\r\\n added to end of quit")); 782 printf(" %s\n", _("String to send to the server"));
667 printf (" %s\n", "-s, --send=STRING"); 783 printf(" %s\n", "-e, --expect=STRING");
668 printf (" %s\n", _("String to send to the server")); 784 printf(" %s %s\n", _("String to expect in server response"), _("(may be repeated)"));
669 printf (" %s\n", "-e, --expect=STRING"); 785 printf(" %s\n", "-A, --all");
670 printf (" %s %s\n", _("String to expect in server response"), _("(may be repeated)")); 786 printf(" %s\n", _("All expect strings need to occur in server response. Default is any"));
671 printf (" %s\n", "-A, --all"); 787 printf(" %s\n", "-q, --quit=STRING");
672 printf (" %s\n", _("All expect strings need to occur in server response. Default is any")); 788 printf(" %s\n", _("String to send server to initiate a clean close of the connection"));
673 printf (" %s\n", "-q, --quit=STRING"); 789 printf(" %s\n", "-r, --refuse=ok|warn|crit");
674 printf (" %s\n", _("String to send server to initiate a clean close of the connection")); 790 printf(" %s\n", _("Accept TCP refusals with states ok, warn, crit (default: crit)"));
675 printf (" %s\n", "-r, --refuse=ok|warn|crit"); 791 printf(" %s\n", "-M, --mismatch=ok|warn|crit");
676 printf (" %s\n", _("Accept TCP refusals with states ok, warn, crit (default: crit)")); 792 printf(" %s\n",
677 printf (" %s\n", "-M, --mismatch=ok|warn|crit"); 793 _("Accept expected string mismatches with states ok, warn, crit (default: warn)"));
678 printf (" %s\n", _("Accept expected string mismatches with states ok, warn, crit (default: warn)")); 794 printf(" %s\n", "-j, --jail");
679 printf (" %s\n", "-j, --jail"); 795 printf(" %s\n", _("Hide output from TCP socket"));
680 printf (" %s\n", _("Hide output from TCP socket")); 796 printf(" %s\n", "-m, --maxbytes=INTEGER");
681 printf (" %s\n", "-m, --maxbytes=INTEGER"); 797 printf(" %s\n", _("Close connection once more than this number of bytes are received"));
682 printf (" %s\n", _("Close connection once more than this number of bytes are received")); 798 printf(" %s\n", "-d, --delay=INTEGER");
683 printf (" %s\n", "-d, --delay=INTEGER"); 799 printf(" %s\n", _("Seconds to wait between sending string and polling for response"));
684 printf (" %s\n", _("Seconds to wait between sending string and polling for response"));
685 800
686#ifdef HAVE_SSL 801#ifdef HAVE_SSL
687 printf (" %s\n", "-D, --certificate=INTEGER[,INTEGER]"); 802 printf(" %s\n", "-D, --certificate=INTEGER[,INTEGER]");
688 printf (" %s\n", _("Minimum number of days a certificate has to be valid.")); 803 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).")); 804 printf(" %s\n", _("1st is #days for warning, 2nd is critical (if not specified - 0)."));
690 printf (" %s\n", "-S, --ssl"); 805 printf(" %s\n", "-S, --ssl");
691 printf (" %s\n", _("Use SSL for the connection.")); 806 printf(" %s\n", _("Use SSL for the connection."));
692 printf (" %s\n", "--sni=STRING"); 807 printf(" %s\n", "--sni=STRING");
693 printf (" %s\n", _("SSL server_name")); 808 printf(" %s\n", _("SSL server_name"));
694#endif 809#endif
695 810
696 printf (UT_WARN_CRIT); 811 printf(UT_WARN_CRIT);
697 812
698 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 813 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
699 814
700 printf (UT_VERBOSE); 815 printf(UT_OUTPUT_FORMAT);
816 printf(UT_VERBOSE);
701 817
702 printf (UT_SUPPORT); 818 printf(UT_SUPPORT);
703} 819}
704 820
705 821void print_usage(void) {
706void 822 printf("%s\n", _("Usage:"));
707print_usage (void) 823 printf("%s -H host -p port [-w <warning time>] [-c <critical time>] [-s <send string>]\n",
708{ 824 progname);
709 printf ("%s\n", _("Usage:")); 825 printf("[-e <expect string>] [-q <quit string>][-m <maximum bytes>] [-d <delay>]\n");
710 printf ("%s -H host -p port [-w <warning time>] [-c <critical time>] [-s <send string>]\n",progname); 826 printf("[-t <timeout seconds>] [-r <refuse state>] [-M <mismatch state>] [-v] [-4|-6] [-j]\n");
711 printf ("[-e <expect string>] [-q <quit string>][-m <maximum bytes>] [-d <delay>]\n"); 827 printf("[-D <warn days cert expire>[,<crit days cert expire>]] [-S <use SSL>] [-E]\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} 828}