Annotation of embedaddon/freevrrpd/vrrp_misc.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_misc.c,v 1.8 2004/04/04 19:45:46 rival Exp $
        !            33:  */
        !            34: 
        !            35: #include <errno.h>
        !            36: #include "vrrp_misc.h"
        !            37: #ifdef ENABLE_VRRP_AH
        !            38: #include "vrrp_ah.h"
        !            39: #endif
        !            40: 
        !            41: /* this code is based on ifconfig.c */
        !            42: #define ROUNDUP(a) \
        !            43: ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
        !            44: #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
        !            45: 
        !            46: void 
        !            47: rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo * rtinfo)
        !            48: {
        !            49:        struct sockaddr *sa;
        !            50:        int             i;
        !            51: 
        !            52:        memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
        !            53:        for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
        !            54:                if ((rtinfo->rti_addrs & (1 << i)) == 0)
        !            55:                        continue;
        !            56:                rtinfo->rti_info[i] = sa = (struct sockaddr *) cp;
        !            57:                ADVANCE(cp, sa);
        !            58:        }
        !            59: }
        !            60: 
        !            61: char 
        !            62: vrrp_misc_get_if_infos(char *if_name, struct ether_addr * ethaddr, struct in_addr * ip_addrs, int *size)
        !            63: {
        !            64:        int             addrcount;
        !            65:        struct if_msghdr *ifm, *nextifm;
        !            66:        struct ifa_msghdr *ifam;
        !            67:        struct sockaddr_dl *sdl;
        !            68:        struct sockaddr_in *sin;
        !            69:        char           *buf, *lim, *next;
        !            70:        char            name[64];
        !            71:        struct rt_addrinfo info;
        !            72:        size_t          needed;
        !            73:        int             mib[6];
        !            74:        int             sizes = *size;
        !            75:        char            myinterface = 0;
        !            76: 
        !            77:        mib[0] = CTL_NET;
        !            78:        mib[1] = PF_ROUTE;
        !            79:        mib[2] = 0;
        !            80:        mib[3] = AF_INET;
        !            81:        mib[4] = NET_RT_IFLIST;
        !            82:        mib[5] = 0;
        !            83: 
        !            84:        if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
        !            85:                syslog(LOG_ERR, "iflist-sysctl-estimate: %s", strerror(errno));
        !            86:                return -1;
        !            87:        }
        !            88:        if ((buf = malloc(needed)) == NULL) {
        !            89:                syslog(LOG_ERR, "malloc: %s", strerror(errno));
        !            90:                return -1;
        !            91:        }
        !            92:        if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
        !            93:                syslog(LOG_ERR, "actual retrieval of interface table: %s", strerror(errno));
        !            94:                free(buf);
        !            95:                return -1;
        !            96:        }
        !            97:        lim = buf + needed;
        !            98: 
        !            99:        next = buf;
        !           100:        while (next < lim) {
        !           101:                *size = sizes;
        !           102:                ifm = (struct if_msghdr *) next;
        !           103:                if (ifm->ifm_type == RTM_IFINFO) {
        !           104:                        sdl = (struct sockaddr_dl *) (ifm + 1);
        !           105:                        strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
        !           106:                        name[sdl->sdl_nlen] = '\0';
        !           107:                } else {
        !           108:                        syslog(LOG_ERR, "there is an error: ifm->ifm_type != RTM_INFO");
        !           109:                        free(buf);
        !           110:                        return -1;
        !           111:                }
        !           112:                if (strlen(name) != sdl->sdl_nlen)
        !           113:                        continue;
        !           114:                if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0)
        !           115:                        continue;
        !           116:                myinterface = (sdl->sdl_nlen == strlen(if_name)) && (!strncmp(if_name, sdl->sdl_data, sdl->sdl_nlen));
        !           117:                if (ip_addrs != NULL && size != NULL && *size > 0) {
        !           118:                        next += ifm->ifm_msglen;
        !           119:                        ifam = NULL;
        !           120:                        addrcount = 0;
        !           121:                        while (next < lim) {
        !           122:                                nextifm = (struct if_msghdr *) next;
        !           123:                                if (nextifm->ifm_type != RTM_NEWADDR)
        !           124:                                        break;
        !           125:                                ifam = (struct ifa_msghdr *) nextifm;
        !           126:                                info.rti_addrs = ifam->ifam_addrs;
        !           127:                                rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, &info);
        !           128:                                sin = (struct sockaddr_in *) info.rti_info[RTAX_IFA];
        !           129:                                if (myinterface)
        !           130:                                        ip_addrs[addrcount] = sin->sin_addr;
        !           131:                                addrcount++;
        !           132:                                if (*size <= addrcount)
        !           133:                                        break;
        !           134:                                next += nextifm->ifm_msglen;
        !           135:                        }
        !           136:                        *size = addrcount;
        !           137:                }
        !           138:                if (ethaddr != NULL)
        !           139:                        if (myinterface)
        !           140:                                bcopy(LLADDR(sdl), ethaddr, sizeof(struct ether_addr));
        !           141:                if (myinterface)
        !           142:                        break;
        !           143:        }
        !           144:        free(buf);
        !           145:        return 0;
        !           146: }
        !           147: 
        !           148: char 
        !           149: vrrp_misc_get_vlan_infos(struct vrrp_vr *vr)
        !           150: {
        !           151:        struct sockaddr_dl *sdl;
        !           152:        struct if_msghdr *ifm;
        !           153:        char           *buf, *lim, *next;
        !           154:        char            name[64];
        !           155:        size_t          needed;
        !           156:        int             mib[6];
        !           157: 
        !           158:        if (! vr) {
        !           159:                syslog(LOG_ERR, "vr is NULL. cannot vrrp_misc_get_vlan_infos");
        !           160:                return -1;
        !           161:        }
        !           162:        mib[0] = CTL_NET;
        !           163:        mib[1] = PF_ROUTE;
        !           164:        mib[2] = 0;
        !           165:        mib[3] = AF_INET;
        !           166:        mib[4] = NET_RT_IFLIST;
        !           167:        mib[5] = 0;
        !           168: 
        !           169:        if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
        !           170:                syslog(LOG_ERR, "iflist-sysctl-estimate: %s", strerror(errno));
        !           171:                return -1;
        !           172:        }
        !           173:        if ((buf = malloc(needed)) == NULL) {
        !           174:                syslog(LOG_ERR, "malloc: %s", strerror(errno));
        !           175:                return -1;
        !           176:        }
        !           177:        if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
        !           178:                syslog(LOG_ERR, "actual retrieval of interface table: %s", strerror(errno));
        !           179:                free(buf);
        !           180:                return -1;
        !           181:        }
        !           182:        lim = buf + needed;
        !           183: 
        !           184:        next = buf;
        !           185:        while (next < lim) {
        !           186:                ifm = (struct if_msghdr *) next;
        !           187:                if (ifm->ifm_type == RTM_IFINFO) {
        !           188:                        sdl = (struct sockaddr_dl *) (ifm + 1);
        !           189:                        strncpy(name, sdl->sdl_data, sdl->sdl_nlen);
        !           190:                        name[sdl->sdl_nlen] = '\0';
        !           191:                        if (! bcmp(LLADDR(sdl), &vr->vr_if->ethaddr, sizeof(struct ether_addr))) {
        !           192:                                vrrp_vlanlist_add(vr, name);
        !           193:                        }
        !           194:                }
        !           195:                else
        !           196:                        if (ifm->ifm_type != RTM_NEWADDR) {
        !           197:                                syslog(LOG_ERR, "there is an error: ifm->ifm_type != RTM_INFO");
        !           198:                                free(buf);
        !           199:                                return -1;
        !           200:                        }
        !           201:                next += ifm->ifm_msglen;
        !           202:        }
        !           203:        free(buf);
        !           204:        return 0;
        !           205: }
        !           206: int 
        !           207: vrrp_misc_get_priority(struct vrrp_vr * vr)
        !           208: {
        !           209:        u_char          i = 0, j = 0;
        !           210: 
        !           211:        if (vr->cnt_ip == vr->vr_if->nb_ip) {
        !           212:                while (j < vr->cnt_ip) {
        !           213:                        while (i < vr->vr_if->nb_ip) {
        !           214:                                if (vr->vr_if->ip_addrs[j].s_addr == vr->vr_ip[i].addr.s_addr)
        !           215:                                        break;
        !           216:                                i++;
        !           217:                        }
        !           218:                        if (i >= vr->vr_if->nb_ip)
        !           219:                                return VRRP_PRIORITY_DEFAULT;
        !           220:                        j++;
        !           221:                }
        !           222:                return VRRP_PRIORITY_MASTER;
        !           223:        } else
        !           224:                return VRRP_PRIORITY_DEFAULT;
        !           225: }
        !           226: 
        !           227: u_short 
        !           228: vrrp_misc_compute_checksum(u_short * addr, register int len)
        !           229: {
        !           230:        int             nleft = len;
        !           231:        const u_short * w = addr;
        !           232:        u_short         answer;
        !           233:        int             sum = 0;
        !           234: 
        !           235:        while (nleft > 1) {
        !           236:                sum += *w++;
        !           237:                nleft -= 2;
        !           238:        }
        !           239:        if (nleft == 1)
        !           240:                sum += htons(*(u_char *) w << 8);
        !           241:        sum = (sum >> 16) + (sum & 0xFFFF);
        !           242:        sum += (sum >> 16);
        !           243:        answer = ~sum;
        !           244: 
        !           245:        return answer;
        !           246: }
        !           247: 
        !           248: char 
        !           249: vrrp_misc_calcul_tminterval(struct timeval * timer, u_int interval)
        !           250: {
        !           251:        struct timeval  tm;
        !           252: 
        !           253:        if (gettimeofday(&tm, NULL) == -1) {
        !           254:                syslog(LOG_ERR, "cannot get time with gettimeofday: %s", strerror(errno));
        !           255:                return -1;
        !           256:        }
        !           257:        timer->tv_sec = tm.tv_sec + interval;
        !           258:        timer->tv_usec = tm.tv_usec;
        !           259: 
        !           260:        return 0;
        !           261: }
        !           262: 
        !           263: char 
        !           264: vrrp_misc_calcul_tmrelease(struct timeval * timer, struct timeval * interval)
        !           265: {
        !           266:        struct timeval  tm;
        !           267: 
        !           268:        interval->tv_sec = 0;
        !           269:        interval->tv_usec = 0;
        !           270:        if (gettimeofday(&tm, NULL) == -1) {
        !           271:                syslog(LOG_ERR, "cannot get time with gettimeofday: %s", strerror(errno));
        !           272:                return -1;
        !           273:        }
        !           274:        if (tm.tv_sec < timer->tv_sec || (tm.tv_sec == timer->tv_sec && tm.tv_usec < timer->tv_usec)) {
        !           275:                interval->tv_sec = timer->tv_sec - tm.tv_sec;
        !           276:                if (timer->tv_usec < tm.tv_usec) {
        !           277:                        interval->tv_sec--;
        !           278:                        interval->tv_usec = (timer->tv_usec + 1000000) - tm.tv_usec;
        !           279:                } else
        !           280:                        interval->tv_usec = timer->tv_usec - tm.tv_usec;
        !           281:        }
        !           282:        return 0;
        !           283: }
        !           284: 
        !           285: u_short 
        !           286: vrrp_misc_vphdr_len(struct vrrp_hdr * vph)
        !           287: {
        !           288:        return (sizeof(struct vrrp_hdr) + (vph->cnt_ip << 2) + VRRP_AUTH_DATA_LEN);
        !           289: }
        !           290: 
        !           291: char 
        !           292: vrrp_misc_check_vrrp_packet(struct vrrp_vr * vr, char *packet, ssize_t packetSize)
        !           293: {
        !           294:        struct ip      *iph = (struct ip *) packet;
        !           295: #ifdef ENABLE_VRRP_AH
        !           296:        struct vrrp_hdr *vph = (struct vrrp_hdr *) & packet[sizeof(struct ip)+vrrp_ah_ahhdr_len(vr)];
        !           297: #else
        !           298:        struct vrrp_hdr *vph = (struct vrrp_hdr *) & packet[sizeof(struct ip)];
        !           299: #endif
        !           300:        struct in_addr *ip_addrs = (struct in_addr *) & packet[sizeof(struct ip) + sizeof(struct vrrp_hdr)];
        !           301:        char           *password = NULL;
        !           302:        int             error = 0;
        !           303:        int             cpt, cpt2;
        !           304:        char            detected;
        !           305:        u_short         checksum_orig = vph->csum;
        !           306: 
        !           307:        if (iph->ip_ttl != VRRP_MULTICAST_TTL) {
        !           308:                syslog(LOG_ERR, "ip ttl of vrrp packet isn't set to 255. Packet is discarded !");
        !           309:                return -1;
        !           310:        }
        !           311:        if (vph->vrrp_v != VRRP_PROTOCOL_VERSION) {
        !           312:                syslog(LOG_ERR, "vrrp version of vrrp packet is not valid or compatible with this daemon. Packet is discarded !");
        !           313:                return -1;
        !           314:        }
        !           315:        if (packetSize < sizeof(struct ip) + vrrp_misc_vphdr_len(vph)) {
        !           316:                syslog(LOG_ERR, "invalid vrrp packet received (invalid size). Packet is discarded !");
        !           317:                return -1;
        !           318:        }
        !           319:        vph->csum = 0;
        !           320:        if (vrrp_misc_compute_checksum((u_short *) vph, vrrp_misc_vphdr_len(vph)) != checksum_orig) {
        !           321:                syslog(LOG_ERR, "checksum of vrrp packet is invalid. Packet is discarded !");
        !           322:                return -1;
        !           323:        }
        !           324:        vph->csum = checksum_orig;
        !           325:        if (vph->vr_id != vr->vr_id)
        !           326:                return -1;
        !           327:        if (vph->cnt_ip != vr->cnt_ip)
        !           328:                error = 1;
        !           329:        else {
        !           330:                for (cpt = 0; cpt < vph->cnt_ip; cpt++) {
        !           331:                        detected = 0;
        !           332:                        for (cpt2 = 0; cpt2 < vr->cnt_ip; cpt2++) {
        !           333:                                if (ip_addrs[cpt].s_addr == vr->vr_ip[cpt2].addr.s_addr)
        !           334:                                        detected = 1;
        !           335:                        }
        !           336:                        if (! detected) {
        !           337:                                syslog(LOG_ERR, "error to 1 because not detected");
        !           338:                                error = 1;
        !           339:                                break;
        !           340:                        }
        !           341:                }
        !           342:        }
        !           343:        if (error == 1) {
        !           344:                syslog(LOG_ERR, "detection of misconfigured server on the network for vrid = %u and priority = %u", vph->vr_id, vph->priority);
        !           345:                if (vph->priority != VRRP_PRIORITY_MASTER) {
        !           346:                        syslog(LOG_ERR, "this server is not a master virtual router. Packet is discarded !");
        !           347:                        return -1;
        !           348:                }
        !           349:        }
        !           350:        if (vph->adv_int != vr->adv_int) {
        !           351:                syslog(LOG_ERR, "the advertisement interval set on received vrrp packet isn't same localy. Packet is discarded !");
        !           352:                return -1;
        !           353:        }
        !           354: #ifdef ENABLE_VRRP_AH
        !           355:        /* checking function */
        !           356:        vrrp_ah_check_ahhdr(packet,vr);
        !           357: #endif
        !           358:        /* Verification of Authentification */
        !           359:        password = (char *)&ip_addrs[vph->cnt_ip];
        !           360:        if (vr->auth_type == 1 && strncmp(vr->password, password, 8)) {
        !           361:                syslog(LOG_ERR, "authentification incorrect in a received vrrp packet. Packet is discarded !");
        !           362:                return -1;
        !           363:        }
        !           364:        return 0;
        !           365: }
        !           366: 
        !           367: void 
        !           368: vrrp_misc_quit(int coderet)
        !           369: {
        !           370:        exit(coderet);
        !           371: }
        !           372: 
        !           373: struct vrrp_if *
        !           374: vrrp_misc_search_if_entry(char *name)
        !           375: {
        !           376:        int             cpt = 0;
        !           377: 
        !           378:        while (cpt < VRRP_PROTOCOL_MAX_VRID) {
        !           379:                if (vr_ptr[cpt] == NULL)
        !           380:                        break;
        !           381:                if (!strncmp(vr_ptr[cpt]->vr_if->if_name, name, strlen(name)))
        !           382:                        return vr_ptr[cpt]->vr_if;
        !           383:                cpt++;
        !           384:        }
        !           385: 
        !           386:        return NULL;
        !           387: }

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