diff options
Diffstat (limited to 'plugins')
| -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 | |||
