如何确定原始数据包中IP头和TCP头的起始字节

时间:2013-03-15 10:48:59

标签: tcp udp ip libpcap

我想使用libpcap来捕获数据包 但由于以太网报头或802.11报头的长度可能会有所不同 并且IP头的长度也可能不同, 如何确定IP头和TCP头的起始字节(指针) 另外,如何区分数据包是纯IP数据包,TCP数据包还是UDP数据包? 有没有API或方法来做到这一点? 谢谢!

1 个答案:

答案 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;
    }