【发布时间】:2011-09-05 14:59:06
【问题描述】:
我正在尝试编写一个 .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;
【问题讨论】:
-
注意字节顺序——我认为捕获的数据包总是使用网络字节顺序,但您可能需要检查标头的字节顺序。如果文件格式使用
magic_number字段来确定标头的字节顺序,则可能不是问题。 -
幻数让你可以用大端或小端写入,如果你愿意,你甚至可以在每个数据包后来回切换。幻数还会提醒您因文件传输不当造成的损坏。
-
幻数不让你以big-endian或little-endian顺序写出数据包data;你必须按照它出现在线路上的顺序写出来,对于以太网、IP、TCP 和 UDP 多字节整数字段,它是大端的。它确实让您可以按照本机字节顺序写出文件中的字段并记录标题,但您不妨让 libpcap/WinPcap 完成这项工作。而且,遗憾的是,幻数不受例如在 Windows 和 UN*X 之间以 ASCII 模式 FTP 文件的影响。