C - 将结构写入文件 (.pcap)
我正在尝试编写一个 .pcap 文件,该文件可以在 Wireshark 中使用。 为了做到这一点,我需要将几个具有各种数据类型的结构写入文件。 (参见代码)
因此,我创建结构实例,填充数据,使用 FILE* fp = fopen("test.pcap","w"),然后我不确定如何将其正确写入文件。我相信我应该使用 memcpy 但我不确定最好的方法。过去我主要依靠 C++ 库来完成此任务。有什么建议吗?
typedef struct pcap_hdr_s {
uint32_t magic_number; /* magic number */
uint16_t version_major; /* major version number */
uint16_t version_minor; /* minor version number */
int32_t thiszone; /* GMT to local correction */
uint32_t sigfigs; /* accuracy of timestamps */
uint32_t snaplen; /* max length of captured packets, in octets */
uint32_t network; /* data link type */
} pcap_hdr_t;
typedef struct pcaprec_hdr_s {
uint32_t ts_sec; /* timestamp seconds */
uint32_t ts_usec; /* timestamp microseconds */
uint32_t incl_len; /* number of octets of packet saved in file */
uint32_t orig_len; /* actual length of packet */
} pcaprec_hdr_t;
typedef struct ethernet_hdr_s {
uint8_t dst[6]; /* destination host address */
uint8_t src[6]; /* source host address */
uint16_t type; /* IP? ARP? RARP? etc */
} ethernet_hdr_t;
typedef struct ip_hdr_s {
uint8_t ip_hl:4, /* both fields are 4 bits */
ip_v:4;
uint8_t ip_tos;
uint16_t ip_len;
uint16_t ip_id;
uint16_t ip_off;
uint8_t ip_ttl;
uint8_t ip_p;
uint16_t ip_sum;
uint32_t ip_src;
uint32_t ip_dst;
}ip_hdr_t;
typedef struct udp_header
{
uint16_t src;
uint16_t dst;
uint16_t length;
uint16_t checksum;
} udp_header_t;
I am trying to write a .pcap file, which is something that can be used in Wireshark.
In order to do that, I have a couple of structs with various data types I need to write to a file. (see code)
So, I create the struct instances, fill in the data, use FILE* fp = fopen("test.pcap","w"), and then I'm unsure how to properly write it to the file. I believe I should use memcpy but I'm not sure of the best way to do it. I have mostly resorted to C++ libraries in the past to do this. Any suggestions?
typedef struct pcap_hdr_s {
uint32_t magic_number; /* magic number */
uint16_t version_major; /* major version number */
uint16_t version_minor; /* minor version number */
int32_t thiszone; /* GMT to local correction */
uint32_t sigfigs; /* accuracy of timestamps */
uint32_t snaplen; /* max length of captured packets, in octets */
uint32_t network; /* data link type */
} pcap_hdr_t;
typedef struct pcaprec_hdr_s {
uint32_t ts_sec; /* timestamp seconds */
uint32_t ts_usec; /* timestamp microseconds */
uint32_t incl_len; /* number of octets of packet saved in file */
uint32_t orig_len; /* actual length of packet */
} pcaprec_hdr_t;
typedef struct ethernet_hdr_s {
uint8_t dst[6]; /* destination host address */
uint8_t src[6]; /* source host address */
uint16_t type; /* IP? ARP? RARP? etc */
} ethernet_hdr_t;
typedef struct ip_hdr_s {
uint8_t ip_hl:4, /* both fields are 4 bits */
ip_v:4;
uint8_t ip_tos;
uint16_t ip_len;
uint16_t ip_id;
uint16_t ip_off;
uint8_t ip_ttl;
uint8_t ip_p;
uint16_t ip_sum;
uint32_t ip_src;
uint32_t ip_dst;
}ip_hdr_t;
typedef struct udp_header
{
uint16_t src;
uint16_t dst;
uint16_t length;
uint16_t checksum;
} udp_header_t;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用 libpcap 或 WinPcap -
pcap_open_dead()
获取“假”pcap_t
,与pcap_dump_open()
一起使用来指定链路层标头类型(对于以太网,使用DLT_EN10MB
)和快照长度(使用65535),pcap_dump_open()
打开文件写入,pcap_dump()
写出数据包,pcap_dump_close()
关闭文件。 比直接使用fopen()
、fwrite()
和fclose()
简单得多(这些是 libpcap 的功能) /WinPcap 使用“幕后”)。是的,您必须确保数据包中的字节顺序正确。字节顺序取决于协议;对于以太网标头中的
type
字段以及 IP、TCP 和 UDP 标头中的所有多字节字段,它们必须采用大端顺序。 (pcap 文件中的幻数与此无关 - 它仅指示文件头和每个数据包记录头中字段的字节顺序,不数据包,以及由于 Linux 中的实现方式,Linux USB 捕获中数据包开头的元数据应该看起来与“在线上”完全相同。)Use libpcap or WinPcap -
pcap_open_dead()
to get a "fake"pcap_t
to use withpcap_dump_open()
to specify the link-layer header type (for Ethernet, useDLT_EN10MB
) and snapshot length (use 65535),pcap_dump_open()
to open the file for writing,pcap_dump()
to write out a packet, andpcap_dump_close()
to close the file. MUCH easier than directly usingfopen()
,fwrite()
, andfclose()
(which are what libpcap/WinPcap use "under the hood").And, yes, you have to get the byte order in the packets correct. The byte order depends on the protocol; for the
type
field in the Ethernet header, and for all multi-byte fields in IP, TCP, and UDP headers, they have to be in big-endian order. (The magic number in the pcap file is irrelevant to this - it only indicates the byte order of the fields in the file header and the per-packet record header, NOT the byte order of the fields in the packet, as well as, due to the way it's implemented in Linux, the meta-data at the beginning of packets in Linux USB captures. The packet data is supposed to look exactly as it would "on the wire".)使用fwrite()。您需要检查此信息,但我认为 .pcap 文件是以二进制模式编写的。
例子:
Use fwrite(). You need to check this info but I think .pcap files are written in binary mode.
Example:
这是我对盖伊·哈里斯建议的理解。因此,根据 Kyslik 的要求,我们有:
Here's my understanding of what Guy Harris is suggesting. So, as per Kyslik's request, we have: