標(biāo)簽: Wireshark
版權(quán)聲明:轉(zhuǎn)載時(shí)請以超鏈接形式標(biāo)明文章原始出處和作者信息及本聲明
http://www.blogbus.com/shujiantang-logs/35858037.html
本文是Wireshark官方開發(fā)文檔9.2節(jié)《添加一個(gè)基礎(chǔ)的解析器》的翻譯
9.2.2. 解析協(xié)議細(xì)節(jié)
現(xiàn)在我們已經(jīng)有了一個(gè)可以運(yùn)用的簡單解析器,讓我們再為它添點(diǎn)兒什么吧。首先想到的應(yīng)該就是標(biāo)示數(shù)據(jù)包的有效信息了。解析器在這方面給我們提供了支持会涎。
首先要做的事情是創(chuàng)建一個(gè)子樹以容納我們的解析結(jié)果。這會使協(xié)議的細(xì)節(jié)顯示得井井有條∪鸫眨現(xiàn)在解析器在兩種情況下被調(diào)用:其一末秃,用于獲得數(shù)據(jù)包的概要信息练慕;其二,用于獲得數(shù)據(jù)包的詳細(xì)信息铃将。這兩種情況可以通過樹指針參數(shù)tree
來進(jìn)行區(qū)分哑梳。如果樹指針為NULL
,我們只需要提供概要信息鸠真;反之,我們就需要拆解協(xié)議完成細(xì)節(jié)的顯示了锡垄。基于此路操,讓我們來增強(qiáng)這個(gè)解析器吧千贯。
例 9.4. 插入數(shù)據(jù)包解析.
static void dissect_foo(tvbuff_t *tvb,packet_info *pinfo,proto_tree *tree)
{
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(tree)
{
/* we are being asked for details */
proto_item *ti=NULL;
ti=proto_tree_add_item(tree,proto_foo,tvb,0,-1,FALSE);
}
}
這里我們?yōu)榻馕鎏砑右粋€(gè)子樹。它將用于保管協(xié)議的細(xì)節(jié)祭钉,僅在必要時(shí)顯示這些內(nèi)容己沛。
我們還要標(biāo)識被協(xié)議占據(jù)的數(shù)據(jù)區(qū)域距境。在我們的這種情況下,協(xié)議占據(jù)了傳入數(shù)據(jù)的全部垫桂,因?yàn)槲覀兗僭O(shè)協(xié)議沒有封裝其它內(nèi)容诬滩。因此,我們用
proto_tree_add_item
函數(shù)添加新的樹結(jié)點(diǎn)疼鸟,將它添加到傳入的協(xié)議樹tree
中,用協(xié)議句柄proto_foo
標(biāo)識它浩淘,用傳入的緩沖區(qū)tvb
作為數(shù)據(jù)吴攒,并將有效數(shù)據(jù)范圍的起點(diǎn)設(shè)為0
,長度設(shè)為-1
(表示緩沖區(qū)內(nèi)的全部數(shù)據(jù))署惯。至于最后的參數(shù)FALSE
镣隶,我們暫且忽略诡右。做了這個(gè)更改之后怀酷,在包明細(xì)面板區(qū)中應(yīng)該會出現(xiàn)一個(gè)針對該協(xié)議的標(biāo)簽;選擇該標(biāo)簽后桅锄,在包字節(jié)面板區(qū)中包的剩余內(nèi)容就會高亮顯示样眠。
現(xiàn)在進(jìn)入下一步,添加一些協(xié)議解析功能辫秧。在這一步我們需要構(gòu)建一組幫助解析的表結(jié)構(gòu)被丧。這需要對proto_register_foo
函數(shù)做些修改。首先定義一組靜態(tài)數(shù)組柿究。
例 9.5. 定義數(shù)據(jù)結(jié)構(gòu).
static hf_register_info hf[]=
{
{
&hf_foo_pdu_type,
{"FOO PDU Type","foo.type",FT_UINT8,BASE_DEC,NULL, 0x0,NULL,HFILL}
}
};
/* Setup protocol subtree array */
static gint *ett[]=
{
&ett_foo
};
接下來黄选,在協(xié)議注冊代碼之后,我們對這些數(shù)組進(jìn)行注冊貌夕。
例 9.6. 注冊數(shù)據(jù)結(jié)構(gòu).
proto_register_field_array(proto_foo,hf,array_length(hf));
proto_register_subtree_array(ett,array_length(ett));
變量hf_foo_pdu_type
和ett_foo
依然需要在文件頂部的某處予以聲明民镜。
例 9.7. 解析器全局?jǐn)?shù)據(jù)結(jié)構(gòu).
static int hf_foo_pdu_type=-1;
static gint ett_foo=-1;
現(xiàn)在我們就可以對協(xié)議細(xì)節(jié)的顯示做一番改善了。
例 9.8. 解析器開始數(shù)據(jù)包解析.
if(tree)
{
/* we are being asked for details */
proto_item *ti=NULL;
proto_tree *foo_tree=NULL;
ti=proto_tree_add_item(tree,proto_foo,tvb,0,-1,FALSE);
foo_tree=proto_item_add_subtree(ti,ett_foo);
proto_tree_add_item(foo_tree,hf_foo_pdu_type,tvb,0,1,FALSE);
}
協(xié)議的解析變得愈發(fā)有趣了植旧。我們提取出協(xié)議的第一部分离唐。數(shù)據(jù)包的首字節(jié)定義了foo協(xié)議的包類型。
函數(shù)
proto_item_add_subtree
的調(diào)用在協(xié)議樹中添加了一個(gè)子樹完沪,我們就在這里進(jìn)行細(xì)節(jié)解析。子樹的展開受控于變量ett_foo
听皿。當(dāng)您在協(xié)議間切換時(shí)宽档,由它記錄子樹是否展開。正像您從下面的函數(shù)調(diào)用中看到的那樣又厉,隨后的所有解析都會添加到該子樹中椎瘟。函數(shù)
proto_tree_add_item
用于為子樹foo_tree
添加項(xiàng),這次調(diào)用使用變量hf_foo_pdu_type
控制項(xiàng)格式煌妈。PDU(協(xié)議數(shù)據(jù)單元)類型是一個(gè)單字節(jié)數(shù)據(jù)宣羊,位于數(shù)據(jù)包的首字節(jié),我們將有效數(shù)據(jù)范圍的起點(diǎn)設(shè)為0
腮猖,長度設(shè)為1
赞枕。我們假設(shè)它依照網(wǎng)絡(luò)字節(jié)順序坪创,所以將最后一個(gè)參數(shù)設(shè)為FALSE
(TRUE
表示"little endian",FALSE
表示"big endian")。盡管對于單字節(jié)數(shù)據(jù)無所謂字節(jié)順序柠掂,但我們最好還是保持指定字節(jié)順序的良好習(xí)慣依沮。如果詳細(xì)查看靜態(tài)數(shù)組中
hf_foo_pdu_type
的聲明,我們能夠獲悉定義的明細(xì):
hf_foo_pdu_type
:節(jié)點(diǎn)索引宋渔。FOO PDU Type
:項(xiàng)標(biāo)示辜限。foo.type
:過濾字符串。我們可以在過濾框中輸入諸如foo.type=1
的結(jié)構(gòu)氧急。FT_UNIT8
:指定該項(xiàng)數(shù)據(jù)是一個(gè)8比特位的無符號整型。這和我們之前調(diào)用函數(shù)時(shí)設(shè)置的一字節(jié)有效數(shù)據(jù)是相一致的吩坝。BASE_DEC
:針對整型數(shù)據(jù)钉寝,指定將其作為十進(jìn)制數(shù)顯示。當(dāng)然視具體情況也可以設(shè)置為“BASE_HEX”(十六進(jìn)制)和“BASE_OCT”(八進(jìn)制),以使數(shù)據(jù)更易辨識瘩蚪。- 至于結(jié)構(gòu)中余下的部分我們暫且忽略。
如果您現(xiàn)在安裝并試用這個(gè)插件疹瘦,就會發(fā)現(xiàn)一些有用的東西了。
接下來讓我們完成這個(gè)簡單協(xié)議的解析工作吧邓嘹。我們需要再添加一些hf數(shù)組成員和程序調(diào)用险胰。
例 9.9. 完成數(shù)據(jù)包解析.
//添加到文件開始的某個(gè)地方,作為全局變量
static int hf_foo_flags=-1;
static int hf_foo_sequenceno=-1;
static int hf_foo_initialip=-1;
//添加到“proto_register_foo”函數(shù)中的“hf”數(shù)組中棚贾,作為數(shù)組的成員
{
&hf_foo_flags,
{"FOO PDU Flags","foo.flags",FT_UINT8,BASE_HEX,NULL,0x0,NULL,HFILL}
},
{
&hf_foo_sequenceno,
{"FOO PDU Sequence Number","foo.seqn",FT_UINT16,BASE_DEC,NULL,0x0,NULL,HFILL}
},
{
&hf_foo_initialip,
{"FOO PDU Initial IP","foo.initialip",FT_IPv4,BASE_NONE,NULL,0x0,NULL,HFILL}
},
//添加到“dissect_foo”函數(shù)中榆综,實(shí)現(xiàn)數(shù)據(jù)包的解析
gint offset=0;
ti = proto_tree_add_item(tree,proto_foo,tvb,0,-1,FALSE);
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;
proto_tree_add_item(foo_tree,hf_foo_flags,tvb,offset,1,FALSE);
offset+=1;
proto_tree_add_item(foo_tree,hf_foo_sequenceno,tvb,offset,2,FALSE);
offset+=2;
proto_tree_add_item(foo_tree,hf_foo_initialip,tvb,offset,4,FALSE);
offset+=4;
- 這段代碼解析了這個(gè)簡單的虛構(gòu)協(xié)議的全部內(nèi)容鼻疮。我們引入了一個(gè)新的變量
offset
以記錄數(shù)據(jù)包解析的位置。將這些額外的代碼塊放入合適的位置耿芹,整個(gè)協(xié)議就可以得到全面的解析挪哄。