Ethereal-dev: [Ethereal-dev] [Patch] Reassembly of COTP packets
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: MEYER Laurent <laurent.meyer@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 28 May 2003 18:06:16 +0200
Hi,
Here is a patch to add COTP reassembly capabilities,
Thanks a lot.
Laurent MEYER.
--- packet-clnp.c.orig Mon May 26 17:49:31 2003
+++ packet-clnp.c Wed May 28 17:31:45 2003
@@ -49,6 +49,10 @@
static gint ett_clnp_segment = -1;
static gint ett_clnp_disc_pdu = -1;
+static gint ett_cotp_segments = -1;
+static gint ett_cotp_segment = -1;
+
+
static int hf_clnp_id = -1;
static int hf_clnp_length = -1;
static int hf_clnp_version = -1;
@@ -69,6 +73,16 @@
static int hf_clnp_segment_error = -1;
static int hf_clnp_reassembled_in = -1;
+static int hf_cotp_segments = -1;
+static int hf_cotp_segment = -1;
+static int hf_cotp_segment_overlap = -1;
+static int hf_cotp_segment_overlap_conflict = -1;
+static int hf_cotp_segment_multiple_tails = -1;
+static int hf_cotp_segment_too_long_segment = -1;
+static int hf_cotp_segment_error = -1;
+static int hf_cotp_reassembled_in = -1;
+
+
static int proto_cotp = -1;
static gint ett_cotp = -1;
@@ -95,6 +109,21 @@
"segments"
};
+static const fragment_items cotp_frag_items = {
+ &ett_cotp_segment,
+ &ett_cotp_segments,
+ &hf_cotp_segments,
+ &hf_cotp_segment,
+ &hf_cotp_segment_overlap,
+ &hf_cotp_segment_overlap_conflict,
+ &hf_cotp_segment_multiple_tails,
+ &hf_cotp_segment_too_long_segment,
+ &hf_cotp_segment_error,
+ &hf_cotp_reassembled_in,
+ "segments"
+};
+
+
static dissector_handle_t clnp_handle;
static dissector_handle_t data_handle;
@@ -315,10 +344,17 @@
static GHashTable *clnp_segment_table = NULL;
static GHashTable *clnp_reassembled_table = NULL;
+/*
+ * Reassembly of COTP.
+ */
+static GHashTable *cotp_segment_table = NULL;
+static GHashTable *cotp_reassembled_table = NULL;
+
/* options */
static guint tp_nsap_selector = NSEL_TP;
static gboolean always_decode_transport = FALSE;
static gboolean clnp_reassemble = FALSE;
+static gboolean cotp_reassemble = FALSE;
/* function definitions */
@@ -717,6 +753,8 @@
reason = tvb_get_guint8(tvb, offset + P_REASON_IN_DR);
+ pinfo->srcport = src_ref;
+ pinfo->destport = dst_ref;
switch(reason) {
case (128+0): str = "Normal Disconnect"; break;
case (128+1): str = "Remote transport entity congestion"; break;
@@ -777,7 +815,10 @@
guint16 dst_ref;
guint tpdu_nr;
guint fragment = 0;
+ guint32 fragment_length = 0;
tvbuff_t *next_tvb;
+ tvbuff_t *reassembled_tvb = NULL;
+ fragment_data *fd_head;
/* VP_CHECKSUM is the only parameter allowed in the variable part.
(This means we may misdissect this if the packet is bad and
@@ -833,6 +874,9 @@
break;
}
+ pinfo->destport = dst_ref;
+ pinfo->srcport = 0;
+ pinfo->fragmented = fragment;
if (check_col(pinfo->cinfo, COL_INFO)) {
if (is_class_234) {
col_append_fstr(pinfo->cinfo, COL_INFO, "DT TPDU (%u) dst-ref: 0x%04x %s",
@@ -893,22 +937,65 @@
offset += li;
next_tvb = tvb_new_subset(tvb, offset, -1, -1);
- if (uses_inactive_subset){
- if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
- pinfo, tree)) {
- *subdissector_found = TRUE;
- } else {
+ if (cotp_reassemble) {
+ fragment_length = tvb_length(next_tvb);
+ fd_head = fragment_add_seq_check(next_tvb, 0, pinfo, dst_ref,
+ cotp_segment_table,
+ cotp_reassembled_table,
+ tpdu_nr,
+ fragment_length, fragment);
+ if (fd_head) {
+ if (fd_head->next) {
+ /* This is the last packet */
+ reassembled_tvb = tvb_new_real_data(fd_head->data,
+ fd_head->len,
+ fd_head->len);
+ tvb_set_child_real_data_tvbuff(next_tvb, reassembled_tvb);
+ add_new_data_source(pinfo, reassembled_tvb, "Reassembled COTP");
+
+ show_fragment_seq_tree(fd_head,
+ &cotp_frag_items,
+ cotp_tree,
+ pinfo, reassembled_tvb);
+ pinfo->fragmented = fragment;
+ next_tvb = reassembled_tvb;
+ }
+ }
+ if (fragment && reassembled_tvb == NULL) {
+ proto_tree_add_text(cotp_tree, tvb, offset, -1,
+ "User data (%u byte%s)", fragment_length,
+ plurality(fragment_length, "", "s"));
+ }
+
+ }
+
+ if (uses_inactive_subset) {
+ if (dissector_try_heuristic(cotp_is_heur_subdissector_list, next_tvb,
+ pinfo, tree)) {
+ *subdissector_found = TRUE;
+ } else {
/* Fill in other Dissectors using inactive subset here */
call_dissector(data_handle,next_tvb, pinfo, tree);
}
} else {
+ /*
+ * We dissect payload if one of the following is TRUE:
+ *
+ * - Reassembly option for COTP in preferences is unchecked
+ * - Reassembly option is checked and this packet is the last fragment
+ *
+ */
+ if ( (!cotp_reassemble) ||
+ ((cotp_reassemble) && (!fragment))) {
if (dissector_try_heuristic(cotp_heur_subdissector_list, next_tvb,
pinfo, tree)) {
*subdissector_found = TRUE;
} else {
call_dissector(data_handle,next_tvb, pinfo, tree);
}
- }
+ }
+ }
+
offset += tvb_length_remaining(tvb, offset);
/* we dissected all of the containing PDU */
@@ -968,6 +1055,9 @@
} /* li */
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
+
+ pinfo->destport = dst_ref;
+ pinfo->srcport = 0;
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, "ED TPDU (%u) dst-ref: 0x%04x",
tpdu_nr, dst_ref);
@@ -1046,6 +1136,9 @@
}
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
+
+ pinfo->destport = dst_ref;
+ pinfo->srcport = 0;
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, "RJ TPDU (%u) dst-ref: 0x%04x",
tpdu_nr, dst_ref);
@@ -1099,6 +1192,8 @@
return -1;
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
+ pinfo->srcport = src_ref;
+ pinfo->destport = dst_ref;
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO,
"%s TPDU src-ref: 0x%04x dst-ref: 0x%04x",
@@ -1174,6 +1269,8 @@
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
src_ref = tvb_get_ntohs(tvb, offset + P_SRC_REF);
+ pinfo->srcport = src_ref;
+ pinfo->destport = dst_ref;
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO,
"DC TPDU src-ref: 0x%04x dst-ref: 0x%04x",
@@ -1230,6 +1327,8 @@
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
tpdu_nr = tvb_get_guint8(tvb, offset + P_TPDU_NR_234);
+ pinfo->srcport = 0;
+ pinfo->destport = dst_ref;
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, "AK TPDU (%u) dst-ref: 0x%04x",
tpdu_nr, dst_ref);
@@ -1367,6 +1466,8 @@
} /* li */
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
+ pinfo->srcport = 0;
+ pinfo->destport = dst_ref;
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO,
"EA TPDU (%u) dst-ref: 0x%04x", tpdu_nr, dst_ref);
@@ -1446,6 +1547,8 @@
}
dst_ref = tvb_get_ntohs(tvb, offset + P_DST_REF);
+ pinfo->srcport = 0;
+ pinfo->destport = dst_ref;
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO, "ER TPDU dst-ref: 0x%04x", dst_ref);
@@ -2003,6 +2106,13 @@
reassembled_table_init(&clnp_reassembled_table);
}
+static void
+cotp_reassemble_init(void)
+{
+ fragment_table_init(&cotp_segment_table);
+ reassembled_table_init(&cotp_reassembled_table);
+}
+
void proto_register_clnp(void)
{
static hf_register_info hf[] = {
@@ -2088,6 +2198,7 @@
register_dissector("clnp", dissect_clnp, proto_clnp);
register_heur_dissector_list("clnp", &clnp_heur_subdissector_list);
register_init_routine(clnp_reassemble_init);
+ register_init_routine(cotp_reassemble_init);
clnp_module = prefs_register_protocol(proto_clnp, NULL);
prefs_register_uint_preference(clnp_module, "tp_nsap_selector",
@@ -2127,14 +2238,49 @@
{ &hf_cotp_type,
{ "COTP PDU Type", "cotp.type", FT_UINT8, BASE_HEX, VALS(cotp_tpdu_type_abbrev_vals), 0x0,
"COTP PDU Type", HFILL}},
+ { &hf_cotp_segment_overlap,
+ { "Segment overlap", "cotp.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Segment overlaps with other segments", HFILL }},
+ { &hf_cotp_segment_overlap_conflict,
+ { "Conflicting data in segment overlap", "cotp.segment.overlap.conflict", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Overlapping segments contained conflicting data", HFILL }},
+ { &hf_cotp_segment_multiple_tails,
+ { "Multiple tail segments found", "cotp.segment.multipletails", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Several tails were found when reassembling the packet", HFILL }},
+ { &hf_cotp_segment_too_long_segment,
+ { "Segment too long", "cotp.segment.toolongsegment", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
+ "Segment contained data past end of packet", HFILL }},
+ { &hf_cotp_segment_error,
+ { "Reassembly error", "cotp.segment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "Reassembly error due to illegal segments", HFILL }},
+ { &hf_cotp_segment,
+ { "COTP Segment", "cotp.segment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "COTP Segment", HFILL }},
+ { &hf_cotp_segments,
+ { "COTP Segments", "cotp.segments", FT_NONE, BASE_DEC, NULL, 0x0,
+ "COTP Segments", HFILL }},
+ { &hf_cotp_reassembled_in,
+ { "Reassembled COTP in frame", "cotp.reassembled_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
+ "This COTP packet is reassembled in this frame", HFILL }},
+
};
static gint *ett[] = {
&ett_cotp,
+ &ett_cotp_segment,
+ &ett_cotp_segments,
};
+ module_t *cotp_module;
+
proto_cotp = proto_register_protocol(PROTO_STRING_COTP, "COTP", "cotp");
proto_register_field_array(proto_cotp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+ cotp_module = prefs_register_protocol(proto_cotp, NULL);
+
+ prefs_register_bool_preference(cotp_module, "reassemble",
+ "Reassemble segmented COTP datagrams",
+ "Whether segmented COTP datagrams should be reassembled",
+ &cotp_reassemble);
/* subdissector code in inactive subset */
register_heur_dissector_list("cotp_is", &cotp_is_heur_subdissector_list);
- Follow-Ups:
- Re: [Ethereal-dev] [Patch] Reassembly of COTP packets
- From: Guy Harris
- Re: [Ethereal-dev] [Patch] Reassembly of COTP packets
- Prev by Date: [Ethereal-dev] Other fixes for free() vs g_free() bug
- Next by Date: Re: [Ethereal-dev] more options for decode as...
- Previous by thread: [Ethereal-dev] Other fixes for free() vs g_free() bug
- Next by thread: Re: [Ethereal-dev] [Patch] Reassembly of COTP packets
- Index(es):





