如何使用 libpcap 和 C 获取 VLAN 标签?

How do I fetch the VLAN tags using libpcap and C?

我正在尝试使用 #include 解析包含不同类型网络数据包(有些被标记为 VLAN 而有些不是)的 pcap 文件。 到目前为止,这是我的代码:

pcap_t *pcap;
const unsigned char *packet;
char errbuf[PCAP_ERRBUF_SIZE];
struct pcap_pkthdr header;
pcap = pcap_open_offline(argv[0], errbuf);
if (pcap == NULL)
    {
    fprintf(stderr, "error reading pcap file: %s\n", errbuf);
    exit(1);
}
while ((packet = pcap_next(pcap, &header)) != NULL)
{
    struct ip_header *ip;
    unsigned int IP_header_length;
    packet += sizeof(struct ether_header);
    capture_len -= sizeof(struct ether_header);
    ip = (struct ip_header*) packet;
    IP_header_length = ip->vhl * 4; /* ip_hl is in 4-byte words */
    char *sinfo = strdup(inet_ntoa(ip->src));
    char *dinfo = strdup(inet_ntoa(ip->dst));
    printf ("%s<-__->%s\n", sinfo ,dinfo);
    free (sinfo);
    free (dinfo);
}

代码中一定有地方检查 VLAN 并跳过它们 correctly.How 我应该区分 VLAN 数据包和非 VLAN 数据包吗?

(如果您在 'live' 环境中进行测试,请务必记住,路由器可以在转发到非中继线路之前删除 802.1q 标签。)

如果您有一个特定的平台和协议,最快的方法总是'manually'检查一个帧:

htonl( ((uint32_t)(ETH_P_8021Q) << 16U)
     | ((uint32_t)customer_tci & 0xFFFFU) ) T

但是,libpcapcompiling a BPF filters 函数的形式提供了一个便携且干净的数据包过滤器,并将其应用于数据包流(尽管重要的是要注意有不同的在线与离线过滤的功能集)

以这种方式,我们可以使用pcap_offline_filter to apply the compiled BPF filter directive to a PCAP file. I've used the filter expression vlan here, you may want something else like vlan or ip. If you need something more complex, you can consult the documentation)

...

pcap_t *pcap;
char errbuf[PCAP_ERRBUF_SIZE];
const unsigned char *packet;
struct pcap_pkthdr header;
struct bpf_program fp; // Our filter expression
pcap = pcap_open_offline(argv[0], errbuf);
if (pcap == NULL) {
    fprintf(stderr, "error reading pcap file: %s\n", errbuf);
    exit(1);
}

// Compile a basic filter expression, you can exam
if (pcap_compile(pcap, &fp, "vlan", 0, net) == -1) {
    fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
    return 2;
}

while ((packet = pcap_next(pcap, &header) != NULL)
       && pcap_offline_filter(&fp, header, packet)) {
    struct ip_header *ip;
    unsigned int IP_header_length;
    packet += sizeof(struct ether_header);
    capture_len -= sizeof(struct ether_header);
    ip = (struct ip_header*) packet;
    IP_header_length = ip->vhl * 4; /* ip_hl is in 4-byte words */
    char *sinfo = strdup(inet_ntoa(ip->src));
    char *dinfo = strdup(inet_ntoa(ip->dst));
    printf ("%s<-__->%s\n", sinfo ,dinfo);
    free (sinfo);
    free (dinfo);
}

...