#include <glib.h>
#include <epan/packet.h>
-#include <epan/llcsaps.h>
+#include <epan/conversation.h>
#include <epan/reassemble.h>
#include <epan/prefs.h>
#include "packet-windows-common.h"
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_min_version = -1;
static int hf_smb_direct_max_version = -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,
static heur_dissector_list_t smb_direct_heur_subdissector_list;
static dissector_handle_t data_handle;
+static gboolean smb_direct_reassemble = TRUE;
+static GHashTable *smb_direct_fragment_table = NULL;
+static GHashTable *smb_direct_reassemble_table = NULL;
+
static void
-dissect_smb_direct_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+smb_direct_reassemble_init(void)
{
- if (!dissector_try_heuristic(smb_direct_heur_subdissector_list,
- tvb, pinfo, tree, NULL))
- call_dissector(data_handle,tvb, pinfo, tree);
+ fragment_table_init(&smb_direct_fragment_table);
+ reassembled_table_init(&smb_direct_reassemble_table);
+}
+
+static void
+dissect_smb_direct_payload(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint32 remaining_length _U_)
+{
+ gboolean save_fragmented = pinfo->fragmented;
+ int visited = pinfo->fd->flags.visited;
+ conversation_t *conversation = NULL;
+ fragment_data *fd_head = NULL;
+ tvbuff_t *next_tvb = NULL;
+
+ if (!smb_direct_reassemble) {
+ pinfo->fragmented = FALSE;
+ if (!dissector_try_heuristic(smb_direct_heur_subdissector_list,
+ tvb, pinfo, tree, NULL)) {
+ call_dissector(data_handle,tvb, pinfo, tree);
+ }
+ pinfo->fragmented = save_fragmented;
+ pinfo->fd->flags.visited = visited;
+ return;
+ }
+
+ conversation = find_or_create_conversation(pinfo);
+
+ pinfo->fd->flags.visited = 0;
+ fd_head = fragment_add_seq_next(tvb, 0, pinfo,
+ conversation->index,
+ smb_direct_fragment_table,
+ smb_direct_reassemble_table,
+ tvb_length(tvb),
+ remaining_length > 0 ? TRUE : FALSE /* more_frags */);
+
+ next_tvb = process_reassembled_data(tvb, 0, pinfo,
+ "Reassembled SMB Direct",
+ fd_head,
+ &smb_direct_frag_items,
+ NULL, /* update_col_info*/
+ tree);
+
+ if (next_tvb != NULL) {
+ pinfo->fragmented = FALSE;
+ if (!dissector_try_heuristic(smb_direct_heur_subdissector_list,
+ next_tvb, pinfo, tree, NULL)) {
+ call_dissector(data_handle,tvb, pinfo, tree);
+ }
+ pinfo->fragmented = save_fragmented;
+ pinfo->fd->flags.visited = visited;
+ return;
+ }
+
+ pinfo->fragmented = save_fragmented;
+ pinfo->fd->flags.visited = visited;
}
static void
guint16 flags;
proto_tree *flags_tree = NULL;
proto_item *item = NULL;
+ guint32 remaining_length;
guint32 data_offset;
guint32 data_length;
gint len = 0;
/* 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;
}
if (next_tvb) {
- 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;
}
&ett_smb_direct,
&ett_smb_direct_hdr,
&ett_smb_direct_flags,
+ &ett_smb_direct_fragment,
+ &ett_smb_direct_fragments,
};
static hf_register_info hf[] = {
{ &hf_smb_direct_min_version,
- { "MinVersion", "smb_direct.version.min", FT_UINT16, BASE_HEX,
- NULL, 0, NULL, HFILL }},
+ { "MinVersion", "smb_direct.version.min",
+ FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
+
{ &hf_smb_direct_max_version,
- { "MaxVersion", "smb_direct.version.max", FT_UINT16, BASE_HEX,
- NULL, 0, NULL, HFILL }},
+ { "MaxVersion", "smb_direct.version.max",
+ FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
+
{ &hf_smb_direct_negotiated_version,
- { "NegotiatedVersion", "smb_direct.version.negotiated", FT_UINT16, BASE_HEX,
- NULL, 0, NULL, HFILL }},
+ { "NegotiatedVersion", "smb_direct.version.negotiated",
+ FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
{ &hf_smb_direct_credits_requested,
- { "CreditsRequested", "smb_direct.credits.requested", FT_UINT16, BASE_DEC,
- NULL, 0, NULL, HFILL }},
+ { "CreditsRequested", "smb_direct.credits.requested",
+ FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
+
{ &hf_smb_direct_credits_granted,
- { "CreditsGranted", "smb_direct.credits.granted", FT_UINT16, BASE_DEC,
- NULL, 0, NULL, HFILL }},
+ { "CreditsGranted", "smb_direct.credits.granted",
+ FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
{ &hf_smb_direct_status,
- { "Status", "smb_direct.status", FT_UINT32, BASE_HEX,
- VALS(NT_errors), 0, "NT Status code", HFILL }},
+ { "Status", "smb_direct.status",
+ FT_UINT32, BASE_HEX, VALS(NT_errors), 0,
+ "NT Status code", HFILL }},
{ &hf_smb_direct_max_read_write_size,
- { "MaxReadWriteSize", "smb_direct.max_read_write_size", FT_UINT32, BASE_DEC,
- NULL, 0, NULL, HFILL }},
+ { "MaxReadWriteSize", "smb_direct.max_read_write_size",
+ FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
{ &hf_smb_direct_preferred_send_size,
- { "PreferredSendSize", "smb_direct.preferred_send_size", FT_UINT32, BASE_DEC,
- NULL, 0, NULL, HFILL }},
+ { "PreferredSendSize", "smb_direct.preferred_send_size",
+ FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
{ &hf_smb_direct_max_receive_size,
- { "MaxReceiveSize", "smb_direct.max_receive_size", FT_UINT32, BASE_DEC,
- NULL, 0, NULL, HFILL }},
+ { "MaxReceiveSize", "smb_direct.max_receive_size",
+ FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
{ &hf_smb_direct_max_fragmented_size,
- { "MaxFragmentedSize", "smb_direct.max_fragmented_size", FT_UINT32, BASE_DEC,
- NULL, 0, NULL, HFILL }},
+ { "MaxFragmentedSize", "smb_direct.max_fragmented_size",
+ FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
{ &hf_smb_direct_flags,
- { "Flags", "smb_direct.flags", FT_UINT16, BASE_HEX,
- NULL, 0, NULL, HFILL }},
+ { "Flags", "smb_direct.flags",
+ FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
#define SMB_DIRECT_RESPONSE_REQUESTED 0x0001
{ &hf_smb_direct_flags_response_requested,
- { "ResponseRequested", "smb_direct.flags.response_requested", FT_BOOLEAN, 16,
- NULL, SMB_DIRECT_RESPONSE_REQUESTED, NULL, HFILL }},
+ { "ResponseRequested", "smb_direct.flags.response_requested",
+ FT_BOOLEAN, 16, NULL, SMB_DIRECT_RESPONSE_REQUESTED,
+ NULL, HFILL }},
{ &hf_smb_direct_remaining_length,
- { "RemainingLength", "smb_direct.remaining_length", FT_UINT32, BASE_DEC,
- NULL, 0, NULL, HFILL }},
+ { "RemainingLength", "smb_direct.remaining_length",
+ FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
{ &hf_smb_direct_data_offset,
- { "DataOffset", "smb_direct.data_offset", FT_UINT32, BASE_DEC,
- NULL, 0, NULL, HFILL }},
+ { "DataOffset", "smb_direct.data_offset",
+ FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL }},
{ &hf_smb_direct_data_length,
- { "DataLength", "smb_direct.data_length", FT_UINT32, BASE_DEC,
- NULL, 0, NULL, HFILL }},
+ { "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");
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