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):