龙空技术网

压缩的 pcap 数据包索引程序

码农世界 131

前言:

现在小伙伴们对“pcap时间戳”大约比较关怀,看官们都想要学习一些“pcap时间戳”的相关内容。那么小编也在网上收集了一些关于“pcap时间戳””的相关知识,希望兄弟们能喜欢,大家快快来了解一下吧!

序言

压缩 pcap 数据包索引程序 (cppip) 是一种工具,可以从压缩的 pcap 文件中极快地提取数据包。此工具适用于处理大型 pcap 文件的安全和网络人员。本文提供了该工具的完整讨论,分为两部分。第一部分面向最终用户,将详细解释如何构建和使用该工具。第二部分面向C程序员,涵盖了cppip的内部工作原理。

简介

Cppip 是一个命令行实用程序,旨在非常快速地从大型 pcap 文件中提取数据包,而无需解压缩整个文件。它依赖于使用免费提供的 bgzip 压缩的 pcap 文件,bgzip 是一种向后兼容的 gzip 实用程序,拥有特殊的添加剂——能够快速、廉价地动态解压缩文件的特定区域。如果您使用大型 pcap 文件并需要提取一个或多个数据包以进行后续检查,您会发现 cpip 非常有用。如您所见,准备 pcap 文件以与 cpip 一起使用是一个两步过程,即使用 bgzip 压缩 pcap 文件,然后使用 cpppp 对其进行索引。但在使用 cpppp 之前,您首先必须安装它。

安装

Cppip 与 GNU autoconf 脚本一起分发,旨在让您的生活更轻松。那些熟悉自动配置基架工具的人熟悉用于配置和构建此类软件包的命令序列“./configure && make”。然而,在 cppip 的情况下,核心依赖项之一 tabix 库不会在没有一些干预的情况下将自己整齐地安装在主机操作系统上。因为 tabix 维护者没有使用 GNU 强大的 autoconf 框架,所以在构建和安装 cpip 之前,你必须做一些准备工作。为此,请按照以下简单步骤操作:

下载 cppip:Cppip 住在 GitHub,可以在这里找到。下载并构建 tabixtools: 下载最新版本的 tabix 工具包(在撰写本文时为 0.2.6):[sb:~]$ curl -O 它包含bgzip实用程序以及libtabix.a,一个简单的静态C库,包含所有bgzip函数。要构建和使用 cppip,您需要两者(bgzip 将用于压缩您的 pcap 文件,并且您需要链接 cpip 工具的库)。解压缩和取消存档后,继续运行“./configure && make”来构建工具和库。不幸的是,tabix 维护者没有在他们的 Makefile 中包含安装目标,因此您不能只运行“make install”并将所有内容存放在您需要的地方。因此,建议您在$PATH的某个地方复制 bgzip,以便于使用(/usr/local/bin 或 /opt/local/bin 可能是不错的选择)。也是因为缺少安装目标,您必须执行以下两个步骤:告诉 cpipp 的配置脚本 libtabix.a 库所在的位置:这里有两个简单的选项:将libtabix.a复制到类似/usr/local/lib的东西,配置脚本可以在其中找到它:

[sb:tabix-0.2.6]$ sudo cp libtabix.a /usr/local/lib

或者,如果您没有 root 权限或不打算再次使用 libtabix.a,则可以将构建 libtabix.a 的完全限定路径(通常类似于“tabix-0.2.6”)传递给 cppip 的配置脚本。例如,如果您在 cpip 旁边的目录中构建了 tabixtools,如下所示:[sb:cppip]$ ls cppip tabix-0.2.6然后,您将调用类似以下内容的配置:[sb:cppip]$ ./configure LDFLAGS=-L/Users/mike/Code/cppip/tabix-0.2.6/通知配置 bgzf.h 的保存位置: 与上面大致相同,如果您打算再次使用 libtabix.a,您可以将其复制到 /usr/local/include 配置可以找到它的位置:[sb:tabix-0.2.6]$ sudo cp bgzf.h /usr/local/include否则,您可以传递另一个参数进行配置,以告诉它在哪里可以找到头文件:[sb:cppip]$ ./configure CPPFLAGS=-I/Users/mike/Code/cppip/tabix-0.2.6/使用添加的选项调用配置:您可以使用以下内容指示两组标志:[sb:cppip]$ ./configure CPPFLAGS=-I/Users/mike/Code/cppip/tabix-0.2.6/ LDFLAGS=-L/Users/mike/Code/cppip/tabix-0.2.6/构建 cppip:现在运行“制作”。

工具:CPPIP

您将使用 cpppp 的第一个正式版本 1.3。在深入了解一些示例之前,让我们首先探索一下使用该工具时可以指定的所有选项,为此,请使用 -h 开关调用 cppip:

[sb:cppip] $ ./src/cppip -hCompressed Pcap Packet Indexing Program(c) Cisco Systems 2013, IncMike Schiffman Fast compressed pcap indexing and extraction, made easysee  for complete documentationUsage: cppip [options] [file(s)...]Indexing: -i index_mode:index_level index.cppip pcap.gz			index a bgzip compressed pcap.gz file using `index_mode`			index.cppip will be created or overwritten and packets			will be indexed at every `index_level` mark.			invoke with -I for more information/help on indexing -I			print supported index/extract modes/format guidelines -v index.cppip		verify index file -d index.cppip		dump index fileExtracting: -e index_mode:n|n-m index.cppip pcap.gz new.pcap			extract using `index_mode` the nth packet or n-m packets			from pcap.gz into new.pcap			invoke with -I for more information/help on extracting -f			enable fuzzy matching (timestamp extraction only)General Options: -D			enable debug messages -V			program version -h			this message

让我们谈谈一些主要选项:

-i (索引)通常,这是第一步 — 您将为每个 pcap 创建一个索引文件.gz-e (摘录)当您要从 pcap 中提取一个或多个数据包时,使用此模式.gz-I (打印模式)此选项显示支持的索引模式-v (验证)此选项用于验证索引文件是否已正确生成、检查其版本以及查看它有多少条记录-d (转储)此选项转储整个索引文件-f(模糊匹配)此选项允许在时间戳模式下提取时进行模糊匹配(稍后会详细介绍)-D (调试)启用调试消息

压缩 pcap

首先要做的事。我们需要使用 bgzip 压缩您的 pcap 文件。 在以下示例中,为了获取有关 pcap 文件(压缩或非压缩)内内容的信息,我们将使用 Wireshark 的 capinfos 工具。对于以下所有示例,我们将使用包含超过 7.5M 数据包的 5GB pcap 文件:

[sb:cppip]$ ls -l *.pcap-rw-r--r--   1 mike  staff  2000000101 Apr 19 20:43 pktdump.pcap[sb:cppip]$ capinfos -cuae pktdump.pcap.gzFile name:           pktdump.pcap.gzNumber of packets:   7552072Capture duration:    411 secondsStart time:          Fri Apr 19 16:56:44 2013End time:            Fri Apr 19 17:03:35 2013

作为参考,您会注意到 pcap 使用普通的旧 gzip 压缩到大约 892M:

[sb:cppip]$ ls -l *.pcap*-rw-r--r--   1 mike  staff  838087510 Apr 19 20:43 pktdump.pcap.gz

使用 bgzip 压缩文件会带来一些开销,在我们的例子中,在 7M 时只有大约 838%:

[sb:cppip]$ bgzip pktdump.pcap[sb:cppip]$ ls -l *.pcap*-rw-r--r--   1 mike  staff  892089319 Apr 19 20:43 pktdump.pcap.gz

数据包索引 压缩文件

后,需要使用 cpppp 对其进行索引。编制索引时,cppip 将创建一个配套文件,其中包含 pcap.gz 中数据包的 bgzip 偏移量。换句话说,索引文件将保存位于压缩 pcap 中的数据包的地址。这些地址随后将用于稍后快速提取数据包。

目前,cppip 支持两种索引模式:数据包编号时间戳。数据包编号模式通过数据包在 pcap 文件中的序号位置对数据包进行索引,而时间戳模式则通过数据包的 pcap 标头时间戳为数据包编制索引。决定使用哪种模式来构建索引将与您期望如何提取数据包有关。我们将在接下来的几节中了解有关两者的更多信息。

确定索引模式后,需要选择索引级别。这是一个值,指示 cppip 将存储地址的数据包数。在理想情况下,您可以选择尽可能小的索引级别,并在某些情况下存储每个数据包的地址,并具有近乎即时的查找。这也会导致索引文件非常大。实际上,索引级别将是一个较大的值,可在索引文件大小和查找速度之间提供良好的平衡。要查看 cpip 期望如何指定索引级别,请使用 -I 选项调用 cppip:

[sb:cppip] $ ./src/cppip -Ipkt-num:		index_level should be a single integer from:			1 - (total number of packets - 1)			To index every 1000 packets:	-i pkt-num:1000timestamp:		index_level should be a number indicating the index			followed by a time range specifier which can be one of			following:			d - days			h - hours			m - minutes			s - seconds			To index every 100 seconds:	-i timestamp:100s

通过数据包编号进行数据包索引 选择数据包编号

索引级别时,需要考虑 pcap 中的数据包数量.gz并确定哪个更重要:磁盘空间或执行速度。较小的索引级别转换为更多的数据包被索引,并导致更大的索引文件。对于具有大量数据包的 pcap 文件,这将导致一个非常大的索引文件。这样做的好处是寻道时间越快,因为索引越细,平均而言,cppip 就越接近您的目标提取(我们很快就会看到这一点)。如果您选择尽可能小的索引级别 1,则告诉 cppip “请将每个数据包的地址存储在我的索引文件中”,它将尽职尽责地为 pcap 中的每个数据包写入索引记录。这将导致尽可能大的索引文件和尽可能快的提取,因为 cpip 将知道每个数据包的地址,并可以直接查找包含所需数据包的 BGZF 偏移量的索引记录。在实践中,您可能希望选择在索引文件大小方面提供平衡的东西。

在以下示例中,我们将使用合理的索引级别 1,000 为 pcap.gz 文件编制索引,这将生成 120K 的索引文件:

[sb:cppip]$ ./src/cppip -i pkt-num:1000 index-pn-1000.cppip pktdump.pcap.gzindexing pktdump.pcap.gz...wrote 7552072 records to index-pn-01.cppip[sb:cppip]$ ls -l index-pn-1000.cppip-rw-r--r--  1 mike  staff  120876 Apr 15 12:03 index-pn-1000.cppip

通过数据包编号

提取数据包 现在您已经构建了索引文件,您实际上可以完成一些工作了!假设您迫切需要来自该 pcap.gz 内部的数据包 3,480,123 到 4,080,012。下面的信息图描述了这个典型的工作流方案:

Cppip 在索引文件中查询:使用指定的数据包范围,cppip 在索引文件内部查找起始数据包的最近 BGZF 偏移量。如果 cpppip 足够幸运地直接登陆数据包索引,它将知道您想要的数据包范围在 pcap.gz 中开始的确切地址。如果没有,就像上面的情况一样,它将尽可能接近。这是有效的,因为数据包以顺序、单调递增的方式存储。因此,cppip 知道数据包编号 3,473,920 是它知道所需起始数据包 3,480,123 的地址的最接近的前置邻居。Cppip 索引直接到 pcap.gz:使用从索引文件查询中获得的 BGZF 偏移量,cpip 将直接在 pcap 中查找该地址.gz并进行线性搜索以查找所需的起始数据包。Cppip 将数据包写入 new.pcap:找到起始数据包后,cppip 将复制原始的 24 字节 pcap 文件头,然后将指定范围内的每个数据包写入 new.pcap。

让我们看看这在命令行上是什么样子的,这样你就知道这需要多长时间,让我们计时:

[sb:cppip] $ time ./src/cppip -e pkt-num:3480123-4080012 index-pn-1000.cppip pktdump.pcap.gz new.pcapwrote 599890 packets to new.pcap        1.42 real         0.56 user         0.84 sys

甜。在我公认的速度很快的MacBook Pro上使用每7,552个数据包记录的数据包编号索引文件,cppip花了不到一秒半的时间来定位,读取和写入近600,000个数据包。为了更好地衡量,让我们检查一下cppip的工作:

[sb:cppip] $ capinfos -c new.pcapFile name:           new.pcapNumber of packets:   599890

看起来不错!使用数据包编号索引,cppip 可以从压缩的 pcap 文件中提取单个数据包或一系列数据包。接下来,我们将继续介绍 cpipp 的时间戳索引和提取功能。

通过时间戳进行数据包索引 时间戳

索引根据数据包在 pcap 文件中的捕获时间戳对数据包进行索引。Cppip 将根据数据包到达 pcap.gz 文件的时间而不是它们在文件中的相对位置来对数据包进行密钥。虽然数据包时间戳几乎总是会增加,但我们不能依赖它们单调地这样做。选择时间戳索引级别时,需要了解捕获文件的持续时间。

目前,从版本 1.3 开始,可以为时间戳索引级别选择的最小值为 1 秒。让我们看一下基于时间戳的索引和提取的标准工作流程:

由于我们知道 pcap.gz 文件跨越相对较短的 411 秒时间范围,让我们使用 1 秒的最小索引级别创建一个索引文件,这将产生一个包含 411 条记录的微小索引文件:

[sb:cppip]$ ./src/cppip -i timestamp:1s index-ts-1s.cppip pktdump.pcap.gzindexing ../pktdump.pcap.gz...wrote 411 records to index-ts-1s.cppip[sb:cppip]$ ls -l index-ts-1s.cppip-rw-r--r--  1 mike  staff  9920 Apr 20 16:21 index-ts-1s.cppip

通过时间戳提取数据包

虽然无法为数据包索引指定微秒分辨率,但可以选择提取。您可以指定带或不带微秒的时间戳:

以微秒为单位:YYYY-MM-DD:HH:MM:SS.uuuuuu无微秒: YYYY-MM-DD:HH:MM:SS

让我们来看看另一个典型的 cppip 用例。在这种情况下,您的坚定的思科 IPS 已通知您当地时间下午 5:00 发生了一次闯入尝试。内部取证团队需要从下午 4:59 到下午 5:02 的所有网络流量。由于您之前已设置了一个 bgzip 压缩和索引所有外围 pcap 文件的自动化过程,因此您已准备好处理此请求。让我们抓取事件发生前一分钟和事件发生后两分钟的所有数据包:

此操作的命令行如下所示:

[sb:cppip] $ ./src/cppip -e timestamp:2012-10-07:16:59:00-2012-10-07:17:02:00 index-ts:1s pktdump_20121008000335.pcap.gz new2.pcapextracting from pktdump.pcap.gz using index-ts:1s...extract(): 2013-04-19 16:59:00.000000 not found, closest is 2013-04-19 16:59:00.000102 (try -f)wrote 0 packets to new2.pcap.

这里发生了什么?显然,我们没有为 cpppp 指定一个特定的足够时间戳来匹配相应的起始数据包。要解决此问题,您有两种选择:

指定特定时间戳:Cppip 很好心地告诉您与您的请求最接近的匹配时间戳,因此您可以使用该时间戳。但是,您可能会遇到关闭时间戳的相同问题(但是,这是捕获从开始时间戳到pcap.gz结束的所有数据包的有用方法)。使用模糊匹配:有了这个方便的选项,cppip 将查找指定的时间戳,但如果找不到它,cpip 将在最接近命令行指定的时间戳上开始和停止匹配。让我们试试看。

[sb:cppip] $ ./src/cppip -f -e timestamp:2012-10-07:16:59:00-2012-10-07:17:02:00 index-ts:1s pktdump_20121008000335.pcap.gz new2.pcapextracting from pktdump_20121008000335.pcap.gz using index-ts:1s...start ts: 2012-10-07 16:59:00.000000 not found, instead fuzzy matched on 2012-10-07 16:59:00.000102stop ts: 2012-10-07 17:02:00.000000 not found, instead fuzzy matched on 2012-10-07 17:02:00.000046wrote 3461342 packets to new2.pcap.

棒!您已经拿到了数据包,是时候进行一些取证分析了。

最后,让我们探讨一下 cppip 的一些诊断功能。

数据包验证和索引转储

Cppip 提供了一些诊断功能,让您有机会查看索引文件以确保其有效性并浏览其内容。第一个是验证索引文件并显示其一些元数据的简单命令:

[sb:cppip] mike% ./src/cppip -v index-pn-1000.cppip valid cppip index fileversion:	1.3created:	2013-04-19 20:03:17.463926packets in pcap:7552072indexing mode:	packet-numberindex level:	1000record count:	7552

我们看到我们的索引文件几乎符合预期。这里的一个要点是确保您使用的索引文件的版本与 cpppp 的版本一致。我可以保证我会尝试使未来的版本向后兼容,但与所有事情一样,您的里程可能会有所不同。

cppip 公开的另一个漂亮的诊断功能是转储索引文件内容的选项。如果您想查看数据包在 pcap 中的物理布局方式,这将非常有用.gz:

[sjc-vpn5-288:~/Code/cppip/cppip] mike% ./src/cppip -d index-pn-1000.cppip |& morevalid cppip index fileversion:        1.3created:        2013-04-19 20:03:17.463926packets in pcap:7552072indexing mode:  packet-numberindex level:    1000record count:   7552pkt num:1000offset: 153b9d4c5pkt num:2000offset: 30e3bae9fpkt num:3000offset: 4dadb7482pkt num:4000...

用户手册到此结束,所以让我们继续看看cppip是如何做到的。

正如我过去所做的那样,在我发布代码的所有技术博客中,我喜欢选择一些关键的代码块并讨论它。那么cppip是如何做到的呢?让我们来了解一下!我们将深入了解索引文件头、索引记录和一些用于提取索引的函数。

数据包编号索引记录 由于我们将探索数据包编号模式的索引和提取过程,因此我们最好先查看数据包编号索引记录

。如您所料,这是一个非常简单的结构。它有一个无符号的 32 位计数器用于数据包编号,并在 pcap 中有一个 64 位地址.gz:

/*  * Packet Number Index Record: * *  0                   1                   2                   3 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |                        Packet Number                          | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |              Virtual BGZF Virtual Record Locator              | * |                                                               | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */struct cppip_record_pn{    uint32_t pkt_num;           /** the packet number */    uint64_t bgzf_offset;       /** its offset into bgzf file */};typedef struct cppip_record_pn cppip_record_pn_t;#define CPPIP_REC_PN_SIZ sizeof(struct cppip_record_pn)

数据包编号索引 下一个块是用于构建索引

文件的主事件循环。你会注意到 cpipp 做的第一件事是获取文件指针的当前地址到 pcap.gz。未显示的是已经读取并写出 pcap 文件头的代码块,因此对于循环的第一次迭代,对 bgzf_tell() 的调用将反映 cppip 已经读取这些字节的事实。在读取数据包并确保它没有遇到错误或文件末尾后,cppip 会检查它是否在 pcap 中获得了第一个数据包,或者(通过模运算符)一个是索引级别的倍数。如果任一状态为 true,cppip 将写入数据包编号、偏移量到索引文件,并增加几个计数器。如果启用了调试,您将收到一条很好的消息,通知您刚刚发生的事情。下一个块只是跳过数据包的内容——cppip 在索引时不关心它们。此过程将重复,直到遇到错误或 cpip 到达 pcap.gz 的末尾。

    for (rec_cnt = 0, pkt_cnt = 1, done = 0; !done; pkt_cnt++)    {        /** ...[pcap packet header][packet]...          *     ^          * bgzf fp is pointing here, the BGZF offset to this         * packet.. This is         * the offset we will record in our index         */        offset = bgzf_tell(c->pcap);        switch (bgzf_read(c->pcap, buf, PCAP_PKTH_SIZ))        {            case -1:                snprintf(c->errbuf, BUFSIZ, "bgzf_read() error\n");                return (-1);            case 0:                /* all done */                done = 1;                break;            default:                pcap_h = (pcap_offline_pkthdr_t *)buf;                /** write first packet then write as per index_level */                if (pkt_cnt == 1 || pkt_cnt % c->index_level.num == 0)                {                    cppip_rec.pkt_num     = pkt_cnt;                    cppip_rec.bgzf_offset = offset;                    if (write(c->index, &cppip_rec, CPPIP_REC_PN_SIZ) == -1)                    {                        snprintf(c->errbuf, BUFSIZ, "write(): %s",                                 strerror(errno));                        return (-1);                    }                    rec_cnt++;                    if (c->flags & CPPIP_CTRL_DEBUG)                    {                        fprintf(stderr, "DBG: add> [%d]: %d @ %llx\n",                                rec_cnt, pkt_cnt, offset);                    }                }                /**                 * we don't care about the contents -- we skip past the                 * packet                 */                if (bgzf_skip(c->pcap, pcap_h->caplen) == -1)                {                    snprintf(c->errbuf, BUFSIZ, "bgzf_skip() error\n");                    return (-1);                }        }    }

数据包编号提取 提取

逻辑负责获取数据包。

让我们看看它是如何工作的。

首先,cppip 希望确保您没有在命令行上搞砸,并指定一个超过 pcap.gz 中数据包总数的停止数据包。如果您的输入通过了该测试,cppip 将自行设置为查找起始数据包。

如果起始数据包小于索引级别,cppip 将从第一个数据包发出线性搜索,直到到达指定的起始数据包。如果起始数据包大于索引级别,cppip 会将第一个数据包除以索引级别以获得最接近的索引记录,然后 lseek() 到索引文件中的该位置。

接下来,cppip 读取该记录,在 pcap.gz 中寻找适当的位置,然后再次执行线性搜索,直到找到起始数据包。然后,Cppip 下降到提取循环中,读取 pcap 标头以获取数据包捕获长度,然后读取数据包本身。然后,它将 pcap 标头和数据包复制到内存缓冲区,并将该缓冲区写入新的 pcap 文件。Cppip 继续此过程,直到它命中停止数据包或遇到错误。

    /** sanity check only checks stop, we verified earlier stop > start */    if (c->e_pkts.pkt_stop  > c->cppip_h.pkt_cnt)    {        snprintf(c->errbuf, BUFSIZ,             "extraction would exceed packet count, %d and/or %d > %d\n",             c->e_pkts.pkt_start, c->e_pkts.pkt_stop, c->cppip_h.pkt_cnt);        return (-1);    }    /**     * We need to locate the offset of pkt_start and then we can     * extract in a linear fashion until we hit pkt_last.     *     * If the indexing is too coarse the pkt_start will lie before the     * first index. If this is the case we have to do a linear search from     * the very first packet until we find pkt_first...     */    if (c->e_pkts.pkt_start < c->cppip_index_pn_hdr.index_level)    {        if (linear_search(c, 1, c->e_pkts.pkt_start) == -1)        {            return (-1);        }    }    /** seek to index, obtain closest offset, linear search from there */    else    {        /**         * pkt_start / index_level will give us the closest index record to our         * starting packet. We lseek to 1 before this location so we don't         * step past the record we need.         */        if (lseek(c->index,             (((c->e_pkts.pkt_start / c->cppip_index_pn_hdr.index_level) - 1)            * CPPIP_REC_PN_SIZ) + CPPIP_FH_SIZ + CPPIP_INDEX_PN_H_SIZ,             SEEK_SET) == -1)        {            snprintf(c->errbuf, BUFSIZ, "lseek() error: %s\n", strerror(errno));            return (-1);        }        if (read(c->index, (cppip_record_pn_t *)&rec, CPPIP_REC_PN_SIZ)             != CPPIP_REC_PN_SIZ)        {            snprintf(c->errbuf, BUFSIZ, "read() error: %s\n", strerror(errno));            return (-1);        }        if (bgzf_seek(c->pcap, rec.bgzf_offset, SEEK_SET) == -1)        {            snprintf(c->errbuf, BUFSIZ, "bgzf_seek() error.\n");            return (-1);        }        if (linear_search(c, rec.pkt_num, c->e_pkts.pkt_start) == -1)        {            return (-1);        }    }    /** we've got pkt_first, do extraction until we hit pkt_last */    for (c->e_pkts.pkts_w = 0, i = c->e_pkts.pkt_start;             i < (c->e_pkts.pkt_stop + 1); i++, c->e_pkts.pkts_w++)    {        if (bgzf_read(c->pcap, (pcap_offline_pkthdr_t *)&pcap_h, PCAP_PKTH_SIZ)            != PCAP_PKTH_SIZ)        {            snprintf(c->errbuf, BUFSIZ,                 "bgzf_read() error: cant read pcap hdr\n");            return (-1);        }        pkt_caplen = pcap_h.caplen;        if (bgzf_read(c->pcap, buf, pkt_caplen) != pkt_caplen)        {            snprintf(c->errbuf, BUFSIZ,                 "bgzf_read() error: can't read packet\n");            return (-1);        }        memcpy(&buf2, &pcap_h, PCAP_PKTH_SIZ);        memcpy(&buf2[PCAP_PKTH_SIZ], &buf, pkt_caplen);        if (write(c->pcap_new, buf2, PCAP_PKTH_SIZ + pkt_caplen) !=                 PCAP_PKTH_SIZ + pkt_caplen)        {            snprintf(c->errbuf, BUFSIZ, "write() error: %s\n", strerror(errno));            return (-1);        }    }    return (1);

结论与未来

在本文中,您了解了压缩 pcap 数据包索引和提取 (cpppip) 的最新热潮。我们探讨了如何安装和使用该工具,并偷看了它的一些内部结构。将来,我计划进行相当数量的代码清理和优化。我还计划在文件头中添加微秒级时间戳索引、字节序信息、创建 C 库,可能还有一些基于协议的新索引方法。一如既往,欢迎拉取请求。感谢您抽出宝贵时间,请随时发表评论!

地址:

标签: #pcap时间戳 #pcap解析c语言