PCAP 编码 :: 我的代码设置了错误的以太网类型
PCAP Coding :: My Code is Setting the Wrong Type of Ethernet
我正在编写一个 C 程序,它构建一个 Ethernet/IPv4/TCP 网络数据包,然后将数据包写入 PCAP 文件以供检查。我的代码基于 SO post here. 我的代码的第一个版本运行完美,但它是一个很大的 main()
函数,不能移植到更大的程序中。
所以我重新组织了代码,以便我可以将它移植到另一个程序中。在此post,我不想深究版本 1 和版本 2 之间的区别。但不用说,除了一个恼人的怪癖,版本 2 工作得很好。当 Wireshark 打开 Version 1 PCAP 文件时,它看到我的第 2 层是 Ethernet II:
Frame 1: 154 bytes on wire (1232 bits), 154 bytes captured (1232 bits)
Ethernet II, Src: 64:96:c8:fa:fc:ff (64:96:c8:fa:fc:ff), Dst: Woonsang_04:05:06 (01:02:03:04:05:06)
Destination: Woonsang_04:05:06 (01:02:03:04:05:06)
Source: 64:96:c8:fa:fc:ff (64:96:c8:fa:fc:ff)
Type: IPv4 (0x0800)
Internet Protocol Version 4, Src: 10.10.10.10, Dst: 20.20.20.20
Transmission Control Protocol, Src Port: 22, Dst Port: 55206, Seq: 1, Ack: 1, Len: 100
SSH Protocol
但是在版本 2 中,第 2 层 header 变成了 802.3 以太网:
Frame 1: 154 bytes on wire (1232 bits), 134 bytes captured (1072 bits)
IEEE 802.3 Ethernet
Destination: Vibratio_1c:08:00 (00:09:70:1c:08:00)
Source: 45:00:23:28:06:cf (45:00:23:28:06:cf)
Length: 64
Trailer: 050401040204000001020506040400070602040704060202…
Logical-Link Control
Data (61 bytes)
[Packet size limited during capture: Ethernet truncated]
我不是网络专家,但我猜我的第 2 版 PCAP 文件在某处格式不正确。我应该 而不是 那里有一个 Logical-Link 控件 header;我的代码认为它正在编写 Ethernet II / IPv4 / TCP headers。在这一点上,我的直觉是 PCAP 数据包 header(处理 PCAP 文件中的每个数据包所必需的)或我的以太网 header 不知何故不正确。这会告诉 Wireshark“接下来的 X 个字节是以太网 II header?”
这是我的代码,摘录如下:
PCAP header 和以太网帧的结构直接来自 the before-mentioned SO post. post 的解决方案是对 PCAP 数据包使用 pcap_sf_pkthdr
结构header:
// struct for PCAP Packet Header - Timestamp
struct pcap_timeval {
bpf_int32 tv_sec; // seconds
bpf_int32 tv_usec; // microseconds
};
// struct for PCAP Packet Header
struct pcap_sf_pkthdr {
struct pcap_timeval ts; // time stamp
bpf_u_int32 caplen; // length of portion present
bpf_u_int32 len; // length this packet (off wire)
};
而以太网header来自原来的post:
// struct for the Ethernet header
struct ethernet {
u_char mac1[6];
u_char mac2[6];
u_short protocol; // will be ETHERTYPE_IP, for IPv4
};
这两个结构都没有太多内容,对吧?我真的不明白Wireshark是怎么看这个的,知道数据包的前20个字节是以太网。
这是实际代码,略有删节:
#include <netinet/in.h> // for ETHERTYPE_IP
struct pcap_sf_pkthdr* allocatePCAPPacketHdr(struct pcap_sf_pkthdr* pcapPacketHdr ){
pcapPacketHdr = malloc( sizeof(struct pcap_sf_pkthdr) );
if( pcapPacketHdr == NULL ){
return NULL;
}
uint32_t frameSize = sizeof( struct ethernet) + …correctly computed here
bzero( pcapPacketHdr, sizeof( struct pcap_sf_pkthdr ) );
pcapPacketHdr->ts.tv_sec = 0; // for now
pcapPacketHdr->ts.tv_usec = 0; // for now
pcapPacketHdr->caplen = frameSize;
pcapPacketHdr->len = frameSize;
return pcapPacketHdr;
}
void* allocateL2Hdr( packetChecklist* pc, void* l2header ){
l2header = malloc( sizeof( struct ethernet ) );
if( l2header == NULL ){
return NULL;
}
bzero( ((struct ethernet*)l2header)->mac1, 6 );
bzero( ((struct ethernet*)l2header)->mac2, 6 );
// …MAC addresses filled in later…
((struct ethernet*)l2header)->protocol = ETHERTYPE_IP; // This is correctly set
return l2header;
}
...以及使用上述功能的代码...
struct pcap_sf_pkthdr* pcapPacketHdr;
pcapPacketHdr = allocatePCAPPacketHdr( pcapPacketHdr );
struct ethernet* l2header;
l2header = allocateL2Hdr( l2header );
稍后,代码填充这些结构并将它们与 IPv4 header、TCP header 等一起写入文件。
但我认为我的问题是我真的不明白 Wireshark 如何知道我的以太网 header 是以太网 II 而不是带有 Logical-Link [=64= 的 802.3 以太网].是在 PCAP 数据包 Header 中传达的吗?或者在某个地方的以太网帧中?我希望得到建议。谢谢
Wireshark is supposed to know that my Ethernet header is Ethernet II and not 802.3 Ethernet with an Logical-Link Header. Is that communicated in the PCAP Packet Header?
没有
Or in the ethernet frame somewhere?
是的。
如果您需要详细信息,请参阅 the "Types" section of the Wikipedia "Ethernet frame" page。
但是,问题似乎是您正在写入文件的数据包中没有完整的 6 字节目标地址和源地址 - 目标地址的最后两个字节是 0x08 0x00,这是ETHERTYPE_IP(0x0800)的big-endian值的前两个字节,源地址的第一个字节是0x45,这是一个没有的IPv4数据包的IPv4报头的第一个字节IP 选项。
不知何故,您的程序版本 1 将目标地址和源地址放入 pcap 记录的数据部分,但版本 2 没有。
我正在编写一个 C 程序,它构建一个 Ethernet/IPv4/TCP 网络数据包,然后将数据包写入 PCAP 文件以供检查。我的代码基于 SO post here. 我的代码的第一个版本运行完美,但它是一个很大的 main()
函数,不能移植到更大的程序中。
所以我重新组织了代码,以便我可以将它移植到另一个程序中。在此post,我不想深究版本 1 和版本 2 之间的区别。但不用说,除了一个恼人的怪癖,版本 2 工作得很好。当 Wireshark 打开 Version 1 PCAP 文件时,它看到我的第 2 层是 Ethernet II:
Frame 1: 154 bytes on wire (1232 bits), 154 bytes captured (1232 bits)
Ethernet II, Src: 64:96:c8:fa:fc:ff (64:96:c8:fa:fc:ff), Dst: Woonsang_04:05:06 (01:02:03:04:05:06)
Destination: Woonsang_04:05:06 (01:02:03:04:05:06)
Source: 64:96:c8:fa:fc:ff (64:96:c8:fa:fc:ff)
Type: IPv4 (0x0800)
Internet Protocol Version 4, Src: 10.10.10.10, Dst: 20.20.20.20
Transmission Control Protocol, Src Port: 22, Dst Port: 55206, Seq: 1, Ack: 1, Len: 100
SSH Protocol
但是在版本 2 中,第 2 层 header 变成了 802.3 以太网:
Frame 1: 154 bytes on wire (1232 bits), 134 bytes captured (1072 bits)
IEEE 802.3 Ethernet
Destination: Vibratio_1c:08:00 (00:09:70:1c:08:00)
Source: 45:00:23:28:06:cf (45:00:23:28:06:cf)
Length: 64
Trailer: 050401040204000001020506040400070602040704060202…
Logical-Link Control
Data (61 bytes)
[Packet size limited during capture: Ethernet truncated]
我不是网络专家,但我猜我的第 2 版 PCAP 文件在某处格式不正确。我应该 而不是 那里有一个 Logical-Link 控件 header;我的代码认为它正在编写 Ethernet II / IPv4 / TCP headers。在这一点上,我的直觉是 PCAP 数据包 header(处理 PCAP 文件中的每个数据包所必需的)或我的以太网 header 不知何故不正确。这会告诉 Wireshark“接下来的 X 个字节是以太网 II header?”
这是我的代码,摘录如下:
PCAP header 和以太网帧的结构直接来自 the before-mentioned SO post. post 的解决方案是对 PCAP 数据包使用 pcap_sf_pkthdr
结构header:
// struct for PCAP Packet Header - Timestamp
struct pcap_timeval {
bpf_int32 tv_sec; // seconds
bpf_int32 tv_usec; // microseconds
};
// struct for PCAP Packet Header
struct pcap_sf_pkthdr {
struct pcap_timeval ts; // time stamp
bpf_u_int32 caplen; // length of portion present
bpf_u_int32 len; // length this packet (off wire)
};
而以太网header来自原来的post:
// struct for the Ethernet header
struct ethernet {
u_char mac1[6];
u_char mac2[6];
u_short protocol; // will be ETHERTYPE_IP, for IPv4
};
这两个结构都没有太多内容,对吧?我真的不明白Wireshark是怎么看这个的,知道数据包的前20个字节是以太网。
这是实际代码,略有删节:
#include <netinet/in.h> // for ETHERTYPE_IP
struct pcap_sf_pkthdr* allocatePCAPPacketHdr(struct pcap_sf_pkthdr* pcapPacketHdr ){
pcapPacketHdr = malloc( sizeof(struct pcap_sf_pkthdr) );
if( pcapPacketHdr == NULL ){
return NULL;
}
uint32_t frameSize = sizeof( struct ethernet) + …correctly computed here
bzero( pcapPacketHdr, sizeof( struct pcap_sf_pkthdr ) );
pcapPacketHdr->ts.tv_sec = 0; // for now
pcapPacketHdr->ts.tv_usec = 0; // for now
pcapPacketHdr->caplen = frameSize;
pcapPacketHdr->len = frameSize;
return pcapPacketHdr;
}
void* allocateL2Hdr( packetChecklist* pc, void* l2header ){
l2header = malloc( sizeof( struct ethernet ) );
if( l2header == NULL ){
return NULL;
}
bzero( ((struct ethernet*)l2header)->mac1, 6 );
bzero( ((struct ethernet*)l2header)->mac2, 6 );
// …MAC addresses filled in later…
((struct ethernet*)l2header)->protocol = ETHERTYPE_IP; // This is correctly set
return l2header;
}
...以及使用上述功能的代码...
struct pcap_sf_pkthdr* pcapPacketHdr;
pcapPacketHdr = allocatePCAPPacketHdr( pcapPacketHdr );
struct ethernet* l2header;
l2header = allocateL2Hdr( l2header );
稍后,代码填充这些结构并将它们与 IPv4 header、TCP header 等一起写入文件。
但我认为我的问题是我真的不明白 Wireshark 如何知道我的以太网 header 是以太网 II 而不是带有 Logical-Link [=64= 的 802.3 以太网].是在 PCAP 数据包 Header 中传达的吗?或者在某个地方的以太网帧中?我希望得到建议。谢谢
Wireshark is supposed to know that my Ethernet header is Ethernet II and not 802.3 Ethernet with an Logical-Link Header. Is that communicated in the PCAP Packet Header?
没有
Or in the ethernet frame somewhere?
是的。
如果您需要详细信息,请参阅 the "Types" section of the Wikipedia "Ethernet frame" page。
但是,问题似乎是您正在写入文件的数据包中没有完整的 6 字节目标地址和源地址 - 目标地址的最后两个字节是 0x08 0x00,这是ETHERTYPE_IP(0x0800)的big-endian值的前两个字节,源地址的第一个字节是0x45,这是一个没有的IPv4数据包的IPv4报头的第一个字节IP 选项。
不知何故,您的程序版本 1 将目标地址和源地址放入 pcap 记录的数据部分,但版本 2 没有。