[关闭]
@natsumi 2015-02-25T14:49:58.000000Z 字数 3602 阅读 1563

【转】【翻译】Wireshark:添加一个基础的解析器(2)

Wireshark


版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://www.blogbus.com/shujiantang-logs/35858037.html
本文是Wireshark官方开发文档9.2节《添加一个基础的解析器》的翻译

9.2.2. 解析协议细节

现在我们已经有了一个可以运用的简单解析器,让我们再为它添点儿什么吧。首先想到的应该就是标示数据包的有效信息了。解析器在这方面给我们提供了支持。

首先要做的事情是创建一个子树以容纳我们的解析结果。这会使协议的细节显示得井井有条。现在解析器在两种情况下被调用:其一,用于获得数据包的概要信息;其二,用于获得数据包的详细信息。这两种情况可以通过树指针参数tree来进行区分。如果树指针为NULL,我们只需要提供概要信息;反之,我们就需要拆解协议完成细节的显示了。基于此,让我们来增强这个解析器吧。

例 9.4. 插入数据包解析.

  1. static void dissect_foo(tvbuff_t *tvb,packet_info *pinfo,proto_tree *tree)
  2. {
  3. if(check_col(pinfo->cinfo,COL_PROTOCOL))
  4. {
  5. col_set_str(pinfo->cinfo,COL_PROTOCOL,"FOO");
  6. }
  7. /* Clear out stuff in the info column */
  8. if(check_col(pinfo->cinfo,COL_INFO))
  9. {
  10. col_clear(pinfo->cinfo,COL_INFO);
  11. }
  12. if(tree)
  13. {
  14. /* we are being asked for details */
  15. proto_item *ti=NULL;
  16. ti=proto_tree_add_item(tree,proto_foo,tvb,0,-1,FALSE);
  17. }
  18. }

现在进入下一步,添加一些协议解析功能。在这一步我们需要构建一组帮助解析的表结构。这需要对proto_register_foo函数做些修改。首先定义一组静态数组。
例 9.5. 定义数据结构.

  1. static hf_register_info hf[]=
  2. {
  3. {
  4. &hf_foo_pdu_type,
  5. {"FOO PDU Type","foo.type",FT_UINT8,BASE_DEC,NULL, 0x0,NULL,HFILL}
  6. }
  7. };
  8. /* Setup protocol subtree array */
  9. static gint *ett[]=
  10. {
  11. &ett_foo
  12. };

接下来,在协议注册代码之后,我们对这些数组进行注册。
例 9.6. 注册数据结构.

  1. proto_register_field_array(proto_foo,hf,array_length(hf));
  2. proto_register_subtree_array(ett,array_length(ett));

变量hf_foo_pdu_typeett_foo依然需要在文件顶部的某处予以声明。
例 9.7. 解析器全局数据结构.

  1. static int hf_foo_pdu_type=-1;
  2. static gint ett_foo=-1;

现在我们就可以对协议细节的显示做一番改善了。
例 9.8. 解析器开始数据包解析.

  1. if(tree)
  2. {
  3. /* we are being asked for details */
  4. proto_item *ti=NULL;
  5. proto_tree *foo_tree=NULL;
  6. ti=proto_tree_add_item(tree,proto_foo,tvb,0,-1,FALSE);
  7. foo_tree=proto_item_add_subtree(ti,ett_foo);
  8. proto_tree_add_item(foo_tree,hf_foo_pdu_type,tvb,0,1,FALSE);
  9. }

协议的解析变得愈发有趣了。我们提取出协议的第一部分。数据包的首字节定义了foo协议的包类型。

  • hf_foo_pdu_type:节点索引。
  • FOO PDU Type:项标示。
  • foo.type:过滤字符串。我们可以在过滤框中输入诸如foo.type=1的结构。
  • FT_UNIT8:指定该项数据是一个8比特位的无符号整型。这和我们之前调用函数时设置的一字节有效数据是相一致的。
  • BASE_DEC:针对整型数据,指定将其作为十进制数显示。当然视具体情况也可以设置为“BASE_HEX”(十六进制)和“BASE_OCT”(八进制),以使数据更易辨识。
  • 至于结构中余下的部分我们暂且忽略。

如果您现在安装并试用这个插件,就会发现一些有用的东西了。

接下来让我们完成这个简单协议的解析工作吧。我们需要再添加一些hf数组成员和程序调用。
例 9.9. 完成数据包解析.

  1. //添加到文件开始的某个地方,作为全局变量
  2. static int hf_foo_flags=-1;
  3. static int hf_foo_sequenceno=-1;
  4. static int hf_foo_initialip=-1;
  5. //添加到“proto_register_foo”函数中的“hf”数组中,作为数组的成员
  6. {
  7. &hf_foo_flags,
  8. {"FOO PDU Flags","foo.flags",FT_UINT8,BASE_HEX,NULL,0x0,NULL,HFILL}
  9. },
  10. {
  11. &hf_foo_sequenceno,
  12. {"FOO PDU Sequence Number","foo.seqn",FT_UINT16,BASE_DEC,NULL,0x0,NULL,HFILL}
  13. },
  14. {
  15. &hf_foo_initialip,
  16. {"FOO PDU Initial IP","foo.initialip",FT_IPv4,BASE_NONE,NULL,0x0,NULL,HFILL}
  17. },
  18. //添加到“dissect_foo”函数中,实现数据包的解析
  19. gint offset=0;
  20. ti = proto_tree_add_item(tree,proto_foo,tvb,0,-1,FALSE);
  21. foo_tree=proto_item_add_subtree(ti,ett_foo);
  22. proto_tree_add_item(foo_tree,hf_foo_pdu_type,tvb,offset,1,FALSE);
  23. offset+=1;
  24. proto_tree_add_item(foo_tree,hf_foo_flags,tvb,offset,1,FALSE);
  25. offset+=1;
  26. proto_tree_add_item(foo_tree,hf_foo_sequenceno,tvb,offset,2,FALSE);
  27. offset+=2;
  28. proto_tree_add_item(foo_tree,hf_foo_initialip,tvb,offset,4,FALSE);
  29. offset+=4;
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注