/* connects to a host on a specified port, sends a string, and gets a response */ int process_request (const char *server_address, int server_port, int proto, const char *send_buffer, char *recv_buffer, int recv_size) { int result; int sd; result = np_net_connect (server_address, server_port, &sd, proto); if (result != STATE_OK) return STATE_CRITICAL; result = send_request (sd, proto, send_buffer, recv_buffer, recv_size); close (sd); return result; }
int main (int argc, char **argv) { int result = STATE_UNKNOWN; int i; char *status = NULL; struct timeval tv; size_t len; int match = -1; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); /* determine program- and service-name quickly */ progname = strrchr(argv[0], '/'); if(progname != NULL) progname++; else progname = argv[0]; len = strlen(progname); if(len > 6 && !memcmp(progname, "check_", 6)) { SERVICE = strdup(progname + 6); for(i = 0; i < len - 6; i++) SERVICE[i] = toupper(SERVICE[i]); } /* set up a resonable buffer at first (will be realloc()'ed if * user specifies other options) */ server_expect = calloc(sizeof(char *), 2); /* determine defaults for this service's protocol */ if (!strncmp(SERVICE, "UDP", 3)) { PROTOCOL = IPPROTO_UDP; } else if (!strncmp(SERVICE, "FTP", 3)) { EXPECT = "220"; QUIT = "QUIT\r\n"; PORT = 21; } else if (!strncmp(SERVICE, "POP", 3) || !strncmp(SERVICE, "POP3", 4)) { EXPECT = "+OK"; QUIT = "QUIT\r\n"; PORT = 110; } else if (!strncmp(SERVICE, "SMTP", 4)) { EXPECT = "220"; QUIT = "QUIT\r\n"; PORT = 25; } else if (!strncmp(SERVICE, "IMAP", 4)) { EXPECT = "* OK"; QUIT = "a1 LOGOUT\r\n"; PORT = 143; } #ifdef HAVE_SSL else if (!strncmp(SERVICE, "SIMAP", 5)) { EXPECT = "* OK"; QUIT = "a1 LOGOUT\r\n"; flags |= FLAG_SSL; PORT = 993; } else if (!strncmp(SERVICE, "SPOP", 4)) { EXPECT = "+OK"; QUIT = "QUIT\r\n"; flags |= FLAG_SSL; PORT = 995; } else if (!strncmp(SERVICE, "SSMTP", 5)) { EXPECT = "220"; QUIT = "QUIT\r\n"; flags |= FLAG_SSL; PORT = 465; } else if (!strncmp(SERVICE, "JABBER", 6)) { SEND = "<stream:stream to=\'host\' xmlns=\'jabber:client\' xmlns:stream=\'http://etherx.jabber.org/streams\'>\n"; EXPECT = "<?xml version=\'1.0\'?><stream:stream xmlns=\'jabber:client\' xmlns:stream=\'http://etherx.jabber.org/streams\'"; QUIT = "</stream:stream>\n"; flags |= FLAG_HIDE_OUTPUT; PORT = 5222; } else if (!strncmp (SERVICE, "NNTPS", 5)) { server_expect_count = 2; server_expect[0] = "200"; server_expect[1] = "201"; QUIT = "QUIT\r\n"; flags |= FLAG_SSL; PORT = 563; } #endif else if (!strncmp (SERVICE, "NNTP", 4)) { server_expect_count = 2; server_expect = malloc(sizeof(char *) * server_expect_count); server_expect[0] = strdup("200"); server_expect[1] = strdup("201"); QUIT = "QUIT\r\n"; PORT = 119; } else if (!strncmp(SERVICE, "CLAMD", 5)) { SEND = "PING"; EXPECT = "PONG"; QUIT = NULL; PORT = 3310; } /* fallthrough check, so it's supposed to use reverse matching */ else if (strcmp (SERVICE, "TCP")) usage (_("CRITICAL - Generic check_tcp called with unknown service\n")); server_address = "127.0.0.1"; server_port = PORT; server_send = SEND; server_quit = QUIT; status = NULL; /* Parse extra opts if any */ argv=np_extra_opts (&argc, argv, progname); if (process_arguments (argc, argv) == ERROR) usage4 (_("Could not parse arguments")); if(flags & FLAG_VERBOSE) { printf("Using service %s\n", SERVICE); printf("Port: %d\n", server_port); printf("flags: 0x%x\n", (int)flags); } if(EXPECT && !server_expect_count) server_expect_count++; if(PROTOCOL==IPPROTO_UDP && !(server_expect_count && server_send)){ usage(_("With UDP checks, a send/expect string must be specified.")); } /* set up the timer */ signal (SIGALRM, socket_timeout_alarm_handler); alarm (socket_timeout); /* try to connect to the host at the given port number */ gettimeofday (&tv, NULL); result = np_net_connect (server_address, server_port, &sd, PROTOCOL); if (result == STATE_CRITICAL) return STATE_CRITICAL; #ifdef HAVE_SSL if (flags & FLAG_SSL){ result = np_net_ssl_init(sd); if (result == STATE_OK && check_cert == TRUE) { result = np_net_ssl_check_cert(days_till_exp); } } if(result != STATE_OK || check_cert == TRUE){ np_net_ssl_cleanup(); if(sd) close(sd); return result; } #endif /* HAVE_SSL */ if (server_send != NULL) { /* Something to send? */ my_send(server_send, strlen(server_send)); } if (delay > 0) { tv.tv_sec += delay; sleep (delay); } if(flags & FLAG_VERBOSE) { if (server_send) { printf("Send string: %s\n", server_send); } if (server_quit) { printf("Quit string: %s\n", server_quit); } printf("server_expect_count: %d\n", (int)server_expect_count); for(i = 0; i < server_expect_count; i++) printf("\t%d: %s\n", i, server_expect[i]); } /* if(len) later on, we know we have a non-NULL response */ len = 0; if (server_expect_count) { /* watch for the expect string */ while ((i = my_recv(buffer, sizeof(buffer))) > 0) { status = realloc(status, len + i + 1); memcpy(&status[len], buffer, i); len += i; /* stop reading if user-forced or data-starved */ if(i < sizeof(buffer) || (maxbytes && len >= maxbytes)) break; if (maxbytes && len >= maxbytes) break; } /* no data when expected, so return critical */ if (len == 0) die (STATE_CRITICAL, _("No data received from host\n")); /* force null-termination and strip whitespace from end of output */ status[len--] = '\0'; /* print raw output if we're debugging */ if(flags & FLAG_VERBOSE) printf("received %d bytes from host\n#-raw-recv-------#\n%s\n#-raw-recv-------#\n", (int)len + 1, status); while(isspace(status[len])) status[len--] = '\0'; match = np_expect_match(status, server_expect, server_expect_count, (flags & FLAG_MATCH_ALL ? TRUE : FALSE), (flags & FLAG_EXACT_MATCH ? TRUE : FALSE), (flags & FLAG_VERBOSE ? TRUE : FALSE)); } if (server_quit != NULL) { my_send(server_quit, strlen(server_quit)); } #ifdef HAVE_SSL np_net_ssl_cleanup(); #endif if (sd) close (sd); microsec = deltime (tv); elapsed_time = (double)microsec / 1.0e6; if (flags & FLAG_TIME_CRIT && elapsed_time > critical_time) result = STATE_CRITICAL; else if (flags & FLAG_TIME_WARN && elapsed_time > warning_time) result = STATE_WARNING; /* did we get the response we hoped? */ if(match == FALSE && result != STATE_CRITICAL) result = expect_mismatch_state; /* reset the alarm */ alarm (0); /* this is a bit stupid, because we don't want to print the * response time (which can look ok to the user) if we didn't get * the response we were looking for. if-else */ printf("%s %s - ", SERVICE, state_text(result)); if(match == FALSE && len && !(flags & FLAG_HIDE_OUTPUT)) printf("Unexpected response from host/socket: %s", status); else { if(match == FALSE) printf("Unexpected response from host/socket on "); else printf("%.3f second response time on ", elapsed_time); if(server_address[0] != '/') printf("port %d", server_port); else printf("socket %s", server_address); } if (match != FALSE && !(flags & FLAG_HIDE_OUTPUT) && len) printf (" [%s]", status); /* perf-data doesn't apply when server doesn't talk properly, * so print all zeroes on warn and crit. Use fperfdata since * localisation settings can make different outputs */ if(match == FALSE) printf ("|%s", fperfdata ("time", elapsed_time, "s", (flags & FLAG_TIME_WARN ? TRUE : FALSE), 0, (flags & FLAG_TIME_CRIT ? TRUE : FALSE), 0, TRUE, 0, TRUE, socket_timeout) ); else printf("|%s", fperfdata ("time", elapsed_time, "s", (flags & FLAG_TIME_WARN ? TRUE : FALSE), warning_time, (flags & FLAG_TIME_CRIT ? TRUE : FALSE), critical_time, TRUE, 0, TRUE, socket_timeout) ); putchar('\n'); return result; }
/* connects to a host on a specified tcp port, sends a string, and gets a response. loops on select-recv until timeout or eof to get all of a multi-packet answer */ int process_tcp_request2 (const char *server_address, int server_port, const char *send_buffer, char *recv_buffer, int recv_size) { int result; int send_result; int recv_result; int sd; struct timeval tv; fd_set readfds; int recv_length = 0; result = np_net_connect (server_address, server_port, &sd, IPPROTO_TCP); if (result != STATE_OK) return STATE_CRITICAL; send_result = send (sd, send_buffer, strlen (send_buffer), 0); if (send_result<0 || (size_t)send_result!=strlen(send_buffer)) { printf ("%s\n", _("Send failed")); result = STATE_WARNING; } while (1) { /* wait up to the number of seconds for socket timeout minus one for data from the host */ tv.tv_sec = socket_timeout - 1; tv.tv_usec = 0; FD_ZERO (&readfds); FD_SET (sd, &readfds); select (sd + 1, &readfds, NULL, NULL, &tv); /* make sure some data has arrived */ if (!FD_ISSET (sd, &readfds)) { /* it hasn't */ if (!recv_length) { strcpy (recv_buffer, ""); printf ("%s\n", _("No data was received from host!")); result = STATE_WARNING; } else { /* this one failed, but previous ones worked */ recv_buffer[recv_length] = 0; } break; } else { /* it has */ recv_result = recv (sd, recv_buffer + recv_length, (size_t)recv_size - recv_length - 1, 0); if (recv_result == -1) { /* recv failed, bail out */ strcpy (recv_buffer + recv_length, ""); result = STATE_WARNING; break; } else if (recv_result == 0) { /* end of file ? */ recv_buffer[recv_length] = 0; break; } else { /* we got data! */ recv_length += recv_result; if (recv_length >= recv_size - 1) { /* buffer full, we're done */ recv_buffer[recv_size - 1] = 0; break; } } } /* end if(!FD_ISSET(sd,&readfds)) */ } /* end while(1) */ close (sd); return result; }