Annotation of embedaddon/freevrrpd/vrrp_state.c, revision 1.1
1.1 ! misho 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.18 2004/04/02 11:04:46 spe 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>