reassamble...
authorStefan Metzmacher <metze@samba.org>
Fri, 24 Nov 2017 14:26:17 +0000 (15:26 +0100)
committerStefan Metzmacher <metze@samba.org>
Sun, 20 Jan 2019 22:14:58 +0000 (23:14 +0100)
Change-Id: Iaa9cfd359730a046f2b6f03bb95ea4a8994b687c

epan/dissectors/packet-nmf.c

index 53f4cde..08e28b8 100644 (file)
@@ -23,9 +23,9 @@
 #include "config.h"
 
 #include <epan/packet.h>
-#include <epan/reassemble.h>
 #include <epan/prefs.h>
 #include <epan/proto_data.h>
+#include "packet-tcp.h"
 #include "packet-windows-common.h"
 #include "packet-gssapi.h"
 
@@ -49,6 +49,8 @@ static int hf_nmf_known_mode_value = -1;
 static int hf_nmf_upgrade_length = -1;
 static int hf_nmf_upgrade_protocol = -1;
 
+static gboolean nmf_reassemble = TRUE;
+
 enum nmf_record_type {
        NMF_VERSION_RECORD              = 0x00,
        NMF_MODE_RECORD                 = 0x01,
@@ -110,7 +112,6 @@ static int
 dissect_nmf_record_size(tvbuff_t *tvb, proto_tree *tree,
                        int hf_index, int offset, guint32 *_size)
 {
-       proto_item *item = NULL;
        guint8 byte = tvb_get_guint8(tvb, offset);
        guint32 size = 0;
        guint8 shift = 0;
@@ -128,11 +129,14 @@ dissect_nmf_record_size(tvbuff_t *tvb, proto_tree *tree,
                *_size = size;
        }
 
-       item = proto_tree_add_item(tree, hf_index, tvb,
-                                  start_offset, -1, ENC_NA);
-       proto_item_set_end(item, tvb, offset);
-       proto_item_append_text(item, ": %u (0x%x)",
-                               (guint)size, (guint)size);
+       if (tree != NULL && hf_index != -1) {
+               proto_item *item = NULL;
+               item = proto_tree_add_item(tree, hf_index, tvb,
+                                          start_offset, -1, ENC_NA);
+               proto_item_set_end(item, tvb, offset);
+               proto_item_append_text(item, ": %u (0x%x)",
+                                       (guint)size, (guint)size);
+       }
 
        return offset;
 }
@@ -244,6 +248,97 @@ dissect_nmf_record(tvbuff_t *tvb, packet_info *pinfo,
        return offset;
 }
 
+static guint
+nmf_get_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *_info)
+{
+       nmf_conv_info_t *nmf_info = (nmf_conv_info_t *)_info;
+       enum nmf_record_type record_type;
+       guint32 size = 0;
+       int start_offset = offset;
+
+       if (pinfo->fd->num > nmf_info->fnum_upgraded) {
+               return tvb_captured_length_remaining(tvb, offset);
+       }
+
+       record_type = (enum nmf_record_type)tvb_get_guint8(tvb, offset);
+       offset += 1;
+
+       switch (record_type) {
+       case NMF_VERSION_RECORD:
+               offset += 2;
+               break;
+       case NMF_MODE_RECORD:
+               offset += 1;
+               break;
+       case NMF_VIA_RECORD:
+               offset = dissect_nmf_record_size(tvb, NULL, -1,
+                                                offset, &size);
+               if (offset <= 0) {
+                       return 0;
+               }
+               offset += size;
+               break;
+       case NMF_KNOWN_ENCODING_RECORD:
+               offset += 1;
+               break;
+       case NMF_EXTENSIBLE_ENCODING_RECORD:
+               /* TODO */
+               break;
+       case NMF_UNSIZED_ENVELOPE_RECORD:
+               /* TODO */
+               break;
+       case NMF_SIZED_ENVELOPE_RECORD:
+               /* TODO */
+               break;
+       case NMF_END_RECORD:
+               /* TODO */
+               break;
+       case NMF_FAULT_RECORD:
+               /* TODO */
+               break;
+       case NMF_UPGRADE_REQUEST_RECORD:
+               offset = dissect_nmf_record_size(tvb, NULL, -1,
+                                                offset, &size);
+               if (offset <= 0) {
+                       return 0;
+               }
+               offset += size;
+               break;
+
+       case NMF_UPGRADE_RESPONSE_RECORD:
+               break;
+       case NMF_PREAMBLE_ACK_RECORD:
+               /* TODO */
+               break;
+       case NMF_PREAMBLE_END_RECORD:
+               /* TODO */
+               break;
+       }
+
+       return offset - start_offset;
+}
+
+static int
+dissect_nmf_pdu(tvbuff_t *tvb, packet_info *pinfo,
+               proto_tree *tree, void *_info)
+{
+       nmf_conv_info_t *nmf_info = (nmf_conv_info_t *)_info;
+
+       if (pinfo->fd->num > nmf_info->fnum_upgraded) {
+               proto_item *item = proto_tree_get_parent(tree);
+               guint len = tvb_reported_length(tvb);
+
+               col_add_fstr(pinfo->cinfo, COL_INFO,
+                            "Upgraded Packet len: %u (0x%x)",
+                            (unsigned)len, (unsigned)len);
+               proto_item_append_text(item, ", Upgraded Packet len: %u (0x%x)",
+                               (unsigned)len, (unsigned)len);
+               return len;
+       }
+
+       return dissect_nmf_record(tvb, pinfo, nmf_info, tree, 0);
+}
+
 static int
 dissect_nmf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, _U_ void *_unused)
 {
@@ -251,8 +346,6 @@ dissect_nmf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, _U_ void
        nmf_conv_info_t *nmf_info = NULL;
        proto_tree *tree = NULL;
        proto_item *item = NULL;
-       guint len = tvb_reported_length(tvb);
-       int offset = 0;
 
        conv = find_or_create_conversation(pinfo);
        nmf_info = (nmf_conv_info_t *)conversation_get_proto_data(conv,
@@ -264,7 +357,7 @@ dissect_nmf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, _U_ void
        }
 
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "NMF");
-       col_clear(pinfo->cinfo, COL_INFO);
+       col_set_str(pinfo->cinfo, COL_INFO, "NMF...");
 
        if (parent_tree != NULL) {
                item = proto_tree_add_item(parent_tree, proto_nmf, tvb, 0, -1, ENC_NA);
@@ -275,23 +368,12 @@ dissect_nmf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, _U_ void
                return -1;
        }
 
-       if (pinfo->fd->num > nmf_info->fnum_upgraded) {
-               proto_item_append_text(item, ", Upgraded Packet len: %u (0x%x)",
-                               (unsigned)len, (unsigned)len);
-               offset += len;
-               return offset;
-       }
-
-       while (len > 0) {
-               int start_offset = offset;
-               offset = dissect_nmf_record(tvb, pinfo, nmf_info, tree, offset);
-               if (offset <= 0) {
-                       return -1;
-               }
-               len -= (offset - start_offset);
-       }
-
-       return offset;
+       tcp_dissect_pdus(tvb, pinfo, tree, nmf_reassemble,
+                        1, /* fixed_length */
+                        nmf_get_pdu_len,
+                        dissect_nmf_pdu,
+                        nmf_info);
+       return tvb_captured_length(tvb);
 }
 
 void proto_register_nmf(void)
@@ -331,13 +413,22 @@ void proto_register_nmf(void)
                { "Upgrade Protocol", "nmf.upgrade.protocol",
                FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
        };
+       module_t *nmf_module = NULL;
 
        proto_nmf = proto_register_protocol("NMF (.NET Message Framing Protocol)",
                                            "NMF", "nmf");
        proto_register_subtree_array(ett, array_length(ett));
        proto_register_field_array(proto_nmf, hf, array_length(hf));
+
+       nmf_module = prefs_register_protocol(proto_nmf, NULL);
+       prefs_register_bool_preference(nmf_module,
+                                      "reassemble_nmf",
+                                      "Reassemble NMF fragments",
+                                      "Whether the NMF dissector should reassemble fragmented payloads",
+                                      &nmf_reassemble);
 }
 
+
 void
 proto_reg_handoff_nmf(void)
 {