Skip to content
Wireshark Wiki 中文翻译整理专题首页原始页面

WiretapPcapng

  • 介绍
  • 对 wiretap 内部机制的更改
  • 对 wiretap 公共读取端 API 的更改
  • 对 wiretap 写入端 API 的更改
  • 未决问题:

介绍

为了完整支持 pcapng 格式,我计划对 wiretap API(即 libwiretap)做出重大更改。总体模型是让 wiretap 在内部维护的数据结构方面更像 pcapng 文件格式,并在外部 API 上表现得更像 pcapng 文件格式。

这样做的理由是,我认为 pcapng 本质上是我们支持的所有文件格式的超集;如果某种文件格式支持 pcapng 不支持的内容,我也有相应计划。(后面讨论)

目前,wiretap 存在以下问题:

  • 每个文件只支持单个 SHB section
  • 不会报告在文件中间读取到的非数据包信息,例如新的 IDB、NRB 等
  • 除了打开 dump 文件时之外,不提供向 dump 文件写入非数据包信息的方法
  • 不提供将专有或未知数据从输入文件复制到输出文件的方法

上述问题会给我们的各种程序/工具带来麻烦。例如,如果 pcapng 文件中间出现 IDB,tshark 就无法保存该文件,即使在 2-pass 模式下也是如此。另一个例子是,如果中间出现 IDB,capinfos 和 mergecap 会出错。

为了处理这些类型的问题,我计划执行本页概述的更改。

对 wiretap 内部机制的更改

  1. 更改内部 wtap 结构,使其紧密遵循 pcapng 文件格式模型。例如,进行以下更改:
  • 将 SHB 信息改为数组
  • 将 IDB 移到每个 SHB 内部,并赋予它们 shb_id
  • 将 NRB 信息改为数组(我也想把它移到 SHB 内部,但还不确定)
  • 为“未知块”添加一个数组,可能也放在 SHB 内部

“未知块”将是一个由我们不了解的 pcapng block type 组成的数组。(详见后文)

  1. 以与 wtap 结构相同的方式更改内部 wtap_dumper 结构,但还包括以下内容:
  • 添加一个 last_recorded_shb_id 整数成员,用于标识到目前为止已写入文件的最高索引 SHB
  1. 更改 wtap_pkthdr,使其更接近 EPB 模型,并进行以下更改:
  • 将 comments 改为数组
  • 添加未知 pcapng options 的数组
  • 添加 shb_id,用于标识该数据包的 interface_id 所在的 SHB(以及数据包本身)

“未知 pcapng options”将是一个由我们不了解且没有离散成员表示的选项组成的数组;每个选项条目都按照 pcapng 规范进行结构化和格式化。换句话说,它将保存数据包除 comments、drop count 和 flags 之外的任何 option。

  1. 对于没有 pcapng 等价物的记录类型,例如某些新文件格式中包含 pcapng 没有的某种记录类型,它会返回 pcapng record_type 0x40000BAD,即 pcapng 中表示具有 do-not-copy 行为的 Custom Block 的 block type;并且它会使用自己的 PEN number。我们也可以提供一种使用 Wireshark PEN number 的方法,但必须仔细考虑其内部结构。

数据包“options”也类似——如果文件格式有一些它想公开的每包信息,可以将其添加到“未知 pcapng options”数组中,使用 option type 0x4BAD,即 pcapng 中表示具有 do-not-copy 行为的 Custom Option 的 option type;并且它会使用自己的 PEN number。

对于 pcapng 文件中 wiretap 并不明确了解的 block/option type,它只会使用该 block/option 在 pcapng 文件中使用的相同代码编号。

对 wiretap 公共读取端 API 的更改

  1. 创建一个新的 wtap_read_record() 公共函数,用于从文件中读取下一个“record”。返回的信息(如果成功)将是 record_type 和一个指向基于该 record_type 的结构体的 void pointer。record_type 编号将是 wiretap/wtap.h 中的 REC_TYPE_ 值。如果某种记录类型对多种文件格式都有意义,因而可以被定义为:特定文件格式中的记录能够无损映射到一个公共结构,并且该结构可以在所有这些格式中写出(可能会丢失该文件格式不支持的信息),则应分配一个新的 REC_TYPE_;否则,应使用 REC_TYPE_FT_SPECIFIC_EVENT 或 REC_TYPE_FT_SPECIFIC_REPORT(适用于所有文件格式,包括 pcapng)。

如果 record_type 表示一个数据包,例如 pcapng 中的 EPB、SPB 或 PB,则会使用 REC_TYPE_PACKET,并且 wtap_read_record() 会像以前一样设置 phdr 信息(加上前面提到的更改),读者会将其作为传回的“record”使用,而不是使用 void pointer。

如果记录类型表示 SHB,或者如果任何其他文件格式有 pcapng 风格的 section 概念(据我所知没有),即类似 SHB 的记录,则会使用 REC_TYPE_SECTION_HEADER(我们会添加到 wiretap 的新类型),并且返回的结构将是当前的 wtapng_section_t。对于没有 pcapng 风格 section 概念、因而没有类似 SHB 记录的文件格式,将合成一个 REC_TYPE_SECTION_HEADER,并将其作为第一条记录提供。

如果记录描述一个或多个接口,例如 pcapng 中的 IDB,或 Microsoft Network Monitor 文件中的 “Netmon Network Info Ex” “packet”,则会使用 REC_TYPE_INTERFACE_DESCRIPTIONS(我们会添加到 wiretap 的新类型),并且使用接口数量,后面跟一个 wtapng_if_descr_t 结构的数组(“Netmon Network Info Ex” 包含捕获中所有接口的列表,而不只是单个接口;这样我们就可以让该记录在 NetMon 文件的数据包列表中显示为单条记录,从而使 Wireshark 读取时的 NetMon 数据包编号与 NetMon 读取时保持一致——我认为有一个关于此问题的 bug)。

如果记录包含接口统计信息,例如 pcapng 中的 ISB,则会使用 REC_TYPE_INTERFACE_STATISTICS(我们会添加到 wiretap 的新类型),并返回一个 wtapng_if_stats_t 结构。如果某种文件格式在一条记录中提供多个接口的信息,我们可以提供多条这样的记录,也可以像 REC_TYPE_INTERFACE_DESCRIPTIONS 那样提供一条包含多个统计信息的记录。

如果记录包含名称解析信息,则会使用 REC_TYPE_NAME_RESOLUTION(我们会添加到 wiretap 的新类型),并返回一个 wtapng_name_res_t 结构。

对于其他记录类型,如果我们认为它们对多种文件类型有用,就定义新的 REC_TYPE_ 值;否则就只对它们使用 REC_TYPE_FT_SPECIFIC_EVENT 或 REC_TYPE_FT_SPECIFIC_REPORT。

wtap_read_record() 函数还会按需将传回的 block struct 添加到内部 wtap 结构中。例如,对于 REC_TYPE_INTERFACE_DESCRIPTIONS,新的 IDB 或多个 IDB 会在内部自动追加到最近 SHB 的 IDB 数组中。这在向 dump 文件写入内容时会产生影响,如后文所述。

  1. 创建一个新的 wtap_seek_read_record(),其模型与(3)类似,但它永远不会把 block 添加到 wtap 的内部结构中。这里的前提是假设此前已经调用过 wtap_read_record(),因此已经把 block 添加到了 wtap 中。

  2. 更改当前的 wtap_read() 公共函数,使其在内部调用这个 wtap_read_record(),并持续调用直到遇到 REC_TYPE_PACKET。(即,对于 wtap_read() 的用户来说,相比之前的行为不会有重大变化)当前的 wtap_seek_read() 将只用于访问 packet record,不需要更改。

  3. 更改 wtap_open_offline(),使其不要为 legacy PCAP 文件读取器生成假的 IDB——让 PCAP 文件读取器以及所有其他文件中没有 interface description record 的格式读取器,合成一个 REC_TYPE_INTERFACE_DESCRIPTIONS record,并在合成的 REC_TYPE_SECTION_HEADER 之后提供它,前提是它们在文件头中有足够信息可这样做。对于 iptrace,由于每个数据包都有关联的 interface name,其读取器会跟踪接口名称,并在每次看到尚未见过的接口名称时合成一个 REC_TYPE_INTERFACE_DESCRIPTIONS;其他一些文件格式也可能做类似处理。

  4. 更改 wtap_file_encap(),使其对文件中的初始 IDB 执行 peek 并返回 encap;如果没有 IDB,则可能为 WTAP_ENCAP_UNKNOWN;但不要查看整个文件——除非有一个 boolean 指示要查看整个文件。这里的“peek”是指让它读取文件中的 IDB,但不要将其保存到 wtap 中。

对 wiretap 写入端 API 的更改

  1. 更改 wtap_dump_open_ng()/wtap_dump_fdopen_ng() 例程,使其在打开文件时只写入第一个 SHB 以及当前与其关联的 IDB 的信息,但仍将所有传入的 SHB/IDB/NRB 的内部副本保存到 wtap_dumper 中。由于以后传入的每个 wtap_pkthdr 都会标识其各自的 SHB(和 IDB),因此可以按后文所述使用其他 SHB。

  2. 创建一个新的 wtap_dump_record() 公共函数,可用于写入任何 REC_TYPE_ 值,包括所有 packet type、新增类型,以及 REC_TYPE_FT_SPECIFIC_EVENT 和 REC_TYPE_FT_SPECIFIC_REPORT。如果传入的数据包记录属于一个已在内部 wtap_dumper 结构数组中但尚未写入文件(使用 last_recorded_shb_id 值判断)的 SHB,则它会在写入数据包之前将该 SHB+IDB 写入文件,同时写入该 SHB 的所有 IDB。(不确定 NRB 是否应该推迟到 close 时处理)

如果使用 REC_TYPE_SECTION_HEADER、REC_TYPE_INTERFACE_DESCRIPTIONS 等调用 wtap_dump_record(),则它会将它们写入文件,并保存到 wtap_dumper 结构中。

这样,应用程序就可以执行单遍读取和写入,例如 tshark/editcap/mergecap 所做的那样,其中新的 REC_TYPE_SECTION_HEADER、REC_TYPE_INTERFACE_DESCRIPTIONS 等会出现在读取+写入过程的中间。它还允许应用在任意位置+任意时间插入 block。

对于不能处理多个 SHB 的文件格式(我认为除了 pcapng 之外都是如此),如果使用新的 SHB record 调用 wtap_dump_record() 写入,或者某个数据包标识自己属于第一个 SHB 之外的 SHB,那么它们会在 dumping 期间失败。Mergecap 或 editcap 需要增强,以便能够将多个 SHB section 合并为一个。

  1. 让 wtap_dump() 在内部调用 wtap_dump_record(),但仅用于数据包。

未决问题:

  1. 我们是否应该从 wtap 中移除 add_new_ipv4/ipv6 callbacks,并让应用程序基于传回的 NRB block 执行该操作?

  2. 我们是否应该直接去掉 wtap_read()/wtap_seek_read()?

  • 是的,我们应该将 Wireshark 中的所有用法转换到新 API,然后删除旧 API。-guy
  1. 我们是否应该直接去掉 wtap_dump()?
  • 是的,我们应该将 Wireshark 中的所有用法转换到新 API,然后删除旧 API。-guy
  1. 我们是否应该添加一个 API,允许 dissectors(或 libwireshark)注册捕获文件特定的偏好设置(例如 decryption keys、desegmentation、name resolution、columns、decode as 等)?
  • 做这类事情的挑战在于,pcapng 文件需要永远可用/可读——既要能被未来版本的软件工具(如 wireshark)读取,也要能被旧版本的 wireshark 读取。所以,设想我们添加一个 pcapng block 或 option,用来指示给定 TCP 端口的 “decode as” protocol “foo”。从那以后,我们就不能再更改 “foo” 的 protocol name,否则会破坏 decode-as 设置。如果我们在未来的 wireshark 版本中添加某个 protocol “bar”,那么在那个未来 wireshark 中保存了 “decade-as bar” 设置的文件,就必须以某种方式在理解 “decode-as” 但不理解 “bar” 部分的旧版 wireshark 中处理。因此,我们必须让这些设置成为 wireshark 尝试应用的 best-effort 内容,同时围绕各种失败方式提供大量保护。-hadriel

  • 对于 decryption keys,是的,我原本设想我们会创建一个 Custom Block 来保存 session keys(不是 private keys)和 algorithm meta-data 内容,并在 EPB 中使用一个 custom option 指示该数据包使用哪个 Custom Block 加密。-hadriel

  • 关于初步想法,请参阅 Wireshark Custom Blocks/Options 的 strawman proposal。

Imported from https://wiki.wireshark.org/WiretapPcapng on 2020-08-11 23:27:37 UTC

相关 Wireshark Wiki 页面

网络分析技术档案