"bt-dht [...] should also be common dissectors while not only heuristic
ones. So we can use them with 'Decode As...' command."
Essentially:
-Register dissector handle so the dissector can be accessed via "decode-as".
From me:
1. Given that the current heuristic is much too weak and
causes 'false positives':
Add a preference to allow enabling/disabling of heuristic dissection.
The default is 'disabled' since the current heuristic is quite weak.
(For example: The heuristic incorrectly dissects about 40
files in menagerie/public as being the BT-DHT protocol).
Note: only heuristic dissection is disabled; 'decode-as' remains
enabled.
Also:
1. Fix some bugs wherein bytes in the hex pane were not highlighted
when a field was selected in the details pane.
2. Do some minor re-formatting of the source code.
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@40603
f5534014-38df-0310-8fa8-
9805f1628bb7
#include <epan/packet.h>
#include <epan/conversation.h>
#include <epan/packet.h>
#include <epan/conversation.h>
/* Specifications: BEP-0005
* http://www.bittorrent.org/beps/bep_0005.html
/* Specifications: BEP-0005
* http://www.bittorrent.org/beps/bep_0005.html
static int proto_bt_dht = -1;
static dissector_handle_t bt_dht_handle;
static int proto_bt_dht = -1;
static dissector_handle_t bt_dht_handle;
+static gboolean bt_dht_enable_heuristic_dissection = FALSE; /* disabled by default since heuristic is weak */
+
/* fields */
static int hf_bencoded_int = -1;
static int hf_bencoded_string = -1;
/* fields */
static int hf_bencoded_int = -1;
static int hf_bencoded_string = -1;
* dissect a bencoded string from tvb, start at offset. it's like "5:abcde"
* *result will be the decoded value
*/
* dissect a bencoded string from tvb, start at offset. it's like "5:abcde"
* *result will be the decoded value
*/
-static int dissect_bencoded_string(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, guint offset, char **result, gboolean tohex, char *label )
+
+static int
+dissect_bencoded_string(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, guint offset, char **result, gboolean tohex, char *label )
{
guint string_len_start;
guint string_len;
{
guint string_len_start;
guint string_len;
string_len_start = offset;
while( tvb_get_guint8(tvb,offset) != ':' )
string_len_start = offset;
while( tvb_get_guint8(tvb,offset) != ':' )
string_len = atoi( tvb_get_ephemeral_string(tvb,string_len_start,offset-string_len_start) );
/* skip the ':' */
string_len = atoi( tvb_get_ephemeral_string(tvb,string_len_start,offset-string_len_start) );
/* skip the ':' */
/* fill the return data */
if( tohex )
/* fill the return data */
if( tohex )
* dissect a bencoded integer from tvb, start at offset. it's like "i5673e"
* *result will be the decoded value
*/
* dissect a bencoded integer from tvb, start at offset. it's like "i5673e"
* *result will be the decoded value
*/
-static int dissect_bencoded_int(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, guint offset, char **result, char *label )
+static int
+dissect_bencoded_int(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree *tree, guint offset, char **result, char *label )
{
guint start_offset;
start_offset = offset;
{
guint start_offset;
start_offset = offset;
- /* we has confirmed that the first byte is 'i' */
- offset ++;
+ /* we have confirmed that the first byte is 'i' */
+ offset += 1;
while( tvb_get_guint8(tvb,offset)!='e' )
while( tvb_get_guint8(tvb,offset)!='e' )
*result = tvb_get_ephemeral_string( tvb, offset, offset-start_offset-1 );
proto_tree_add_string_format( tree, hf_bencoded_int, tvb, offset, offset-start_offset-1, *result,
"%s: %s", label, *result );
*result = tvb_get_ephemeral_string( tvb, offset, offset-start_offset-1 );
proto_tree_add_string_format( tree, hf_bencoded_int, tvb, offset, offset-start_offset-1, *result,
"%s: %s", label, *result );
static int dissect_bencoded_dict(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, char *label );
/* dissect a bencoded list from tvb, start at offset. it's like "lXXXe", "X" is any bencoded thing */
static int dissect_bencoded_dict(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, char *label );
/* dissect a bencoded list from tvb, start at offset. it's like "lXXXe", "X" is any bencoded thing */
-static int dissect_bencoded_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, char *label )
+static int
+dissect_bencoded_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, char *label )
{
proto_item *ti;
proto_tree *sub_tree;
{
proto_item *ti;
proto_tree *sub_tree;
- guint one_byte;
- char *result;
+ guint one_byte;
+ char *result;
ti = proto_tree_add_none_format( tree, hf_bencoded_list, tvb, offset, 0, "%s: list...", label );
sub_tree = proto_item_add_subtree( ti, ett_bencoded_list);
/* skip the 'l' */
ti = proto_tree_add_none_format( tree, hf_bencoded_list, tvb, offset, 0, "%s: list...", label );
sub_tree = proto_item_add_subtree( ti, ett_bencoded_list);
/* skip the 'l' */
while( (one_byte=tvb_get_guint8(tvb,offset)) != 'e' )
{
while( (one_byte=tvb_get_guint8(tvb,offset)) != 'e' )
{
return offset;
}
/* dissect a bt dht error from tvb, start at offset. it's like "li201e9:error msge" */
return offset;
}
/* dissect a bt dht error from tvb, start at offset. it's like "li201e9:error msge" */
-static int dissect_bt_dht_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, char **result, char *label )
+static int
+dissect_bt_dht_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, char **result, char *label )
{
proto_item *ti;
proto_tree *sub_tree;
{
proto_item *ti;
proto_tree *sub_tree;
- char *error_no, *error_msg;
+ char *error_no, *error_msg;
- ti = proto_tree_add_item( tree, hf_bt_dht_error, tvb, offset, 0, ENC_NA );
+ ti = proto_tree_add_item( tree, hf_bt_dht_error, tvb, offset, 0, ENC_NA );
sub_tree = proto_item_add_subtree( ti, ett_bt_dht_error);
/* we have confirmed that the first byte is 'l' */
sub_tree = proto_item_add_subtree( ti, ett_bt_dht_error);
/* we have confirmed that the first byte is 'l' */
/* dissect bt-dht error number and message */
offset = dissect_bencoded_int( tvb, pinfo, sub_tree, offset, &error_no, "Error ID" );
/* dissect bt-dht error number and message */
offset = dissect_bencoded_int( tvb, pinfo, sub_tree, offset, &error_no, "Error ID" );
}
/* dissect a bt dht values list from tvb, start at offset. it's like "l6:....6:....e" */
}
/* dissect a bt dht values list from tvb, start at offset. it's like "l6:....6:....e" */
-static int dissect_bt_dht_values(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, char **result, char *label )
+static int
+dissect_bt_dht_values(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, char **result, char *label )
{
proto_item *ti;
proto_tree *sub_tree;
proto_item *value_ti;
proto_tree *value_tree;
{
proto_item *ti;
proto_tree *sub_tree;
proto_item *value_ti;
proto_tree *value_tree;
- guint peer_index;
- guint string_len_start;
- guint string_len;
- guint16 port;
+ guint peer_index;
+ guint string_len_start;
+ guint string_len;
+ guint16 port;
ti = proto_tree_add_item( tree, hf_bt_dht_peers, tvb, offset, 0, ENC_NA );
sub_tree = proto_item_add_subtree( ti, ett_bt_dht_peers);
peer_index = 0;
/* we has confirmed that the first byte is 'l' */
ti = proto_tree_add_item( tree, hf_bt_dht_peers, tvb, offset, 0, ENC_NA );
sub_tree = proto_item_add_subtree( ti, ett_bt_dht_peers);
peer_index = 0;
/* we has confirmed that the first byte is 'l' */
/* dissect bt-dht values */
while( tvb_get_guint8(tvb,offset)!='e' )
{
string_len_start = offset;
while( tvb_get_guint8(tvb,offset) != ':' )
/* dissect bt-dht values */
while( tvb_get_guint8(tvb,offset)!='e' )
{
string_len_start = offset;
while( tvb_get_guint8(tvb,offset) != ':' )
string_len = atoi( tvb_get_ephemeral_string(tvb,string_len_start,offset-string_len_start) );
/* skip the ':' */
string_len = atoi( tvb_get_ephemeral_string(tvb,string_len_start,offset-string_len_start) );
/* skip the ':' */
/* 4 bytes ip, 2 bytes port */
for( ; string_len>=6; string_len-=6, offset+=6 )
{
/* 4 bytes ip, 2 bytes port */
for( ; string_len>=6; string_len-=6, offset+=6 )
{
SET_ADDRESS( &addr, AT_IPv4, 4, tvb_get_ptr( tvb, offset, 4) );
port = tvb_get_letohl( tvb, offset+4 );
SET_ADDRESS( &addr, AT_IPv4, 4, tvb_get_ptr( tvb, offset, 4) );
port = tvb_get_letohl( tvb, offset+4 );
-static int dissect_bt_dht_nodes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, char **result, char *label )
+static int
+dissect_bt_dht_nodes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, char **result, char *label )
{
proto_item *ti;
proto_tree *sub_tree;
proto_item *node_ti;
proto_tree *node_tree;
{
proto_item *ti;
proto_tree *sub_tree;
proto_item *node_ti;
proto_tree *node_tree;
- guint node_index;
- guint string_len_start;
- guint string_len;
- address addr;
- guint16 port;
- guint8 *id;
+ guint node_index;
+ guint string_len_start;
+ guint string_len;
+ address addr;
+ guint16 port;
+ guint8 *id;
ti = proto_tree_add_item( tree, hf_bt_dht_nodes, tvb, offset, 0, ENC_NA );
sub_tree = proto_item_add_subtree( ti, ett_bt_dht_nodes);
ti = proto_tree_add_item( tree, hf_bt_dht_nodes, tvb, offset, 0, ENC_NA );
sub_tree = proto_item_add_subtree( ti, ett_bt_dht_nodes);
string_len_start = offset;
while( tvb_get_guint8(tvb,offset) != ':' )
string_len_start = offset;
while( tvb_get_guint8(tvb,offset) != ':' )
string_len = atoi( tvb_get_ephemeral_string(tvb,string_len_start,offset-string_len_start) );
/* skip the ':' */
string_len = atoi( tvb_get_ephemeral_string(tvb,string_len_start,offset-string_len_start) );
/* skip the ':' */
/* 20 bytes id, 4 bytes ip, 2 bytes port */
for( ; string_len>=26; string_len-=26, offset+=26 )
{
/* 20 bytes id, 4 bytes ip, 2 bytes port */
for( ; string_len>=26; string_len-=26, offset+=26 )
{
id = tvb_bytes_to_str(tvb, offset, 20 );
SET_ADDRESS( &addr, AT_IPv4, 4, tvb_get_ptr( tvb, offset, 4) );
id = tvb_bytes_to_str(tvb, offset, 20 );
SET_ADDRESS( &addr, AT_IPv4, 4, tvb_get_ptr( tvb, offset, 4) );
-static int dissect_bencoded_dict_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset )
+static int
+dissect_bencoded_dict_entry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset )
{
proto_item *ti;
proto_tree *sub_tree;
{
proto_item *ti;
proto_tree *sub_tree;
- gboolean tohex;
- char *key, *val;
+ gboolean tohex;
+ char *key, *val;
+ guint orig_offset = offset;
- ti = proto_tree_add_item( tree, hf_bencoded_dict_entry, tvb, offset, 0, ENC_NA );
+ ti = proto_tree_add_item( tree, hf_bencoded_dict_entry, tvb, offset, 0, ENC_NA );
sub_tree = proto_item_add_subtree( ti, ett_bencoded_dict_entry);
/* dissect the key, it must be a string */
sub_tree = proto_item_add_subtree( ti, ett_bencoded_dict_entry);
/* dissect the key, it must be a string */
- offset = dissect_bencoded_string( tvb, pinfo, sub_tree, offset, &key, FALSE, "Key" );
+ offset = dissect_bencoded_string( tvb, pinfo, sub_tree, offset, &key, FALSE, "Key" );
- /* it is a dict, just recursion */
+ /* If it is a dict, then just do recursion */
switch( tvb_get_guint8(tvb,offset) )
{
case 'd':
offset = dissect_bencoded_dict( tvb, pinfo, sub_tree, offset, "Value" );
switch( tvb_get_guint8(tvb,offset) )
{
case 'd':
offset = dissect_bencoded_dict( tvb, pinfo, sub_tree, offset, "Value" );
break;
case 'l':
if( strcmp(key,"e")==0 )
break;
case 'l':
if( strcmp(key,"e")==0 )
val = (char*)val_to_str( val[0], short_val_name_value_string, val );
proto_item_set_text( ti, "%s: %s", key, val );
val = (char*)val_to_str( val[0], short_val_name_value_string, val );
proto_item_set_text( ti, "%s: %s", key, val );
+ proto_item_set_len( ti, offset-orig_offset );
if( strcmp(key,"message_type")==0 || strcmp(key,"request_type")==0 )
col_append_fstr(pinfo->cinfo, COL_INFO, "%s=%s ", key, val);
if( strcmp(key,"message_type")==0 || strcmp(key,"request_type")==0 )
col_append_fstr(pinfo->cinfo, COL_INFO, "%s=%s ", key, val);
-static int dissect_bencoded_dict(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, char *label )
+static int
+dissect_bencoded_dict(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, char *label )
{
proto_item *ti;
proto_tree *sub_tree;
{
proto_item *ti;
proto_tree *sub_tree;
+ guint orig_offset = offset;
ti = proto_tree_add_none_format( tree, hf_bencoded_dict, tvb, offset, 0, "%s: dictionary...", label );
sub_tree = proto_item_add_subtree( ti, ett_bencoded_dict);
/* skip the first char('d') */
ti = proto_tree_add_none_format( tree, hf_bencoded_dict, tvb, offset, 0, "%s: dictionary...", label );
sub_tree = proto_item_add_subtree( ti, ett_bencoded_dict);
/* skip the first char('d') */
while( tvb_get_guint8(tvb,offset)!='e' )
offset = dissect_bencoded_dict_entry( tvb, pinfo, sub_tree, offset );
while( tvb_get_guint8(tvb,offset)!='e' )
offset = dissect_bencoded_dict_entry( tvb, pinfo, sub_tree, offset );
+ offset += 1;
+ proto_item_set_len( ti, offset-orig_offset );
+
-static void dissect_bt_dht(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static int
+dissect_bt_dht(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
col_set_str(pinfo->cinfo, COL_PROTOCOL, "BT-DHT");
col_clear(pinfo->cinfo, COL_INFO);
{
col_set_str(pinfo->cinfo, COL_PROTOCOL, "BT-DHT");
col_clear(pinfo->cinfo, COL_INFO);
- if( tree )
- dissect_bencoded_dict(tvb, pinfo, tree, 0, "BT-DHT Protocol" );
+
+ return dissect_bencoded_dict(tvb, pinfo, tree, 0, "BT-DHT Protocol" );
-static gboolean test_bt_dht_packet (tvbuff_t *tvb, packet_info *pinfo,
+static
+gboolean dissect_bt_dht_heur (tvbuff_t *tvb, packet_info *pinfo,
- conversation_t *conversation;
-
+ /* XXX: This is a very weak heuristic; so: heuristic dissection is disabled by default */
if( tvb_get_guint8(tvb,0)=='d' )
{
if( tvb_get_guint8(tvb,0)=='d' )
{
- conversation = find_or_create_conversation(pinfo);
- conversation_set_dissector(conversation, bt_dht_handle);
+ conversation_t *conversation;
- dissect_bt_dht(tvb, pinfo, tree);
- return TRUE;
+ conversation = find_or_create_conversation(pinfo);
+ conversation_set_dissector(conversation, bt_dht_handle);
+
+ dissect_bt_dht(tvb, pinfo, tree);
+ return TRUE;
-void proto_register_bt_dht(void)
+void proto_reg_handoff_bt_dht(void);
+
+void
+proto_register_bt_dht(void)
{
static hf_register_info hf[] = {
{ &hf_bencoded_string,
{
static hf_register_info hf[] = {
{ &hf_bencoded_string,
&ett_bencoded_dict_entry
};
&ett_bencoded_dict_entry
};
+ module_t *bt_dht_module;
+
proto_bt_dht = proto_register_protocol (
"Bittorrent DHT Protocol", /* name */
"BT-DHT", /* short name */
"bt-dht" /* abbrev */
);
proto_bt_dht = proto_register_protocol (
"Bittorrent DHT Protocol", /* name */
"BT-DHT", /* short name */
"bt-dht" /* abbrev */
);
+ bt_dht_module = prefs_register_protocol(proto_bt_dht, proto_reg_handoff_bt_dht);
+ prefs_register_bool_preference(bt_dht_module, "enable", "Enable BT-DHT heuristic_dissection",
+ "Enable BT-DHT heuristic dissection (default is disabled)",
+ &bt_dht_enable_heuristic_dissection);
+
proto_register_field_array(proto_bt_dht, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
proto_register_field_array(proto_bt_dht, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
-void proto_reg_handoff_bt_dht(void)
+void
+proto_reg_handoff_bt_dht(void)
- heur_dissector_add("udp", test_bt_dht_packet, proto_bt_dht);
+ static gboolean prefs_initialized = FALSE;
+
+ /* "Decode As" is always available;
+ * Heuristic dissection in disabled by default since the heuristic is quite weak.
+ */
+ if (!prefs_initialized) {
+ heur_dissector_add("udp", dissect_bt_dht_heur, proto_bt_dht);
+
+ bt_dht_handle = new_create_dissector_handle(dissect_bt_dht, proto_bt_dht);
+ dissector_add_handle("udp.port", bt_dht_handle); /* for "decode_as" */
+
+ prefs_initialized = TRUE;
+ }
+
+ heur_dissector_set_enabled("udp", dissect_bt_dht_heur, proto_bt_dht, bt_dht_enable_heuristic_dissection);
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 2
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=2 tabstop=8 expandtab:
+ * :indentSize=2:tabSize=8:noTabs=true:
+ */
+