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

时间:2016-09-25 19:42:48

标签: c libpcap vlan

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

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并正确跳过它们。如何区分VLAN数据包和非VLAN?

1 个答案:

答案 0 :(得分:1)

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

如果你有一个特定的平台&amp;在考虑到协议的情况下,最快方式将始终是手动&#39;检查框架:

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

然而,libpcap提供了便携式和便携式设备。以compiling a BPF filters的函数形式清理数据包过滤器并将其应用于数据包流(尽管重要的是要注意,有一些不同的函数用于线上和离线过滤)

以这种方式,我们可以使用pcap_offline_filter将已编译的BPF过滤器指令应用于PCAP文件。我在这里使用了过滤器表达式vlan,您可能需要其他类似vlan or ip的内容。如果您需要更复杂的内容,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);
}

...