aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Sipos <brian.sipos@gmail.com>2021-10-17 19:08:30 -0400
committerWireshark GitLab Utility <gerald+gitlab-utility@wireshark.org>2021-10-19 19:30:34 +0000
commitc1c5db86b6b944a7b51ab68e3beb4de518b2ddbe (patch)
tree2914d8732159ee9b366623fb113b4edf7dd18257
parent2e65045db60e7c4c9731eaa2bfa7f4e29b229f43 (diff)
TCPCL: Reassemble with full 64-bit transfer ID
-rw-r--r--epan/dissectors/packet-tcpcl.c132
1 files changed, 92 insertions, 40 deletions
diff --git a/epan/dissectors/packet-tcpcl.c b/epan/dissectors/packet-tcpcl.c
index d2565e1736..b63636add8 100644
--- a/epan/dissectors/packet-tcpcl.c
+++ b/epan/dissectors/packet-tcpcl.c
@@ -549,7 +549,6 @@ static expert_field ei_tcpclv4_xfer_seg_duplicate_start = EI_INIT;
static expert_field ei_tcpclv4_xfer_seg_missing_end = EI_INIT;
static expert_field ei_tcpclv4_xfer_seg_duplicate_end = EI_INIT;
static expert_field ei_tcpclv4_xfer_seg_no_relation = EI_INIT;
-static expert_field ei_xfer_seg_large_xferid = EI_INIT;
static expert_field ei_xfer_seg_over_total_len = EI_INIT;
static expert_field ei_xfer_mismatch_total_len = EI_INIT;
static expert_field ei_xfer_ack_mismatch_flags = EI_INIT;
@@ -584,7 +583,6 @@ static ei_register_info ei_tcpcl[] = {
{&ei_tcpclv4_xfer_seg_no_relation, { "tcpcl.v4.xfer_seg_no_relation", PI_SEQUENCE, PI_NOTE, "XFER_SEGMENT has no related XFER_ACK", EXPFILL}},
{&ei_tcpclv4_xfer_refuse_no_transfer, { "tcpcl.v4.xfer_refuse_no_transfer", PI_SEQUENCE, PI_NOTE, "XFER_REFUSE has no related XFER_SEGMENT(s)", EXPFILL}},
{&ei_tcpclv4_xferload_over_xfer_mru, { "tcpcl.v4.xferload_over_xfer_mru", PI_SEQUENCE, PI_NOTE, "Transfer larger than peer MRU", EXPFILL}},
- {&ei_xfer_seg_large_xferid, { "tcpcl.xfer_seg_large_xferid", PI_REASSEMBLE, PI_WARN, "XFER_SEGMENT has a transfer ID larger than Wireshark can handle", EXPFILL}},
{&ei_xfer_seg_over_total_len, { "tcpcl.xfer_seg_over_total_len", PI_SEQUENCE, PI_ERROR, "XFER_SEGMENT has accumulated length beyond the Transfer Length extension", EXPFILL}},
{&ei_xfer_mismatch_total_len, { "tcpcl.xfer_mismatch_total_len", PI_SEQUENCE, PI_ERROR, "Transfer has total length different than the Transfer Length extension", EXPFILL}},
{&ei_xfer_ack_mismatch_flags, { "tcpcl.xfer_ack_mismatch_flags", PI_SEQUENCE, PI_ERROR, "XFER_ACK does not have flags matching XFER_SEGMENT", EXPFILL}},
@@ -881,6 +879,69 @@ static void try_negotiate(tcpcl_dissect_ctx_t *ctx, packet_info *pinfo) {
}
}
+typedef struct {
+ // key type for addresses_ports_reassembly_table_functions
+ void *addr_port;
+ // TCPCL ID
+ guint64 xfer_id;
+} tcpcl_fragment_key_t;
+
+static guint fragment_key_hash(gconstpointer ptr) {
+ const tcpcl_fragment_key_t *obj = (const tcpcl_fragment_key_t *)ptr;
+ return (
+ addresses_ports_reassembly_table_functions.hash_func(obj->addr_port)
+ ^ g_int64_hash(&(obj->xfer_id))
+ );
+}
+
+static gboolean fragment_key_equal(gconstpointer ptrA, gconstpointer ptrB) {
+ const tcpcl_fragment_key_t *objA = (const tcpcl_fragment_key_t *)ptrA;
+ const tcpcl_fragment_key_t *objB = (const tcpcl_fragment_key_t *)ptrB;
+ return (
+ addresses_ports_reassembly_table_functions.equal_func(objA->addr_port, objB->addr_port)
+ && (objA->xfer_id == objB->xfer_id)
+ );
+}
+
+static gpointer fragment_key_temporary(const packet_info *pinfo, const guint32 id, const void *data) {
+ tcpcl_fragment_key_t *obj = g_slice_new(tcpcl_fragment_key_t);
+ obj->addr_port = addresses_ports_reassembly_table_functions.temporary_key_func(pinfo, id, NULL);
+ obj->xfer_id = *((const guint64 *)data);
+ return (gpointer)obj;
+}
+
+static gpointer fragment_key_persistent(const packet_info *pinfo, const guint32 id, const void *data) {
+ tcpcl_fragment_key_t *obj = g_slice_new(tcpcl_fragment_key_t);
+ obj->addr_port = addresses_ports_reassembly_table_functions.persistent_key_func(pinfo, id, NULL);
+ obj->xfer_id = *((const guint64 *)data);
+ return (gpointer)obj;
+}
+
+static void fragment_key_free_temporary(gpointer ptr) {
+ tcpcl_fragment_key_t *obj = (tcpcl_fragment_key_t *)ptr;
+ if (obj) {
+ addresses_ports_reassembly_table_functions.free_temporary_key_func(obj->addr_port);
+ g_slice_free(tcpcl_fragment_key_t, obj);
+ }
+}
+
+static void fragment_key_free_persistent(gpointer ptr) {
+ tcpcl_fragment_key_t *obj = (tcpcl_fragment_key_t *)ptr;
+ if (obj) {
+ addresses_ports_reassembly_table_functions.free_persistent_key_func(obj->addr_port);
+ g_slice_free(tcpcl_fragment_key_t, obj);
+ }
+}
+
+static reassembly_table_functions xfer_reassembly_table_functions = {
+ fragment_key_hash,
+ fragment_key_equal,
+ fragment_key_temporary,
+ fragment_key_persistent,
+ fragment_key_free_temporary,
+ fragment_key_free_persistent
+};
+
/** Record metadata about one segment in a transfer.
*/
static void transfer_add_segment(tcpcl_dissect_ctx_t *ctx, guint64 xfer_id, guint8 flags,
@@ -1221,24 +1282,22 @@ dissect_v3_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
}
if (tcpcl_desegment_transfer) {
- // wireshark fragment set IDs are 32-bits only
- const guint32 corr_id = *xfer_id & 0xFFFFFFFF;
// Reassemble the segments
fragment_head *frag_msg;
frag_msg = fragment_add_seq_next(
- &xfer_reassembly_table,
- tvb, offset,
- pinfo, corr_id, NULL,
- segment_length,
- !(conv_hdr & TCPCLV3_DATA_END_FLAG)
+ &xfer_reassembly_table,
+ tvb, offset,
+ pinfo, 0, xfer_id,
+ segment_length,
+ !(conv_hdr & TCPCLV3_DATA_END_FLAG)
);
ctx->xferload = process_reassembled_data(
- tvb, offset, pinfo,
- "Reassembled Transfer",
- frag_msg,
- &xfer_frag_items,
- NULL,
- proto_tree_get_parent_tree(tree)
+ tvb, offset, pinfo,
+ "Reassembled Transfer",
+ frag_msg,
+ &xfer_frag_items,
+ NULL,
+ proto_tree_get_parent_tree(tree)
);
}
offset += segment_length;
@@ -1561,7 +1620,7 @@ dissect_v4_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
offset += 1;
guint64 xfer_id = tvb_get_guint64(tvb, offset, ENC_BIG_ENDIAN);
- proto_item *item_xfer_id = proto_tree_add_uint64(tree_msg, hf_tcpclv4_xfer_id, tvb, offset, 8, xfer_id);
+ proto_tree_add_uint64(tree_msg, hf_tcpclv4_xfer_id, tvb, offset, 8, xfer_id);
offset += 8;
if (flags & TCPCLV4_TRANSFER_FLAG_START) {
@@ -1653,29 +1712,22 @@ dissect_v4_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
}
if (tcpcl_desegment_transfer) {
- // wireshark fragment set IDs are 32-bits only
- const guint32 corr_id = xfer_id & 0xFFFFFFFF;
- if (corr_id != xfer_id) {
- expert_add_info(pinfo, item_xfer_id, &ei_xfer_seg_large_xferid);
- }
- else {
- // Reassemble the segments
- fragment_head *xferload_frag_msg = fragment_add_seq_next(
- &xfer_reassembly_table,
- tvb, data_offset,
- pinfo, corr_id, NULL,
- data_len_clamp,
- !(flags & TCPCLV4_TRANSFER_FLAG_END)
- );
- ctx->xferload = process_reassembled_data(
- tvb, data_offset, pinfo,
- "Reassembled Transfer",
- xferload_frag_msg,
- &xfer_frag_items,
- NULL,
- proto_tree_get_parent_tree(tree)
- );
- }
+ // Reassemble the segments
+ fragment_head *xferload_frag_msg = fragment_add_seq_next(
+ &xfer_reassembly_table,
+ tvb, data_offset,
+ pinfo, 0, &xfer_id,
+ data_len_clamp,
+ !(flags & TCPCLV4_TRANSFER_FLAG_END)
+ );
+ ctx->xferload = process_reassembled_data(
+ tvb, data_offset, pinfo,
+ "Reassembled Transfer",
+ xferload_frag_msg,
+ &xfer_frag_items,
+ NULL,
+ proto_tree_get_parent_tree(tree)
+ );
}
break;
@@ -2115,7 +2167,7 @@ proto_register_tcpclv3(void)
reassembly_table_register(
&xfer_reassembly_table,
- &addresses_reassembly_table_functions
+ &xfer_reassembly_table_functions
);
}