Fix Fix "bt-dht [..] NOT registered properly" as reported in Bug #6571.
authorwmeier <wmeier@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 20 Jan 2012 03:24:05 +0000 (03:24 +0000)
committerwmeier <wmeier@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 20 Jan 2012 03:24:05 +0000 (03:24 +0000)
"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

epan/dissectors/packet-bt-dht.c

index ed242b3f92b28b8f7a3e34d1700fdb10d3f09b7b..b821d37e8d2bb251d84e4f91328495825a5eb6f6 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <epan/packet.h>
 #include <epan/conversation.h>
+#include <epan/prefs.h>
 
 /* 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:
+ */
+