Wireshark-dev: Re: [Wireshark-dev] Undissected packet bytes
From: Dario Lombardo <[email protected]>
Date: Thu, 5 Feb 2015 17:49:59 +0100
Evan,
please find attached a patch that implements what I was trying to do. I'd like to share it here with you and other devels in order to understand if it goes in the right direction and maybe to open discussions on it. If it seems good, I'll move it to gerrit for code review.

To test it, simply comment any proto_tree_add_item() from a dissector of your choice, and open a packet with wireshark or with tshark -V.

Comments are welcome.
Dario.

On Thu, Feb 5, 2015 at 1:41 PM, Dario Lombardo <[email protected]> wrote:
On Thu, Feb 5, 2015 at 1:19 PM, Evan Huus <[email protected]> wrote:
I believe g_log and friends go to standard out, but maybe not on all
platforms. An expert info under conditional compilation would probably
be enough though, I hadn't thought of that.

Another question. I've found a promising point to put the check (packet.c:call_dissector_with_data()). This function is called many times (I can count 4 times per packet). Sometimes when tree is open, sometimes when it's closed. How can I navigate (and check) the tree only and only if it's open? 
Only in this case I can check if there are undecoded bytes.

commit c14aab04326ab438304a0b0a87821b68359c7ebb
Author: Dario Lombardo <[email protected]>
Date:   Wed Feb 4 10:25:16 2015 +0100

    TRY
    
    Change-Id: I03e592dd3d54fc0e1c4af09d5d5336dda93f950e

diff --git a/epan/packet.c b/epan/packet.c
index 2899b7d..d277596 100644
--- a/epan/packet.c
+++ b/epan/packet.c
@@ -43,6 +43,7 @@
 
 #include "addr_resolv.h"
 #include "tvbuff.h"
+#include "log.h"
 #include "epan_dissect.h"
 
 #include "wmem/wmem.h"
@@ -52,6 +53,7 @@
 #include <epan/stream.h>
 #include <epan/expert.h>
 #include <epan/range.h>
+#include <epan/proto.h>
 
 static gint proto_malformed = -1;
 static dissector_handle_t frame_handle = NULL;
@@ -2397,6 +2399,29 @@ call_dissector_with_data(dissector_handle_t handle, tvbuff_t *tvb,
 		call_dissector_work(data_handle, tvb, pinfo, tree, TRUE, NULL);
 		return tvb_length(tvb);
 	}
+
+	if (tree && tree->tree_data->visible && strncmp(handle->name, "frame", 5)) {
+		gchar* decoded;
+		guint length;
+		guint i;
+		guint byte;
+		guint bit;
+
+		length = tvb_captured_length(tvb);
+		decoded = proto_seek_undecoded_data(tree, length);
+
+		for (i = 0; i < length; i++) {
+			field_info* fi = proto_find_field_from_offset(tree, i, tvb);
+			byte = i / 8;
+			bit = i % 8;
+			if (!(decoded[byte] & ((1 << bit) & 0xFF)) && strncmp(fi->hfinfo->abbrev, "frame", 5)) {
+				g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_WARNING,
+					"Dissector %s incomplete: undecoded byte %u\n",
+					fi->hfinfo->abbrev, i);
+			}
+		}
+        }
+
 	return ret;
 }
 
diff --git a/epan/proto.c b/epan/proto.c
index e12f3b6..1cd1bc1 100644
--- a/epan/proto.c
+++ b/epan/proto.c
@@ -6940,6 +6940,36 @@ proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
 	return offsearch.finfo;
 }
 
+
+static gboolean
+check_for_undecoded(proto_node *node, const gpointer data)
+{
+	field_info *fi = PNODE_FINFO(node);
+	gchar* decoded = (gchar*)data;
+	gint i;
+	guint byte;
+	guint bit;
+
+	if (fi && fi->hfinfo->type != FT_PROTOCOL) {
+		for (i = fi->start; i < fi->start + fi->length; i++) {
+			byte = i / 8;
+			bit = i % 8;
+			decoded[byte] |= ((1 << bit) & 0xFF);
+		}
+	}
+
+	return FALSE;
+}
+
+gchar*
+proto_seek_undecoded_data(proto_tree *tree, guint length)
+{
+	gchar* decoded = (gchar*)wmem_alloc0(wmem_packet_scope(), length / 8 + 1);
+
+	proto_tree_traverse_pre_order(tree, check_for_undecoded, decoded);
+	return decoded;
+}
+
 /* Dumps the protocols in the registration database to stdout.	An independent
  * program can take this output and format it into nice tables or HTML or
  * whatever.
diff --git a/epan/proto.h b/epan/proto.h
index e9b4f10..fbd9728 100644
--- a/epan/proto.h
+++ b/epan/proto.h
@@ -2221,6 +2221,14 @@ proto_construct_match_selected_string(field_info *finfo, struct epan_dissect *ed
 WS_DLL_PUBLIC field_info*
 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb);
 
+/** Find undecoded bytes in a tree
+ @param tree tree of interest
+ @param offset offset in the tvb
+ @param length the length of the frame
+ @return an array to be used as bitmap of decoded bytes */
+WS_DLL_PUBLIC gchar*
+proto_find_undecoded_data(proto_tree *tree, guint length);
+
 /** This function will dissect a sequence of bytes that describe a bitmask.
  @param tree the tree to append this item to
  @param tvb the tv buffer of the current data