From 1311f29800d0bda5895cf200804b7872bbd0c0a7 Mon Sep 17 00:00:00 2001 From: Bill Meier Date: Fri, 20 Jan 2012 03:24:05 +0000 Subject: Fix Fix "bt-dht [..] NOT registered properly" as reported in Bug #6571. "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. svn path=/trunk/; revision=40603 --- epan/dissectors/packet-bt-dht.c | 180 ++++++++++++++++++++++++++-------------- 1 file changed, 119 insertions(+), 61 deletions(-) (limited to 'epan/dissectors/packet-bt-dht.c') diff --git a/epan/dissectors/packet-bt-dht.c b/epan/dissectors/packet-bt-dht.c index ed242b3f92..b821d37e8d 100644 --- a/epan/dissectors/packet-bt-dht.c +++ b/epan/dissectors/packet-bt-dht.c @@ -32,6 +32,7 @@ #include #include +#include /* Specifications: BEP-0005 * http://www.bittorrent.org/beps/bep_0005.html @@ -40,6 +41,8 @@ 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; @@ -93,7 +96,9 @@ static const char list_str[] = "list..."; * 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; @@ -101,11 +106,11 @@ static int dissect_bencoded_string(tvbuff_t *tvb, packet_info _U_*pinfo, proto_t string_len_start = offset; while( tvb_get_guint8(tvb,offset) != ':' ) - offset ++; + offset += 1; string_len = atoi( tvb_get_ephemeral_string(tvb,string_len_start,offset-string_len_start) ); /* skip the ':' */ - offset++; + offset += 1; /* fill the return data */ if( tohex ) @@ -122,23 +127,24 @@ static int dissect_bencoded_string(tvbuff_t *tvb, packet_info _U_*pinfo, proto_t * 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; - /* 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' ) - offset ++; + offset += 1; *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 ); - offset ++; + offset += 1; return offset; } @@ -146,18 +152,19 @@ static int dissect_bencoded_int(tvbuff_t *tvb, packet_info _U_*pinfo, proto_tree 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; - 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' */ - offset++; + offset += 1; while( (one_byte=tvb_get_guint8(tvb,offset)) != 'e' ) { @@ -181,25 +188,26 @@ static int dissect_bencoded_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree * break; } } - offset++; + offset += 1; 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; - char *error_no, *error_msg; + char *error_no, *error_msg; - error_no = NULL; + error_no = NULL; error_msg = NULL; - 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' */ - offset ++; + offset += 1; /* dissect bt-dht error number and message */ offset = dissect_bencoded_int( tvb, pinfo, sub_tree, offset, &error_no, "Error ID" ); @@ -213,40 +221,41 @@ static int dissect_bt_dht_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t } /* 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; - address addr; + address addr; - 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' */ - offset ++; + offset += 1; /* dissect bt-dht values */ while( tvb_get_guint8(tvb,offset)!='e' ) { string_len_start = offset; while( tvb_get_guint8(tvb,offset) != ':' ) - offset ++; + offset += 1; string_len = atoi( tvb_get_ephemeral_string(tvb,string_len_start,offset-string_len_start) ); /* skip the ':' */ - offset++; + offset += 1; /* 4 bytes ip, 2 bytes port */ for( ; string_len>=6; string_len-=6, offset+=6 ) { - peer_index ++; + peer_index += 1; SET_ADDRESS( &addr, AT_IPv4, 4, tvb_get_ptr( tvb, offset, 4) ); port = tvb_get_letohl( tvb, offset+4 ); @@ -271,19 +280,20 @@ static int dissect_bt_dht_values(tvbuff_t *tvb, packet_info *pinfo, proto_tree * return offset; } -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; - 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); @@ -291,16 +301,16 @@ static int dissect_bt_dht_nodes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t string_len_start = offset; while( tvb_get_guint8(tvb,offset) != ':' ) - offset ++; + offset += 1; string_len = atoi( tvb_get_ephemeral_string(tvb,string_len_start,offset-string_len_start) ); /* skip the ':' */ - offset++; + offset += 1; /* 20 bytes id, 4 bytes ip, 2 bytes port */ for( ; string_len>=26; string_len-=26, offset+=26 ) { - node_index++; + node_index += 1; id = tvb_bytes_to_str(tvb, offset, 20 ); SET_ADDRESS( &addr, AT_IPv4, 4, tvb_get_ptr( tvb, offset, 4) ); @@ -326,28 +336,30 @@ static int dissect_bt_dht_nodes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t return offset; } -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; - gboolean tohex; - char *key, *val; + gboolean tohex; + char *key, *val; + guint orig_offset = offset; key = NULL; val = NULL; - 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 */ - 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" ); - val = (char*)dict_str; + val = (char*)dict_str; break; case 'l': if( strcmp(key,"e")==0 ) @@ -385,6 +397,7 @@ static int dissect_bencoded_dict_entry(tvbuff_t *tvb, packet_info *pinfo, proto_ 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); @@ -393,50 +406,60 @@ static int dissect_bencoded_dict_entry(tvbuff_t *tvb, packet_info *pinfo, proto_ } /* dict = d...e */ -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; + 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') */ - offset ++; + offset += 1; while( tvb_get_guint8(tvb,offset)!='e' ) offset = dissect_bencoded_dict_entry( tvb, pinfo, sub_tree, offset ); - offset++; + offset += 1; + proto_item_set_len( ti, offset-orig_offset ); + return 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); - 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, proto_tree *tree) { - conversation_t *conversation; - /* try dissecting */ + /* XXX: This is a very weak heuristic; so: heuristic dissection is disabled by default */ 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; } return FALSE; } -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, @@ -508,18 +531,53 @@ void proto_register_bt_dht(void) &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 */ ); + 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)); } -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: + */ + -- cgit v1.2.1