aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2015-05-04 16:52:32 +0200
committerMichael Mann <mmann78@netscape.net>2015-11-10 01:13:38 +0000
commit411112a1ff172a6ef7530c06a8887de1973a1205 (patch)
treecd95b8ef36ee43a8ea3d52882460310b1b6402b1
parentd64cf48ce0395d89ef3c595a6707d9d5bfd06611 (diff)
packet-smb2: provide reassembling support for Named Pipe subdissectors (e.g. DCERPC)
Change-Id: Ie6f28fd749219ddadc53820f94866e91cca297cb Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-on: https://code.wireshark.org/review/11596 Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
-rw-r--r--epan/dissectors/packet-dcerpc.c2
-rw-r--r--epan/dissectors/packet-mswsp.c2
-rw-r--r--epan/dissectors/packet-smb2.c343
3 files changed, 324 insertions, 23 deletions
diff --git a/epan/dissectors/packet-dcerpc.c b/epan/dissectors/packet-dcerpc.c
index fdbf2b7d9e..a3120c9ea9 100644
--- a/epan/dissectors/packet-dcerpc.c
+++ b/epan/dissectors/packet-dcerpc.c
@@ -6981,7 +6981,7 @@ proto_reg_handoff_dcerpc(void)
heur_dissector_add("netbios", dissect_dcerpc_cn_pk, "DCE/RPC over NetBios", "dcerpc_netbios", proto_dcerpc, HEURISTIC_ENABLE);
heur_dissector_add("udp", dissect_dcerpc_dg, "DCE/RPC over UDP", "dcerpc_udp", proto_dcerpc, HEURISTIC_ENABLE);
heur_dissector_add("smb_transact", dissect_dcerpc_cn_smbpipe, "DCE/RPC over SMB", "dcerpc_smb_transact", proto_dcerpc, HEURISTIC_ENABLE);
- heur_dissector_add("smb2_heur_subdissectors", dissect_dcerpc_cn_smb2, "DCE/RPC over SMB2", "dcerpc_smb2", proto_dcerpc, HEURISTIC_ENABLE);
+ heur_dissector_add("smb2_pipe_subdissectors", dissect_dcerpc_cn_smb2, "DCE/RPC over SMB2", "dcerpc_smb2", proto_dcerpc, HEURISTIC_ENABLE);
heur_dissector_add("http", dissect_dcerpc_cn_bs, "DCE/RPC over HTTP", "dcerpc_http", proto_dcerpc, HEURISTIC_ENABLE);
dcerpc_smb_init(proto_dcerpc);
diff --git a/epan/dissectors/packet-mswsp.c b/epan/dissectors/packet-mswsp.c
index 092d393cc0..6989500a3d 100644
--- a/epan/dissectors/packet-mswsp.c
+++ b/epan/dissectors/packet-mswsp.c
@@ -8094,7 +8094,7 @@ void
proto_reg_handoff_mswsp(void)
{
heur_dissector_add("smb_transact", dissect_mswsp_smb, "WSP over SMB1", "smb1_wsp", proto_mswsp, HEURISTIC_ENABLE);
- heur_dissector_add("smb2_heur_subdissectors", dissect_mswsp_smb2, "WSP over SMB2", "smb2_wsp", proto_mswsp, HEURISTIC_ENABLE);
+ heur_dissector_add("smb2_pipe_subdissectors", dissect_mswsp_smb2, "WSP over SMB2", "smb2_wsp", proto_mswsp, HEURISTIC_ENABLE);
}
diff --git a/epan/dissectors/packet-smb2.c b/epan/dissectors/packet-smb2.c
index 0046e67bec..42f725697e 100644
--- a/epan/dissectors/packet-smb2.c
+++ b/epan/dissectors/packet-smb2.c
@@ -39,6 +39,7 @@
#include <epan/aftypes.h>
#include <epan/to_str.h>
#include <epan/asn1.h>
+#include <epan/reassemble.h>
#include "packet-smb2.h"
#include "packet-ntlmssp.h"
@@ -387,6 +388,17 @@ static int hf_smb2_transform_encrypted_data = -1;
static int hf_smb2_server_component_smb2 = -1;
static int hf_smb2_server_component_smb2_transform = -1;
static int hf_smb2_truncated = -1;
+static int hf_smb2_pipe_fragments = -1;
+static int hf_smb2_pipe_fragment = -1;
+static int hf_smb2_pipe_fragment_overlap = -1;
+static int hf_smb2_pipe_fragment_overlap_conflict = -1;
+static int hf_smb2_pipe_fragment_multiple_tails = -1;
+static int hf_smb2_pipe_fragment_too_long_fragment = -1;
+static int hf_smb2_pipe_fragment_error = -1;
+static int hf_smb2_pipe_fragment_count = -1;
+static int hf_smb2_pipe_reassembled_in = -1;
+static int hf_smb2_pipe_reassembled_length = -1;
+static int hf_smb2_pipe_reassembled_data = -1;
static gint ett_smb2 = -1;
static gint ett_smb2_olb = -1;
@@ -471,6 +483,8 @@ static gint ett_smb2_transform_enc_alg = -1;
static gint ett_smb2_buffercode = -1;
static gint ett_smb2_ioctl_network_interface_capabilities = -1;
static gint ett_qfr_entry = -1;
+static gint ett_smb2_pipe_fragment = -1;
+static gint ett_smb2_pipe_fragments = -1;
static expert_field ei_smb2_invalid_length = EI_INIT;
static expert_field ei_smb2_bad_response = EI_INIT;
@@ -481,8 +495,26 @@ static int smb2_eo_tap = -1;
static dissector_handle_t gssapi_handle = NULL;
static dissector_handle_t ntlmssp_handle = NULL;
static dissector_handle_t rsvd_handle = NULL;
-
-static heur_dissector_list_t smb2_heur_subdissector_list;
+static dissector_handle_t data_handle = NULL;
+
+static heur_dissector_list_t smb2_pipe_subdissector_list;
+
+static const fragment_items smb2_pipe_frag_items = {
+ &ett_smb2_pipe_fragment,
+ &ett_smb2_pipe_fragments,
+ &hf_smb2_pipe_fragments,
+ &hf_smb2_pipe_fragment,
+ &hf_smb2_pipe_fragment_overlap,
+ &hf_smb2_pipe_fragment_overlap_conflict,
+ &hf_smb2_pipe_fragment_multiple_tails,
+ &hf_smb2_pipe_fragment_too_long_fragment,
+ &hf_smb2_pipe_fragment_error,
+ &hf_smb2_pipe_fragment_count,
+ &hf_smb2_pipe_reassembled_in,
+ &hf_smb2_pipe_reassembled_length,
+ &hf_smb2_pipe_reassembled_data,
+ "Fragments"
+};
#define SMB2_CLASS_FILE_INFO 0x01
#define SMB2_CLASS_FS_INFO 0x02
@@ -4499,14 +4531,13 @@ dissect_smb2_cancel_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *t
return offset;
}
-static void
-smb2_set_dcerpc_file_id(packet_info *pinfo, smb2_info_t *si)
+static const smb2_fid_info_t *
+smb2_pipe_get_fid_info(const smb2_info_t *si)
{
- guint64 persistent;
smb2_fid_info_t *file = NULL;
if (si == NULL) {
- return;
+ return NULL;
}
if (si->file != NULL) {
file = si->file;
@@ -4514,6 +4545,20 @@ smb2_set_dcerpc_file_id(packet_info *pinfo, smb2_info_t *si)
file = si->saved->file;
}
if (file == NULL) {
+ return NULL;
+ }
+
+ return file;
+}
+
+static void
+smb2_pipe_set_file_id(packet_info *pinfo, smb2_info_t *si)
+{
+ guint64 persistent;
+ const smb2_fid_info_t *file = NULL;
+
+ file = smb2_pipe_get_fid_info(si);
+ if (file == NULL) {
return;
}
@@ -4522,20 +4567,232 @@ smb2_set_dcerpc_file_id(packet_info *pinfo, smb2_info_t *si)
dcerpc_set_transport_salt(persistent, pinfo);
}
+static gboolean smb2_pipe_reassembly = TRUE;
+static reassembly_table smb2_pipe_reassembly_table;
+
+static void
+smb2_pipe_reassembly_init(void)
+{
+ /*
+ * XXX - addresses_ports_reassembly_table_functions?
+ * Probably correct for SMB-over-NBT and SMB-over-TCP,
+ * as stuff from two different connections should
+ * probably not be combined, but what about other
+ * transports for SMB, e.g. NBF or Netware?
+ */
+ reassembly_table_init(&smb2_pipe_reassembly_table,
+ &addresses_reassembly_table_functions);
+}
+
static int
-dissect_file_data_dcerpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, int offset, guint32 datalen, proto_tree *top_tree, void *data)
+dissect_file_data_smb2_pipe(tvbuff_t *raw_tvb, packet_info *pinfo, proto_tree *tree _U_, int offset, guint32 datalen, proto_tree *top_tree, void *data)
{
- tvbuff_t *dcerpc_tvb;
+ /*
+ * Note: si is NULL for some callers from packet-smb.c
+ */
+ const smb2_info_t *si = (const smb2_info_t *)data;
+ gboolean result=0;
+ gboolean save_fragmented;
+ gint remaining;
+ guint reported_len;
+ const smb2_fid_info_t *file = NULL;
+ guint32 id;
+ fragment_head *fd_head;
+ tvbuff_t *tvb;
+ tvbuff_t *new_tvb;
+ proto_item *frag_tree_item;
heur_dtbl_entry_t *hdtbl_entry;
- dcerpc_tvb = tvb_new_subset(tvb, offset, MIN((int)datalen, tvb_captured_length_remaining(tvb, offset)), datalen);
+ file = smb2_pipe_get_fid_info(si);
+ id = (guint32)(GPOINTER_TO_UINT(file) & G_MAXUINT32);
+
+ remaining = tvb_captured_length_remaining(raw_tvb, offset);
+
+ tvb = tvb_new_subset(raw_tvb, offset,
+ MIN((int)datalen, remaining),
+ datalen);
+
+ /*
+ * Offer desegmentation service to Named Pipe subdissectors (e.g. DCERPC)
+ * if we have all the data. Otherwise, reassembly is (probably) impossible.
+ */
+ pinfo->can_desegment = 0;
+ pinfo->desegment_offset = 0;
+ pinfo->desegment_len = 0;
+ reported_len = tvb_reported_length(tvb);
+ if (smb2_pipe_reassembly && tvb_captured_length(tvb) >= reported_len) {
+ pinfo->can_desegment = 2;
+ }
+
+ save_fragmented = pinfo->fragmented;
+
+ /*
+ * if we are not offering desegmentation, just try the heuristics
+ *and bail out
+ */
+ if (!pinfo->can_desegment) {
+ result = dissector_try_heuristic(smb2_pipe_subdissector_list,
+ tvb, pinfo, top_tree,
+ &hdtbl_entry, NULL);
+ goto clean_up_and_exit;
+ }
+
+ /* below this line, we know we are doing reassembly */
+
+ /*
+ * this is a new packet, see if we are already reassembling this
+ * pdu and if not, check if the dissector wants us
+ * to reassemble it
+ */
+ if (!pinfo->fd->flags.visited) {
+ /*
+ * This is the first pass.
+ *
+ * Check if we are already reassembling this PDU or not;
+ * we check for an in-progress reassembly for this FID
+ * in this direction, by searching for its reassembly
+ * structure.
+ */
+ fd_head = fragment_get(&smb2_pipe_reassembly_table,
+ pinfo, id, NULL);
+ if (!fd_head) {
+ /*
+ * No reassembly, so this is a new pdu. check if the
+ * dissector wants us to reassemble it or if we
+ * already got the full pdu in this tvb.
+ */
+
+ /*
+ * Try the heuristic dissectors and see if we
+ * find someone that recognizes this payload.
+ */
+ result = dissector_try_heuristic(smb2_pipe_subdissector_list,
+ tvb, pinfo, top_tree,
+ &hdtbl_entry, NULL);
+
+ /* no this didn't look like something we know */
+ if (!result) {
+ goto clean_up_and_exit;
+ }
+
+ /* did the subdissector want us to reassemble any
+ more data ?
+ */
+ if (pinfo->desegment_len) {
+ fragment_add_check(&smb2_pipe_reassembly_table,
+ tvb, 0, pinfo, id, NULL,
+ 0, reported_len, TRUE);
+ fragment_set_tot_len(&smb2_pipe_reassembly_table,
+ pinfo, id, NULL,
+ pinfo->desegment_len+reported_len);
+ }
+ goto clean_up_and_exit;
+ }
+
+ /* OK, we're already doing a reassembly for this FID.
+ skip to last segment in the existing reassembly structure
+ and add this fragment there
+
+ XXX we might add code here to use any offset values
+ we might pick up from the Read/Write calls instead of
+ assuming we always get them in the correct order
+ */
+ while (fd_head->next) {
+ fd_head = fd_head->next;
+ }
+ fd_head = fragment_add_check(&smb2_pipe_reassembly_table,
+ tvb, 0, pinfo, id, NULL,
+ fd_head->offset+fd_head->len,
+ reported_len, TRUE);
+
+ /* if we completed reassembly */
+ if (fd_head) {
+ new_tvb = tvb_new_chain(tvb, fd_head->tvb_data);
+ add_new_data_source(pinfo, new_tvb,
+ "Named Pipe over SMB2");
+ pinfo->fragmented=FALSE;
+
+ tvb = new_tvb;
+
+ /* list what segments we have */
+ show_fragment_tree(fd_head, &smb2_pipe_frag_items,
+ tree, pinfo, tvb, &frag_tree_item);
+
+ /* dissect the full PDU */
+ result = dissector_try_heuristic(smb2_pipe_subdissector_list,
+ tvb, pinfo, top_tree,
+ &hdtbl_entry, NULL);
+ }
+ goto clean_up_and_exit;
+ }
+
+ /*
+ * This is not the first pass; see if it's in the table of
+ * reassembled packets.
+ *
+ * XXX - we know that several of the arguments aren't going to
+ * be used, so we pass bogus variables. Can we clean this
+ * up so that we don't have to distinguish between the first
+ * pass and subsequent passes?
+ */
+ fd_head = fragment_add_check(&smb2_pipe_reassembly_table,
+ tvb, 0, pinfo, id, NULL, 0, 0, TRUE);
+ if (!fd_head) {
+ /* we didn't find it, try any of the heuristic dissectors
+ and bail out
+ */
+ result = dissector_try_heuristic(smb2_pipe_subdissector_list,
+ tvb, pinfo, top_tree,
+ &hdtbl_entry, NULL);
+ goto clean_up_and_exit;
+ }
+ if (!(fd_head->flags&FD_DEFRAGMENTED)) {
+ /* we don't have a fully reassembled frame */
+ result = dissector_try_heuristic(smb2_pipe_subdissector_list,
+ tvb, pinfo, top_tree,
+ &hdtbl_entry, NULL);
+ goto clean_up_and_exit;
+ }
+
+ /* it is reassembled but it was reassembled in a different frame */
+ if (pinfo->fd->num != fd_head->reassembled_in) {
+ proto_item *item;
+ item = proto_tree_add_uint(top_tree, hf_smb2_pipe_reassembled_in,
+ tvb, 0, 0, fd_head->reassembled_in);
+ PROTO_ITEM_SET_GENERATED(item);
+ goto clean_up_and_exit;
+ }
+
+ /* display the reassembled pdu */
+ new_tvb = tvb_new_chain(tvb, fd_head->tvb_data);
+ add_new_data_source(pinfo, new_tvb,
+ "Named Pipe over SMB2");
+ pinfo->fragmented = FALSE;
+
+ tvb = new_tvb;
+
+ /* list what segments we have */
+ show_fragment_tree(fd_head, &smb2_pipe_frag_items,
+ top_tree, pinfo, tvb, &frag_tree_item);
/* dissect the full PDU */
- if (dissector_try_heuristic(smb2_heur_subdissector_list, dcerpc_tvb, pinfo, top_tree, &hdtbl_entry, data)) {
+ result = dissector_try_heuristic(smb2_pipe_subdissector_list,
+ tvb, pinfo, top_tree,
+ &hdtbl_entry, NULL);
+clean_up_and_exit:
+ /* clear out the variables */
+ pinfo->can_desegment=0;
+ pinfo->desegment_offset = 0;
+ pinfo->desegment_len = 0;
- offset += datalen;
+ if (!result) {
+ call_dissector(data_handle, tvb, pinfo, top_tree);
}
+
+ pinfo->fragmented = save_fragmented;
+
+ offset += datalen;
return offset;
}
@@ -4653,11 +4910,11 @@ dissect_smb2_write_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
break;
}
- /* data or dcerpc ?*/
+ /* data or namedpipe ?*/
if (length) {
int oldoffset = offset;
- smb2_set_dcerpc_file_id(pinfo, si);
- offset = dissect_file_data_dcerpc(tvb, pinfo, tree, offset, length, si->top_tree, si);
+ smb2_pipe_set_file_id(pinfo, si);
+ offset = dissect_file_data_smb2_pipe(tvb, pinfo, tree, offset, length, si->top_tree, si);
if (offset != oldoffset) {
/* managed to dissect pipe data */
return offset;
@@ -4755,7 +5012,7 @@ dissect_smb2_FSCTL_OFFLOAD_READ(tvbuff_t *tvb,
static void
dissect_smb2_FSCTL_PIPE_TRANSCEIVE(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *top_tree, gboolean data_in _U_, void *data)
{
- dissect_file_data_dcerpc(tvb, pinfo, tree, offset, tvb_captured_length_remaining(tvb, offset), top_tree, data);
+ dissect_file_data_smb2_pipe(tvb, pinfo, tree, offset, tvb_captured_length_remaining(tvb, offset), top_tree, data);
}
static void
@@ -5409,14 +5666,14 @@ dissect_smb2_ioctl_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, pro
static void
dissect_smb2_ioctl_data_in(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si)
{
- smb2_set_dcerpc_file_id(pinfo, si);
+ smb2_pipe_set_file_id(pinfo, si);
dissect_smb2_ioctl_data(tvb, pinfo, tree, si->top_tree, si->ioctl_function, TRUE, si);
}
static void
dissect_smb2_ioctl_data_out(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si)
{
- smb2_set_dcerpc_file_id(pinfo, si);
+ smb2_pipe_set_file_id(pinfo, si);
dissect_smb2_ioctl_data(tvb, pinfo, tree, si->top_tree, si->ioctl_function, FALSE, si);
}
@@ -5495,6 +5752,7 @@ dissect_smb2_ioctl_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
switch (si->status) {
case 0x00000000: break;
+ case 0x80000005: break;
default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
}
@@ -5646,11 +5904,11 @@ dissect_smb2_read_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/* reserved */
offset += 4;
- /* data or dcerpc ?*/
+ /* data or namedpipe ?*/
if (length) {
int oldoffset = offset;
- smb2_set_dcerpc_file_id(pinfo, si);
- offset = dissect_file_data_dcerpc(tvb, pinfo, tree, offset, length, si->top_tree, si);
+ smb2_pipe_set_file_id(pinfo, si);
+ offset = dissect_file_data_smb2_pipe(tvb, pinfo, tree, offset, length, si->top_tree, si);
if (offset != oldoffset) {
/* managed to dissect pipe data */
return offset;
@@ -9239,6 +9497,40 @@ proto_register_smb2(void)
{ &hf_smb2_truncated,
{ "Truncated...", "smb2.truncated", FT_NONE, BASE_NONE,
NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_pipe_fragment_overlap,
+ { "Fragment overlap", "smb2.pipe.fragment.overlap", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
+ { &hf_smb2_pipe_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "smb2.pipe.fragment.overlap.conflict", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "Overlapping fragments contained conflicting data", HFILL }},
+ { &hf_smb2_pipe_fragment_multiple_tails,
+ { "Multiple tail fragments found", "smb2.pipe.fragment.multipletails", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "Several tails were found when defragmenting the packet", HFILL }},
+ { &hf_smb2_pipe_fragment_too_long_fragment,
+ { "Fragment too long", "smb2.pipe.fragment.toolongfragment", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "Fragment contained data past end of packet", HFILL }},
+ { &hf_smb2_pipe_fragment_error,
+ { "Defragmentation error", "smb2.pipe.fragment.error", FT_FRAMENUM,
+ BASE_NONE, NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
+ { &hf_smb2_pipe_fragment_count,
+ { "Fragment count", "smb2.pipe.fragment.count", FT_UINT32,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_smb2_pipe_fragment,
+ { "Fragment SMB2 Named Pipe", "smb2.pipe.fragment", FT_FRAMENUM,
+ BASE_NONE, NULL, 0x0, "SMB2 Named Pipe Fragment", HFILL }},
+ { &hf_smb2_pipe_fragments,
+ { "Reassembled SMB2 Named Pipe fragments", "smb2.pipe.fragments", FT_NONE,
+ BASE_NONE, NULL, 0x0, "SMB2 Named Pipe Fragments", HFILL }},
+ { &hf_smb2_pipe_reassembled_in,
+ { "This SMB2 Named Pipe payload is reassembled in frame", "smb2.pipe.reassembled_in", FT_FRAMENUM,
+ BASE_NONE, NULL, 0x0, "The Named Pipe PDU is completely reassembled in this frame", HFILL }},
+ { &hf_smb2_pipe_reassembled_length,
+ { "Reassembled SMB2 Named Pipe length", "smb2.pipe.reassembled.length", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "The total length of the reassembled payload", HFILL }},
+ { &hf_smb2_pipe_reassembled_data,
+ { "Reassembled SMB2 Named Pipe Data", "smb2.pipe.reassembled.data", FT_BYTES,
+ BASE_NONE, NULL, 0x0, "The reassembled payload", HFILL }},
};
static gint *ett[] = {
@@ -9325,6 +9617,8 @@ proto_register_smb2(void)
&ett_smb2_buffercode,
&ett_smb2_ioctl_network_interface_capabilities,
&ett_qfr_entry,
+ &ett_smb2_pipe_fragment,
+ &ett_smb2_pipe_fragments,
};
static ei_register_info ei[] = {
@@ -9347,7 +9641,13 @@ proto_register_smb2(void)
"Whether the export object functionality will take the full path file name as file identifier",
&eosmb2_take_name_as_fid);
- smb2_heur_subdissector_list = register_heur_dissector_list("smb2_heur_subdissectors");
+ prefs_register_bool_preference(smb2_module, "pipe_reassembly",
+ "Reassemble Named Pipes over SMB2",
+ "Whether the dissector should reassemble Named Pipes over SMB2 commands",
+ &smb2_pipe_reassembly);
+ smb2_pipe_subdissector_list = register_heur_dissector_list("smb2_pipe_subdissectors");
+ register_init_routine(smb2_pipe_reassembly_init);
+
smb2_tap = register_tap("smb2");
smb2_eo_tap = register_tap("smb_eo"); /* SMB Export Object tap */
@@ -9360,6 +9660,7 @@ proto_reg_handoff_smb2(void)
gssapi_handle = find_dissector("gssapi");
ntlmssp_handle = find_dissector("ntlmssp");
rsvd_handle = find_dissector("rsvd");
+ data_handle = find_dissector("data");
heur_dissector_add("netbios", dissect_smb2_heur, "SMB2 over Netbios", "smb2_netbios", proto_smb2, HEURISTIC_ENABLE);
heur_dissector_add("smb_direct", dissect_smb2_heur, "SMB2 over SMB Direct", "smb2_smb_direct", proto_smb2, HEURISTIC_ENABLE);
}