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>