Annotation of embedaddon/freevrrpd/vrrp_misc.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_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>