标签: Wireshark
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://www.blogbus.com/shujiantang-logs/35858316.html
本文是Wireshark官方开发文档9.2节《添加一个基础的解析器》的翻译
9.2.3. 改善解析信息
我们可以添加一些数据来改善协议的显示。第一步是添加一些文本标签。我们先来标示数据包类型。对于这类情况,添加一些额外的数据是有好处的。首先我们添加一个简单的类型名表。
例 9.10. 命名数据包类型.
static const value_string packettypenames[]=
{
{1,"Initialise"},
{2,"Terminate"},
{3,"Data"},
{0,NULL}
};
该数据结构可以方便地查询到值所对应的名称。有对其直接操作的函数,不过我们不需调用它们,因为这已经由相关的支持代码实现了。
我们仅需使用VALS
宏在数据的适当部分指定细节即可。
例 9.11. 为协议添加名称.
{
&hf_foo_pdu_type,
{"FOO PDU Type","foo.type",FT_UINT8,BASE_DEC,VALS(packettypenames),0x0,NULL,HFILL}
}
这有助于数据包的辨认,我们可以对标志结构做类似的处理。
不过实现这个还需向表中添加更多的数据。
例 9.12. 为协议添加标志.
//添加到文件头部
#define FOO_START_FLAG 0x01
#define FOO_END_FLAG 0x02
#define FOO_PRIORITY_FLAG 0x04
static int hf_foo_startflag=-1;
static int hf_foo_endflag=-1;
static int hf_foo_priorityflag=-1;
//添加到“proto_register_foo”函数中的“hf”数组中,作为数组的成员
{
&hf_foo_startflag,
{"FOO PDU Start Flags","foo.flags.start",FT_BOOLEAN,8,NULL,FOO_START_FLAG,NULL,HFILL}
},
{
&hf_foo_endflag,
{"FOO PDU End Flags","foo.flags.end",FT_BOOLEAN,8,NULL,FOO_END_FLAG,NULL,HFILL}
},
{
&hf_foo_priorityflag,
{"FOO PDU Priority Flags","foo.flags.priority",FT_BOOLEAN,8,NULL,FOO_PRIORITY_FLAG,NULL,HFILL}
},
//添加到“dissect_foo”函数中的合适位置
proto_tree_add_item(foo_tree,hf_foo_flags,tvb,offset,1,FALSE);
proto_tree_add_item(foo_tree,hf_foo_startflag,tvb,offset,1,FALSE);
proto_tree_add_item(foo_tree,hf_foo_endflag,tvb,offset,1,FALSE);
proto_tree_add_item(foo_tree,hf_foo_priorityflag,tvb,offset,1,FALSE);
offset+=1;
这里需要解释一下:
- 对于标志字段,由于每位表示一种标志,我们就采用
FT_BOOLEAN
类型,以表示标志是否设置。 - 其次,我们在数据的第七域中包含了标志掩码,以使系统获得相关的比特位。
- 我们也将第五域改为
8
,指示当获取标志字段时读取8位数据。 - 最后我们将这些新建的结构添加到解析程序中。注意,我们一定要对每个标志处理保持相同的偏移。
现在,该解析器的功能已显得相当完整了,但我们仍可实施一套方案使其趋于完美。目前我们的解析仅用“Foo Protocol”来标示数据包,这虽然正确但实用价值不大。
我们能够添加一些细节来对其增强。首先我们需要获得协议类型的实际值,这可以通过函数tvb_get_guint8
方便地做到。获得该值后我们就可以开展工作了。首先我们可以在包列表面板区的“信息(INFO)”列显示PDU的类别信息——当查看协议踪迹时这是非常有用的。其次,我们也可以在包明细面板区中显示这些信息。
例 9.13. 增强显示.
static void dissect_foo(tvbuff_t *tvb,packet_info *pinfo,proto_tree *tree)
{
guint8 packet_type=tvb_get_guint8(tvb,0);
if(check_col(pinfo->cinfo,COL_PROTOCOL))
{
col_set_str(pinfo->cinfo,COL_PROTOCOL,"FOO");
}
/* Clear out stuff in the info column */
if(check_col(pinfo->cinfo,COL_INFO))
{
col_clear(pinfo->cinfo,COL_INFO);
}
if(check_col(pinfo->cinfo,COL_INFO))
{
col_add_fstr(pinfo->cinfo,COL_INFO,"Type %s",val_to_str(packet_type,packettypenames,"Unknown (0x%02x)"));
}
if(tree)
{
/* we are being asked for details */
proto_item *ti=NULL;
proto_tree *foo_tree=NULL;
gint offset=0;
ti=proto_tree_add_item(tree,proto_foo,tvb,0,-1,FALSE);
proto_item_append_text(ti,", Type %s",val_to_str(packet_type,packettypenames,"Unknown (0x%02x)"));
foo_tree=proto_item_add_subtree(ti,ett_foo);
proto_tree_add_item(foo_tree,hf_foo_pdu_type,tvb,offset,1,FALSE);
offset+=1;
}
}
这里,在获得前8比特位的值后,我们使用内置的应用函数val_to_str
获得该值对应的数据。如果值不存在,我们会直接以16进制形式显示该值。我们使用该数据两次,一次用于列表的“信息(INFO)”字段,当然是在它显示的情况下,同样,我们也会将该数据添加到解析树的基部。