예제 #1
0
파일: smtp.c 프로젝트: Grip/keepalived-1
static int
smtp_send_thread(thread_t * thread)
{
	smtp_t *smtp = THREAD_ARG(thread);

	if (thread->type == THREAD_WRITE_TIMEOUT) {
		log_message(LOG_INFO, "Timeout sending data to remote SMTP server [%s]:%d."
				    , inet_sockaddrtos(&global_data->smtp_server), SMTP_PORT);
		SMTP_FSM_READ(QUIT, thread, 0);
		return 0;
	}

	SMTP_FSM_SEND(smtp->stage, thread);

	/* Handle END command */
	if (smtp->stage == END) {
		SMTP_FSM_READ(QUIT, thread, 0);
		return 0;
	}

	/* Registering next smtp command processing thread */
	if (smtp->stage != ERROR) {
		thread_add_read(thread->master, smtp_read_thread, smtp,
				thread->u.fd, global_data->smtp_connection_to);
	} else {
		log_message(LOG_INFO, "Can not send data to remote SMTP server [%s]:%d."
				    , inet_sockaddrtos(&global_data->smtp_server)
				    , SMTP_PORT);
		SMTP_FSM_READ(QUIT, thread, 0);
	}

	return 0;
}
예제 #2
0
파일: check_smtp.c 프로젝트: Addision/LVS
/*
 * Used as a callback from dump_list() to print out all
 * the list elements in smtp_checker->host.
 */
void
smtp_dump_host(void *data)
{
        smtp_host_t *smtp_host = data;
        log_message(LOG_INFO, "   Checked ip = %s", inet_sockaddrtos(&smtp_host->dst));
        log_message(LOG_INFO, "           port = %d", ntohs(ntohs(inet_sockaddrport(&smtp_host->dst))));
	if (smtp_host->bindto.ss_family)
        	log_message(LOG_INFO, "           bindto = %s", inet_sockaddrtos(&smtp_host->bindto));
}
예제 #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;
}
예제 #4
0
/* Store new weight in real_server struct and then update kernel. */
void
update_svr_wgt(int weight, virtual_server * vs, real_server * rs)
{
	char rsip[INET6_ADDRSTRLEN];

	if (weight != rs->weight) {
		log_message(LOG_INFO, "Changing weight from %d to %d for %s service [%s]:%d of VS [%s]:%d"
				    , rs->weight
				    , weight
				    , ISALIVE(rs) ? "active" : "inactive"
				    , inet_sockaddrtos2(&rs->addr, rsip)
				    , ntohs(inet_sockaddrport(&rs->addr))
				    , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
				    , ntohs(inet_sockaddrport(&vs->addr)));
		rs->weight = weight;
		/*
		 * Have weight change take effect now only if rs is in
		 * the pool and alive and the quorum is met (or if
		 * there is no sorry server). If not, it will take
		 * effect later when it becomes alive.
		 */
		if (rs->set && ISALIVE(rs) &&
		    (vs->quorum_state == UP || !vs->s_svr || !ISALIVE(vs->s_svr)))
			ipvs_cmd(LVS_CMD_EDIT_DEST, check_data->vs_group, vs, rs);
		update_quorum_state(vs);
	}
}
예제 #5
0
/* Remove a realserver IPVS rule */
static int
clear_service_rs(list vs_group, virtual_server * vs, list l)
{
	element e;
	real_server *rs;
	char rsip[INET6_ADDRSTRLEN];

	for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
		rs = ELEMENT_DATA(e);
		if (ISALIVE(rs)) {
			if (!ipvs_cmd(LVS_CMD_DEL_DEST, vs_group, vs, rs))
				return 0;
			UNSET_ALIVE(rs);
			if (!vs->omega)
				continue;

			/* In Omega mode we call VS and RS down notifiers
			 * all the way down the exit, as necessary.
			 */
			if (rs->notify_down) {
				log_message(LOG_INFO, "Executing [%s] for service [%s]:%d in VS [%s]:%d"
						    , rs->notify_down
						    , inet_sockaddrtos2(&rs->addr, rsip)
						    , ntohs(inet_sockaddrport(&rs->addr))
						    , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
						    , ntohs(inet_sockaddrport(&vs->addr)));
				notify_exec(rs->notify_down);
			}

			/* Sooner or later VS will lose the quorum (if any). However,
			 * we don't push in a sorry server then, hence the regression
			 * is intended.
			 */
			if (vs->quorum_state == UP && vs->quorum_down &&
			    weigh_live_realservers(vs) < vs->quorum - vs->hysteresis) {
				vs->quorum_state = DOWN;
				log_message(LOG_INFO, "Executing [%s] for VS [%s]:%d"
						    , vs->quorum_down
						    , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
						    , ntohs(inet_sockaddrport(&vs->addr)));
				notify_exec(vs->quorum_down);
			}
		}
	}

	return 1;
}
예제 #6
0
/* Sync checkers activity with netlink kernel reflection */
void
update_checker_activity(sa_family_t family, void *address, int enable)
{
	checker_t *checker;
	sa_family_t vip_family;
	element e;
	char addr_str[INET6_ADDRSTRLEN];
	void *addr;

	/* Display netlink operation */
	if (debug & 32) {
		inet_ntop(family, address, addr_str, sizeof(addr_str));
		log_message(LOG_INFO, "Netlink reflector reports IP %s %s"
				    , addr_str, (enable) ? "added" : "removed");
	}

	/* Processing Healthcheckers queue */
	if (!LIST_ISEMPTY(checkers_queue)) {
		for (e = LIST_HEAD(checkers_queue); e; ELEMENT_NEXT(e)) {
			checker = ELEMENT_DATA(e);
			vip_family = checker->vs->addr.ss_family;

			if (vip_family != family)
				continue;

			if (family == AF_INET6) {
				addr = (void *) &((struct sockaddr_in6 *)&checker->vs->addr)->sin6_addr;
			} else {
				addr = (void *) &((struct sockaddr_in *)&checker->vs->addr)->sin_addr;
			}

			if (inaddr_equal(family, addr, address) &&
			    CHECKER_HA_SUSPEND(checker)) {
				if (!CHECKER_ENABLED(checker) && enable)
					log_message(LOG_INFO, "Activating healthchecker for service [%s]:%d"
							    , inet_sockaddrtos(&checker->rs->addr)
							    , ntohs(inet_sockaddrport(&checker->rs->addr)));
				if (CHECKER_ENABLED(checker) && !enable)
					log_message(LOG_INFO, "Suspending healthchecker for service [%s]:%d"
							    , inet_sockaddrtos(&checker->rs->addr)
							    , ntohs(inet_sockaddrport(&checker->rs->addr)));
				checker->enabled = enable;
			}
		}
	}
}
예제 #7
0
/* dump checker data */
static void
dump_checker(void *data)
{
	checker_t *checker = data;
	log_message(LOG_INFO, " [%s]:%d"
			    , inet_sockaddrtos(&checker->rs->addr)
			    , ntohs(inet_sockaddrport(&checker->rs->addr)));
	(*checker->dump_func) (checker);
}
예제 #8
0
파일: smtp.c 프로젝트: Grip/keepalived-1
static int
connection_timeout(thread_t * thread)
{
	smtp_t *smtp = THREAD_ARG(thread);

	log_message(LOG_INFO, "Timeout connecting SMTP server [%s]:%d."
			    , inet_sockaddrtos(&global_data->smtp_server), SMTP_PORT);
	free_smtp_all(smtp);
	return 0;
}
예제 #9
0
파일: smtp.c 프로젝트: Grip/keepalived-1
/* layer4 connection handlers */
static int
connection_error(thread_t * thread)
{
	smtp_t *smtp = THREAD_ARG(thread);

	log_message(LOG_INFO, "SMTP connection ERROR to [%s]:%d."
			    , inet_sockaddrtos(&global_data->smtp_server), SMTP_PORT);
	free_smtp_all(smtp);
	return 0;
}
예제 #10
0
void
dump_tcp_check(void *data)
{
	tcp_checker_t *tcp_chk = CHECKER_DATA(data);

	log_message(LOG_INFO, "   Keepalive method = TCP_CHECK");
	log_message(LOG_INFO, "   Connection port = %d", ntohs(inet_sockaddrport(&tcp_chk->dst)));
	if (tcp_chk->bindto.ss_family)
		log_message(LOG_INFO, "   Bind to = %s", inet_sockaddrtos(&tcp_chk->bindto));
	log_message(LOG_INFO, "   Connection timeout = %d", tcp_chk->connection_to/TIMER_HZ);
}
예제 #11
0
파일: smtp.c 프로젝트: Grip/keepalived-1
static int
connection_success(thread_t * thread)
{
	smtp_t *smtp = THREAD_ARG(thread);

	log_message(LOG_INFO, "Remote SMTP server [%s]:%d connected."
			    , inet_sockaddrtos(&global_data->smtp_server), SMTP_PORT);

	smtp->stage = connect_success;
	thread_add_read(thread->master, smtp_read_thread, smtp,
			smtp->fd, global_data->smtp_connection_to);
	return 0;
}
예제 #12
0
파일: smtp.c 프로젝트: Grip/keepalived-1
static int
connection_code(thread_t * thread, int status)
{
	smtp_t *smtp = THREAD_ARG(thread);

	if (status == 220) {
		smtp->stage++;
	} else {
		log_message(LOG_INFO, "Error connecting SMTP server[%s]:%d."
				      " SMTP status code = %d"
				    , inet_sockaddrtos(&global_data->smtp_server)
				    , SMTP_PORT, status);
		smtp->stage = ERROR;
	}

	return 0;
}
예제 #13
0
파일: smtp.c 프로젝트: Grip/keepalived-1
static int
data_code(thread_t * thread, int status)
{
	smtp_t *smtp = THREAD_ARG(thread);

	if (status == 354) {
		smtp->stage++;
	} else {
		log_message(LOG_INFO, "Error processing DATA cmd on SMTP server [%s]:%d."
				      " SMTP status code = %d"
				    , inet_sockaddrtos(&global_data->smtp_server)
				    , SMTP_PORT, status);
		smtp->stage = ERROR;
	}

	return 0;
}
예제 #14
0
/* register checkers to the global I/O scheduler */
void
register_checkers_thread(void)
{
	checker_t *checker;
	element e;

	for (e = LIST_HEAD(checkers_queue); e; ELEMENT_NEXT(e)) {
		checker = ELEMENT_DATA(e);
		log_message(LOG_INFO, "Activating healthchecker for service [%s]:%d"
				    , inet_sockaddrtos(&checker->rs->addr)
				    , ntohs(inet_sockaddrport(&checker->rs->addr)));
		CHECKER_ENABLE(checker);
		if (checker->launch)
			thread_add_timer(master, checker->launch, checker,
					 BOOTSTRAP_DELAY);
	}
}
예제 #15
0
파일: smtp.c 프로젝트: Grip/keepalived-1
/* Main entry point */
void
smtp_alert(real_server_t * rs, vrrp_t * vrrp,
	   vrrp_sgroup_t * vgroup, const char *subject, const char *body)
{
	smtp_t *smtp;

	/* Only send mail if email specified */
	if (!LIST_ISEMPTY(global_data->email) && global_data->smtp_server.ss_family != 0) {
		/* allocate & initialize smtp argument data structure */
		smtp = (smtp_t *) MALLOC(sizeof(smtp_t));
		smtp->subject = (char *) MALLOC(MAX_HEADERS_LENGTH);
		smtp->body = (char *) MALLOC(MAX_BODY_LENGTH);
		smtp->buffer = (char *) MALLOC(SMTP_BUFFER_MAX);
		smtp->email_to = (char *) MALLOC(SMTP_BUFFER_MAX);

		/* format subject if rserver is specified */
		if (rs) {
			snprintf(smtp->subject, MAX_HEADERS_LENGTH, "[%s] Realserver [%s]:%d - %s"
					      , global_data->router_id
					      , inet_sockaddrtos(&rs->addr)
					      , ntohs(inet_sockaddrport(&rs->addr))
					      , subject);
		} else if (vrrp)
			snprintf(smtp->subject, MAX_HEADERS_LENGTH, "[%s] VRRP Instance %s - %s"
					      , global_data->router_id
					      , vrrp->iname
					      , subject);
		else if (vgroup)
			snprintf(smtp->subject, MAX_HEADERS_LENGTH, "[%s] VRRP Group %s - %s"
					      , global_data->router_id
					      , vgroup->gname
					      , subject);
		else if (global_data->router_id)
			snprintf(smtp->subject, MAX_HEADERS_LENGTH, "[%s] %s"
					      , global_data->router_id
					      , subject);
		else
			snprintf(smtp->subject, MAX_HEADERS_LENGTH, "%s", subject);

		strncpy(smtp->body, body, MAX_BODY_LENGTH);
		build_to_header_rcpt_addrs(smtp);

		smtp_connect(smtp);
	}
}
예제 #16
0
파일: smtp.c 프로젝트: Grip/keepalived-1
static int
body_code(thread_t * thread, int status)
{
	smtp_t *smtp = THREAD_ARG(thread);

	if (status == 250) {
		log_message(LOG_INFO, "SMTP alert successfully sent.");
		smtp->stage++;
	} else {
		log_message(LOG_INFO, "Error processing DOT cmd on SMTP server [%s]:%d."
				      " SMTP status code = %d"
				    , inet_sockaddrtos(&global_data->smtp_server)
				    , SMTP_PORT, status);
		smtp->stage = ERROR;
	}

	return 0;
}
예제 #17
0
파일: smtp.c 프로젝트: Grip/keepalived-1
static int
connection_in_progress(thread_t * thread)
{
	int status;

	DBG("SMTP connection to [%s]:%d now IN_PROGRESS.",
	    inet_sockaddrtos(&global_data->smtp_server), SMTP_PORT);

	/*
	 * Here we use the propriety of a union structure,
	 * each element of the structure have the same value.
	 */
	status = tcp_socket_state(thread->u.fd, thread, connection_in_progress);

	if (status != connect_in_progress)
		SMTP_FSM_SEND(status, thread);

	return 0;
}
예제 #18
0
/* add or remove _alive_ real servers from a virtual server */
void
perform_quorum_state(virtual_server *vs, int add)
{
	element e;
	real_server *rs;

	if (LIST_ISEMPTY(vs->rs))
		return;

	log_message(LOG_INFO, "%s the pool for VS [%s]:%d"
			    , add?"Adding alive servers to":"Removing alive servers from"
			    , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
			    , ntohs(inet_sockaddrport(&vs->addr)));
	for (e = LIST_HEAD(vs->rs); e; ELEMENT_NEXT(e)) {
		rs = ELEMENT_DATA(e);
		if (!ISALIVE(rs)) /* We only handle alive servers */
			continue;
		if (add)
			rs->alive = 0;
		ipvs_cmd(add?LVS_CMD_ADD_DEST:LVS_CMD_DEL_DEST, check_data->vs_group, vs, rs);
		rs->alive = 1;
	}
}
예제 #19
0
파일: smtp.c 프로젝트: Grip/keepalived-1
static int
rcpt_code(thread_t * thread, int status)
{
	smtp_t *smtp = THREAD_ARG(thread);
	char *fetched_email;

	if (status == 250) {
		smtp->email_it++;

		fetched_email = fetch_next_email(smtp);

		if (!fetched_email)
			smtp->stage++;
	} else {
		log_message(LOG_INFO, "Error processing RCPT cmd on SMTP server [%s]:%d."
				      " SMTP status code = %d"
				    , inet_sockaddrtos(&global_data->smtp_server)
				    , SMTP_PORT, status);
		smtp->stage = ERROR;
	}

	return 0;
}
예제 #20
0
void
vrrp_print(FILE *file, void *data)
{
	vrrp_t *vrrp = data;
	char auth_data[sizeof(vrrp->auth_data) + 1];
	fprintf(file, " VRRP Instance = %s\n", vrrp->iname);
	fprintf(file, " VRRP Version = %d\n", vrrp->version);
	if (vrrp->family == AF_INET6)
		fprintf(file, "   Using Native IPv6\n");
	if (vrrp->state == VRRP_STATE_BACK) {
		fprintf(file, "   State = BACKUP\n");
		fprintf(file, "   Master router = %s\n",
			inet_sockaddrtos(&vrrp->master_saddr));
		fprintf(file, "   Master priority = %d\n",
			vrrp->master_priority);
	}
	else if (vrrp->state == VRRP_STATE_FAULT)
		fprintf(file, "   State = FAULT\n");
	else if (vrrp->state == VRRP_STATE_MAST)
		fprintf(file, "   State = MASTER\n");
	else
		fprintf(file, "   State = %d\n", vrrp->state);
	fprintf(file, "   Last transition = %ld\n",
		vrrp->last_transition.tv_sec);
	fprintf(file, "   Listening device = %s\n", IF_NAME(vrrp->ifp));
	if (vrrp->dont_track_primary)
		fprintf(file, "   VRRP interface tracking disabled\n");
	fprintf(file, "   Using src_ip = %s\n", inet_sockaddrtos(&vrrp->saddr));
	if (vrrp->lvs_syncd_if)
		fprintf(file, "   Runing LVS sync daemon on interface = %s\n",
		       vrrp->lvs_syncd_if);
	if (vrrp->garp_delay)
		fprintf(file, "   Gratuitous ARP delay = %d\n",
		       vrrp->garp_delay/TIMER_HZ);
	fprintf(file, "   Virtual Router ID = %d\n", vrrp->vrid);
	fprintf(file, "   Priority = %d\n", vrrp->base_priority);
	fprintf(file, "   Advert interval = %d %s\n",
		(vrrp->version == VRRP_VERSION_2) ? (vrrp->adver_int / TIMER_HZ) :
		(vrrp->adver_int * 1000 / TIMER_HZ),
		(vrrp->version == VRRP_VERSION_2) ? "sec" : "milli-sec");
	fprintf(file, "   Accept = %s\n", ((vrrp->accept) ? "enabled" : "disabled"));
	if (vrrp->nopreempt)
		fprintf(file, "   Preempt = disabled\n");
	else
		fprintf(file, "   Preempt = enabled\n");
	if (vrrp->preempt_delay)
		fprintf(file, "   Preempt delay = %ld secs\n",
		       vrrp->preempt_delay / TIMER_HZ);
	if (vrrp->auth_type) {
		fprintf(file, "   Authentication type = %s\n",
		       (vrrp->auth_type ==
			VRRP_AUTH_AH) ? "IPSEC_AH" : "SIMPLE_PASSWORD");
		if (vrrp->auth_type != VRRP_AUTH_AH) {
			/* vrrp->auth_data is not \0 terminated */
			memcpy(auth_data, vrrp->auth_data, sizeof(vrrp->auth_data));
			auth_data[sizeof(vrrp->auth_data)] = '\0';
			fprintf(file, "   Password = %s\n", auth_data);
		}
	}
	else
		fprintf(file, "   Authentication type = none\n");

	if (!LIST_ISEMPTY(vrrp->track_ifp)) {
		fprintf(file, "   Tracked interfaces = %d\n",
			LIST_SIZE(vrrp->track_ifp));
		vrrp_print_list(file, vrrp->track_ifp, &if_print);
	}
	if (!LIST_ISEMPTY(vrrp->track_script)) {
		fprintf(file, "   Tracked scripts = %d\n",
		       LIST_SIZE(vrrp->track_script));
		vrrp_print_list(file, vrrp->track_script, &vscript_print);
	}
	if (!LIST_ISEMPTY(vrrp->vip)) {
		fprintf(file, "   Virtual IP = %d\n", LIST_SIZE(vrrp->vip));
		vrrp_print_list(file, vrrp->vip, &address_print);
	}
	if (!LIST_ISEMPTY(vrrp->evip)) {
		fprintf(file, "   Virtual IP Excluded = %d\n",
			LIST_SIZE(vrrp->evip));
		vrrp_print_list(file, vrrp->evip, &address_print);
	}
	if (!LIST_ISEMPTY(vrrp->vroutes)) {
		fprintf(file, "   Virtual Routes = %d\n", LIST_SIZE(vrrp->vroutes));
		vrrp_print_list(file, vrrp->vroutes, &route_print);
	}
	if (!LIST_ISEMPTY(vrrp->vrules)) {
		fprintf(file, "   Virtual Rules = %d\n", LIST_SIZE(vrrp->vrules));
		vrrp_print_list(file, vrrp->vrules, &rule_print);
	}
	if (vrrp->script_backup)
		fprintf(file, "   Backup state transition script = %s\n",
		       vrrp->script_backup);
	if (vrrp->script_master)
		fprintf(file, "   Master state transition script = %s\n",
		       vrrp->script_master);
	if (vrrp->script_fault)
		fprintf(file, "   Fault state transition script = %s\n",
		       vrrp->script_fault);
	if (vrrp->script_stop)
		fprintf(file, "   Stop state transition script = %s\n",
		       vrrp->script_stop);
	if (vrrp->script)
		fprintf(file, "   Generic state transition script = '%s'\n",
		       vrrp->script);
	if (vrrp->smtp_alert)
			fprintf(file, "   Using smtp notification\n");
}
예제 #21
0
파일: smtp.c 프로젝트: Grip/keepalived-1
/* SMTP protocol handlers */
static int
smtp_read_thread(thread_t * thread)
{
	smtp_t *smtp;
	char *buffer;
	char *reply;
	int rcv_buffer_size = 0;
	int status = -1;

	smtp = THREAD_ARG(thread);

	if (thread->type == THREAD_READ_TIMEOUT) {
		log_message(LOG_INFO, "Timeout reading data to remote SMTP server [%s]:%d."
				    , inet_sockaddrtos(&global_data->smtp_server), SMTP_PORT);
		SMTP_FSM_READ(QUIT, thread, 0);
		return -1;
	}

	buffer = smtp->buffer;

	rcv_buffer_size = read(thread->u.fd, buffer + smtp->buflen,
			       SMTP_BUFFER_LENGTH - smtp->buflen);

	if (rcv_buffer_size == -1) {
		if (errno == EAGAIN)
			goto end;
		log_message(LOG_INFO, "Error reading data from remote SMTP server [%s]:%d."
				    , inet_sockaddrtos(&global_data->smtp_server), SMTP_PORT);
		SMTP_FSM_READ(QUIT, thread, 0);
		return 0;
	}

	/* received data overflow buffer size ? */
	if (smtp->buflen >= SMTP_BUFFER_MAX) {
		log_message(LOG_INFO, "Received buffer from remote SMTP server [%s]:%d"
				      " overflow our get read buffer length."
				    , inet_sockaddrtos(&global_data->smtp_server), SMTP_PORT);
		SMTP_FSM_READ(QUIT, thread, 0);
		return 0;
	} else {
		smtp->buflen += rcv_buffer_size;
		buffer[smtp->buflen] = 0;	/* NULL terminate */
	}

      end:

	/* parse the buffer, finding the last line of the response for the code */
	reply = buffer;
	while (reply < buffer + smtp->buflen) {
		char *p;

		p = strstr(reply, "\r\n");
		if (!p) {
			memmove(buffer, reply,
				smtp->buflen - (reply - buffer));
			smtp->buflen -= (reply - buffer);
			buffer[smtp->buflen] = 0;

			thread_add_read(thread->master, smtp_read_thread,
					smtp, thread->u.fd,
					global_data->smtp_connection_to);
			return 0;
		}

		if (reply[3] == '-') {
			/* Skip over the \r\n */
			reply = p + 2;
			continue;
		}

		status = ((reply[0] - '0') * 100) + ((reply[1] - '0') * 10) + (reply[2] - '0');

		reply = p + 2;
		break;
	}

	memmove(buffer, reply, smtp->buflen - (reply - buffer));
	smtp->buflen -= (reply - buffer);
	buffer[smtp->buflen] = 0;

	if (status == -1) {
		thread_add_read(thread->master, smtp_read_thread, smtp,
				thread->u.fd, global_data->smtp_connection_to);
		return 0;
	}

	SMTP_FSM_READ(smtp->stage, thread, status);

	/* Registering next smtp command processing thread */
	if (smtp->stage != ERROR) {
		thread_add_write(thread->master, smtp_send_thread, smtp,
				 smtp->fd, global_data->smtp_connection_to);
	} else {
		log_message(LOG_INFO, "Can not read data from remote SMTP server [%s]:%d."
				    , inet_sockaddrtos(&global_data->smtp_server), SMTP_PORT);
		SMTP_FSM_READ(QUIT, thread, 0);
	}

	return 0;
}
예제 #22
0
/* manipulate add/remove rs according to alive state */
void
perform_svr_state(int alive, virtual_server * vs, real_server * rs)
{
	char rsip[INET6_ADDRSTRLEN];

	/*
	 * | ISALIVE(rs) | alive | context
	 * | 0           | 0     | first check failed under alpha mode, unreachable here
	 * | 0           | 1     | RS went up, add it to the pool
	 * | 1           | 0     | RS went down, remove it from the pool
	 * | 1           | 1     | first check succeeded w/o alpha mode, unreachable here
	 */
	if (!ISALIVE(rs) && alive) {
		log_message(LOG_INFO, "%s service [%s]:%d to VS [%s]:%d"
				    , (rs->inhibit) ? "Enabling" : "Adding"
				    , inet_sockaddrtos2(&rs->addr, rsip)
				    , ntohs(inet_sockaddrport(&rs->addr))
				    , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
				    , ntohs(inet_sockaddrport(&vs->addr)));
		/* Add only if we have quorum or no sorry server */
		if (vs->quorum_state == UP || !vs->s_svr || !ISALIVE(vs->s_svr)) {
			ipvs_cmd(LVS_CMD_ADD_DEST, check_data->vs_group, vs, rs);
		}
		rs->alive = alive;
		if (rs->notify_up) {
			log_message(LOG_INFO, "Executing [%s] for service [%s]:%d in VS [%s]:%d"
					    , rs->notify_up
					    , inet_sockaddrtos2(&rs->addr, rsip)
					    , ntohs(inet_sockaddrport(&rs->addr))
					    , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
					    , ntohs(inet_sockaddrport(&vs->addr)));
			notify_exec(rs->notify_up);
		}

		/* We may have gained quorum */
		update_quorum_state(vs);
	}

	if (ISALIVE(rs) && !alive) {
		log_message(LOG_INFO, "%s service [%s]:%d from VS [%s]:%d"
				    , (rs->inhibit) ? "Disabling" : "Removing"
				    , inet_sockaddrtos2(&rs->addr, rsip)
				    , ntohs(inet_sockaddrport(&rs->addr))
				    , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
				    , ntohs(inet_sockaddrport(&vs->addr)));

		/* server is down, it is removed from the LVS realserver pool
		 * Remove only if we have quorum or no sorry server
		 */
		if (vs->quorum_state == UP || !vs->s_svr || !ISALIVE(vs->s_svr)) {
			ipvs_cmd(LVS_CMD_DEL_DEST, check_data->vs_group, vs, rs);
		}
		rs->alive = alive;
		if (rs->notify_down) {
			log_message(LOG_INFO, "Executing [%s] for service [%s]:%d in VS [%s]:%d"
					    , rs->notify_down
					    , inet_sockaddrtos2(&rs->addr, rsip)
					    , ntohs(inet_sockaddrport(&rs->addr))
					    , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
					    , ntohs(inet_sockaddrport(&vs->addr)));
			notify_exec(rs->notify_down);
		}

		/* We may have lost quorum */
		update_quorum_state(vs);
	}
}
예제 #23
0
/* set quorum state depending on current weight of real servers */
void
update_quorum_state(virtual_server * vs)
{
	char rsip[INET6_ADDRSTRLEN];

	/* If we have just gained quorum, it's time to consider notify_up. */
	if (vs->quorum_state == DOWN &&
	    weigh_live_realservers(vs) >= vs->quorum + vs->hysteresis) {
		vs->quorum_state = UP;
		log_message(LOG_INFO, "Gained quorum %lu+%lu=%lu <= %u for VS [%s]:%d"
				    , vs->quorum
				    , vs->hysteresis
				    , vs->quorum + vs->hysteresis
				    , weigh_live_realservers(vs)
				    , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
				    , ntohs(inet_sockaddrport(&vs->addr)));
		if (vs->s_svr && ISALIVE(vs->s_svr)) {
			log_message(LOG_INFO, "Removing sorry server [%s]:%d from VS [%s]:%d"
					    , inet_sockaddrtos2(&vs->s_svr->addr, rsip)
					    , ntohs(inet_sockaddrport(&vs->s_svr->addr))
					    , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
					    , ntohs(inet_sockaddrport(&vs->addr)));

			ipvs_cmd(LVS_CMD_DEL_DEST, check_data->vs_group, vs, vs->s_svr);
			vs->s_svr->alive = 0;

			/* Adding back alive real servers */
			perform_quorum_state(vs, 1);
		}
		if (vs->quorum_up) {
			log_message(LOG_INFO, "Executing [%s] for VS [%s]:%d"
					    , vs->quorum_up
					    , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
					    , ntohs(inet_sockaddrport(&vs->addr)));
			notify_exec(vs->quorum_up);
		}
		return;
	}

	/* If we have just lost quorum for the VS, we need to consider
	 * VS notify_down and sorry_server cases
	 */
	if (vs->quorum_state == UP &&
	    weigh_live_realservers(vs) < vs->quorum - vs->hysteresis) {
		vs->quorum_state = DOWN;
		log_message(LOG_INFO, "Lost quorum %lu-%lu=%lu > %u for VS [%s]:%d"
				    , vs->quorum
				    , vs->hysteresis
				    , vs->quorum - vs->hysteresis
				    , weigh_live_realservers(vs)
				    , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
				    , ntohs(inet_sockaddrport(&vs->addr)));
		if (vs->quorum_down) {
			log_message(LOG_INFO, "Executing [%s] for VS [%s]:%d"
					    , vs->quorum_down
					    , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
					    , ntohs(inet_sockaddrport(&vs->addr)));
			notify_exec(vs->quorum_down);
		}
		if (vs->s_svr) {
			log_message(LOG_INFO, "Adding sorry server [%s]:%d to VS [%s]:%d"
					    , inet_sockaddrtos2(&vs->s_svr->addr, rsip)
					    , ntohs(inet_sockaddrport(&vs->s_svr->addr))
					    , (vs->vsgname) ? vs->vsgname : inet_sockaddrtos(&vs->addr)
					    , ntohs(inet_sockaddrport(&vs->addr)));

			/* the sorry server is now up in the pool, we flag it alive */
			ipvs_cmd(LVS_CMD_ADD_DEST, check_data->vs_group, vs, vs->s_svr);
			vs->s_svr->alive = 1;

			/* Remove remaining alive real servers */
			perform_quorum_state(vs, 0);
		}
		return;
	}
}
예제 #24
0
static void
vrrp_print(FILE *file, void *data)
{
	vrrp_t *vrrp = data;
#ifdef _WITH_VRRP_AUTH_
	char auth_data[sizeof(vrrp->auth_data) + 1];
#endif
	char time_str[26];

	fprintf(file, " VRRP Instance = %s\n", vrrp->iname);
	fprintf(file, " VRRP Version = %d\n", vrrp->version);
	if (vrrp->family == AF_INET6)
		fprintf(file, "   Using Native IPv6\n");
	if (vrrp->state == VRRP_STATE_BACK) {
		fprintf(file, "   State = BACKUP\n");
		fprintf(file, "   Master router = %s\n",
			inet_sockaddrtos(&vrrp->master_saddr));
		fprintf(file, "   Master priority = %d\n",
			vrrp->master_priority);
	}
	else if (vrrp->state == VRRP_STATE_FAULT)
		fprintf(file, "   State = FAULT\n");
	else if (vrrp->state == VRRP_STATE_MAST)
		fprintf(file, "   State = MASTER\n");
	else
		fprintf(file, "   State = %d\n", vrrp->state);
	ctime_r(&vrrp->last_transition.tv_sec, time_str);
	time_str[sizeof(time_str)-2] = '\0';	/* Remove '\n' char */
	fprintf(file, "   Last transition = %ld (%s)\n",
		vrrp->last_transition.tv_sec, time_str);
	fprintf(file, "   Listening device = %s\n", IF_NAME(vrrp->ifp));
	if (vrrp->dont_track_primary)
		fprintf(file, "   VRRP interface tracking disabled\n");
	if (vrrp->skip_check_adv_addr)
		fprintf(file, "   Skip checking advert IP addresses\n");
	if (vrrp->strict_mode)
		fprintf(file, "   Enforcing VRRP compliance\n");
	fprintf(file, "   Using src_ip = %s\n", inet_sockaddrtos(&vrrp->saddr));
	fprintf(file, "   Gratuitous ARP delay = %d\n",
		       vrrp->garp_delay/TIMER_HZ);
	fprintf(file, "   Gratuitous ARP repeat = %d\n", vrrp->garp_rep);
	fprintf(file, "   Gratuitous ARP refresh = %lu\n",
		       vrrp->garp_refresh.tv_sec/TIMER_HZ);
	fprintf(file, "   Gratuitous ARP refresh repeat = %d\n", vrrp->garp_refresh_rep);
	fprintf(file, "   Gratuitous ARP lower priority delay = %d", vrrp->garp_lower_prio_delay / TIMER_HZ);
	fprintf(file, "   Gratuitous ARP lower priority repeat = %d", vrrp->garp_lower_prio_rep);
	fprintf(file, "   Send advert after receive lower priority advert = %s", vrrp->lower_prio_no_advert ? "false" : "true");
	fprintf(file, "   Virtual Router ID = %d\n", vrrp->vrid);
	fprintf(file, "   Priority = %d\n", vrrp->base_priority);
	fprintf(file, "   Advert interval = %d %s\n",
		(vrrp->version == VRRP_VERSION_2) ? (vrrp->adver_int / TIMER_HZ) :
		(vrrp->adver_int / (TIMER_HZ / 1000)),
		(vrrp->version == VRRP_VERSION_2) ? "sec" : "milli-sec");
	fprintf(file, "   Accept = %s\n", ((vrrp->accept) ? "enabled" : "disabled"));
	if (vrrp->nopreempt)
		fprintf(file, "   Preempt = disabled\n");
	else
		fprintf(file, "   Preempt = enabled\n");
	if (vrrp->preempt_delay)
		fprintf(file, "   Preempt delay = %ld secs\n",
		       vrrp->preempt_delay / TIMER_HZ);
#if defined _WITH_VRRP_AUTH_
	if (vrrp->auth_type) {
		fprintf(file, "   Authentication type = %s\n",
		       (vrrp->auth_type ==
			VRRP_AUTH_AH) ? "IPSEC_AH" : "SIMPLE_PASSWORD");
		if (vrrp->auth_type != VRRP_AUTH_AH) {
			/* vrrp->auth_data is not \0 terminated */
			memcpy(auth_data, vrrp->auth_data, sizeof(vrrp->auth_data));
			auth_data[sizeof(vrrp->auth_data)] = '\0';
			fprintf(file, "   Password = %s\n", auth_data);
		}
	}
	else
		fprintf(file, "   Authentication type = none\n");
#endif

	if (!LIST_ISEMPTY(vrrp->track_ifp)) {
		fprintf(file, "   Tracked interfaces = %d\n",
			LIST_SIZE(vrrp->track_ifp));
		vrrp_print_list(file, vrrp->track_ifp, &if_print);
	}
	if (!LIST_ISEMPTY(vrrp->track_script)) {
		fprintf(file, "   Tracked scripts = %d\n",
		       LIST_SIZE(vrrp->track_script));
		vrrp_print_list(file, vrrp->track_script, &vscript_print);
	}
	if (!LIST_ISEMPTY(vrrp->vip)) {
		fprintf(file, "   Virtual IP = %d\n", LIST_SIZE(vrrp->vip));
		vrrp_print_list(file, vrrp->vip, &address_print);
	}
	if (!LIST_ISEMPTY(vrrp->evip)) {
		fprintf(file, "   Virtual IP Excluded = %d\n",
			LIST_SIZE(vrrp->evip));
		vrrp_print_list(file, vrrp->evip, &address_print);
	}
#ifdef _HAVE_FIB_ROUTING_
	if (!LIST_ISEMPTY(vrrp->vroutes)) {
		fprintf(file, "   Virtual Routes = %d\n", LIST_SIZE(vrrp->vroutes));
		vrrp_print_list(file, vrrp->vroutes, &route_print);
	}
	if (!LIST_ISEMPTY(vrrp->vrules)) {
		fprintf(file, "   Virtual Rules = %d\n", LIST_SIZE(vrrp->vrules));
		vrrp_print_list(file, vrrp->vrules, &rule_print);
	}
#endif
	if (vrrp->script_backup)
		fprintf(file, "   Backup state transition script = %s\n",
		       vrrp->script_backup);
	if (vrrp->script_master)
		fprintf(file, "   Master state transition script = %s\n",
		       vrrp->script_master);
	if (vrrp->script_fault)
		fprintf(file, "   Fault state transition script = %s\n",
		       vrrp->script_fault);
	if (vrrp->script_stop)
		fprintf(file, "   Stop state transition script = %s\n",
		       vrrp->script_stop);
	if (vrrp->script)
		fprintf(file, "   Generic state transition script = '%s'\n",
		       vrrp->script);
	if (vrrp->smtp_alert)
			fprintf(file, "   Using smtp notification\n");
}