int tcp_check_thread(thread_t * thread) { checker_t *checker; tcp_checker_t *tcp_check; int status; checker = THREAD_ARG(thread); tcp_check = CHECKER_ARG(checker); status = tcp_socket_state(thread->u.fd, thread, tcp_check_thread); /* If status = connect_success, TCP connection to remote host is established. * Otherwise we have a real connection error or connection timeout. */ if (status == connect_success) { close(thread->u.fd); if (!svr_checker_up(UP, checker->id, checker->rs)) { log_message(LOG_INFO, "TCP connection to [%s]:%d success." , inet_sockaddrtos(&tcp_check->dst) , ntohs(inet_sockaddrport(&tcp_check->dst))); smtp_alert(checker->rs, NULL, NULL, "UP", "=> TCP CHECK succeed on service <="); update_svr_checker_state(UP, checker->id , checker->vs , checker->rs); } } else { if (svr_checker_up(DOWN, checker->id, checker->rs)) { log_message(LOG_INFO, "TCP connection to [%s]:%d failed !!!" , inet_sockaddrtos(&tcp_check->dst) , ntohs(inet_sockaddrport(&tcp_check->dst))); smtp_alert(checker->rs, NULL, NULL, "DOWN", "=> TCP CHECK failed on service <="); update_svr_checker_state(DOWN, checker->id , checker->vs , checker->rs); } } /* Register next timer checker */ if (status != connect_in_progress) thread_add_timer(thread->master, tcp_connect_thread, checker, checker->vs->delay_loop); return 0; }
/* Asynchronous SSL stream reader */ int ssl_read_thread(thread_t * thread) { checker_t *checker = THREAD_ARG(thread); http_checker_t *http_get_check = CHECKER_ARG(checker); http_arg_t *http_arg = HTTP_ARG(http_get_check); request_t *req = HTTP_REQ(http_arg); unsigned char digest[16]; int r = 0; int val; /* Handle read timeout */ if (thread->type == THREAD_READ_TIMEOUT && !req->extracted) return timeout_epilog(thread, "=> SSL CHECK failed on service" " : recevice data <=\n\n", "SSL read"); /* Set descriptor non blocking */ val = fcntl(thread->u.fd, F_GETFL, 0); fcntl(thread->u.fd, F_SETFL, val | O_NONBLOCK); /* read the SSL stream */ r = SSL_read(req->ssl, req->buffer + req->len, MAX_BUFFER_LENGTH - req->len); /* restore descriptor flags */ fcntl(thread->u.fd, F_SETFL, val); req->error = SSL_get_error(req->ssl, r); if (req->error == SSL_ERROR_WANT_READ) { /* async read unfinished */ thread_add_read(thread->master, ssl_read_thread, checker, thread->u.fd, http_get_check->connection_to); } else if (r > 0 && req->error == 0) { /* Handle response stream */ http_process_response(req, r); /* * Register next ssl stream reader. * Register itself to not perturbe global I/O multiplexer. */ thread_add_read(thread->master, ssl_read_thread, checker, thread->u.fd, http_get_check->connection_to); } else if (req->error) { /* All the SSL streal has been parsed */ MD5_Final(digest, &req->context); SSL_set_quiet_shutdown(req->ssl, 1); r = (req->error == SSL_ERROR_ZERO_RETURN) ? SSL_shutdown(req->ssl) : 0; if (r && !req->extracted) { /* check if server is currently alive */ if (svr_checker_up(checker->id, checker->rs)) { smtp_alert(checker->rs, NULL, NULL, "DOWN", "=> SSL CHECK failed on service" " : cannot receive data <=\n\n"); update_svr_checker_state(DOWN, checker->id , checker->vs , checker->rs); } return epilog(thread, 1, 0, 0); } /* Handle response stream */ http_handle_response(thread, digest, (!req->extracted) ? 1 : 0); } return 0; }
int misc_check_child_thread(thread * thread_obj) { int wait_status; checker *checker_obj; misc_checker *misc_chk; checker_obj = THREAD_ARG(thread_obj); misc_chk = CHECKER_ARG(checker_obj); if (thread_obj->type == THREAD_CHILD_TIMEOUT) { pid_t pid; pid = THREAD_CHILD_PID(thread_obj); /* The child hasn't responded. Kill it off. */ if (svr_checker_up(checker_obj->id, checker_obj->rs)) { log_message(LOG_INFO, "Misc check to [%s] for [%s] timed out", inet_ntop2(CHECKER_RIP(checker_obj)), misc_chk->path); smtp_alert(checker_obj->rs, NULL, NULL, "DOWN", "=> MISC CHECK script timeout on service <="); update_svr_checker_state(DOWN, checker_obj->id , checker_obj->vs , checker_obj->rs); } kill(pid, SIGTERM); thread_add_child(thread_obj->master, misc_check_child_timeout_thread, checker_obj, pid, 2); return 0; } wait_status = THREAD_CHILD_STATUS(thread_obj); if (WIFEXITED(wait_status)) { int status; status = WEXITSTATUS(wait_status); if (status == 0 || (misc_chk->dynamic == 1 && status >= 2 && status <= 255)) { /* * The actual weight set when using misc_dynamic is two less than * the exit status returned. Effective range is 0..253. * Catch legacy case of status being 0 but misc_dynamic being set. */ if (misc_chk->dynamic == 1 && status != 0) update_svr_wgt(status - 2, checker_obj->vs, checker_obj->rs); /* everything is good */ if (!svr_checker_up(checker_obj->id, checker_obj->rs)) { log_message(LOG_INFO, "Misc check to [%s] for [%s] success.", inet_ntop2(CHECKER_RIP(checker_obj)), misc_chk->path); smtp_alert(checker_obj->rs, NULL, NULL, "UP", "=> MISC CHECK succeed on service <="); update_svr_checker_state(UP, checker_obj->id , checker_obj->vs , checker_obj->rs); } } else { if (svr_checker_up(checker_obj->id, checker_obj->rs)) { log_message(LOG_INFO, "Misc check to [%s] for [%s] failed.", inet_ntop2(CHECKER_RIP(checker_obj)), misc_chk->path); smtp_alert(checker_obj->rs, NULL, NULL, "DOWN", "=> MISC CHECK failed on service <="); update_svr_checker_state(DOWN, checker_obj->id , checker_obj->vs , checker_obj->rs); } } } return 0; }