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
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.