epan/dissectors/packet-iwarp-mpa.c tcp_dissect_pdus
authorStefan Metzmacher <metze@samba.org>
Wed, 22 Aug 2018 15:02:37 +0000 (17:02 +0200)
committerStefan Metzmacher <metze@samba.org>
Sun, 20 Jan 2019 22:14:58 +0000 (23:14 +0100)
Change-Id: Ib9e4dc4790f10bede0732261404507132771b01f

epan/dissectors/packet-iwarp-mpa.c

index 81c5301..8aeb2a8 100644 (file)
@@ -829,6 +829,104 @@ dissect_iwarp_mpa(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *dat
        return FALSE;
 }
 
+static guint
+iwrap_mpa_pdu_length(packet_info *pinfo _U_, tvbuff_t *tvb,
+                    int offset, void *data _U_)
+{
+       guint64 tag;
+       gint remaining = tvb_captured_length_remaining(tvb, offset);
+       guint pdu_length = 0;
+       guint16 PD_Length;
+
+       tag = tvb_get_ntoh64(tvb, offset);
+       if (tag != MPA_REQ_REP_FRAME) {
+               /* FPDU */
+               guint16 ULPDU_Length;
+               guint8 pad_length;
+
+               ULPDU_Length = tvb_get_ntohs(tvb, offset);
+               pad_length = fpdu_pad_length(ULPDU_Length);
+
+               pdu_length += MPA_ULPDU_LENGTH_LEN;
+               pdu_length += ULPDU_Length;
+               pdu_length += pad_length;
+               pdu_length += MPA_CRC_LEN;
+
+               return pdu_length;
+       }
+
+       /*
+        * MPA Request and Reply Frame Format...
+        */
+
+       if (remaining < MPA_REQ_REP_FRAME_HEADER_LEN) {
+               /*
+                * We need more data.
+                */
+               return 0;
+       }
+
+       offset += MPA_REQ_REP_FRAME_HEADER_LEN;
+       offset -= MPA_REQ_REP_PDLENGTH_LEN;
+
+       PD_Length = tvb_get_ntohs(tvb, offset);
+
+       pdu_length += MPA_REQ_REP_FRAME_HEADER_LEN;
+       pdu_length += PD_Length;
+
+       return pdu_length;
+}
+
+static int
+dissect_iwarp_mpa_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+       gboolean ok;
+       guint len;
+
+       len = iwrap_mpa_pdu_length(pinfo, tvb, 0, data);
+       ok = dissect_iwarp_mpa(tvb, pinfo, tree, data);
+       if (!ok) {
+               return -1;
+       }
+
+       return len;
+}
+
+static gboolean
+dissect_iwarp_mpa_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+       struct tcpinfo *tcpinfo = NULL;
+       gboolean is_mpa_pdu = FALSE;
+
+       if (data == NULL)
+               return FALSE;
+       tcpinfo = (struct tcpinfo *)data;
+
+       /* MPA REQUEST or MPA REPLY */
+       if (tvb_captured_length(tvb) >= MPA_REQ_REP_FRAME_HEADER_LEN) {
+               if (is_mpa_req(tvb, pinfo)) {
+                       is_mpa_pdu = TRUE;
+               } else if (is_mpa_rep(tvb, pinfo)) {
+                       is_mpa_pdu = TRUE;
+               }
+       }
+       if (tvb_captured_length(tvb) >= MPA_SMALLEST_FPDU_LEN && is_mpa_fpdu(pinfo)) {
+               is_mpa_pdu = TRUE;
+       }
+
+       if (!is_mpa_pdu) {
+               return FALSE;
+       }
+
+       tcp_dissect_pdus(tvb, pinfo, tree,
+                        TRUE, /* proto_desegment*/
+                        MPA_SMALLEST_FPDU_LEN,
+                        iwrap_mpa_pdu_length,
+                        dissect_iwarp_mpa_pdu,
+                        tcpinfo);
+       return TRUE;
+}
+
 /* registers this protocol with Wireshark */
 void proto_register_mpa(void)
 {
@@ -949,7 +1047,7 @@ proto_reg_handoff_mpa(void)
         * MPA does not use any specific TCP port so, when not on a specific
         * port, try this dissector whenever there is TCP traffic.
         */
-       heur_dissector_add("tcp", dissect_iwarp_mpa, "IWARP_MPA over TCP", "iwarp_mpa_tcp", proto_iwarp_mpa, HEURISTIC_ENABLE);
+       heur_dissector_add("tcp", dissect_iwarp_mpa_heur, "IWARP_MPA over TCP", "iwarp_mpa_tcp", proto_iwarp_mpa, HEURISTIC_ENABLE);
        ddp_rdmap_handle = find_dissector_add_dependency("iwarp_ddp_rdmap", proto_iwarp_mpa);
 }