標簽: 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)”字段,當然是在它顯示的情況下,同樣,我們也會將該數據添加到解析樹的基部。