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 | |||
