Annotation of embedaddon/freevrrpd/vrrp_network.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_network.c,v 1.27 2004/04/04 19:45:46 rival 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>