File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / freevrrpd / vrrp_state.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 14 12:01:54 2017 UTC (7 years ago) by misho
Branches: freevrrpd, MAIN
CVS tags: v1_1, HEAD
freevrrpd 1.1

    1: /*
    2:  * Copyright (c) 2001,2002 Sebastien Petit <spe@bsdfr.org>
    3:  *
    4:  * Redistribution and use in source forms, with and without modification,
    5:  * are permitted provided that the following conditions are met:
    6:  * 1. Redistributions of source code must retain the above copyright notice,
    7:  *    this list of conditions and the following disclaimer.
    8:  * 2. Redistributions in binary form must reproduce the above copyright notice,
    9:  *    this list of conditions and the following disclaimer in the documentation
   10:  *    and/or other materials provided with the distribution. Obviously, it
   11:  *    would be nice if you gave credit where credit is due but requiring it
   12:  *    would be too onerous.
   13:  * 3. All advertising materials mentioning features or use of this software
   14:  *    must display the following acknowledgement:
   15:  *      This product includes software developed by Sebastien Petit.
   16:  * 4. Neither the name of its contributors may be used to endorse or promote
   17:  *    products derived from this software without specific prior written
   18:  *    permission.
   19:  *
   20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30:  * SUCH DAMAGE.
   31:  *
   32:  * $Id: vrrp_state.c,v 1.1.1.1 2017/06/14 12:01:54 misho Exp $
   33:  */
   34: 
   35: #include <stdlib.h>
   36: #include <errno.h>
   37: #include "vrrp_state.h"
   38: #ifdef ENABLE_VRRP_AH
   39: #include "vrrp_ah.h"
   40: #endif
   41: 
   42: char 
   43: vrrp_state_initialize(struct vrrp_vr * vr)
   44: {
   45: 	if ((vr->priority == 255) && (! vr->fault)) {
   46: 		if (vrrp_state_set_master(vr) == -1)
   47: 			return -1;
   48: 	} else if (vrrp_state_set_backup(vr) == -1)
   49: 		return -1;
   50: 
   51: 	return 0;
   52: }
   53: 
   54: char 
   55: vrrp_state_set_master(struct vrrp_vr * vr)
   56: {
   57: 	int returnCode = 0;
   58: 	int counter = 0;
   59: 
   60: 	vrrp_network_send_advertisement(vr);
   61: 	vrrp_thread_mutex_lock();
   62: 	vrrp_thread_mutex_lock_monitor();
   63: 	if (vrrp_interface_vripaddr_set(vr) == -1) {
   64: 		vrrp_thread_mutex_unlock_monitor();
   65: 		vrrp_thread_mutex_unlock();
   66: 		return -1;
   67: 	}
   68: 	if (vrrp_interface_up(vr->viface_name) < 0) {
   69: 		vrrp_thread_mutex_unlock_monitor();
   70: 		vrrp_thread_mutex_unlock();
   71: 		return -1;
   72: 	}
   73: 
   74: 	/* Some NICs will reset (eg: bge/em) and wait some seconds before becoming carrier again */
   75: 	/* So we must wait for carrier */
   76: 	if (vr->useMonitoredCircuits) {
   77: 		for (counter = 0; (counter < vr->vr_if->carrier_timeout) && (returnCode != 1); counter++) {
   78: 			returnCode = vrrp_moncircuit_interface_status(vr->sd, vr->vr_if->if_name);
   79: 			sleep(1);
   80: 		}
   81: 	}
   82: 
   83: 	vrrp_thread_mutex_unlock_monitor();
   84: 	vrrp_thread_mutex_unlock();
   85: 	if (vr->spanningTreeLatency) {
   86: 		syslog(LOG_NOTICE, "waiting %d seconds for the spanning tree latency", vr->spanningTreeLatency);
   87: 		sleep(vr->spanningTreeLatency);
   88: 	}
   89: 	if (vrrp_misc_calcul_tminterval(&vr->tm.adv_tm, vr->adv_int) == -1)
   90: 		return -1;
   91: 	vr->state = VRRP_STATE_MASTER;
   92: 	syslog(LOG_NOTICE, "server state vrid %d: master", vr->vr_id);
   93: 	printf("server state vrid %d: master\n", vr->vr_id);
   94: 	if (vr->master_script) {
   95: 		syslog(LOG_INFO, "[master] executing script %s\n", vr->master_script);
   96: 		if (system(vr->master_script) == -1)
   97: 			syslog(LOG_ERR, "[master] cannot execute script %s\n", vr->master_script);
   98: 		else
   99: 			syslog(LOG_INFO, "[master] script %s has been executed\n", vr->master_script);
  100: 	}
  101: 
  102: 	return 0;
  103: }
  104: 
  105: char 
  106: vrrp_state_set_backup(struct vrrp_vr * vr)
  107: {
  108: 	int returnCode = 0;
  109: 	int counter = 0;
  110: 
  111: 	vrrp_thread_mutex_lock();
  112: 	vrrp_interface_vripaddr_delete(vr);
  113: 	vrrp_thread_mutex_lock_monitor();
  114: 	if (vrrp_interface_down(vr->viface_name) < 0) {
  115: 		vrrp_thread_mutex_unlock_monitor();
  116: 		vrrp_thread_mutex_unlock();
  117: 		return -1;
  118: 	}
  119: 
  120: 	/* Some NICs will reset (eg: bge/em) and wait some seconds before becoming carrier again */
  121: 	/* So we must wait for carrier */
  122: 	if (vr->useMonitoredCircuits) {
  123: 		for (counter = 0; (counter < vr->vr_if->carrier_timeout) && (returnCode != 1); counter++) {
  124: 			returnCode = vrrp_moncircuit_interface_status(vr->sd, vr->vr_if->if_name);
  125: 			sleep(1);
  126: 		}
  127: 	}
  128: 	vrrp_thread_mutex_unlock_monitor();
  129: 	vrrp_thread_mutex_unlock();
  130: 	if (vr->spanningTreeLatency) {
  131: 		syslog(LOG_NOTICE, "waiting %d seconds for the spanning tree latency", vr->spanningTreeLatency);
  132: 		sleep(vr->spanningTreeLatency);
  133: 	}
  134: 	vr->skew_time = (256 - vr->priority) / 256;
  135: 	vr->master_down_int = (3 * vr->adv_int) + vr->skew_time;
  136: 	if (vrrp_misc_calcul_tminterval(&vr->tm.master_down_tm, vr->master_down_int) == -1)
  137: 		return -1;
  138: 	vr->state = VRRP_STATE_BACKUP;
  139: 	syslog(LOG_NOTICE, "server state vrid %d: backup", vr->vr_id);
  140: 	printf("server state vrid %d: backup\n", vr->vr_id);
  141: 	if (vr->backup_script) {
  142: 		syslog(LOG_INFO, "[backup] executing script %s\n", vr->backup_script);
  143: 		if (system(vr->backup_script) == -1)
  144: 			syslog(LOG_ERR, "[backup] cannot execute script %s\n", vr->backup_script);
  145: 		else
  146: 			syslog(LOG_INFO, "[backup] script %s has been executed\n", vr->backup_script);
  147: 	}
  148: 
  149: 	return 0;
  150: }
  151: 
  152: char 
  153: vrrp_state_select(struct vrrp_vr * vr, struct timeval * interval)
  154: {
  155: 	int             coderet;
  156: 	fd_set          readfds;
  157: 
  158: 	FD_ZERO(&readfds);
  159: 	FD_SET(vr->sd, &readfds);
  160: 	coderet = select(FD_SETSIZE, &readfds, NULL, NULL, interval);
  161: 
  162: 	return coderet;
  163: }
  164: 
  165: /* Operation a effectuer durant l'etat master */
  166: char 
  167: vrrp_state_master(struct vrrp_vr * vr)
  168: {
  169: 	int             coderet;
  170: 	u_char          packet[4096];
  171: 	ssize_t		packetSize;
  172: 	struct ip      *ipp = (struct ip *) packet;
  173: #ifdef ENABLE_VRRP_AH
  174: 	struct vrrp_hdr *vrrph = (struct vrrp_hdr *) & packet[sizeof(struct ip)+vrrp_ah_ahhdr_len(vr)];
  175: #else
  176: 	struct vrrp_hdr *vrrph = (struct vrrp_hdr *) & packet[sizeof(struct ip)];
  177: #endif
  178: 	struct timeval  interval;
  179: 	struct sockaddr_in saddr;
  180: 	socklen_t len;
  181: 
  182: 	for (;;) {
  183: 		if (vrrp_misc_calcul_tmrelease(&vr->tm.adv_tm, &interval) == -1)
  184: 			return -1;
  185: 		coderet = vrrp_state_select(vr, &interval);
  186: 		if (coderet > 0) {
  187: 			len = sizeof(struct sockaddr_in);
  188: 			packetSize = recvfrom(vr->sd, packet, sizeof(packet), 0, (struct sockaddr *)&saddr, &len);
  189: 			if (packetSize == -1) {
  190: 				syslog(LOG_ERR, "can't read on vr->sd socket descriptor: %s", strerror(errno));
  191: 				return -1;
  192: 			}
  193: 			if (vrrp_misc_check_vrrp_packet(vr, packet, packetSize) == -1)
  194: 				continue;
  195: 			if (vrrph->priority == 0) {
  196: 				if (vr->sd == -1)
  197: 					return -1;
  198: 				vrrp_network_send_advertisement(vr);
  199: 				if (vrrp_misc_calcul_tminterval(&vr->tm.adv_tm, vr->adv_int) == -1)
  200: 					return -1;
  201: 				continue;
  202: 			}
  203: 			if (vrrp_state_check_priority(vrrph, vr, ipp->ip_src) || (vr->fault) || (vr->vr_if->alive != 1)) {
  204: 				if (vrrp_state_set_backup(vr) == -1)
  205: 					return -1;
  206: 			}
  207: 			return 0;
  208: 		}
  209: 		if (coderet == 0) {
  210: 			if ((vr->vr_if->alive != 1) || (vr->fault)) {
  211: 				if (vrrp_state_set_backup(vr) == -1)
  212: 					return -1;
  213: 				return 0;
  214: 			}
  215: 			vrrp_network_send_advertisement(vr);
  216: 			if (vrrp_misc_calcul_tminterval(&vr->tm.adv_tm, vr->adv_int) == -1)
  217: 				return -1;
  218: 			continue;
  219: 		}
  220: 		if (coderet == -1) {
  221: 			syslog(LOG_ERR, "select on readfds fd_set failed: %s", strerror(errno));
  222: 			return -1;
  223: 		}
  224: 	}
  225: 
  226: 	/* Normally never executed */
  227: 	return 0;
  228: }
  229: 
  230: char 
  231: vrrp_state_backup(struct vrrp_vr * vr)
  232: {
  233: 	int             coderet;
  234: 	u_char          packet[4096];
  235: 	ssize_t		packetSize;
  236: #ifdef ENABLE_VRRP_AH
  237: 	struct vrrp_hdr *vrrph = (struct vrrp_hdr *) & packet[sizeof(struct ip)+vrrp_ah_ahhdr_len(vr)];
  238: #else
  239: 	struct vrrp_hdr *vrrph = (struct vrrp_hdr *) & packet[sizeof(struct ip)];
  240: #endif
  241: 	struct timeval  interval;
  242: 	struct sockaddr_in saddr;
  243: 	socklen_t len;
  244: 
  245: 	for (;;) {
  246: 		if (vrrp_misc_calcul_tmrelease(&vr->tm.master_down_tm, &interval) == -1)
  247: 			return -1;
  248: 		coderet = vrrp_state_select(vr, &interval);
  249: 		if (coderet > 0) {
  250: 			len = sizeof(struct sockaddr_in);
  251: 			packetSize = recvfrom(vr->sd, packet, sizeof(packet), 0, (struct sockaddr *)&saddr, &len);
  252: 			if (packetSize == -1) {
  253: 				syslog(LOG_ERR, "can't read on vr->sd socket descriptor: %s", strerror(errno));
  254: 				return -1;
  255: 			}
  256: 			if (vrrp_misc_check_vrrp_packet(vr, packet, packetSize) == -1)
  257: 				continue;
  258: 			if (vrrph->priority == 0) {
  259: 				if (vrrp_misc_calcul_tminterval(&vr->tm.master_down_tm, vr->skew_time) == -1)
  260: 					return -1;
  261: 				continue;
  262: 			}
  263: 			if (vr->preempt_mode == 0 || vrrph->priority >= vr->priority)
  264: 				if (vrrp_misc_calcul_tminterval(&vr->tm.master_down_tm, vr->master_down_int) == -1)
  265: 					return -1;
  266: 			continue;
  267: 		}
  268: 		if (coderet == -1) {
  269: 			syslog(LOG_ERR, "select on readfds fd_set failed: %s", strerror(errno));
  270: 			return -1;
  271: 		}
  272: 		if ((! coderet) && (vr->vr_if->alive == 1) && (! vr->fault)) {
  273: 			if (! vrrp_state_set_master(vr))
  274: 				return 0;
  275: 		}
  276: 		else
  277: 			if (vrrp_misc_calcul_tminterval(&vr->tm.master_down_tm, vr->master_down_int) == -1)
  278: 				return -1;
  279: 	}
  280: 
  281: 	/* Normally never executed */
  282: 	return 0;
  283: }
  284: 
  285: char 
  286: vrrp_state_check_priority(struct vrrp_hdr * vrrph, struct vrrp_vr * vr, struct in_addr addr)
  287: {
  288: 	if (vrrph->priority > vr->priority)
  289: 		return 1;
  290: 	if ((vrrph->priority == vr->priority) && (addr.s_addr > vr->vr_if->ip_addrs[0].s_addr))
  291: 		return 1;
  292: 
  293: 	return 0;
  294: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>