diff options
author | Stefan Metzmacher <metze@samba.org> | 2018-08-22 17:02:37 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2021-04-29 14:33:04 +0200 |
commit | 16988d2b4f4bca2b9564b19debdd90577b4b52ea (patch) | |
tree | 7a1698067bcc8dc99d8a3d1bb20f00dc694e9744 | |
parent | f25c3ccc081d05e7d6c62aedb8b2ce0167f7eceb (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.c | 100 |
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); } |