Search code examples
cethernetpcap

Issue sniffing PCAP


I don't understand why my following code doesn't work properly. When I sniff ethernet the bytes that I receive are shifted by 2 bytes

I send use sudo sendip -p ipv4 -p udp 127.0.0.1 -d r8 to send packet to my computer

With the following code:

#include <pcap/pcap.h>

#define SIZE_ETHERNET 14
#define ETHER_ADDR_LEN  6
struct sniff_ethernet {
        u_char  ether_dhost[ETHER_ADDR_LEN];
        u_char  ether_shost[ETHER_ADDR_LEN];
        u_short ether_type;
};


void packet_call_back(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) { 
    struct sniff_ethernet *ethernet = (struct sniff_ethernet*)(bytes);
    printf("test = %#x\n", ethernet->ether_type); // print is 0x0
}

int     main(void) {
    char    errbuf[PCAP_ERRBUF_SIZE];

    pcap_t  *handle = pcap_create("any", errbuf);
    pcap_set_timeout(handle, -1);
    pcap_loop(handle, 0, packet_call_back, NULL);
    pcap_close(handle);
}

The ether_type that I receive is incorrect here 0x0000 instead of 0x0800

but if instead of: struct sniff_ethernet *ethernet = (struct sniff_ethernet*)(bytes); I put struct sniff_ethernet *ethernet = (struct sniff_ethernet*)(bytes + 2); here everything work fine and I can analyse my packet easily.

I compile with gcc test.c -l pcap And I work on an Ubuntu VM with parallels

Thank's for reading


Solution

  • When I sniff ethernet the bytes that I receive are shifted by 2 bytes

    You're not sniffing Ethernet, you're sniffing the "any" device. That will capture on all interfaces, whether they're Ethernet interfaces or not; even if they are all Ethernet interfaces, that doesn't make a difference.

    In order to make this work, a link-layer header type other than Ethernet is used on the "any" device. On Linux, that's a special header; here's what that header looks like.

    ALL programs that use libpcap to capture network traffic or to read a capture file must, after opening the capture device (pcap_activate(), pcap_open_live(), pcap_open()) or the capture file (pcap_open_offline()), call pcap_datalink() to determine the link-layer header type from the device or the file.

    That function returns a value that can be found in the link-layer header types list; it will be one of the values with a name that begins with DLT_. Do not check for the numerical values given there; check for the DLT_ values.