Reputation: 1003
I want to use libpcap to capture packets but since the length of ethernet header or 802.11 header may vary and the length of IP header may also vary, how can I determine the starting byte(pointer) of the IP Header and TCP header besides, how to distinguish whether a packet is a pure IP packet, TCP packet or UDP packet? are there any APIs or ways to do this? thanks!
Upvotes: 1
Views: 1798
Reputation: 240
When you're using libpcap, you can determine the size of link layer header, either by directly looking at the pcap file header (for offline captures) pcap_file_header.linktype
or (for live and offline captures) from a call to pcap_datalink()
. Most of the time this will be LINKTYPE_ETHERNET
. To ensure a packet is IPv4, you can cast into an Ethernet header and check to ensure the ethertype is ETHERTYPE_IP
(make sure you wrap it inside of ntohs()
. I usually apply bpf filters to my pcap instantiations so I never worry about that stuff. To check the higher layer protocols however and assuming you're using pcap_dispatch()
, you can write a callback as per the following: (the libnet library is still useful for its wide array of portable packet structures):
#include <libnet.h>
#include <pcap.h>
void
process_packet(u_char *user, const struct pcap_pkthdr *header, const u_char *packet)
{
struct libnet_ipv4_hdr *ip;
struct libnet_udp_hdr *tcp;
uint16_t ip_hl, udp_hl, header_cruft;
ip = (struct libnet_ipv4_hdr *)(packet + LIBNET_ETH_H);
ip_hl = ip->ip_hl << 2;
switch (ip->ip_p)
{
case IPPROTO_UDP:
udp = (struct libnet_udp_hdr *)(packet + LIBNET_ETH_H + ip_hl);
udp_hl = tcp->th_off << 2;
header_cruft = LIBNET_ETH_H + ip_hl + tcp_hl;
break;
case IPPROTO_TCP:
/** you get the idea */
break;
default:
break;
}
Upvotes: 2