Wireshark Build-in Dissector 注册逻辑

Wireshark代码比较繁杂,这里将其中内置Dissector部分逻辑抽离出来备忘。

搞个流程图占坑

Dissector

首先我们简单了解一下Dissector是什么。

Dissector在Wireshark中是指对协议的一个封装,每一种协议都被封装为一个或一组Dissector,而从字面意思上来说`dissect` 译为解剖、仔细研究、剖析,而dissector在当前场景下自然应翻译为解析器。Dissector是对将协议解析的一段代码逻辑的封装形式。协议解析的实现都是以实现对应协议的Dissector完成,因此我们可以猜测wireshark源码中拥有对所有协议Dissector的注册和管理代码,同时由于不同协议(不同层)之间有类似依赖的关系,因此wireshark还要根据这种关系来对某个网络数据包中一层协议所封装数据的协议进行猜测,例如UDP协议上的RTP协议等。

Dissector黑盒猜测

首先我们可以在这里对Dissector的代码进行一些猜测,首先既然其是对协议的描述,因此应该里面会装有对于协议字段的定义,然后应该有一个函数用来对字节流(某帧中该协议字节数据)进行处理,而后将处理后数据封装到某一个数据结构中供后续消费。而以wireshark角度就是UI上进行数据协议数据展示的部分:

这里我们就对Dissector有了两个猜测:

  • 存在对协议字段及其定义进行存储的数据结构
  • 存在某种数据结构将解析后数据以类似多叉树形式进行存储

但暂时我们从wireshark外部逻辑来说对单个协议就暂时做这两种比较能确定的猜测,实际Dissector所做的事情非常复杂,例如协议的重组、协议会话数据统计、多帧之间数据关联性等。

Dissector定义

首先我们以Wireshark官网上对Dissector的定义搬过来看看:

Wireshark Developer Guide

Each dissector decodes its part of the protocol and then hands off decoding to subsequent dissectors for an encapsulated protocol.
Every dissection starts with the Frame dissector which dissects the details of the capture file itself (e.g. timestamps). From there it passes the data on to the lowest-level data dissector, e.g. the Ethernet dissector for the Ethernet header. The payload is then passed on to the next dissector (e.g. IP) and so on. At each stage, details of the packet are decoded and displayed.
Dissectors can either be built-in to Wireshark or written as a self-registering plugin (a shared library or DLL). There is little difference in having your dissector as either a plugin or built-in. You have limited function access through the ABI exposed by functions declared as WS_DLL_PUBLIC.
The big benefit of writing a dissector as a plugin is that rebuilding a plugin is much faster than rebuilding wireshark after editing a built-in dissector. As such, starting with a plugin often makes initial development quicker, while the finished code may make more sense as a built-in dissector.

这里翻译过来是这样的:

每一个解析器将对属于自己协议的部分数据进行解码,然后将剩余任存在封装协议的包数据交割给后续的Dissector进行处理。

每一次Packet解析都从网络数据帧解析器(Frame Dissector)开始,Frame Dissector将捕获文件自身相关的信息进行解析(实际就是填充该帧的一些和帧数据内容无关的属性,例如从哪个网卡捕获的、数据链路层的封装类型、当前帧捕获时间距启动捕获时时间戳偏移量等)。而后其将数据交给最低层的数据解析器,例如解析以太网包头的以太网(Ethernet)解析器。而后其负载数据将交给下一个解析器,例如IP解析器(Internet Protocol),直到未解析数据没有与任何已知封装协议匹配。每一步执行都会让包数据的详情被解析并展示出来。

解析器可以分为两种类型,第一种是WireShark内置解析器,第二种为自己注册的插件(例如一个共享库或动态链接库)。这两种方式在你编写自己的解析器插件时有一点不同。当使用后者时,插件内仅能使用通过WS_DLL_PUBLIC暴露出来的ABI,因此对wireshark内部的访问受到限制。

将解析器以插件的形式编写时最大的优点是可以在重新构建插件代码时不需要将整个wireshark进行rebuild,因此测试速度会快很多。而将插件以内置形式编写时,每次对插件内部代码的改动都将使整个wireshark进行重新编译,降低开发测试速度。因此在解析器开发初期以插件形式开发将降低很多开发难度,而后在编写测试完成后以内置解析器的形式编译到wireshark内部是一种更加合理的方式。

到这里应该对Dissector有了一定的了解,Dissector内就封装了整个协议对与数据包解析所需要的所有功能,通过wireshark暴露出来的infrastructure API构建Dissector,并将Dissector注册到Wireshark内以便Wireshark调用。

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注