Show
Ignore:
Timestamp:
07/28/06 20:36:04 (2 years ago)
Author:
aturner
Message:

fix bpf injection and a lot of code cleanup
refs #4

Files:
1 modified

Legend:

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

    r1533 r1535  
    7676#include <net/if_dl.h> 
    7777#include <stdlib.h> 
     78#include <unistd.h> 
    7879 
    7980#if defined HAVE_PF_PACKET 
     
    9697#include <sys/socket.h> 
    9798#include <net/if.h> 
     99#include <sys/uio.h> 
     100 
    98101static sendpacket_t *sendpacket_open_bpf(const char *, char *); 
    99102static struct tcpr_ether_addr *get_hwaddr_bpf(sendpacket_t *); 
     
    126129{ 
    127130    int retcode; 
    128 #if defined HAVE_PF_PACKET || defined HAVE_BPF 
     131#if defined HAVE_PF_PACKET 
    129132    struct sockaddr sa; 
    130133#endif 
     
    137140                 
    138141    sp->attempt ++; 
    139  
    140 #if defined HAVE_PF_PACKET || defined HAVE_BPF 
     142     
     143TRY_SEND_AGAIN: 
     144 
     145#if defined HAVE_PF_PACKET  
    141146    memset(&sa, 0, sizeof(sa)); 
    142147    strlcpy(sa.sa_data, sp->device, sizeof(sa.sa_data)); 
    143     if ((retcode = (int)sendto(sp->handle.fd, (void *)data, (size_t)len, 0,  
    144         &sa, sizeof(struct sockaddr))) < 0) { 
     148    retcode = (int)sendto(sp->handle.fd, (void *)data, (size_t)len, 0,  
     149        &sa, sizeof(struct sockaddr)); 
     150    if (retcode < 0 && errno == ENOBUFS && !didsig) { 
     151        sp->retry ++; 
     152        goto TRY_SEND_AGAIN; 
     153    } else if (retcode < 0) { 
    145154        sendpacket_seterr(sp, "Error with sendto(): %s", strerror(errno)); 
    146155    } 
    147156     
     157#elif defined HAVE_BPF 
     158    retcode = write(sp->handle.fd, (void *)data, len); 
     159    if (retcode < 0 && errno == ENOBUFS && !didsig) { 
     160        sp->retry ++; 
     161        goto TRY_SEND_AGAIN; 
     162    } else if (retcode < 0) { 
     163        sendpacket_seterr(sp, "Error with bpf write(): %s", strerror(errno)); 
     164    } 
     165     
     166    /*  
     167     * pcap methods don't seem to support ENOBUFS, so we just straight fail 
     168     * is there a better way??? 
     169     */     
    148170#elif defined HAVE_PCAP_INJECT 
    149171    if ((retcode = pcap_inject(sp->handle.pcap, (void*)data, len)) < 0) 
     
    154176        sendpacket_seterr(sp, "Error with pcap_sendpacket(): %s", pcap_geterr(sp->handle.pcap)); 
    155177 
    156      
    157178#elif defined HAVE_LIBNET 
    158 SEND_VIA_LIBNET: 
    159179    retcode = libnet_adv_write_link(sp->handle.lnet, (u_int8_t*)data, (u_int32_t)len); 
    160180    if (retcode < 0 && errno == ENOBUFS && !didsig) { 
    161181        sp->retry ++; 
    162         goto SEND_VIA_LIBNET; 
     182        goto TRY_SEND_AGAIN; 
    163183    } else if (retcode < 0) { 
    164184        sendpacket_seterr(sp, "Error with libnet_adv_write_link: %s", libnet_geterr(sp->lnet)); 
     
    168188    if (retcode < 0) { 
    169189        sp->failed ++; 
    170     } else if (retcode != len) { 
    171         sendpacket_seterr(sp, "Only able to write %d bytes out of %d bytes total", 
    172             retcode, (int)len); 
     190    } else if (retcode != (int)len) { 
     191        sendpacket_seterr(sp, "Only able to write %d bytes out of %u bytes total", 
     192            retcode, len); 
    173193    } else { 
    174194        sp->bytes_sent += len; 
     
    192212#elif defined HAVE_BPF 
    193213    sp = sendpacket_open_bpf(device, errbuf); 
    194 #elif defined HAVE_PCAP_INJECT || defined HAVE_PCAP_SENDPACKET 
     214#elif (defined HAVE_PCAP_INJECT || defined HAVE_PCAP_SENDPACKET) 
    195215    sp = sendpacket_open_pcap(device, errbuf); 
    196216#elif defined HAVE_LIBNET 
    197217    sp = sendpacket_open_libnet(device, errbuf); 
    198218#endif 
    199     sp->open = 1; 
     219    if (sp != NULL) 
     220        sp->open = 1; 
    200221    return sp; 
    201222} 
     
    222243{ 
    223244    assert(sp); 
    224     sp->open = 0; 
     245 
     246    free(sp); 
    225247    return 0; 
    226248} 
     
    236258    assert(sp); 
    237259     
    238  
     260    /* if we already have our MAC address stored, just return it */ 
     261    if (memcmp(&sp->ether, "\00\00\00\00\00\00", ETHER_ADDR_LEN) != 0) 
     262        return &sp->ether; 
     263         
    239264#if defined HAVE_PF_PACKET 
    240265    addr = get_hwaddr_pf(sp); 
    241266#elif defined HAVE_BPF 
    242267    addr = get_hwaddr_bpf(sp); 
    243 #elif defined HAVE_PCAP_INJECT || defined HAVE_PCAP_SENDPACKET 
     268#elif (defined HAVE_PCAP_INJECT || defined HAVE_PCAP_SENDPACKET) 
    244269    addr = get_hwaddr_pcap(sp); 
    245270#elif defined HAVE_LIBNET 
     
    291316    assert(errbuf); 
    292317     
    293     if ((pcap = pcap_open_live(device, 0, 0, 0, errbuf)) == NULL)  
     318    /* open_pcap_live automatically fills out our errbuf for us */ 
     319    if ((pcap = pcap_open_live(device, 0, 0, 0, errbuf)) == NULL) 
    294320        return NULL; 
    295321         
     
    433459    sendpacket_t *sp; 
    434460    char bpf_dev[10]; 
    435     int dev, mysocket; 
    436     struct ifreq ifr;        
     461    int dev, mysocket, link_offset, link_type; 
     462    struct ifreq ifr; 
     463    struct bpf_version bv; 
     464    u_int v; 
     465#if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) && !(__APPLE__) 
     466    u_int spoof_eth_src = 1; 
     467#endif 
    437468     
    438469    assert(device); 
    439470    assert(errbuf); 
    440      
    441     for (dev = 0; dev <= 20; dev ++) { 
     471    memset(&ifr, '\0', sizeof(struct ifreq)); 
     472     
     473    /* open socket */ 
     474    mysocket = -1; 
     475    for (dev = 0; dev <= 9; dev ++) { 
    442476        memset(bpf_dev, '\0', sizeof(bpf_dev)); 
    443477        snprintf(bpf_dev, sizeof(bpf_dev), "/dev/bpf%d", dev); 
    444         if ((mysocket = open(bpf_dev, O_RDWR|O_NONBLOCK, 0)) > 0) { 
    445             continue; 
     478        if ((mysocket = open(bpf_dev, O_RDWR, 0)) > 0) { 
     479            break; 
    446480        } 
    447481    } 
    448482     
    449     /* error */ 
    450     if (mysocket < 0) 
    451         return NULL; 
    452      
     483    /* error?? */ 
     484    if (mysocket < 0) { 
     485        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE,  
     486            "Unable to open /dev/bpfX: %s", strerror(errno)); 
     487        errbuf[SENDPACKET_ERRBUF_SIZE -1] = '\0'; 
     488        return NULL; 
     489    } 
     490     
     491    /* get BPF version */ 
     492    if (ioctl(mysocket, BIOCVERSION, (caddr_t)&bv) < 0) { 
     493        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Unable to get bpf version: %s", strerror(errno)); 
     494        return NULL; 
     495    } 
     496 
     497    if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor != BPF_MINOR_VERSION) { 
     498        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Kernel's bpf version is out of date."); 
     499        return NULL; 
     500    } 
     501 
     502    /* attach to device */ 
    453503    strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 
    454     if (ioctl(mysocket, BIOCSETIF, &ifr) < 0) { 
    455        snprintf(errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s", strerror(errno)); 
     504    if (ioctl(mysocket, BIOCSETIF, (caddr_t)&ifr) < 0) { 
     505       snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Unable to bind %s to %s: %s",  
     506           bpf_dev, device, strerror(errno)); 
    456507       return NULL; 
    457508    } 
    458509     
     510    /* get datalink type */ 
     511    if (ioctl(mysocket, BIOCGDLT, (caddr_t)&v) < 0) { 
     512        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Unable to get datalink type: %s", 
     513            strerror(errno)); 
     514        return NULL; 
     515    } 
     516     
     517    /* 
     518     *  NetBSD and FreeBSD BPF have an ioctl for enabling/disabling 
     519     *  automatic filling of the link level source address. 
     520     */ 
     521#if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) && !(__APPLE__) 
     522    if (ioctl(mysocket, BIOCSHDRCMPLT, &spoof_eth_src) == -1) { 
     523        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE,  
     524            "Unable to enable spoofing src MAC: %s", strerror(errno)); 
     525        return NULL; 
     526    } 
     527#endif 
     528     
     529    /* assign link type and offset */ 
     530    switch (v) { 
     531        case DLT_SLIP: 
     532            link_offset = 0x10; 
     533            break; 
     534        case DLT_RAW: 
     535            link_offset = 0x0; 
     536            break; 
     537        case DLT_PPP: 
     538            link_offset = 0x04; 
     539            break; 
     540        case DLT_EN10MB: 
     541        default: /* default to Ethernet */ 
     542            link_offset = 0xe; 
     543            break; 
     544    } 
     545#if _BSDI_VERSION - 0 > 199510 
     546    switch (v) { 
     547        case DLT_SLIP: 
     548            v = DLT_SLIP_BSDOS; 
     549            link_offset = 0x10; 
     550            break; 
     551        case DLT_PPP: 
     552            v = DLT_PPP_BSDOS; 
     553            link_offset = 0x04; 
     554            break; 
     555    } 
     556#endif 
     557     
     558    link_type = v; 
     559     
     560    /* allocate our sp handle, and return it */ 
    459561    sp = (sendpacket_t *)safe_malloc(sizeof(sendpacket_t)); 
    460562    strlcpy(sp->device, device, sizeof(sp->device)); 
    461563    sp->handle.fd = mysocket; 
     564    //sp->link_type = link_type; 
     565    //sp->link_offset = link_offset; 
     566     
    462567    return sp;  
    463568}