aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2018-08-22 17:02:37 +0200
committerStefan Metzmacher <metze@samba.org>2021-04-29 14:33:04 +0200
commit16988d2b4f4bca2b9564b19debdd90577b4b52ea (patch)
tree7a1698067bcc8dc99d8a3d1bb20f00dc694e9744
parentf25c3ccc081d05e7d6c62aedb8b2ce0167f7eceb (diff)
packet-iwarp-mpa: make use of tcp_dissect_pdus() to reassamble pdus
There might be more than one mpa frame in a tcp pdu or one mpa frame spans more than one tcp pdu. Signed-off-by: Stefan Metzmacher <metze@samba.org>
-rw-r--r--epan/dissectors/packet-iwarp-mpa.c100
1 files changed, 99 insertions, 1 deletions
diff --git a/epan/dissectors/packet-iwarp-mpa.c b/epan/dissectors/packet-iwarp-mpa.c
index 6da357c4c6..2e14c1e1dd 100644
--- a/epan/dissectors/packet-iwarp-mpa.c
+++ b/epan/dissectors/packet-iwarp-mpa.c
@@ -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);
}