首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从头编写pcap,解算libpcap函数?

如何从头编写pcap,解算libpcap函数?
EN

Stack Overflow用户
提问于 2015-11-04 13:04:45
回答 1查看 7.1K关注 0票数 0

我已经得到了这段代码,它可以很好地用libpcap编写一个pcap (仅使用用于测试的以太网协议):

代码语言:javascript
运行
复制
struct ethernet {
  u_char        mac1[6];
  u_char        mac2[6];
  u_short       protocol;
};

int main() {
  pcap_t *pd;
  pcap_dumper_t *pdumper;

  pd = pcap_open_dead(DLT_EN10MB, 65535);
  pdumper = pcap_dump_open(pd, "test.pcap");
  
  struct pcap_pkthdr packet_header;
  struct timeval ts;

  packet_header.ts = ts;
  packet_header.caplen = sizeof(struct ethernet);
  packet_header.len = sizeof(struct ethernet);

  struct ethernet ethernet;

  bzero(ethernet.mac1, 6);
  bzero(ethernet.mac2, 6);
  ethernet.protocol = 8977; // randomly choose
  pcap_dump((u_char*)pdumper, &packet_header, (const u_char*)&ethernet);
  pcap_close(pd);
  pcap_dump_close(pdumper);
  return 0;
}

但是我不想使用pcap函数,所以我开始对上面使用的函数进行去标记。

以下是我找到的消息来源:

pcap_open_dead函数:dead.c?rev=808a478a2459f3cf0e8bf927fcaad371138efb20

pcap_dump_open,pcap_dump和其他人:http://www.opensource.apple.com/source/libpcap/libpcap-2.1/libpcap/savefile.c

所以,我的想法是:

pcap_open_dead函数有点无用,只是实例化一个pcap_t结构(我不想在代码中使用),然后用参数填充它的值。

pcap_dump_open返回一个pcap_dumper_t (它看起来就像一个文件*),它只是打开文件并在其中写入头(如果我们不关心错误处理)。顺便说一句,它似乎将"p->tzoff“作为sf_write_header的参数,在我的代码中还没有初始化它(而且它还在工作)。关于链接类型,在我们的例子中,它只是等于1。

最后,pcap_dump函数将pcap_dumper_t变量作为第一个参数,该参数被隐式转换为u_char*,然后显式地强制转换为FILE* (为什么不从一开始就使用一个文件?)然后,它使用一个包头和一个数据包数据,用fwrite将它们写入文件中。

我就是这样做的:

代码语言:javascript
运行
复制
FILE *fd = fopen("test.pcap", "w");

struct pcap_file_header header;

header.magic = 0xa1b2c3d4;
header.version_major = 2;
header.version_minor = 4;
header.thiszone = 0;
header.sigfigs = 0;
header.snaplen = 65535;
header.linktype = DLT_EN10MB;

struct pcap_pkthdr packet_header;
struct timeval ts;

packet_header.ts = ts;
packet_header.caplen = sizeof(struct ethernet);
packet_header.len = sizeof(struct ethernet);

struct ethernet ethernet;

bzero(ethernet.mac1, 6);
bzero(ethernet.mac2, 6);
ethernet.protocol = 8977;

fwrite((char*)&header, sizeof(header), 1, fd);
fwrite((char*)&packet_header, sizeof(struct pcap_pkthdr), 1, fd);
fwrite((char*)&ethernet, sizeof(struct ethernet), 1, fd);
close(fd);

不需要使用pcap_t结构,我将snaplen和linktype类型的值直接放在pcap_file_header结构中。

然后,我在pcap函数中使用fwrite的方式与它们相同。

头文件很好,只要在文件中写入头文件,我就可以用wireshark打开该文件。但是,当我添加最后一个fwrite (用于写入数据包头和数据包)时,wireshark告诉我:

代码语言:javascript
运行
复制
The capture file appears to be damaged or corrupt.
(pcap: File has 4195245-byte packet, bigger than maximum of 65535)

我找不到我的错误所在,我也不知道他在哪里看到这么多字节。

编辑

我没有使用未初始化的timeval,而是使用了:

代码语言:javascript
运行
复制
packet_header.ts = (struct timeval){0};

现在这是可行的,但是如何解释它在使用pcap函数时是有效的呢?"ts“仍未初始化。

这段时间的意义是什么?把它设为零有意义吗?

编辑:将幻数更正为0xa1b2c3d4

EN

回答 1

Stack Overflow用户

发布于 2015-11-04 19:34:21

struct pcap_pkthdr packet_header;

这是包头的格式,因为它是提供给程序的。它不一定是数据包报头的格式,因为它存储在文件中;它包含一个struct timeval,其大小取决于time_t是32位还是64位。

你需要的是:

代码语言:javascript
运行
复制
struct pcap_timeval {
    bpf_int32 tv_sec;       /* seconds */
    bpf_int32 tv_usec;      /* microseconds */
};
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) */

};

然后使用struct pcap_sf_pkthdr代替。将struct pcap_pkthdr结构写入文件将在任何系统上产生无效的pcap,而struct timevaltv_sectv_usec字段不是32位;在任何64位系统上都可能出现这种情况。在这种情况下,您很可能会遇到类似“损坏或损坏”的错误。

至于时间戳的含义,在实际捕获中,它表示数据包被捕获代码路径的任何部分看到的时间,这与数据包到达捕获它的机器的时间近似。这是一个UN*X时间戳,所以tv_sec是从1970年1月1日到世界协调时00:00的秒数,而tv_usec是从那一秒开始的微秒数。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33522705

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档