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>