File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / freevrrpd / vrrp_network.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_network.c,v 1.1.1.1 2017/06/14 12:01:54 misho Exp $
   33:  */
   34: 
   35: #include <errno.h>
   36: #include <sys/param.h>
   37: #include "vrrp_network.h"
   38: #include "vrrp_ah.h"
   39: 
   40: u_short         ip_id;
   41: 
   42: /* Initialisation pour l'identification IP */
   43: void 
   44: vrrp_network_initialize(void)
   45: {
   46: 	srand(time(NULL));
   47: 	ip_id = random() % 65535;
   48: 
   49: 	return;
   50: }
   51: 
   52: /* Open VRRP socket for reading */
   53: char 
   54: vrrp_network_open_socket(struct vrrp_vr * vr)
   55: {
   56: 	struct timeval timeout;
   57: 	int hincl = 1;
   58: 
   59: 	vr->sd = socket(AF_INET, SOCK_RAW, IPPROTO_VRRP);
   60: 	if (vr->sd == -1) {
   61: 		syslog(LOG_ERR, "cannot open raw socket for VRRP protocol [ AF_INET, SOCK_RAW, IPPROTO_VRRP ]: %s", strerror(errno));
   62: 		return -1;
   63: 	}
   64: 	if (setsockopt(vr->sd, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof(hincl))) {
   65: 		syslog(LOG_ERR, "cannot set IP_HDRINCL option on the IPPROTO_IP raw socket: %s", strerror(errno));
   66: 		return -1;
   67: 	}
   68: 	timeout.tv_sec  = 0;
   69: 	timeout.tv_usec = 100000;
   70: 	if (setsockopt(vr->sd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == -1) {
   71: 		syslog(LOG_ERR, "cannot set SO_RCVTIMEO option on the IPPROTO_VRRP raw socket: %s", strerror(errno));
   72: 		return -1;
   73: 	}
   74: 
   75: 	return 0;
   76: }
   77: 
   78: ssize_t
   79: vrrp_network_send_packet(char *buffer, int sizebuf, int sd, int log)
   80: {
   81: 	struct sockaddr_in addr;
   82: 	ssize_t          octets;
   83: 
   84: 	addr.sin_family = AF_INET;
   85: 	addr.sin_port = 0;
   86: 	addr.sin_len = sizeof(struct sockaddr_in);
   87: 	addr.sin_addr.s_addr = inet_addr(VRRP_MULTICAST_IP);
   88: 	octets = sendto(sd, buffer, sizebuf, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
   89: 	if (octets < 0) {
   90: 		if (log)
   91: 			syslog(LOG_ERR, "can't write to socket: %s", strerror(errno));
   92: 		return -1;
   93: 	}
   94: 
   95: 	return octets;
   96: }
   97: 
   98: u_int 
   99: vrrp_network_vrrphdr_len(struct vrrp_vr * vr)
  100: {
  101: 	u_int           len = sizeof(struct vrrp_hdr);
  102: 
  103: 	len += (vr->cnt_ip << 2) + VRRP_AUTH_DATA_LEN;
  104: 
  105: 	return len;
  106: }
  107: 
  108: void 	 
  109: vrrp_network_init_iphdr(char *buffer, struct vrrp_vr * vr) 	 
  110: { 	 
  111: 	 struct ip      *iph = (struct ip *)buffer; 	 
  112:   	 
  113: 	 iph->ip_hl = 5;
  114: 	 iph->ip_v = 4;
  115: 	 iph->ip_tos = 0;
  116: #if (defined(__FreeBSD__) && (__FreeBSD_version < 1100030)) || defined(__NetBSD__)
  117: 	 iph->ip_len = sizeof(struct ip) + vrrp_network_vrrphdr_len(vr) + vrrp_ah_ahhdr_len(vr);
  118: #else
  119: 	 iph->ip_len = htons(sizeof(struct ip) + vrrp_network_vrrphdr_len(vr) + vrrp_ah_ahhdr_len(vr));
  120: #endif
  121: 	 /* iph->ip_id = ++ip_id; */
  122: 	 iph->ip_off = 0;
  123: 	 iph->ip_ttl = VRRP_MULTICAST_TTL;
  124: #ifdef ENABLE_VRRP_AH
  125: 	 if (vr->AHencryption == 1)
  126: 	     iph->ip_p = IPPROTO_AH;
  127: 	 else
  128: 	     iph->ip_p = IPPROTO_VRRP;
  129: #else
  130: 	 iph->ip_p = IPPROTO_VRRP;
  131: #endif
  132: 	 iph->ip_src.s_addr = vr->vr_if->ip_addrs[0].s_addr;
  133: 	 iph->ip_dst.s_addr = inet_addr(VRRP_MULTICAST_IP);
  134: 	 iph->ip_sum = vrrp_misc_compute_checksum((u_short *) iph, iph->ip_hl << 2);
  135:   	 
  136: 	return;
  137: }
  138: 
  139: void 
  140: vrrp_network_init_vrrphdr(char *buffer, struct vrrp_vr * vr)
  141: {
  142: 	struct vrrp_hdr *vp;
  143: 	struct in_addr *addr;
  144: 	char           *password;
  145: 	int             cpt;
  146: 
  147: 	vp = (struct vrrp_hdr *)buffer;
  148: 	vp->vrrp_v = VRRP_PROTOCOL_VERSION;
  149: 	vp->vrrp_t = VRRP_PROTOCOL_ADVERTISEMENT;
  150: 	vp->vr_id = vr->vr_id;
  151: 	vp->priority = vr->priority;
  152: 	vp->cnt_ip = vr->cnt_ip;
  153: 	vp->auth_type = vr->auth_type;
  154: 	vp->adv_int = vr->adv_int;
  155: 	addr = (struct in_addr *) & buffer[sizeof(struct vrrp_hdr)];
  156: 	for (cpt = 0; cpt < vr->cnt_ip; cpt++) {
  157: 		addr[cpt].s_addr = vr->vr_ip[cpt].addr.s_addr;
  158: 	}
  159: 	if (vr->auth_type == 1) {
  160: 		password = (char *)&addr[vr->cnt_ip];
  161: 		strncpy(password, vr->password, 8);
  162: 	}
  163: 	vp->csum = vrrp_misc_compute_checksum((u_short *) vp, vrrp_network_vrrphdr_len(vr));
  164: 
  165: 	return;
  166: }
  167: 
  168: char 
  169: vrrp_network_send_advertisement(struct vrrp_vr * vr)
  170: {
  171: 	u_char         *buffer;
  172: #ifdef ENABLE_VRRP_AH
  173: 	u_int           len = sizeof(struct ip) + vrrp_ah_ahhdr_len(vr) + vrrp_network_vrrphdr_len(vr);
  174: #else
  175: 	u_int           len = sizeof(struct ip) + vrrp_network_vrrphdr_len(vr);
  176: #endif
  177: 	ssize_t		bytes = 0;
  178: 
  179: 	buffer = (u_char *) malloc(len);
  180: 	bzero(buffer, len);
  181: 
  182: 	vrrp_network_init_iphdr(buffer, vr);
  183: #ifdef ENABLE_VRRP_AH
  184: 	/* add AH adding code */
  185: 	if (vr->AHencryption == 1) {
  186: 	    vrrp_ah_init_ahhdr(buffer,vr); 
  187: 	    vrrp_network_init_vrrphdr(&buffer[sizeof(struct ip)+vrrp_ah_ahhdr_len(vr)], vr); 
  188: 	    vrrp_ah_hmacmd5(buffer,vr);
  189: 	} else 
  190: 	    vrrp_network_init_vrrphdr(&buffer[sizeof(struct ip)+vrrp_ah_ahhdr_len(vr)], vr); 
  191: #else
  192: 	vrrp_network_init_vrrphdr(&buffer[sizeof(struct ip)], vr);
  193: #endif
  194: 
  195: 	if (vr->fault)
  196: 		bytes = vrrp_network_send_packet(buffer, len, vr->sd, 0);
  197: 	else
  198: 		bytes = vrrp_network_send_packet(buffer, len, vr->sd, 1);
  199: 
  200: 	if (bytes < 0) {
  201: 		syslog(LOG_ERR, "There is a big problem here !");
  202: 		vr->fault = 1;
  203: 		free(buffer);
  204: 		return -1;
  205: 	}
  206: 	vr->fault = 0;
  207: 	free(buffer);
  208: 
  209: 	return 0;
  210: }
  211: 
  212: int
  213: vrrp_network_open_bpf(char *if_name)
  214: {
  215:         struct ifreq    ifr;
  216:         int             n = 0;
  217:         char            device[16];
  218:         int             sd = 0;
  219:         int             yes = 1;
  220:    
  221:         while ((sd <= 0) && (n < 100)) {
  222:                 snprintf(device, sizeof(device), "/dev/bpf%d", n++);
  223:                 sd = open(device, O_WRONLY);
  224:         }
  225:         if (sd < 0) { 
  226:                 syslog(LOG_ERR, "cannot found a valid /dev/bpf* entry, do you have bpf in kernel ?");
  227:                 syslog(LOG_ERR, "perhaps you've not created /dev entry on your chroot directory with bpf* entries");
  228:                 return -1;
  229:         }
  230:         bzero(&ifr, sizeof(ifr));
  231:         strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
  232:         if (ioctl(sd, BIOCSETIF, (caddr_t)&ifr) < 0) {
  233:                 syslog(LOG_ERR, "interface %s doesn't seem to exist, ioctl: %s\n", strerror(errno), ifr.ifr_name);
  234:                 syslog(LOG_ERR, "you must correct your configuration file with a good option for 'interface ='");
  235:                 return -1;
  236:         }
  237:         if (ioctl(sd, BIOCSHDRCMPLT, &yes) < 0) {
  238:                 syslog(LOG_ERR, "cannot do BIOCSHDRCMPLT: %s", strerror(errno));
  239:                 syslog(LOG_ERR, "something is terribly wrong, I can't continue");
  240:                 return -1;
  241:         }
  242: 
  243: 	return sd;
  244: }
  245: 
  246: int 
  247: vrrp_network_send_gratuitous_arp(char *if_name, struct ether_addr *ethaddr, struct in_addr addr)
  248: {
  249:         char buffer[ETHER_HDR_LEN + sizeof(struct arp_header)];
  250:         struct ether_header *ethhdr = (struct ether_header *) buffer;
  251:         struct arp_header *arph = (struct arp_header *) & buffer[ETHER_HDR_LEN];
  252: 	int sd;
  253: 
  254:         memset(ethhdr->ether_dhost, 0xFF, ETHER_ADDR_LEN);
  255:         bcopy(ethaddr, ethhdr->ether_shost, ETHER_ADDR_LEN);
  256:         ethhdr->ether_type = htons(ETHERTYPE_ARP);
  257:         bzero(arph, sizeof(*arph));
  258:         arph->ar_hrd = htons(ARPHRD_ETHER);
  259:         arph->ar_pro = htons(ETHERTYPE_IP);
  260:         arph->ar_hln = ETHER_ADDR_LEN;
  261:         arph->ar_pln = 4;
  262:         arph->ar_op = htons(ARPOP_REQUEST);
  263:         memcpy(arph->ar_sha, ethhdr->ether_shost, ETHER_ADDR_LEN);
  264: 	sd = vrrp_network_open_bpf(if_name);
  265:         if (sd == -1)
  266:                 return -1;
  267:         memcpy(arph->ar_spa, &addr, sizeof(struct in_addr));
  268:         memcpy(arph->ar_tpa, &addr, sizeof(struct in_addr));
  269:         if (write(sd, buffer, ETHER_HDR_LEN + sizeof(struct arp_header)) == -1) {
  270:                 syslog(LOG_ERR, "cannot write on socket descriptor sd: %s", strerror(errno));
  271: 		close(sd);
  272:                 return -1;
  273:         }
  274: 	close(sd);
  275: 
  276:         return 0;
  277: }
  278: 
  279: int
  280: vrrp_network_send_gratuitous_arp_ips(struct vrrp_vr * vr, struct ether_addr * ethaddr)
  281: {
  282:         int             cpt = 0;
  283:         struct in_addr  addrs[MAX_IP_ALIAS];
  284:         int             size = MAX_IP_ALIAS;
  285:         char            coderet = 0;
  286: 
  287:         bzero(addrs, sizeof(addrs));
  288:         vrrp_misc_get_if_infos(vr->vr_if->if_name, NULL, addrs, &size);
  289:         while (addrs[cpt].s_addr) {
  290:                 coderet = vrrp_network_send_gratuitous_arp(vr->vr_if->if_name, ethaddr, addrs[cpt]);
  291:                 syslog(LOG_ERR, "send gratuitous arp %s -> %x:%x:%x:%x:%x:%x", inet_ntoa(addrs[cpt]), ethaddr->octet[0], ethaddr->octet[1], ethaddr->octet[2], ethaddr->octet[3], ethaddr->octet[4], ethaddr->octet[5]);
  292:                 cpt++;
  293:         }
  294: 
  295:         return coderet;
  296: }
  297: 
  298: #define rtm rtmsg.rthdr
  299: char 
  300: vrrp_network_delete_local_route(struct in_addr addr)
  301: {
  302: 	struct routemsg rtmsg;
  303: 	int             sd;
  304: 
  305: 	sd = socket(PF_ROUTE, SOCK_RAW, 0);
  306: 	if (sd == -1) {
  307: 		close(sd);
  308: 		return -1;
  309: 	}
  310: 	bzero(&rtmsg, sizeof(rtmsg));
  311: 	rtm.rtm_type = RTM_DELETE;
  312: 	rtm.rtm_version = RTM_VERSION;
  313: #ifdef __FreeBSD__
  314: 	rtm.rtm_flags = RTF_UP | RTF_HOST | RTF_LOCAL;
  315: #endif
  316: #if __FreeBSD_version < 800059
  317: 	rtm.rtm_flags |= RTF_WASCLONED;
  318: #endif
  319: #ifdef __NetBSD__
  320: 	rtm.rtm_flags = RTF_UP | RTF_HOST | RTF_CLONED;
  321: #endif
  322: 	rtm.rtm_addrs = RTA_DST;
  323: 	rtm.rtm_msglen = sizeof(rtmsg);
  324: 	rtmsg.addr.sin_len = sizeof(rtmsg.addr);
  325: 	rtmsg.addr.sin_family = AF_INET;
  326: 	rtmsg.addr.sin_addr = addr;
  327: 	if (write(sd, &rtmsg, sizeof(rtmsg)) == -1) {
  328: 		close(sd);
  329: 		return -1;
  330: 	}
  331: 	close(sd);
  332: 
  333: 	return 0;
  334: }

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