Annotation of embedaddon/freevrrpd/vrrp_state.c, revision 1.1.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>