改進解析信息
當然,我們可以使用一些額外的數據來改善協議的顯示。第一步是添加一些文本標簽。讓我們從標記數據包類型開始。通過添加一些額外的東西,對這種事情有一些有用的支持。首先,我們為名稱添加一個簡單的類型表。
Naming the packet types
static const value_string packettypenames[] = {
{ 1, "Initialise" },
{ 2, "Terminate" },
{ 3, "Data" },
{ 0, NULL }
};
這是一個方便的數據結構,可用于查找值的名稱。有一些例程可以直接訪問該查找表,但是我們不需要這樣做,因為支持代碼已經添加了該代碼。我們只需使用VALS宏將這些詳細信息提供給數據的適當部分。
Adding Names to the protocol.
{ &hf_foo_pdu_type,
{ "FOO PDU Type", "foo.type",
FT_UINT8, BASE_DEC,
VALS(packettypenames), 0x0,
NULL, HFILL }
}
這有助于解密數據包,并且我們可以對標志結構做類似的事情。為此,我們需要向表中添加更多數據。
*Adding Flags to the protocol. *
#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;
static int
dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
...
...
static int* const bits[] = {
&hf_foo_startflag,
&hf_foo_endflag,
&hf_foo_priorityflag,
NULL
};
proto_tree_add_bitmask(foo_tree, tvb, offset, hf_foo_flags, ett_foo, bits, ENC_BIG_ENDIAN);
offset += 1;
...
...
return tvb_captured_length(tvb);
}
void
proto_register_foo(void) {
...
...
{ &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 }
},
...
...
}
...
這里有幾件事需要注意。對于標志,因為每個位都是不同的標志,所以我們使用類型FT_Boolean,因為標志或者是開,或者是關。其次,我們在數據的第7個字段中包括標志掩碼,這允許系統掩碼相關的位。我們還將第5個字段更改為8,以指示在提取標志時查看的是8位數量。最后,我們將額外的構造添加到解剖例程中。
現在這看起來功能相當齊全,但是我們還可以做一些其他的事情來讓它看起來更漂亮。目前,我們的解剖顯示這些數據包是“foo協議”,雖然這是正確的,但沒有多少信息。我們可以通過添加更多細節來增強這一點。首先,讓我們了解一下協議類型的實際值。我們可以使用方便的函數tvb_get_guint8()來完成此操作。有了這個價值,我們可以做幾件事。首先,我們可以設置非詳細視圖的INFO列,以顯示它是哪種PDU-這在查看協議跟蹤時非常有用。其次,我們還可以在解剖窗口中顯示此信息。
Enhancing the display
static int
dissect_foo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
gint offset = 0;
guint8 packet_type = tvb_get_guint8(tvb, 0);
col_set_str(pinfo->cinfo, COL_PROTOCOL, "FOO");
/* Clear out stuff in the info column */
col_clear(pinfo->cinfo,COL_INFO);
col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s",
val_to_str(packet_type, packettypenames, "Unknown (0x%02x)"));
proto_item *ti = proto_tree_add_item(tree, proto_foo, tvb, 0, -1, ENC_NA);
proto_item_append_text(ti, ", Type %s",
val_to_str(packet_type, packettypenames, "Unknown (0x%02x)"));
proto_tree *foo_tree = proto_item_add_subtree(ti, ett_foo);
proto_tree_add_item(foo_tree, hf_foo_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
return tvb_captured_length(tvb);
}
因此,在這里,在獲取前8位的值之后,我們將其與一個內置實用程序例程一起使用val_to_str()以查找該值。如果找不到該值,我們提供一個后備選項,僅以十六進制打印該值。我們使用兩次,一次在列的INFO字段中(如果顯示的話),并且類似地,我們將此數據附加到解剖樹的底部。
Wireshark中文使用教程(開發版)