是否可以从缓冲区解析 pcap 数据包
Is it possible to parse pcap packets from buffer
我有一堆用 lzma 压缩的巨大 pcap 文件(> 10GB)。我需要在我的机器上解析它们,但我没有足够的 space 来先解压缩它们。有许多库可以从文件中流式传输 lzma。问题出在 libpcap 方面,我读过它 API 好几遍,但找不到任何解析缓冲区的方法。我在库的源代码中看到的是它首先 reads the magic byte and file header 和 fread
:
amt_read = fread((char *)&magic, 1, sizeof(magic), fp);
...
amt_read = fread(((char *)&hdr) + sizeof hdr.magic, 1, sizeof(hdr) - sizeof(hdr.magic), fp);
然后pcap_next_packet
也用fread
to read next packet from file. So it looks like it's hard to pass a buffer from lzma stream to it. On the other hand, these functions are stored in pcap_t structure as pointers。所以我可以为它实现我自己的程序,但是,这样我将不得不从 libpcap 中复制大量代码。有谁知道如何在不侵入 libpcap 的情况下做到这一点?
我是不是在 libpcap 中遗漏了什么 API?
更新: 在@Martin 和其他人的帮助下,我设法使它工作。我将 post 实现,因此寻找实现方法的人可以使用它。
if (check_file_exists("/path/to/file.pcap.xz")) {
return;
}
// first open a pipe
FILE *pipe = popen("xz -d -c /path/to/file.pcap.xz", "r");
if (!pipe) {
// handle error somehow
return;
}
char errbuff[256];
// note pcap_fopen_offline function that takes FILE* instead of name
pcap_t *pcap = pcap_fopen_offline(pipe, errbuff);
struct pcap_pkthdr *header;
uint8_t *data;
while (pcap_next_ex(pcap, &header, &data)) {
// handle packets
}
特别是对于大型 pcap 文件,最好不要先将整个文件读入内存。要正确处理缓冲区管理,您需要了解 pcap 格式以获得正确的长度等。
您可以使用 popen 进行流式传输,例如:
char* cmd = asprintf("/usr/bin/xz -d -c %s", filename);
FILE* fp = popen(cmd , "r");
free(cmd);
然后像未压缩一样从 fp 读取。您还可以为 open 创建一个包装函数,返回一个 FILE* 来确定是通过扩展将其通过各种解压缩器进行管道传输还是只执行普通的 fopen。
总的来说,我发现常规管道在可能的情况下比命名管道更可取,因为它可以节省 (a) 选择一个唯一的名称和 (b) 在所有错误情况下清理它们
或者只是手动解析 pcap,格式相当简单,IIRC 它只是一个 header 结构,然后每个数据包一个。
我有一堆用 lzma 压缩的巨大 pcap 文件(> 10GB)。我需要在我的机器上解析它们,但我没有足够的 space 来先解压缩它们。有许多库可以从文件中流式传输 lzma。问题出在 libpcap 方面,我读过它 API 好几遍,但找不到任何解析缓冲区的方法。我在库的源代码中看到的是它首先 reads the magic byte and file header 和 fread
:
amt_read = fread((char *)&magic, 1, sizeof(magic), fp);
...
amt_read = fread(((char *)&hdr) + sizeof hdr.magic, 1, sizeof(hdr) - sizeof(hdr.magic), fp);
然后pcap_next_packet
也用fread
to read next packet from file. So it looks like it's hard to pass a buffer from lzma stream to it. On the other hand, these functions are stored in pcap_t structure as pointers。所以我可以为它实现我自己的程序,但是,这样我将不得不从 libpcap 中复制大量代码。有谁知道如何在不侵入 libpcap 的情况下做到这一点?
我是不是在 libpcap 中遗漏了什么 API?
更新: 在@Martin 和其他人的帮助下,我设法使它工作。我将 post 实现,因此寻找实现方法的人可以使用它。
if (check_file_exists("/path/to/file.pcap.xz")) {
return;
}
// first open a pipe
FILE *pipe = popen("xz -d -c /path/to/file.pcap.xz", "r");
if (!pipe) {
// handle error somehow
return;
}
char errbuff[256];
// note pcap_fopen_offline function that takes FILE* instead of name
pcap_t *pcap = pcap_fopen_offline(pipe, errbuff);
struct pcap_pkthdr *header;
uint8_t *data;
while (pcap_next_ex(pcap, &header, &data)) {
// handle packets
}
特别是对于大型 pcap 文件,最好不要先将整个文件读入内存。要正确处理缓冲区管理,您需要了解 pcap 格式以获得正确的长度等。
您可以使用 popen 进行流式传输,例如:
char* cmd = asprintf("/usr/bin/xz -d -c %s", filename);
FILE* fp = popen(cmd , "r");
free(cmd);
然后像未压缩一样从 fp 读取。您还可以为 open 创建一个包装函数,返回一个 FILE* 来确定是通过扩展将其通过各种解压缩器进行管道传输还是只执行普通的 fopen。
总的来说,我发现常规管道在可能的情况下比命名管道更可取,因为它可以节省 (a) 选择一个唯一的名称和 (b) 在所有错误情况下清理它们
或者只是手动解析 pcap,格式相当简单,IIRC 它只是一个 header 结构,然后每个数据包一个。