0

我正在用 libpcap 编写一个工具来分析 TCP 流量。我面临的问题是,在提供给我进行测试的 pcap 文件中,我看到 IP 标头从偏移量 0x10 开始(因此在 16 个字节之后),而所有文档 + 实时捕获显示它始终位于 0xE (如文档声明)。

我如何尝试获取 ip 和 tcp 标头:

struct iphdr *ip;
struct tcphdr *tcp;
ip = (struct iphdr *)(packet + sizeof(struct ethhdr));
tcp = (struct tcphdr *)(packet + sizeof(struct ethhdr) + sizeof(struct iphdr)

一些wireshark图像:

实时捕捉 -在此处输入图像描述

如您所见,它在 14 个字节后开始,就像它应该的那样

离线转储文件 -在此处输入图像描述

转储文件 ip 标头在 16 个字节后开始

解析 IP 和 TCP 标头的正确方法是什么?

谢谢

4

1 回答 1

1

罗恩·莫平是 100% 正确的。提供更多细节:

我面临的问题是在提供给我进行测试的 pcap 文件中

pcap-savefile(5) 手册页指出 pcap 文件头中的字段之一是“链路层头类型”字段;正如手册页所说:

一个 4 字节的数字,给出捕获中数据包的链路层标头类型;请参阅 pcap-linktype(7) 了解可以出现在此字段中的 LINKTYPE_ 值。

如果您打开了一个带有pcap_open_offline()或其中一个变体的捕获文件, libpcap中的pcap_datalink()例程将返回链接层标头类型。

链路层报头类型是解释数据包内容的必要条件。例如,对于 IP 数据包,IP 标头位于任何元数据标头和链路层标头之后,并且并非所有元数据标头(如果存在)和所有链路层标头都具有相同的长度,因此您必须知道什么是链接-层标头的存在是为了知道 IP 标头从哪里开始 - 或者,实际上,甚至可以确定数据包是否是 IP 数据包!例如,对于以太网数据包,您必须查看以太网类型/长度字段以查看它是 0x0800(对于 IPv4)还是 0x86dd(对于 IPv6)。

tcpdump.org 链路层标头类型列表指示存在哪些链路层类型。给出的数值是出现在文件的“链路层标头类型”字段中(或在pcapng 文件中接口描述块的 LinkType 字段中出现的数值- libpcap 可以读取一些 pcapng 文件,所有接口描述块其中必须具有相同的 LinkType,并将在pcap_datalink()调用中返回链路层类型)。

返回的pcap_datalink()值是链路层头类型列表中的 DLT_ 值,因此以太网文件(或以太网接口描述块)在头中的值为 1 或 LINKTYPE_ETHERNET,它将映射到 DLT_EN10MB的返回值pcap_datalink()。(在大多数情况下,LINKTYPE_ 值和对应的 DLT_ 值在数值上是相同的,但也有一些例外情况,即不同的操作系统对于相同的 DLT_ 类型具有不同的数值。)第二次捕获在捕获文件中有 LINKTYPE_LINUX_SLL,所以pcap_datalink()会返回 DLT_LINUX_SLL。

链接层标头类型页面对链接层标头类型的描述应该可以帮助您编写代码来解释该链接层标头类型的标头数据。

此外,正如 Ron Maupin 所指出的,在以太网报头之后但在 IP 报头之前也可能有 VLAN 报头。

(而且,由于这是由编写程序来读取捕获文件的人提出的问题,而不是由设计或维护网络的人提出的问题,因此它似乎更适合堆栈溢出而不是网络工程。)

于 2019-09-09T03:47:52.180 回答