使用 libpcap 捕获任何接口时无法获取协议

Can't get protocol while capture any interfaces with libpcap

我使用 libpcap 代码在我的 Ubuntu 中使用以下代码捕获网络流量 我在解析数据包协议时遇到问题:

#include <stdio.h> 
#include <stdlib.h> 
#include <stddef.h>
#include <stdio.h>
#include <time.h>
#include <pcap.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>



int main(int argc, char *argv[]) {
    char *device = "any";
    char error_buffer[PCAP_ERRBUF_SIZE];
    pcap_t *handle;
    const u_char *packet;
    struct pcap_pkthdr packet_header;
    int packet_count_limit = 1;
    int timeout_limit = 20000; /* In milliseconds */
    bpf_u_int32 net;
    bpf_u_int32 mask;

    if ( -1 == pcap_lookupnet(device ,&net,&mask,error_buffer))
    printf("error netmask\n");


    /* Open device for live capture */
    handle = pcap_open_live(
            device ,
            BUFSIZ,
            packet_count_limit,
            timeout_limit,
            error_buffer
        );
    if(NULL == handle)
        printf("error! %s\n",error_buffer);
    struct pcap_pkthdr* header;
    u_char *buffer;

    while(1)
    {
    
        int ret  = pcap_next_ex(handle,&header, &buffer);
    if(header->len ==0)
    {
        printf("cont\n");
        continue;

    }

    struct  iphdr *iph = (struct iphdr*) (buffer + sizeof(struct ethhdr));
    printf("protocol = %d \n", iph->protocol);
    }

    return 0;
}

问题是,当我选择在 any 接口 char *device = "any"; 中捕获时,我总是得到 protocol = 0

但是当我选择 char *device = "ens33"; 时,我得到了正确的协议(比如 6 代表 TCP)

这是为什么?

libpcap 有时会根据所选的接口,将第 2 层 header(在本例中为以太网)替换为 Linux cooked header,其长度与以太网 header。您可以使用 pcap_datalink 函数检查 pcap_t 的数据链路类型。

unsigned int layer_2_header_length;

switch ( pcap_datalink(handle) ) {
case DLT_EN10MB: // Ethernet header
    layer_2_header_length = 14;
    break;

case DLT_LINUX_SLL: // Linux cooked header
    layer_2_header_length = 16;
    break;

// other options
}