Exemple #1
0
int
tcp_connect_thread(thread_t * thread)
{
	checker_t *checker = THREAD_ARG(thread);
	tcp_checker_t *tcp_check = CHECKER_ARG(checker);
	int fd;
	int status;

	/*
	 * Register a new checker thread & return
	 * if checker is disabled
	 */
	if (!CHECKER_ENABLED(checker)) {
		thread_add_timer(thread->master, tcp_connect_thread, checker,
				 checker->vs->delay_loop);
		return 0;
	}

	if ((fd = socket(tcp_check->dst.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
		DBG("TCP connect fail to create socket.");
		return 0;
	}

	status = tcp_bind_connect(fd, &tcp_check->dst, &tcp_check->bindto);
	if (status == connect_error) {
		thread_add_timer(thread->master, tcp_connect_thread, checker,
				 checker->vs->delay_loop);
	}

	/* handle tcp connection status & register check worker thread */
	tcp_connection_state(fd, status, thread, tcp_check_thread,
			     tcp_check->connection_to);
	return 0;
}
Exemple #2
0
int
ssl_connect(thread_t * thread, int new_req)
{
	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);
	int ret = 0;
	int val = 0;

	/* First round, create SSL context */
	if (new_req) {
		req->ssl = SSL_new(check_data->ssl->ctx);
		req->bio = BIO_new_socket(thread->u.fd, BIO_NOCLOSE);
		SSL_set_bio(req->ssl, req->bio, req->bio);
	}

	/* Set descriptor non blocking */
	val = fcntl(thread->u.fd, F_GETFL, 0);
	fcntl(thread->u.fd, F_SETFL, val | O_NONBLOCK);

	ret = SSL_connect(req->ssl);

	/* restore descriptor flags */
	fcntl(thread->u.fd, F_SETFL, val);

	return ret;
}
Exemple #3
0
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;
}
Exemple #4
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;
}
Exemple #5
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;
}
Exemple #6
0
int
misc_check_thread(thread * thread_obj)
{
	checker *checker_obj;
	misc_checker *misc_chk;
	int status, ret;
	pid_t pid;

	checker_obj = THREAD_ARG(thread_obj);
	misc_chk = CHECKER_ARG(checker_obj);

	/*
	 * Register a new checker thread & return
	 * if checker is disabled
	 */
	if (!CHECKER_ENABLED(checker_obj)) {
		/* Register next timer checker */
		thread_add_timer(thread_obj->master, misc_check_thread, checker_obj,
				 checker_obj->vs->delay_loop);
		return 0;
	}

	/* Register next timer checker */
	thread_add_timer(thread_obj->master, misc_check_thread, checker_obj,
			 checker_obj->vs->delay_loop);

	/* Daemonization to not degrade our scheduling timer */
	pid = fork();

	/* In case of fork is error. */
	if (pid < 0) {
		log_message(LOG_INFO, "Failed fork process");
		return -1;
	}

	/* In case of this is parent process */
	if (pid) {
		long timeout;
		timeout = (misc_chk->timeout) ? misc_chk->timeout : checker_obj->vs->delay_loop;

		thread_add_child(thread_obj->master, misc_check_child_thread,
				 checker_obj, pid, timeout);
		return 0;
	}

	/* Child part */
	signal_handler_destroy();
	closeall(0);

	open("/dev/null", O_RDWR);
	ret = dup(0);
	ret = dup(0);

	status = system_call(misc_chk->path);

	if (status < 0 || !WIFEXITED(status))
		status = 0; /* Script errors aren't server errors */
	else
		status = WEXITSTATUS(status);

	exit(status);
}