如何使用 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
但是,libpcap
以 compiling 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);
}
...
我正在尝试使用 #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
但是,libpcap
以 compiling 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);
}
...