aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-smb-direct.c
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2012-10-03 23:01:12 +0200
committerAnders Broman <a.broman58@gmail.com>2014-03-07 06:54:58 +0000
commit7f9acb547a9a8ccc58954acc2a3a666fbb68c19e (patch)
tree10b5830d089dc97d064ace91cc5d8968d9ad4ccb /epan/dissectors/packet-smb-direct.c
parentef94a80bfa86362cfca09e1982010b5a9a47d247 (diff)
packet-smb-direct.c: add support for reassembling of fragments
Change-Id: I6b66867774f369fa49c9ee45a6792a6ad4d4c6e2 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-on: https://code.wireshark.org/review/59 Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/dissectors/packet-smb-direct.c')
-rw-r--r--epan/dissectors/packet-smb-direct.c187
1 files changed, 182 insertions, 5 deletions
diff --git a/epan/dissectors/packet-smb-direct.c b/epan/dissectors/packet-smb-direct.c
index 6ee5ef97d8..102d090874 100644
--- a/epan/dissectors/packet-smb-direct.c
+++ b/epan/dissectors/packet-smb-direct.c
@@ -3,7 +3,7 @@
*
* Routines for [MS-SMBD] the RDMA transport layer for SMB2/3
*
- * Copyright 2012 Stefan Metzmacher <metze@samba.org>
+ * Copyright 2012-2014 Stefan Metzmacher <metze@samba.org>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
@@ -28,6 +28,9 @@
#include <glib.h>
+#include <epan/packet.h>
+#include <epan/reassemble.h>
+#include <epan/prefs.h>
#include "packet-windows-common.h"
#include "packet-iwarp-ddp-rdmap.h"
#include "packet-infiniband.h"
@@ -37,6 +40,8 @@ static int proto_smb_direct = -1;
static gint ett_smb_direct = -1;
static gint ett_smb_direct_hdr = -1;
static gint ett_smb_direct_flags = -1;
+static gint ett_smb_direct_fragment = -1;
+static gint ett_smb_direct_fragments = -1;
static int hf_smb_direct_negotiate_request = -1;
static int hf_smb_direct_negotiate_response = -1;
@@ -56,6 +61,34 @@ static int hf_smb_direct_flags_response_requested = -1;
static int hf_smb_direct_remaining_length = -1;
static int hf_smb_direct_data_offset = -1;
static int hf_smb_direct_data_length = -1;
+static int hf_smb_direct_fragments = -1;
+static int hf_smb_direct_fragment = -1;
+static int hf_smb_direct_fragment_overlap = -1;
+static int hf_smb_direct_fragment_overlap_conflict = -1;
+static int hf_smb_direct_fragment_multiple_tails = -1;
+static int hf_smb_direct_fragment_too_long_fragment = -1;
+static int hf_smb_direct_fragment_error = -1;
+static int hf_smb_direct_fragment_count = -1;
+static int hf_smb_direct_reassembled_in = -1;
+static int hf_smb_direct_reassembled_length = -1;
+static int hf_smb_direct_reassembled_data = -1;
+
+static const fragment_items smb_direct_frag_items = {
+ &ett_smb_direct_fragment,
+ &ett_smb_direct_fragments,
+ &hf_smb_direct_fragments,
+ &hf_smb_direct_fragment,
+ &hf_smb_direct_fragment_overlap,
+ &hf_smb_direct_fragment_overlap_conflict,
+ &hf_smb_direct_fragment_multiple_tails,
+ &hf_smb_direct_fragment_too_long_fragment,
+ &hf_smb_direct_fragment_error,
+ &hf_smb_direct_fragment_count,
+ &hf_smb_direct_reassembled_in,
+ &hf_smb_direct_reassembled_length,
+ &hf_smb_direct_reassembled_data,
+ "SMB Direct fragments"
+};
enum SMB_DIRECT_HDR_TYPE {
SMB_DIRECT_HDR_UNKNOWN = -1,
@@ -69,12 +102,99 @@ enum SMB_DIRECT_HDR_TYPE {
static heur_dissector_list_t smb_direct_heur_subdissector_list;
static dissector_handle_t data_handle;
+static gboolean smb_direct_reassemble = TRUE;
+static reassembly_table smb_direct_reassembly_table;
+
static void
-dissect_smb_direct_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+smb_direct_reassemble_init(void)
{
+ reassembly_table_init(&smb_direct_reassembly_table,
+ &addresses_ports_reassembly_table_functions);
+}
+
+static void
+dissect_smb_direct_payload(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint32 remaining_length)
+{
+ gboolean save_fragmented = pinfo->fragmented;
+ int save_visited = pinfo->fd->flags.visited;
+ conversation_t *conversation = NULL;
+ fragment_head *fd_head = NULL;
+ tvbuff_t *payload_tvb = NULL;
+ gboolean more_frags = FALSE;
+ gboolean fd_head_not_cached = FALSE;
+
+ if (!smb_direct_reassemble) {
+ payload_tvb = tvb;
+ goto dissect_payload;
+ }
+
+ conversation = find_or_create_conversation(pinfo);
+
+ if (remaining_length > 0) {
+ more_frags = TRUE;
+ }
+
+ fd_head = (fragment_head *)p_get_proto_data(wmem_file_scope(), pinfo, proto_smb_direct, 0);
+ if (fd_head == NULL) {
+ fd_head_not_cached = TRUE;
+
+ pinfo->fd->flags.visited = 0;
+ fd_head = fragment_add_seq_next(&smb_direct_reassembly_table,
+ tvb, 0, pinfo,
+ conversation->index,
+ NULL, tvb_captured_length(tvb),
+ more_frags);
+ }
+
+ if (fd_head == NULL) {
+ /*
+ * We really want the fd_head and pass it to
+ * process_reassembled_data()
+ *
+ * So that individual fragments gets the
+ * reassembled in field.
+ */
+ fd_head = fragment_get_reassembled_id(&smb_direct_reassembly_table,
+ pinfo,
+ conversation->index);
+ }
+
+ if (fd_head == NULL) {
+ /*
+ * we need more data...
+ */
+ goto done;
+ }
+
+ if (fd_head_not_cached) {
+ p_add_proto_data(wmem_file_scope(), pinfo,
+ proto_smb_direct, 0, fd_head);
+ }
+
+ payload_tvb = process_reassembled_data(tvb, 0, pinfo,
+ "Reassembled SMB Direct",
+ fd_head,
+ &smb_direct_frag_items,
+ NULL, /* update_col_info*/
+ tree);
+ if (payload_tvb == NULL) {
+ /*
+ * we need more data...
+ */
+ goto done;
+ }
+
+dissect_payload:
+ pinfo->fragmented = FALSE;
if (!dissector_try_heuristic(smb_direct_heur_subdissector_list,
- tvb, pinfo, tree, NULL))
- call_dissector(data_handle,tvb, pinfo, tree);
+ payload_tvb, pinfo, tree, NULL)) {
+ call_dissector(data_handle, payload_tvb, pinfo, tree);
+ }
+done:
+ pinfo->fragmented = save_fragmented;
+ pinfo->fd->flags.visited = save_visited;
+ return;
}
static void
@@ -92,6 +212,7 @@ dissect_smb_direct(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
guint16 flags = 0;
proto_tree *flags_tree = NULL;
proto_item *flags_item = NULL;
+ guint32 remaining_length = 0;
guint32 data_offset = 0;
guint32 data_length = 0;
guint rlen = tvb_reported_length(tvb);
@@ -240,6 +361,7 @@ dissect_smb_direct(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
/* 2 bytes reserved */
offset += 2;
+ remaining_length = tvb_get_letohl(tvb, offset);
proto_tree_add_item(data_tree, hf_smb_direct_remaining_length,
tvb, offset, 4, ENC_LITTLE_ENDIAN);
offset += 4;
@@ -264,7 +386,8 @@ dissect_smb_direct(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
}
if (next_tvb != NULL) {
- dissect_smb_direct_payload(next_tvb, pinfo, parent_tree);
+ dissect_smb_direct_payload(next_tvb, pinfo,
+ parent_tree, remaining_length);
}
/* offset = data_offset + data_length; */
@@ -426,6 +549,8 @@ void proto_register_smb_direct(void)
&ett_smb_direct,
&ett_smb_direct_hdr,
&ett_smb_direct_flags,
+ &ett_smb_direct_fragment,
+ &ett_smb_direct_fragments,
};
static hf_register_info hf[] = {
@@ -503,7 +628,51 @@ void proto_register_smb_direct(void)
{ "DataLength", "smb_direct.data_length",
FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
+ { &hf_smb_direct_fragments,
+ { "Reassembled SMB Direct Fragments", "smb_direct.fragments",
+ FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
+
+ { &hf_smb_direct_fragment,
+ { "SMB Direct Fragment", "smb_direct.fragment",
+ FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }},
+ { &hf_smb_direct_fragment_overlap,
+ { "Fragment overlap", "smb_direct.fragment.overlap",
+ FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }},
+
+ { &hf_smb_direct_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "smb_direct.fragment.overlap.conflict",
+ FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }},
+
+ { &hf_smb_direct_fragment_multiple_tails,
+ { "Multiple tail fragments found", "smb_direct.fragment.multipletails",
+ FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }},
+
+ { &hf_smb_direct_fragment_too_long_fragment,
+ { "Fragment too long", "smb_direct.fragment.toolongfragment",
+ FT_BOOLEAN, BASE_NONE, NULL, 0, NULL, HFILL }},
+
+ { &hf_smb_direct_fragment_error,
+ { "Defragmentation error", "smb_direct.fragment.error",
+ FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }},
+
+ { &hf_smb_direct_fragment_count,
+ { "Fragment count", "smb_direct.fragment.count",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
+
+ { &hf_smb_direct_reassembled_in,
+ { "Reassembled PDU in frame", "smb_direct.reassembled_in",
+ FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }},
+
+ { &hf_smb_direct_reassembled_length,
+ { "Reassembled SMB Direct length", "smb_direct.reassembled.length",
+ FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
+
+ { &hf_smb_direct_reassembled_data,
+ { "Reassembled SMB Direct data", "smb_direct.reassembled.data",
+ FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
+
};
+ module_t *smb_direct_module;
proto_smb_direct = proto_register_protocol("SMB-Direct (SMB RDMA Transport)",
"SMBDirect", "smb_direct");
@@ -512,6 +681,14 @@ void proto_register_smb_direct(void)
register_heur_dissector_list("smb_direct",
&smb_direct_heur_subdissector_list);
+
+ smb_direct_module = prefs_register_protocol(proto_smb_direct, NULL);
+ prefs_register_bool_preference(smb_direct_module,
+ "reassemble_smb_direct",
+ "Reassemble SMB Direct fragments",
+ "Whether the SMB Direct dissector should reassemble fragmented payloads",
+ &smb_direct_reassemble);
+ register_init_routine(smb_direct_reassemble_init);
}
void