File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / freevrrpd / vrrp_misc.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 14 12:01:54 2017 UTC (7 years ago) by misho
Branches: freevrrpd, MAIN
CVS tags: v1_1, HEAD
freevrrpd 1.1

    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.1.1.1 2017/06/14 12:01:54 misho 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>