APP下载

基于Wireshark开源代码移植的DDS通信应用数据解析实现

2019-10-14李江宝

指挥控制与仿真 2019年5期
关键词:数据包报文代码

李江宝

(江苏自动化研究所,江苏连云港 222061)

DDS(Data Distribution Service)是对象管理组织OMG发布的关于分布式实时系统中数据发布的规范,该规范标准化了分布式实时系统中数据发布、传递和接收的接口和行为,定义了以数据为中心的发布-订阅机制,提供了一个与平台无关的数据模型。DDS将分布式网络中传输的数据定义为主题(Topic),将数据的产生和接收对象分别定义为发布者(Publisher)和订阅者(Subscriber),从而构成数据的发布/订阅传输模型。各个节点在逻辑上无主从关系,点与点之间都是对等关系,通信方式可以是点对点、点对多、多对多等,在QoS的控制下建立连接,自动发现和配置网络参数[1]。RTPS(Real-Time Publish-Subscribe)协议是对DDS规范的实时发布-订阅协议规范,该规范确保使用一个供应商的DDS实现发布的某个主题的信息可供相同或不同供应商DDS实现的一个或多个订阅者使用。

基于可提供低延迟、高吞吐量、可控传输性能、数据为中心等优点,目前DDS已越来越多的应用于航空、国防、工业自动化等多个领域[2-4]。随着DDS在各行业中的应用越来越多,产品开发调试过程中需要辅助开发调试,测试工具。目前产品中使用较多的DDS中间件有RTI-DDS、OpenDDS等,这些中间件虽然提供了一些工具辅助进行调试诊断、排除故障等,但是购买费用较高,需要合适的工具进行定制。

以RTI-DDS为例,其软件套件中虽然提供了通信报文解析分析工具,但是只能基于结构化的IDL接口定义,对于序列化报文中的自定义数据结构无法进行解析,而实际项目使用中,需通信的信息结构数量较多,不可能逐一定义为IDL接口,更多的是使用序列化传输数据方式,在序列化传输的数据之下应用协议,由收发双方程序根据协议组织或解析。这种使用方式下由DDS供应商提供的工具就无法解析序列化数据中的应用协议结构;并且开发商提供的通信报文解析分析工具也不支持二次开发,无法将网络报文中的序列化应用数据传递出来,由开发人员分析其中的自定义数据是否符合协议。

应用数据协议报文解析工具对于开发调试以及软件接口测试是必需的,尤其是大系统中多个不同厂家生产的设备之间使用DDS通信时,为进行接口对接更需要一个合适的工具来辅助调试开发。RTPS协议虽然是基于TCP/IP的网络协议,但是为了支持规范要求的各项功能,实际网络传输的应用数据之前封装了不定长的复杂控制数据,无法采用传统的网络抓包分析方法来辅助调试分析报文内容。开发人员根据RTPS规范开发一套解析软件又不现实,而开源网络封包软件Wireshark支持对RTPS协议的封包解析,可以从中提取出相应的协议解析代码嵌入到应用数据协议解析工具中。

1 Wireshark工作原理分析

Wireshark是跨平台的开源网络封包分析软件,在GNU GPL通用许可证的保障范围内,使用者可以免费取得软件与源代码,并拥有针对其源代码修改及定制化的权利。其底层使用Winpcap/libpcap作为网络数据包捕获接口,可实时显示数据包的详细协议信息,并支持其他常用抓包软件的包数据文件导入和导出。其支持700多种协议的解析,几乎包含所有的公开网络协议,并可支持自定义协议解析器的扩展。Wireshark的系统结构如图1所示[5]。

网络数据包经由WinPcap/libpcap捕获之后,经抓包引擎Dumpcap传入接口模块Capture中,Capture模块将数据传入数据包分析引擎Epan解析或者传入Wiretap保存到磁盘中;GUI作为图形界面,处理所有用户的输入/输出;Core则负责将其他模块组织起来。

网络协议解析的核心代码在Epan(Enhanced Packet ANalyzer)模块,源码在epan目录下。其主要包括4个子模块[6]:

Protocol-Tree:保存数据包的协议信息。Wireshark的协议结构采用树形结构,解析协议报文时只需从根节点通过函数句柄依次调用各层解析函数即可;

Dissectors:在epan/dissector目录下的各种协议解析器。支持700多种协议解析,对于每种协议,解码器都能识别出协议字段(field),并显示出字段值(field value)。由于网络协议种类很多,为了使协议和协议间层次关系明显,对数据流里的各个层次的协议能够逐层处理,Wireshark采用了协议树的方式;

Dissector-Plugins:以插件形式实现的协议解析器,源码在plugins目录;

Display-Filters:显示过滤引擎,源码在epan/dfilter目录。

Wireshark的协议解析开发由内置型和插件型构成。插件型协议解析开发相对容易编写,因为它不需要知道系统的整个框架结构以及整个程序的详细流程,只需要根据接口的相关说明直接调用就可以。内置型的协议解析开发对比插件方式而言,需要了解Wireshark的组织架构、哪些协议解析本身是以内置型的方式开发的、源文件存放位置、程序编译和运行信息,需要十分熟悉整个Wireshark的开发。其在编写完解析器之后需要对整个工程进行编译,工作量较大。

虽然通过开发应用协议解析插件方式实现对应用协议数据的解析,但考虑到使用时需要安装整个Wireshark软件并且通过上述分析Wireshark的工作原理可知:其采用协议树逐层解析方式,各种协议解析器之间基本没有相互关联,可以比较方便的将所需协议解析代码从整体代码中剥离出来。所以可采用将RTPS协议解析代码剥离为独立模块嵌入协议解析软件中使用的方式来达到协议解析目的,远远小于开发Wireshark插件所需的工作量,而且还可以根据需要随时修改。

2 RTPS协议解析代码剥离研究

Wireshark源代码中实现对RTPS协议解析的代码是Epan/dissectors目录下的packet-rtps.h和packet-rtps.c两个文件。由于Wireshark的dissectors采用的是协议树逐层解析的方式,与其他网络协议解析器无关联,并且RTPS协议是在TCP/IP层上进行的封装,所以通过将RTPS协议解析代码从Wireshark剥离为独立的模块具备可行性。下面介绍如何将RTPS协议解析相关代码剥离形成独立于Wireshark的模块。

2.1 依赖关联库的处理

由于Wireshark中使用了glib库中的大量结构作为基础元素,特别是作为基础数据类型、链表、字符串等,所以首先需要完成对该库的处理。因为glib库是跨平台的基础库,支持Linux、Windows等多个平台[7],并且提供编译好的二进制库,所以可直接下载使用,不需要剥离移植等,只需要针对使用平台下载对应的头文件和库文件,使用时进行链接即可。

Wireshark使用了GTK/Qt来开发图形界面,因为仅需要实现网络数据报文的解析,不需要图形界面,所以与图形界面相关的代码等也不需要移植。但是源文件中跟界面显示相关的代码以及结构体中的相关字段需要进行去除处理。

Wireshark中的内存管理模块叫wmem,在epan/wmem目录下。该模块除使用了glib库之外,不依赖于其他模块,可以独立出来,所以可将其剥离并编译为一个库使用。

2.2 关联结构的处理

packet-rtps.h和packet-rtps.c两个代码文件包含的其他头文件虽然不多,但是代码中却使用了Wireshark的很多基础数据结构和辅助函数,所以要实现这两个代码文件的剥离独立,必须把其代码中使用的相关数据结构和辅助函数一起剥离独立出来,才能实现整个协议解析功能代码的完全独立。

代码中使用的基础数据结构主要有:frame-data,tvbuff-t、packet-info、proto-node等;

frame-data结构用于存储单个网络报文,虽然该结构中有较多成员,但基本都是基础数据类型或glib中的数据类型,所以代码剥离简单,不需特别处理。

packet-info 结构中除基础数据类型和glib数据类型外,还有一些其他外部数据结构字段,如struct epan-column-info *cinfo,struct wtap-pkthdr *phdr等,由于在RTPS协议解析中并不需要,所以将这些结构的字段直接去除。

proto-node为协议树节点,其中的field-info类型的字段在协议解析中并不需要,将其去除。

tvbuff-t结构是具体的网络数据,struct tvb-ops *ops字段也不需要,直接去除。

将以上主要的结构从Wireshark中剥离后,组合成一个协议解析模块的独立结构定义头文件public-defines.h,并包含到packet-rtps.h中。

2.3 关联辅助函数的处理

协议解析中使用的辅助函数主要是从报文中提取不同类型数据的函数和一些异常处理函数,主要有从报文中取不同类型数据的函数(其中N可以是8、16、32、64):

guintN tvb-get-guintN(tvbuff-t *tvb, const gint offset, const guint encoding);

guint32 tvb-get-ntohl(tvbuff-t *tvb, const gint offset);

guint16 tvb-get-ntohs(tvbuff-t *tvb, const gint offset);

以及检测报文长度的函数:

gint tvb-reported-length-remaining(const tvbuff-t *tvb, const gint offset);

由于检测报文长度函数中使用了异常处理,所以还需将异常处理的except.h和except.c两个文件一起进行移植剥离。这两个异常处理文件并未依赖其他文件,可以直接从代码中剥离。

将以上关联辅助函数从Wireshark中剥离组成单独的协议解析模块辅助函数头文件和源文件。

2.4 RTPS协议解析代码处理

由于RTPS协议解析代码已经从Wireshark中剥离,不需要协议树的注册等,所以将packet-rtps.c文件中的proto-register-rtps函数去除;

由于在数据结构packet-info中已经删除了cinfo字段,所以解析代码中所有与其相关的代码都需去掉。

packet-rtps.c文件中以proto-tree-和proto-item-开头的所有的函数调用也都可以删除。

最后对packet-rtps.c以及依赖代码文件中与剥离协议封装头无关的代码进行注释,去除对其他文件的依赖,最终实现协议解析代码从Wireshark中的剥离。

剥离出的代码主要包含packet-rtps.c、packet-rtps.h、wmem模块,以及定义基础结构的头文件public-defines.h和定义提取函数的tvbuf.h,tvbuf.c和定义异常处理函数的except.h,except.c。

为方便嵌入其他代码模块中,将整个RTPS协议解析代码封装为独立模块,仅通过如下几个函数接口进行调用:

模块初始化接口,进行协议解析模块的内存分配及初始化等,void rtps-init(void);

(1)

协议解析接口;gboolean dissect-rtps(tvbuff-t *tvb, packet-info *pinfo, proto-tree *tree, void *data);

(2)

应用层数据解析回调函数设置接口,其中回调函数定义如(4)所示。

void set-rtps-dissector(dissect-rtps-func-ptr ptr);

(3)

typedef int (*dissect-rtps-func-ptr)(const char *topic, const char *data, int len, int *param);

(4)

使用时按照接口(2)规定的格式将获取的RTPS网络数据包输入函数接口中就可以实现对RTPS协议的解析,剥离RTPS协议封装数据,最终应用层数据将被传入外部定义的应用数据处理回调函数中,输出的参数包括数据的主题号、应用数据、长度和自定义的用户参数,方便其他软件模块对应用数据的解析分析。

3 应用数据协议分析软件设计与实现

为验证RTPS协议解析代码剥离后的有效性,设计了一个简单的应用数据协议分析软件,嵌入剥离出的RTPS协议解析模块,实现对使用DDS通信的应用协议数据报文的解析,同时验证RTPS协议解析模块的有效性。

3.1 软件模块组成

软件包含3个模块,如图2所示,其中网络抓包模块负责从网络抓取数据包,采用Winpcap/libpcap的网络抓包库实现,主要负责打开网卡,并抓取网络通信数据包,送入后续处理模块;协议解析模块负责将网络数据预处理后,根据数据包的不同类型调用不同的解析模块进行协议的解析,上节中剥离出的RTPS协议解析功能代码模块将嵌入此模块中,进行RTPS协议的解析和协议封装头的去除;人机交互模块主要负责将抓取的数据包以及解析结果显示出来。下面重点介绍协议解析模块的处理流程。

图2 协议分析软件模块组成

3.2 协议解析模块处理流程

协议解析模块的处理流程如图3所示。从网络抓包模块中接收网络数据后,首先进行网络层协议解析,判断是否需进行IP组包。由于使用DDS通信时,发送方底层会将待发送的长RTPS协议数据报文或控制报文进行IP层拆包发送,然后由接收方底层组包后再进行解析。收包不全时无法解析出完整内容,所以需对网络层IP封装头部进行解析,判断是否需进行组包处理。

组包完后再经传输层协议解析判断后,再判断是否是RTPS协议包。对于是使用DDS通信的报文,则进行RTPS协议解析,去除协议封包数据后,由应用协议解析子模块进行应用协议数据的解析,最后将解析结果输出至下一个模块。为支持非DDS通信应用数据报文的解析,在判断报文是非RTPS协议报后,直接将数据送入应用协议解析子模块中进行判断解析处理。

图3 协议解析模块处理流程

3.3 RTPS协议解析验证

为进行协议解析验证,假设使用DDS通信的序列化数据报文传输的应用数据协议接口结构定义如CGRAM所示,发送信息主题号为TEST-TOPIC。使用两台计算机点对点互通方式验证,发送信息内容填充为发送方计算机日期和时间。

typedef struct tagCGRAM

{

unsigned short wTLen;

unsigned short wYear;

unsigned char ucMonth;

unsigned char ucDay;

unsigned char ucHour;

unsigned char ucMin;

unsigned char ucSec;

unsigned char ucMday;

char strName[100];

}CGRAM;

为做对比分析,同时使用Wireshark软件和应用数据协议分析软件进行抓包。选取一个完整DDS通信数据包,如图4所示为Wireshark软件中的数据包。Wireshark软件会自动识别DDS通信数据包并执行RTPS协议解析,去除协议封装之后的应用数据如图5所示。由于采用序列化传输方式,所以Wireshark软件无法解析传输的数据是什么结构,各字段的值是多少。在同步运行的应用数据协议分析软件中选择同一个报文进行应用层解析后,如图6所示给出了应用数据中各字段的值。可见解析软件中嵌入的RTPS协议解析模块成功剥离了RTPS协议封装数据,给出了完整的应用数据,而应用协议解析模块也成功对应用数据协议进行了解析,给出了各字段的值。

图4 Wireshark捕获的RTPS数据包

图5 Wireshark对RTPS数据包的解析

图6 协议分析软件对数据包的解析结果

4 结束语

本文针对使用DDS通信的应用程序进行调试、测试时应用数据无法解析的问题进行了分析,并在分析开源网络封包分析软件Wireshark工作原理的基础上,研究实现了剥离其RTPS协议解析代码的方法,最后将剥离出的协议解析代码嵌入到设计的应用协议分析软件中,验证实现了对使用DDS通信的应用协议数据的解析,为进行设备信息互通和接口测试提供了工具,对实现类似基于开源软件的功能代码移植有一定的参考意义。

猜你喜欢

数据包报文代码
基于J1939 协议多包报文的时序研究及应用
以太网QoS技术研究及实践
二维隐蔽时间信道构建的研究*
民用飞机飞行模拟机数据包试飞任务优化结合方法研究
浅析反驳类报文要点
一种基于FPGA的网络串口管理系统的设计
C#串口高效可靠的接收方案设计
神秘的代码
一周机构净增(减)仓股前20名
一行代码玩完19亿元卫星