Reputation: 19684
I am trying to view TCP payload information using libpcap. To do this I need to locate the payload's position in memory. I am using this Programming With Pcap guide to figure out the location of the request payload. When sniffing packets originating from a client that resides on the same machine as the service (loopback adapter) the IP Header length is 0. I cannot successfully find the location of the request payload. Is this to be expected when listening to loopback adapter? I am working on a MacOSx 10.8 system listening to adapter 'lo0'.
Here is what I am trying:
//this callback is called when a packet is found
void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet){
ethernet = (struct sniff_ethernet*)(packet);
ip = (struct sniff_ip*)(packet + SIZE_ETHERNET); <-- the result is 0
size_ip = IP_HL(ip)*4;
if (size_ip < 20) {
printf(" * Invalid IP header length: %u bytes\n", size_ip);
return;
}
tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
size_tcp = TH_OFF(tcp)*4;
if (size_tcp < 20) {
printf(" * Invalid TCP header length: %u bytes\n", size_tcp);
return;
}
payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp);
}
struct sniff_ip:
#define SIZE_ETHERNET 14
/* IP header */
struct sniff_ip {
u_char ip_vhl; /* version << 4 | header length >> 2 */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
Upvotes: 2
Views: 2415
Reputation:
ethernet = (struct sniff_ethernet*)(packet);
ip = (struct sniff_ip*)(packet + SIZE_ETHERNET); <-- the result is 0
If you're capturing on the loopback interface, that code is wrong. Not all interfaces on OS X (or any other OS that supports libpcap/WinPcap) provide Ethernet headers; you need to call pcap_datalink()
to find the link-layer type of the capture device (or capture file, if you're reading a capture file with pcap_open_offline()
) and, based on that, parse the link-layer headers of the packet.
See the list of pcap link-layer header types for a complete list.
DLT_EN10MB
is the link-layer header type for Ethernet devices ("10MB" is historical, and refers to 3MB vs. 10MB Ethernet, which had different headers; DLT_EN10MB
applies to 10 MB and 100 MB and 1 GB and 10 GB and 40 GB and 100 GB and... Ethernet), as well as some non-Ethernet devices that provide fake Ethernet headers.
The link-layer header type for the loopback device on most BSDs and on OS X is DLT_NULL
; as the link-layer header types page says, it has a 4-byte link-layer header containing the OS's PF_
value for the protocol, which will probably be IPv4 or IPv6.
Upvotes: 8