Show
Ignore:
Timestamp:
08/02/06 21:22:14 (2 years ago)
Author:
aturner
Message:

fix linux's PF_PACKET sending by taking the code from libpcap 0.9.4. refs #4

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/common/sendpacket.c

    r1564 r1565  
    44 * Copyright (c) 2006 Aaron Turner. 
    55 * Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com> 
     6 * Copyright (c) 2000 Torsten Landschoff <torsten@debian.org> 
     7 *                    Sebastian Krahmer  <krahmer@cs.uni-potsdam.de> 
    68 * Copyright (c) 1993, 1994, 1995, 1996, 1998 
    79 *      The Regents of the University of California. 
     
    8587 
    8688#if defined HAVE_PF_PACKET 
    87 /* older versions of glibc require different headers */ 
    88 #if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1 
     89#include <fcntl.h> 
     90#include <sys/socket.h> 
     91#include <sys/utsname.h> 
     92#include <net/if.h> 
     93#include <netinet/in.h> 
     94#include <linux/if_ether.h> 
     95#include <net/if_arp.h> 
    8996#include <netpacket/packet.h> 
    90 #include <net/ethernet.h> 
    91 #else 
    92 #include <sys/socket.h> 
    93 #include <netpacket/packet.h> 
    94 #include <net/ethernet.h> 
    95 #endif 
    96 #include <net/if.h> 
     97 
     98#ifndef __GLIBC__ 
     99typedef int socklen_t; 
     100#endif 
    97101 
    98102static sendpacket_t *sendpacket_open_pf(const char *, char *); 
    99103static struct tcpr_ether_addr *sendpacket_get_hwaddr_pf(sendpacket_t *); 
    100 static int get_iface_index(int fd, const int8_t *device); 
     104static int get_iface_index(int fd, const int8_t *device, char *); 
    101105 
    102106#elif defined HAVE_BPF 
     
    148152 
    149153#if defined HAVE_PF_PACKET  
    150     retcode = (int)sendto(sp->handle.fd, (void *)data, len, 0,  
    151         (struct sockaddr *)&sp->sa, sizeof(struct sockaddr)); 
     154    retcode = (int)send(sp->handle.fd, (void *)data, len, 0); 
     155         
     156    /* out of buffers, silently retry */ 
    152157    if (retcode < 0 && errno == ENOBUFS && !didsig) { 
    153158        sp->retry ++; 
    154159        goto TRY_SEND_AGAIN; 
    155     } else if (retcode < 0) { 
    156         sendpacket_seterr(sp, "Error with sendto(): %s", strerror(errno)); 
     160    }  
     161    /* some other kind of error */ 
     162    else if (retcode < 0) { 
     163        sendpacket_seterr(sp, "Error with pf send(): %s", strerror(errno)); 
    157164    } 
    158165     
     
    172179        goto TRY_SEND_AGAIN; 
    173180    } else if (retcode < 0) { 
    174         sendpacket_seterr(sp, "Error with libnet_adv_write_link: %s", libnet_geterror(sp->handle.lnet)); 
     181        sendpacket_seterr(sp, "Error with libnet write: %s", libnet_geterror(sp->handle.lnet)); 
    175182    } 
    176183 
     
    208215    assert(device); 
    209216    assert(errbuf); 
    210  
    211217 
    212218#if defined HAVE_PF_PACKET 
     
    378384    sendpacket_t *sp; 
    379385    struct ifreq ifr; 
    380     int n = 1; 
    381386    struct sockaddr_ll sa; 
     387    int n = 1, err; 
     388    socklen_t errlen = sizeof(err); 
    382389 
    383390    assert(device); 
     
    390397    } 
    391398 
     399    
     400    /* get the interface id for the device */ 
     401    if ((sa.sll_ifindex = get_iface_index(mysocket, device, errbuf)) < 0) { 
     402        close(mysocket); 
     403        return NULL;  
     404    } 
     405 
     406    /* bind socket to our interface id */ 
     407    sa.sll_family = AF_PACKET; 
     408    sa.sll_protocol = htons(ETH_P_ALL); 
     409    if (bind(mysocket, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 
     410        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "bind error: %s", strerror(errno)); 
     411        close(mysocket); 
     412        return NULL; 
     413    } 
     414     
     415    /* check for errors, network down, etc... */ 
     416    if (getsockopt(mysocket, SOL_SOCKET, SO_ERROR, &err, &errlen) < 0) { 
     417        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "error opening %s: %s", device,  
     418            strerror(errno)); 
     419        close(mysocket); 
     420        return NULL; 
     421    } 
     422     
     423    if (err > 0) { 
     424        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "error opening %s: %s", device,  
     425            strerror(err)); 
     426        close(mysocket); 
     427        return NULL; 
     428    } 
     429 
     430    /* get hardware type for our interface */ 
    392431    memset(&ifr, 0, sizeof(ifr)); 
    393432    strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 
    394433     
    395     if (ioctl(mysocket, SIOCGIFHWADDR, (int8_t *)&ifr) < 0) { 
     434    if (ioctl(mysocket, SIOCGIFHWADDR, &ifr) < 0) { 
    396435        close(mysocket); 
    397         sendpacket_seterr(sp, "Error calling SIOCGIFHWADDR: %s", strerror(errno)); 
     436        sendpacket_seterr(sp, "Error getting hardware type: %s", strerror(errno)); 
    398437        return NULL; 
    399438    } 
     
    406445            snprintf(errbuf, SENDPACKET_ERRBUF_SIZE,  
    407446                "unsupported pysical layer type 0x%x", ifr.ifr_hwaddr.sa_family); 
     447            close(mysocket); 
    408448            return NULL; 
    409449    } 
     
    421461        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, 
    422462                "SO_BROADCAS: %s\n", strerror(errno)); 
     463        close(mysocket); 
    423464        return NULL; 
    424465    } 
    425466#endif  /*  SO_BROADCAST  */ 
    426467    
    427     /* get the sendto() sockaddr struct */ 
    428     memset(&sa, 0, sizeof(sa)); 
    429     sa.sll_family = AF_PACKET; 
    430     if ((sa.sll_ifindex = get_iface_index(mysocket, device)) < 0) { 
    431         sendpacket_seterr(sp, "Unable to get inteface index: %s",  
    432             strerror(errno)); 
    433         return NULL;  
    434     } 
    435  
     468  
    436469    /* prep & return our sp handle */ 
    437470    sp = (sendpacket_t *)safe_malloc(sizeof(sendpacket_t)); 
    438471    strlcpy(sp->device, device, sizeof(sp->device)); 
    439     sp->handle.fd = mysocket; 
    440      
    441     /* need this to do a sendto() */ 
    442     memcpy(&sp->sa, &sa, sizeof(sa));  
     472    sp->handle.fd = mysocket;    
    443473     
    444474    return sp; 
     
    447477/* get the interface index (necessary for sending packets w/ PF_PACKET) */ 
    448478static int 
    449 get_iface_index(int fd, const int8_t *device) { 
     479get_iface_index(int fd, const int8_t *device, char *errbuf) { 
    450480    struct ifreq ifr; 
    451481 
    452     /* memset(&ifr, 0, sizeof(ifr)); */ 
     482    memset(&ifr, 0, sizeof(ifr)); 
    453483    strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 
    454484 
    455485    if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) { 
     486        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "ioctl: %s", strerror(errno)); 
    456487        return (-1); 
    457488    } 
     
    478509     
    479510 
    480     /* create dummy device for ioctl */ 
     511    /* create dummy socket for ioctl */ 
    481512    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 
    482513        sendpacket_seterr(sp, "Unable to open dummy socket for get_hwaddr: %s", strerror(errno)); 
     
    489520    if (ioctl(fd, SIOCGIFHWADDR, (int8_t *)&ifr) < 0) { 
    490521        close(fd); 
    491         sendpacket_seterr(sp, "Error calling SIOCGIFHWADDR: %s", strerror(errno)); 
     522        sendpacket_seterr(sp, "Error getting hardware address: %s", strerror(errno)); 
    492523        return NULL; 
    493524    }