我想使用libpcap来捕获数据包 但由于以太网报头或802.11报头的长度可能会有所不同 并且IP头的长度也可能不同, 如何确定IP头和TCP头的起始字节(指针) 另外,如何区分数据包是纯IP数据包,TCP数据包还是UDP数据包? 有没有API或方法来做到这一点? 谢谢!
答案 0 :(得分:2)
当您使用libpcap时,您可以通过直接查看来自呼叫的pcap文件头(用于离线捕获)pcap_file_header.linktype
或(用于实时和离线捕获)来确定链路层标头的大小到pcap_datalink()
。大部分时间都是LINKTYPE_ETHERNET
。为了确保数据包是IPv4,您可以转换为以太网头并检查以确保ethertype为ETHERTYPE_IP
(确保将其包装在ntohs()
内。我通常将bpf过滤器应用于我的pcap实例化所以我从不担心这些问题。然而,要检查更高层协议并假设您正在使用pcap_dispatch()
,您可以按照以下方式编写回调:( libnet库对于其广泛的便携式数据包仍然有用结构):
#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;
}