diff options
author | Brian Sipos <brian.sipos@gmail.com> | 2021-10-17 19:08:30 -0400 |
---|---|---|
committer | Wireshark GitLab Utility <gerald+gitlab-utility@wireshark.org> | 2021-10-19 19:30:34 +0000 |
commit | c1c5db86b6b944a7b51ab68e3beb4de518b2ddbe (patch) | |
tree | 2914d8732159ee9b366623fb113b4edf7dd18257 | |
parent | 2e65045db60e7c4c9731eaa2bfa7f4e29b229f43 (diff) |
TCPCL: Reassemble with full 64-bit transfer ID
-rw-r--r-- | epan/dissectors/packet-tcpcl.c | 132 |
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 ); } |