diff --git a/epan/dissectors/packet-dtn.c b/epan/dissectors/packet-dtn.c index 06cfe59a26..1ad920075c 100644 --- a/epan/dissectors/packet-dtn.c +++ b/epan/dissectors/packet-dtn.c @@ -32,8 +32,24 @@ * http://tools.ietf.org/html/rfc5050 */ +/* + * Modifications were made to this file under designation MFS-33289-1 and + * are Copyright 2015 United States Government as represented by NASA + * Marshall Space Flight Center. All Rights Reserved. + * + * Released under the GNU GPL with NASA legal approval granted 2016-06-10. + * + * The subject software is provided "AS IS" WITHOUT ANY WARRANTY of any kind, + * either expressed, implied or statutory and this agreement does not, + * in any manner, constitute an endorsement by government agency of any + * results, designs or products resulting from use of the subject software. + * See the Agreement for the specific language governing permissions and + * limitations. + */ + #include "config.h" +#include #include #include #include @@ -166,6 +182,7 @@ static int hf_bundle_lifetime_sdnv = -1; /* Secondary Header Processing Flag Variables */ static int hf_bundle_payload_length = -1; static int hf_bundle_payload_header_type = -1; +static int hf_bundle_payload_data = -1; static int hf_bundle_payload_flags = -1; static int hf_bundle_payload_flags_replicate_hdr = -1; static int hf_bundle_payload_flags_xmit_report = -1; @@ -188,12 +205,14 @@ static int hf_block_control_block_cteb_creator_custodian_eid = -1; /* Non-Primary Block Type Code Variable */ static int hf_bundle_block_type_code = -1; +static int hf_bundle_unprocessed_block_data = -1; /* ECOS Flag Variables */ static int hf_ecos_flags = -1; static int hf_ecos_flags_critical = -1; static int hf_ecos_flags_streaming = -1; -static int hf_ecos_flags_ordinal = -1; +static int hf_ecos_flags_flowlabel = -1; +static int hf_ecos_flags_reliable = -1; static int hf_ecos_flow_label = -1; static int hf_ecos_ordinal = -1; @@ -417,6 +436,9 @@ add_dtn_time_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, int hf_dtn_tim nstime_t dtn_time; int sdnv_length, sdnv2_length; int sdnv_value; + int orig_offset; + + orig_offset = offset; sdnv_value = evaluate_sdnv(tvb, offset, &sdnv_length); if (sdnv_value < 0) { @@ -431,7 +453,7 @@ add_dtn_time_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, int hf_dtn_tim return 0; } - proto_tree_add_time(tree, hf_dtn_time, tvb, offset, sdnv_length + sdnv2_length, &dtn_time); + proto_tree_add_time(tree, hf_dtn_time, tvb, orig_offset, sdnv_length + sdnv2_length, &dtn_time); return (sdnv_length + sdnv2_length); } @@ -480,11 +502,12 @@ add_sdnv_to_tree(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, int offset */ static int dissect_dictionary(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, dictionary_data_t* dict_data, - guint8 pri_hdr_procflags, gchar **bundle_custodian) + guint8 pri_hdr_procflags, gchar **bundle_custodian, int creation_timestamp, int timestamp_sequence) { proto_tree *dict_tree; - int sdnv_length; - const gchar *src_node, *dst_node; + const gchar* col_text; + + col_text = col_get_text(pinfo->cinfo, COL_INFO); dict_tree = proto_tree_add_subtree(tree, tvb, offset, dict_data->bundle_header_dict_length, ett_dictionary, NULL, "Dictionary"); @@ -496,49 +519,64 @@ dissect_dictionary(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offs */ if (dict_data->bundle_header_dict_length == 0) { + const gchar *src_node, *dst_node; + /* * Destination info */ - proto_tree_add_string(dict_tree, hf_bundle_dest_scheme, tvb, 0, 0, IPN_SCHEME_STR); if (dict_data->dest_scheme_offset == 0 && dict_data->dest_ssp_offset == 0) { + proto_tree_add_string(dict_tree, hf_bundle_dest_scheme, tvb, 0, 0, DTN_SCHEME_STR); proto_tree_add_string(dict_tree, hf_bundle_dest_ssp, tvb, dict_data->dst_scheme_pos, - dict_data->dst_scheme_len + dict_data->dst_ssp_len, "Null"); + dict_data->dst_scheme_len + dict_data->dst_ssp_len, "none"); + + dst_node = "dtn:none"; } else { + proto_tree_add_string(dict_tree, hf_bundle_dest_scheme, tvb, 0, 0, IPN_SCHEME_STR); proto_tree_add_string(dict_tree, hf_bundle_dest_ssp, tvb, dict_data->dst_scheme_pos, dict_data->dst_scheme_len + dict_data->dst_ssp_len, - wmem_strdup_printf(wmem_packet_scope(), "%d.%d", dict_data->dest_scheme_offset,dict_data->dest_ssp_offset)); + wmem_strdup_printf(wmem_packet_scope(), "%d.%d",dict_data->dest_scheme_offset,dict_data->dest_ssp_offset)); + + dst_node = wmem_strdup_printf(wmem_packet_scope(), "%s:%d.%d", IPN_SCHEME_STR, + dict_data->dest_scheme_offset, dict_data->dest_ssp_offset); } /* * Source info */ - proto_tree_add_string(dict_tree, hf_bundle_source_scheme, tvb, 0, 0, IPN_SCHEME_STR); if (dict_data->source_scheme_offset == 0 && dict_data->source_ssp_offset == 0) { + proto_tree_add_string(dict_tree, hf_bundle_source_scheme, tvb, 0, 0, DTN_SCHEME_STR); proto_tree_add_string(dict_tree, hf_bundle_source_ssp, tvb, dict_data->src_scheme_pos, - dict_data->src_scheme_len + dict_data->src_ssp_len, "Null"); + dict_data->src_scheme_len + dict_data->src_ssp_len, "none"); + + src_node = "dtn:none"; } else { + proto_tree_add_string(dict_tree, hf_bundle_source_scheme, tvb, 0, 0, IPN_SCHEME_STR); proto_tree_add_string(dict_tree, hf_bundle_source_ssp, tvb, dict_data->src_scheme_pos, dict_data->src_scheme_len + dict_data->src_ssp_len, wmem_strdup_printf(wmem_packet_scope(), "%d.%d", dict_data->source_scheme_offset, dict_data->source_ssp_offset)); + + src_node = wmem_strdup_printf(wmem_packet_scope(), "%s:%d.%d", IPN_SCHEME_STR, + dict_data->source_scheme_offset, dict_data->source_ssp_offset); } /* * Report to info */ - proto_tree_add_string(dict_tree, hf_bundle_report_scheme, tvb, 0, 0, IPN_SCHEME_STR); if (dict_data->report_scheme_offset == 0 && dict_data->report_ssp_offset == 0) { + proto_tree_add_string(dict_tree, hf_bundle_report_scheme, tvb, 0, 0, DTN_SCHEME_STR); proto_tree_add_string(dict_tree, hf_bundle_report_ssp, tvb, dict_data->rpt_scheme_pos, - dict_data->rpt_scheme_len + dict_data->rpt_ssp_len, "Null"); + dict_data->rpt_scheme_len + dict_data->rpt_ssp_len, "none"); } else { + proto_tree_add_string(dict_tree, hf_bundle_report_scheme, tvb, 0, 0, IPN_SCHEME_STR); proto_tree_add_string(dict_tree, hf_bundle_report_ssp, tvb, dict_data->rpt_scheme_pos, dict_data->rpt_scheme_len + dict_data->rpt_ssp_len, wmem_strdup_printf(wmem_packet_scope(), "%d.%d", dict_data->report_scheme_offset, dict_data->report_ssp_offset)); @@ -547,40 +585,33 @@ dissect_dictionary(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offs /* * Custodian info */ - proto_tree_add_string(dict_tree, hf_bundle_custodian_scheme, tvb, 0, 0, IPN_SCHEME_STR); if (dict_data->cust_scheme_offset == 0 && dict_data->cust_ssp_offset == 0) { + proto_tree_add_string(dict_tree, hf_bundle_custodian_scheme, tvb, 0, 0, DTN_SCHEME_STR); proto_tree_add_string(dict_tree, hf_bundle_custodian_ssp, tvb, dict_data->cust_scheme_pos, - dict_data->cust_scheme_len + dict_data->cust_ssp_len, "Null"); + dict_data->cust_scheme_len + dict_data->cust_ssp_len, "none"); } else { + proto_tree_add_string(dict_tree, hf_bundle_custodian_scheme, tvb, 0, 0, IPN_SCHEME_STR); proto_tree_add_string(dict_tree, hf_bundle_custodian_ssp, tvb, dict_data->cust_scheme_pos, dict_data->cust_scheme_len + dict_data->cust_ssp_len, wmem_strdup_printf(wmem_packet_scope(), "%d.%d", dict_data->cust_scheme_offset, dict_data->cust_ssp_offset)); } - if (dict_data->source_scheme_offset == 0 && dict_data->source_ssp_offset == 0) - { - src_node = "Null"; - } - else - { - src_node = wmem_strdup_printf(wmem_packet_scope(), "%s:%d.%d", IPN_SCHEME_STR, - dict_data->source_scheme_offset, dict_data->source_ssp_offset); - } - if (dict_data->dest_scheme_offset == 0 && dict_data->dest_ssp_offset == 0) - { - dst_node = "Null"; - } - else - { - dst_node = wmem_strdup_printf(wmem_packet_scope(), "%s:%d.%d", IPN_SCHEME_STR, - dict_data->dest_scheme_offset, dict_data->dest_ssp_offset); - } - - col_add_fstr(pinfo->cinfo, COL_INFO, "%s > %s", src_node, dst_node); /* remember custodian, for use in checking cteb validity */ + col_set_writable(pinfo->cinfo, COL_INFO, FALSE); + col_clear_fence(pinfo->cinfo, COL_INFO); + if (col_text && strstr(col_text, " > ")) { + if (! strstr(col_text, "[multiple]")) { + col_append_str(pinfo->cinfo, COL_INFO, ", [multiple]"); + } + } else { + col_clear(pinfo->cinfo, COL_INFO); + col_add_fstr(pinfo->cinfo, COL_INFO, "%s > %s %d.%d", src_node, dst_node, creation_timestamp, timestamp_sequence); + } + col_set_fence(pinfo->cinfo, COL_INFO); + *bundle_custodian = wmem_strdup_printf(wmem_packet_scope(), "%s:%d.%d", IPN_SCHEME_STR, dict_data->cust_scheme_offset, dict_data->cust_ssp_offset); } @@ -630,11 +661,21 @@ dissect_dictionary(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offs * Add Source/Destination to INFO Field */ - col_add_fstr(pinfo->cinfo, COL_INFO, "%s:%s > %s:%s", - tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset + dict_data->source_scheme_offset, NULL, ENC_ASCII), - tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset + dict_data->source_ssp_offset, NULL, ENC_ASCII), - tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset + dict_data->dest_scheme_offset, NULL, ENC_ASCII), - tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset + dict_data->dest_ssp_offset, NULL, ENC_ASCII)); + col_set_writable(pinfo->cinfo, COL_INFO, FALSE); + col_clear_fence(pinfo->cinfo, COL_INFO); + if (col_text && strstr(col_text, " > ")) + col_append_str(pinfo->cinfo, COL_INFO, ", [multiple]"); + else { + col_clear(pinfo->cinfo, COL_INFO); + col_add_fstr(pinfo->cinfo, COL_INFO, "%s:%s > %s:%s %d.%d", + tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset + dict_data->source_scheme_offset, NULL, ENC_ASCII), + tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset + dict_data->source_ssp_offset, NULL, ENC_ASCII), + tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset + dict_data->dest_scheme_offset, NULL, ENC_ASCII), + tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset + dict_data->dest_ssp_offset, NULL, ENC_ASCII), + creation_timestamp, timestamp_sequence); + } + col_set_fence(pinfo->cinfo, COL_INFO); + /* remember custodian, for use in checking cteb validity */ *bundle_custodian = wmem_strdup_printf(wmem_packet_scope(), @@ -653,6 +694,7 @@ dissect_dictionary(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offs */ if (pri_hdr_procflags & BUNDLE_PROCFLAGS_FRAG_MASK) { + int sdnv_length; sdnv_length = add_sdnv_to_tree(tree, tvb, pinfo, offset, hf_bundle_primary_fragment_offset); if (sdnv_length < 0) { return 0; @@ -813,7 +855,7 @@ dissect_version_4_primary_header(packet_info *pinfo, proto_tree *primary_tree, t } offset += sdnv_length; - offset = dissect_dictionary(pinfo, primary_tree, tvb, offset, &dict_data, *pri_hdr_procflags, bundle_custodian); + offset = dissect_dictionary(pinfo, primary_tree, tvb, offset, &dict_data, *pri_hdr_procflags, bundle_custodian, 0, 0); return offset; } @@ -835,8 +877,13 @@ dissect_version_5_and_6_primary_header(packet_info *pinfo, int sdnv_length; dictionary_data_t dict_data; int timestamp_sequence; + int creation_timestamp; guint8 srrflags; proto_item *ti; + proto_item *ti_dst_scheme_offset, *ti_dst_ssp_offset; + proto_item *ti_src_scheme_offset, *ti_src_ssp_offset; + proto_item *ti_cust_scheme_offset, *ti_cust_ssp_offset; + proto_item *ti_rprt_scheme_offset, *ti_rprt_ssp_offset; proto_tree *gen_flag_tree, *srr_flag_tree, *proc_flag_tree, *cos_flag_tree; static const int * pri_flags[] = { &hf_bundle_procflags_fragment, @@ -921,22 +968,16 @@ dissect_version_5_and_6_primary_header(packet_info *pinfo, dict_data.dst_scheme_pos = offset; dict_data.dst_scheme_len = sdnv_length; - ti = proto_tree_add_int(primary_tree, hf_bundle_dest_scheme_offset_i32, tvb, offset, sdnv_length, + ti_dst_scheme_offset = proto_tree_add_int(primary_tree, hf_bundle_dest_scheme_offset_i32, tvb, offset, sdnv_length, dict_data.dest_scheme_offset); - if ((dict_data.dest_scheme_offset < 0) || (dict_data.dest_scheme_offset > bundle_header_length)) { - expert_add_info_format(pinfo, ti, &ei_bundle_offset_error, "Destination Scheme Offset Error"); - } offset += sdnv_length; /* -- dest_ssp -- */ dict_data.dest_ssp_offset = evaluate_sdnv(tvb, offset, &sdnv_length); dict_data.dst_ssp_len = sdnv_length; - ti = proto_tree_add_int(primary_tree, hf_bundle_dest_ssp_offset_i32, tvb, offset, sdnv_length, + ti_dst_ssp_offset = proto_tree_add_int(primary_tree, hf_bundle_dest_ssp_offset_i32, tvb, offset, sdnv_length, dict_data.dest_ssp_offset); - if ((dict_data.dest_ssp_offset < 0) || (dict_data.dest_ssp_offset > bundle_header_length)) { - expert_add_info_format(pinfo, ti, &ei_bundle_offset_error, "Destination SSP Offset Error"); - } offset += sdnv_length; /* -- source_scheme -- */ @@ -944,22 +985,16 @@ dissect_version_5_and_6_primary_header(packet_info *pinfo, dict_data.src_scheme_pos = offset; dict_data.src_scheme_len = sdnv_length; - ti = proto_tree_add_int(primary_tree, hf_bundle_source_scheme_offset_i32, tvb, offset, sdnv_length, + ti_src_scheme_offset = proto_tree_add_int(primary_tree, hf_bundle_source_scheme_offset_i32, tvb, offset, sdnv_length, dict_data.source_scheme_offset); - if ((dict_data.source_scheme_offset < 0) || (dict_data.source_scheme_offset > bundle_header_length)) { - expert_add_info_format(pinfo, ti, &ei_bundle_offset_error, "Source Scheme Offset Error"); - } offset += sdnv_length; /* -- source_ssp -- */ dict_data.source_ssp_offset = evaluate_sdnv(tvb, offset, &sdnv_length); dict_data.src_ssp_len = sdnv_length; - ti = proto_tree_add_int(primary_tree, hf_bundle_source_ssp_offset_i32, tvb, offset, sdnv_length, + ti_src_ssp_offset = proto_tree_add_int(primary_tree, hf_bundle_source_ssp_offset_i32, tvb, offset, sdnv_length, dict_data.source_ssp_offset); - if ((dict_data.source_ssp_offset < 0) || (dict_data.source_ssp_offset > bundle_header_length)) { - expert_add_info_format(pinfo, ti, &ei_bundle_offset_error, "Source SSP Offset Error"); - } offset += sdnv_length; /* -- report_scheme -- */ @@ -967,22 +1002,16 @@ dissect_version_5_and_6_primary_header(packet_info *pinfo, dict_data.rpt_scheme_pos = offset; dict_data.rpt_scheme_len = sdnv_length; - ti = proto_tree_add_int(primary_tree, hf_bundle_report_scheme_offset_i32, tvb, offset, + ti_rprt_scheme_offset = proto_tree_add_int(primary_tree, hf_bundle_report_scheme_offset_i32, tvb, offset, sdnv_length, dict_data.report_scheme_offset); - if ((dict_data.report_scheme_offset < 0) || (dict_data.report_scheme_offset > bundle_header_length)) { - expert_add_info_format(pinfo, ti, &ei_bundle_offset_error, "Report Scheme Offset Error"); - } offset += sdnv_length; /* -- report_ssp -- */ dict_data.report_ssp_offset = evaluate_sdnv(tvb, offset, &sdnv_length); dict_data.rpt_ssp_len = sdnv_length; - ti = proto_tree_add_int(primary_tree, hf_bundle_report_ssp_offset_i32, tvb, offset, sdnv_length, + ti_rprt_ssp_offset = proto_tree_add_int(primary_tree, hf_bundle_report_ssp_offset_i32, tvb, offset, sdnv_length, dict_data.report_ssp_offset); - if ((dict_data.report_ssp_offset < 0) || (dict_data.report_ssp_offset > bundle_header_length)) { - expert_add_info_format(pinfo, ti, &ei_bundle_offset_error, "Report SSP Offset Error"); - } offset += sdnv_length; @@ -991,25 +1020,20 @@ dissect_version_5_and_6_primary_header(packet_info *pinfo, dict_data.cust_scheme_pos = offset; dict_data.cust_scheme_len = sdnv_length; - ti = proto_tree_add_int(primary_tree, hf_bundle_cust_scheme_offset_i32, tvb, offset, sdnv_length, + ti_cust_scheme_offset = proto_tree_add_int(primary_tree, hf_bundle_cust_scheme_offset_i32, tvb, offset, sdnv_length, dict_data.cust_scheme_offset); - if ((dict_data.cust_scheme_offset < 0) || (dict_data.cust_scheme_offset > bundle_header_length)) { - expert_add_info_format(pinfo, ti, &ei_bundle_offset_error, "Custodian Scheme Offset Error"); - } offset += sdnv_length; /* -- cust_ssp -- */ dict_data.cust_ssp_offset = evaluate_sdnv(tvb, offset, &sdnv_length); dict_data.cust_ssp_len = sdnv_length; - ti = proto_tree_add_int(primary_tree, hf_bundle_cust_ssp_offset_i32, tvb, offset, sdnv_length, + ti_cust_ssp_offset = proto_tree_add_int(primary_tree, hf_bundle_cust_ssp_offset_i32, tvb, offset, sdnv_length, dict_data.cust_ssp_offset); - if ((dict_data.cust_ssp_offset < 0) || (dict_data.cust_ssp_offset > bundle_header_length)) { - expert_add_info_format(pinfo, ti, &ei_bundle_offset_error, "Custodian SSP Offset Error"); - } offset += sdnv_length; + creation_timestamp = evaluate_sdnv(tvb, offset, &sdnv_length); sdnv_length = add_sdnv_time_to_tree(primary_tree, tvb, offset, hf_bundle_primary_timestamp); if (sdnv_length == 0) return 0; @@ -1047,7 +1071,41 @@ dissect_version_5_and_6_primary_header(packet_info *pinfo, } offset += sdnv_length; - offset = dissect_dictionary(pinfo, primary_tree, tvb, offset, &dict_data, *pri_hdr_procflags, bundle_custodian); + if ((dict_data.dest_scheme_offset < 0) || + (dict_data.bundle_header_dict_length > 0 && (dict_data.dest_scheme_offset > bundle_header_length))) { + expert_add_info_format(pinfo, ti_dst_scheme_offset, &ei_bundle_offset_error, "Destination Scheme Offset Error"); + } + if ((dict_data.dest_ssp_offset < 0) || + (dict_data.bundle_header_dict_length > 0 && (dict_data.dest_ssp_offset > bundle_header_length))) { + expert_add_info_format(pinfo, ti_dst_ssp_offset, &ei_bundle_offset_error, "Destination SSP Offset Error"); + } + if ((dict_data.source_scheme_offset < 0) || + (dict_data.bundle_header_dict_length > 0 && (dict_data.source_scheme_offset > bundle_header_length))) { + expert_add_info_format(pinfo, ti_src_scheme_offset, &ei_bundle_offset_error, "Source Scheme Offset Error"); + } + if ((dict_data.source_ssp_offset < 0) || + (dict_data.bundle_header_dict_length > 0 && (dict_data.source_ssp_offset > bundle_header_length))) { + expert_add_info_format(pinfo, ti_src_ssp_offset, &ei_bundle_offset_error, "Source SSP Offset Error"); + } + if ((dict_data.report_scheme_offset < 0) || + (dict_data.bundle_header_dict_length > 0 && (dict_data.report_scheme_offset > bundle_header_length))) { + expert_add_info_format(pinfo, ti_rprt_scheme_offset, &ei_bundle_offset_error, "Report Scheme Offset Error"); + } + if ((dict_data.report_ssp_offset < 0) || + (dict_data.bundle_header_dict_length > 0 && (dict_data.report_ssp_offset > bundle_header_length))) { + expert_add_info_format(pinfo, ti_rprt_ssp_offset, &ei_bundle_offset_error, "Report SSP Offset Error"); + } + if ((dict_data.cust_scheme_offset < 0) || + (dict_data.bundle_header_dict_length > 0 && (dict_data.cust_scheme_offset > bundle_header_length))) { + expert_add_info_format(pinfo, ti_cust_scheme_offset, &ei_bundle_offset_error, "Custodian Scheme Offset Error"); + } + if ((dict_data.cust_ssp_offset < 0) || + (dict_data.bundle_header_dict_length > 0 && (dict_data.cust_ssp_offset > bundle_header_length))) { + expert_add_info_format(pinfo, ti_cust_ssp_offset, &ei_bundle_offset_error, "Custodian SSP Offset Error"); + } + + offset = dissect_dictionary(pinfo, primary_tree, tvb, offset, &dict_data, *pri_hdr_procflags, bundle_custodian, + creation_timestamp, timestamp_sequence); return offset; } @@ -1059,11 +1117,13 @@ static int dissect_payload_header(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset, guint8 version, guint8 pri_hdr_procflags, gboolean *lastheader) { - proto_item *payload_item, *ti; - proto_tree *payload_tree; + proto_item *payload_block, *payload_item, *ti; + proto_tree *payload_block_tree, *payload_tree; int sdnv_length, payload_length; - payload_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_payload_hdr, &payload_item, "Payload Header"); + payload_block_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_payload_hdr, &payload_block, "Payload Block"); + + payload_tree = proto_tree_add_subtree(payload_block_tree, tvb, offset, -1, ett_payload_hdr, &payload_item, "Payload Header"); proto_tree_add_uint(payload_tree, hf_bundle_payload_header_type, tvb, offset, 1, 1); ++offset; @@ -1135,6 +1195,7 @@ dissect_payload_header(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int } proto_item_set_len(payload_item, 2 + sdnv_length); + proto_item_set_len(payload_block, 2 + sdnv_length + payload_length); offset += sdnv_length; if (pri_hdr_procflags & BUNDLE_PROCFLAGS_ADMIN_MASK) { @@ -1144,15 +1205,19 @@ dissect_payload_header(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int * XXXX - Have not allowed for admin record spanning multiple segments! */ - offset = dissect_admin_record(payload_tree, tvb, pinfo, offset, payload_length, &success); + offset = dissect_admin_record(payload_block_tree, tvb, pinfo, offset, payload_length, &success); if (!success) { /* Force quiting */ *lastheader = TRUE; return offset; } + } else { + proto_tree_add_string(payload_block_tree, hf_bundle_payload_data, tvb, offset, payload_length, + wmem_strdup_printf(wmem_packet_scope(), "<%d bytes>",payload_length)); + offset += payload_length; } - return payload_length + offset; + return offset; } /* @@ -1162,7 +1227,7 @@ static int dissect_admin_record(proto_tree *primary_tree, tvbuff_t *tvb, packet_info *pinfo, int offset, int payload_length, gboolean* success) { - proto_item *admin_record_item, *ti; + proto_item *admin_record_item; proto_tree *admin_record_tree; proto_item *timestamp_sequence_item; guint8 record_type; @@ -1372,10 +1437,10 @@ dissect_admin_record(proto_tree *primary_tree, tvbuff_t *tvb, packet_info *pinfo } /* case ADMIN_REC_TYPE_CUSTODY_SIGNAL */ case ADMIN_REC_TYPE_AGGREGATE_CUSTODY_SIGNAL: { + proto_item *ti; int payload_bytes_processed = 0; int right_edge = -1; - int fill_start = -1; - int fill_gap = -1; + int fill_start; int fill_length = -1; int sdnv_length_start = -1; int sdnv_length_gap = -1; @@ -1412,6 +1477,7 @@ dissect_admin_record(proto_tree *primary_tree, tvbuff_t *tvb, packet_info *pinfo /* now attempt to consume all the rest of the data in the * payload as additional fills */ while (payload_bytes_processed < payload_length) { + int fill_gap; fill_gap = evaluate_sdnv(tvb, offset, &sdnv_length_gap); ti = proto_tree_add_int(admin_record_tree, hf_bundle_custody_id_range_start, tvb, offset, sdnv_length_gap, fill_gap); if (fill_gap < 0 || sdnv_length_gap < 0) { @@ -1450,22 +1516,24 @@ dissect_admin_record(proto_tree *primary_tree, tvbuff_t *tvb, packet_info *pinfo } static int -display_metadata_block(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset, gchar *bundle_custodian, gboolean *lastheader) +display_extension_block(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset, gchar *bundle_custodian, gboolean *lastheader) { proto_item *block_item, *ti, *block_flag_replicate_item, *block_flag_eid_reference_item; proto_tree *block_tree; int sdnv_length; int block_length; + int block_overhead; guint8 type; unsigned int control_flags; proto_tree *block_flag_tree; proto_item *block_flag_item; type = tvb_get_guint8(tvb, offset); - block_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_metadata_hdr, &block_item, "Metadata Block"); + block_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_metadata_hdr, &block_item, "Extension Block"); proto_tree_add_item(block_tree, hf_bundle_block_type_code, tvb, offset, 1, ENC_BIG_ENDIAN); ++offset; + block_overhead = 1; control_flags = (unsigned int)evaluate_sdnv(tvb, offset, &sdnv_length); if (control_flags & BLOCK_CONTROL_LAST_BLOCK) { @@ -1491,6 +1559,7 @@ display_metadata_block(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int block_flag_eid_reference_item = proto_tree_add_boolean(block_flag_tree, hf_block_control_eid_reference, tvb, offset, sdnv_length, control_flags); offset += sdnv_length; + block_overhead += sdnv_length; /* TODO: if this block has EID references, add them to display tree */ if (control_flags & BLOCK_CONTROL_EID_REFERENCE) { @@ -1499,14 +1568,17 @@ display_metadata_block(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int num_eid_ref = evaluate_sdnv(tvb, offset, &sdnv_length); offset += sdnv_length; + block_overhead += sdnv_length; for (i = 0; i < num_eid_ref; i++) { evaluate_sdnv(tvb, offset, &sdnv_length); offset += sdnv_length; + block_overhead += sdnv_length; evaluate_sdnv(tvb, offset, &sdnv_length); offset += sdnv_length; + block_overhead += sdnv_length; } } @@ -1519,8 +1591,10 @@ display_metadata_block(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int return offset; } offset += sdnv_length; + block_overhead += sdnv_length; + /* now we have enough info to know total length of metadata block */ - proto_item_set_len(block_item, offset + block_length); + proto_item_set_len(block_item, block_overhead + block_length); switch (type) { @@ -1531,6 +1605,7 @@ display_metadata_block(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int case BUNDLE_BLOCK_TYPE_METADATA_EXTENSION: case BUNDLE_BLOCK_TYPE_EXTENSION_SECURITY: { + proto_tree_add_string(block_tree, hf_bundle_unprocessed_block_data, tvb, offset, block_length, "Block data"); /* not yet dissected, skip past data */ offset += block_length; break; @@ -1584,11 +1659,12 @@ display_metadata_block(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int } case BUNDLE_BLOCK_TYPE_EXTENDED_COS: { - int flags, flow_label; + int flags; static const int * ecos_flags_fields[] = { &hf_ecos_flags_critical, &hf_ecos_flags_streaming, - &hf_ecos_flags_ordinal, + &hf_ecos_flags_flowlabel, + &hf_ecos_flags_reliable, NULL }; @@ -1610,7 +1686,8 @@ display_metadata_block(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset += 1; /* optional flow label sdnv */ - if ((flags & ECOS_FLAGS_ORDINAL) != 0) { + if ((flags & ECOS_FLAGS_FLOWLABEL) != 0) { + int flow_label; flow_label = evaluate_sdnv(tvb, offset, &sdnv_length); ti = proto_tree_add_int(block_tree, hf_ecos_flow_label, tvb, offset, sdnv_length, flow_label); if (flow_label < 0) { @@ -1626,6 +1703,7 @@ display_metadata_block(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int } default: { + proto_tree_add_string(block_tree, hf_bundle_unprocessed_block_data, tvb, offset, block_length, "Block data"); /* unknown bundle type, skip past data */ offset += block_length; break; @@ -1644,6 +1722,10 @@ evaluate_sdnv(tvbuff_t *tvb, int offset, int *bytecount) *bytecount = 0; + if (!tvb_bytes_exist(tvb, offset, 1)) { + return -1; + } + /* * Get 1st byte and continue to get them while high-order bit is 1 */ @@ -1657,6 +1739,10 @@ evaluate_sdnv(tvbuff_t *tvb, int offset, int *bytecount) value |= (curbyte & SDNV_MASK); ++offset; ++*bytecount; + + if (!tvb_bytes_exist(tvb, offset, 1)) { + return -1; + } } /* @@ -1670,6 +1756,7 @@ evaluate_sdnv(tvbuff_t *tvb, int offset, int *bytecount) } /* Special Function to evaluate 64 bit SDNVs */ +/*3rd arg is number of bytes in field (returned)*/ gint64 evaluate_sdnv_64(tvbuff_t *tvb, int offset, int *bytecount) { @@ -1678,6 +1765,10 @@ evaluate_sdnv_64(tvbuff_t *tvb, int offset, int *bytecount) *bytecount = 0; + if (!tvb_bytes_exist(tvb, offset, 1)) { + return -1; + } + /* * Get 1st byte and continue to get them while high-order bit is 1 */ @@ -1691,6 +1782,10 @@ evaluate_sdnv_64(tvbuff_t *tvb, int offset, int *bytecount) value |= (curbyte & SDNV_MASK); ++offset; ++*bytecount; + + if (!tvb_bytes_exist(tvb, offset, 1)) { + return -1; + } } /* @@ -1703,6 +1798,158 @@ evaluate_sdnv_64(tvbuff_t *tvb, int offset, int *bytecount) return value; } +/* Special Function to evaluate 32 bit unsigned SDNVs with error indication + * bytecount returns the number bytes consumed + * value returns the actual value + * + * result is TRUE (1) on success else FALSE (0) + */ +int +evaluate_sdnv32(tvbuff_t *tvb, int offset, int *bytecount, guint32 *value) +{ + int result; + int num_bits_in_value; + guint8 curbyte; + guint8 high_bit; + + *value = 0; + *bytecount = 0; + + result = FALSE; + num_bits_in_value = 0; + + if (tvb_bytes_exist(tvb, offset, 1)) { + /* + * Get 1st byte and continue to get them while high-order bit is 1 + */ + result = TRUE; + + /* Determine number of non-zero bits in first SDNV byte */ + /* technically 0x80 0x80 ... 0x81 is a valid inefficient representation of "1" */ + while ((0 == num_bits_in_value) && ((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK)) { + if (!tvb_bytes_exist(tvb, offset, 1)) { + result = FALSE; + break; + } else { + num_bits_in_value = 7; + high_bit = 0x40; + while ((num_bits_in_value > 0) && (!(curbyte & high_bit))) { + --num_bits_in_value; + high_bit = high_bit >> 1; + } + + *value |= (curbyte & SDNV_MASK); + ++offset; + ++*bytecount; + } + } + + + /* Process additional bytes that have the high order bit set */ + while (result && ((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK)) { + /* Since the high order bit is set there must be 7 low order bits after this byte */ + if (!tvb_bytes_exist(tvb, offset, 1) || ((num_bits_in_value + 7) > (32 - 7))) { + result = FALSE; + } else { + *value = *value << 7; + *value |= (curbyte & SDNV_MASK); + ++offset; + ++*bytecount; + } + } + + if (result) { + /* + * Add in the byte whose high-order bit is 0 (last one) + */ + *value = *value << 7; + *value |= (curbyte & SDNV_MASK); + ++*bytecount; + } else { + *bytecount = 0; + } + } + + return result; +} + + +/* Special Function to evaluate 64 bit unsigned SDNVs with error indication + * bytecount returns the number bytes consumed or zero on error + * value returns the actual value + * + * result is TRUE (1) on success else FALSE (0) + */ +int +evaluate_sdnv64(tvbuff_t *tvb, int offset, int *bytecount, guint64 *value) +{ + int result; + int num_bits_in_value; + guint8 curbyte; + guint8 high_bit; + + *value = 0; + *bytecount = 0; + + result = FALSE; + num_bits_in_value = 0; + + if (tvb_bytes_exist(tvb, offset, 1)) { + /* + * Get 1st byte and continue to get them while high-order bit is 1 + */ + result = TRUE; + + /* Determine number of non-zero bits in first SDNV byte */ + /* technically 0x80 0x80 ... 0x81 is a valid inefficient representation of "1" */ + while ((0 == num_bits_in_value) && ((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK)) { + if (!tvb_bytes_exist(tvb, offset, 1)) { + result = FALSE; + break; + } else { + num_bits_in_value = 7; + high_bit = 0x40; + while ((num_bits_in_value > 0) && (!(curbyte & high_bit))) { + --num_bits_in_value; + high_bit = high_bit >> 1; + } + + *value |= (curbyte & SDNV_MASK); + ++offset; + ++*bytecount; + } + } + + + /* Process additional bytes that have the high order bit set */ + while (result && ((curbyte = tvb_get_guint8(tvb, offset)) & ~SDNV_MASK)) { + /* Since the high order bit is set there must be 7 low order bits after this byte */ + if (!tvb_bytes_exist(tvb, offset, 1) || ((num_bits_in_value + 7) > (64 - 7))) { + result = FALSE; + } else { + *value = *value << 7; + *value |= (curbyte & SDNV_MASK); + ++offset; + ++*bytecount; + } + } + + if (result) { + /* + * Add in the byte whose high-order bit is 0 (last one) + */ + *value = *value << 7; + *value |= (curbyte & SDNV_MASK); + ++*bytecount; + } else { + *bytecount = 0; + } + } + + return result; +} + + static guint get_dtn_contact_header_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) @@ -1727,6 +1974,7 @@ dissect_dtn_contact_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCPCL"); col_clear(pinfo->cinfo,COL_INFO); /* Clear out stuff in the info column */ + col_add_str(pinfo->cinfo, COL_INFO, "Contact Header"); ti = proto_tree_add_item(tree, proto_tcp_conv, tvb, offset, -1, ENC_NA); conv_proto_tree = proto_item_add_subtree(ti, ett_tcp_conv); @@ -1772,7 +2020,6 @@ get_tcpcl_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data switch (conv_hdr & TCP_CONVERGENCE_TYPE_MASK) { case TCP_CONVERGENCE_DATA_SEGMENT: - case TCP_CONVERGENCE_ACK_SEGMENT: /* get length from sdnv */ len = evaluate_sdnv(tvb, offset+1, &bytecount); if (len < 0) @@ -1780,6 +2027,14 @@ get_tcpcl_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data return len+bytecount+1; + case TCP_CONVERGENCE_ACK_SEGMENT: + /* get length from sdnv */ + len = evaluate_sdnv(tvb, offset+1, &bytecount); + if (len < 0) + return 0; + + return bytecount+1; + case TCP_CONVERGENCE_KEEP_ALIVE: case TCP_CONVERGENCE_REFUSE_BUNDLE: /* always 1 byte */ @@ -1802,7 +2057,7 @@ get_tcpcl_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data } static int -dissect_tcpcl_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +dissect_tcpcl_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { guint8 conv_hdr; int offset = 0; @@ -1812,10 +2067,25 @@ dissect_tcpcl_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat fragment_head *frag_msg; tvbuff_t *new_tvb; gboolean more_frags; + int processed_length = 0; + const gchar* col_text; + gboolean bundle_in_col_info; + + static guint32 frag_id = 0; + static guint32 last_frame = 0; + static int last_raw_offset = 0; + + if (last_frame != pinfo->fd->num || tvb_raw_offset(tvb) < last_raw_offset) + frag_id = 0; + last_frame = pinfo->fd->num; + last_raw_offset = tvb_raw_offset(tvb); col_set_str(pinfo->cinfo, COL_PROTOCOL, "TCPCL"); col_clear(pinfo->cinfo,COL_INFO); /* Clear out stuff in the info column */ + col_text = col_get_text(pinfo->cinfo, COL_INFO); + bundle_in_col_info = (col_text && strstr(col_text, " > ")); + ci = proto_tree_add_item(tree, proto_tcp_conv, tvb, offset, -1, ENC_NA); conv_proto_tree = proto_item_add_subtree(ci, ett_tcp_conv); @@ -1823,7 +2093,7 @@ dissect_tcpcl_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat conv_hdr = tvb_get_guint8(tvb, offset); proto_tree_add_item(conv_tree, hf_tcp_convergence_pkt_type, tvb, offset, 1, ENC_BIG_ENDIAN); - col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const((conv_hdr>>4)&0xF, packet_type_vals, "Unknown")); + col_add_str(pinfo->cinfo, COL_INFO, val_to_str_const((conv_hdr>>4)&0xF, packet_type_vals, "Unknown")); switch (conv_hdr & TCP_CONVERGENCE_TYPE_MASK) { @@ -1866,28 +2136,32 @@ dissect_tcpcl_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat more_frags = TRUE; } - /* - * Note: The reassembled bundle will only include the first - * Convergence layer header. - */ frag_msg = fragment_add_seq_next(&msg_reassembly_table, - tvb, offset + convergence_hdr_size, - pinfo, 0, NULL, - segment_length, more_frags); + tvb, offset + convergence_hdr_size, + pinfo, frag_id, data, + segment_length, more_frags); + + if (!more_frags) ++frag_id; + + processed_length = convergence_hdr_size + segment_length; + if (frag_msg && !more_frags) { + int save_fd_head_layer = frag_msg->reas_in_layer_num; + frag_msg->reas_in_layer_num = pinfo->curr_layer_num; + sub_item = proto_tree_add_item(tree, proto_bundle, tvb, offset, -1, ENC_NA); sub_tree = proto_item_add_subtree(sub_item, ett_bundle); new_tvb = process_reassembled_data(tvb, offset + convergence_hdr_size, pinfo, "Reassembled DTN", frag_msg, &msg_frag_items, NULL, sub_tree); + + frag_msg->reas_in_layer_num = save_fd_head_layer; } if (new_tvb) { - int bundle_size = call_dissector(bundle_handle, new_tvb, pinfo, sub_tree); - - if (bundle_size == 0) { + if (0 == call_dissector_with_data(bundle_handle, new_tvb, pinfo, sub_tree, data)) { /*Couldn't parse bundle, treat as raw data */ call_data_dissector(new_tvb, pinfo, sub_tree); return tvb_captured_length(tvb); @@ -1904,21 +2178,46 @@ dissect_tcpcl_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat * think it is informative in the multi-segment case although confusing in the * 2-segment case. */ - col_set_str(pinfo->cinfo, COL_INFO, "[Reassembled Segment of a Bundle]"); + col_add_str(pinfo->cinfo, COL_INFO, "[Bundle TCPCL Segment]"); } break; case TCP_CONVERGENCE_ACK_SEGMENT: + if (bundle_in_col_info) { + if (!strstr(col_text, ", TCPL ACK")) { + col_add_str(pinfo->cinfo, COL_INFO, ", TCPL ACK Segment(s)"); + } + } else { + col_set_str(pinfo->cinfo, COL_INFO, "TCPL ACK Segment(s)"); + } segment_length = evaluate_sdnv(tvb, offset+1, &sdnv_length); sub_item = proto_tree_add_int(conv_tree, hf_tcp_convergence_ack_length, tvb, offset+1, sdnv_length, segment_length); if (segment_length < 0) { expert_add_info(pinfo, sub_item, &ei_tcp_convergence_ack_length); + processed_length = tvb_captured_length(tvb); + } else { + processed_length = sdnv_length + 1; } break; case TCP_CONVERGENCE_KEEP_ALIVE: + if (bundle_in_col_info) { + if (!strstr(col_text, ", TCPL KEEPALIVE")) { + col_add_str(pinfo->cinfo, COL_INFO, ", TCPL KEEPALIVE Segment"); + } + } else { + col_set_str(pinfo->cinfo, COL_INFO, "TCPL KEEPALIVE Sgement"); + } /*No valid flags in Keep Alive*/ + processed_length = 1; break; case TCP_CONVERGENCE_SHUTDOWN: + if (bundle_in_col_info) { + if (!strstr(col_text, ", TCPL SHUTDOWN")) { + col_add_str(pinfo->cinfo, COL_INFO, ", TCPL SHUTDOWN Segment"); + } + } else { + col_set_str(pinfo->cinfo, COL_INFO, "TCPL SHUTDOWN Sgement"); + } /* Add tree for Shutdown Flags */ sub_item = proto_tree_add_item(conv_tree, hf_tcp_convergence_shutdown_flags, tvb, offset, 1, ENC_BIG_ENDIAN); @@ -1943,11 +2242,19 @@ dissect_tcpcl_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat } break; case TCP_CONVERGENCE_REFUSE_BUNDLE: + if (bundle_in_col_info) { + if (!strstr(col_text, ", TCPL REFUSE")) { + col_add_str(pinfo->cinfo, COL_INFO, ", TCPL REFUSE_BUNDLE Segment"); + } + } else { + col_set_str(pinfo->cinfo, COL_INFO, "TCPL REFUSE_BUNDLE Sgement"); + } /*No valid flags*/ + processed_length = tvb_captured_length(tvb); break; } - return tvb_captured_length(tvb); + return processed_length; } static int @@ -1955,6 +2262,7 @@ dissect_tcpcl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { guint8 conv_hdr; int offset, bytecount; + int processed_length; /* Make sure we have a convergence header byte */ if (!tvb_bytes_exist(tvb, 0, 1)) @@ -1969,8 +2277,11 @@ dissect_tcpcl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) offset = 1; bytecount = 1; - if (!tvb_bytes_exist(tvb, offset, 1)) + if (!tvb_bytes_exist(tvb, offset, 1)) { + pinfo->desegment_offset = 0; + pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; return 0; + } while (tvb_get_guint8(tvb, offset) & ~SDNV_MASK) { if (bytecount > (int)sizeof(int)) { @@ -1978,11 +2289,14 @@ dissect_tcpcl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) return 0; } - if (!tvb_bytes_exist(tvb, offset, 1)) - return 0; - bytecount++; offset++; + + if (!tvb_bytes_exist(tvb, offset, 1)) { + pinfo->desegment_offset = 0; + pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT; + return 0; + } } break; case TCP_CONVERGENCE_KEEP_ALIVE: @@ -2011,14 +2325,17 @@ dissect_tcpcl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) return 0; }; + processed_length = get_tcpcl_pdu_len(pinfo, tvb, 0, data); + tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 1, get_tcpcl_pdu_len, dissect_tcpcl_pdu, data); - return tvb_captured_length(tvb); + + return processed_length; } static int dissect_bundle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { - proto_item *ti; + proto_item *ti, *ti_bundle_protocol; proto_tree *bundle_tree, *primary_tree; int primary_header_size; gboolean lastheader = FALSE; @@ -2027,6 +2344,7 @@ dissect_bundle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _ /* Custodian from Primary Block, used to validate CTEB */ gchar *bundle_custodian = NULL; + version = tvb_get_guint8(tvb, offset); /* Primary Header Version */ if ((version != 4) && (version != 5) && (version != 6)) { return 0; @@ -2036,10 +2354,10 @@ dissect_bundle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _ /* Clear out stuff in the info column */ col_clear(pinfo->cinfo,COL_INFO); - ti = proto_tree_add_item(tree, proto_bundle, tvb, offset, -1, ENC_NA); - bundle_tree = proto_item_add_subtree(ti, ett_bundle); + ti_bundle_protocol = proto_tree_add_item(tree, proto_bundle, tvb, offset, -1, ENC_NA); + bundle_tree = proto_item_add_subtree(ti_bundle_protocol, ett_bundle); - primary_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_primary_hdr, &ti, "Primary Bundle Header"); + primary_tree = proto_tree_add_subtree(bundle_tree, tvb, offset, -1, ett_primary_hdr, &ti, "Primary Bundle Header"); proto_tree_add_item(primary_tree, hf_bundle_pdu_version, tvb, offset, 1, ENC_BIG_ENDIAN); if (version == 4) { @@ -2052,7 +2370,7 @@ dissect_bundle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _ } if (primary_header_size == 0) { /*Couldn't parse primary header*/ - col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); + col_add_str(pinfo->cinfo, COL_INFO, "Protocol Error"); return(0); /*Give up*/ } @@ -2075,10 +2393,12 @@ dissect_bundle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _ offset = dissect_payload_header(bundle_tree, tvb, pinfo, offset, version, pri_hdr_procflags, &lastheader); } else { /*Assume anything else is a Metadata Block*/ - offset = display_metadata_block(bundle_tree, tvb, pinfo, offset, bundle_custodian, &lastheader); + offset = display_extension_block(bundle_tree, tvb, pinfo, offset, bundle_custodian, &lastheader); } } + proto_item_set_len(ti_bundle_protocol, offset); + return(offset); } @@ -2176,7 +2496,7 @@ proto_register_bundle(void) FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_APP_ACK_MASK, NULL, HFILL} }, {&hf_bundle_control_flags, - {"Bundle Processing Control Flags", "bundle.control.flag", + {"Bundle Processing Control Flags", "bundle.primary.proc.flag", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_procflags_general, @@ -2184,7 +2504,7 @@ proto_register_bundle(void) FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_procflags_cos, - {"Cloass of Service Flags", "bundle.primary.proc.cos", + {"Class of Service Flags", "bundle.primary.proc.cos", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_procflags_status, @@ -2244,7 +2564,7 @@ proto_register_bundle(void) FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_primary_timestamp_seq_num64, - {"Timestamp Sequence Number", "bundle.primary.timestamp_seq_num64", + {"Timestamp Sequence Number", "bundle.primary.timestamp_seq_num", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_primary_timestamp_seq_num32, @@ -2256,67 +2576,67 @@ proto_register_bundle(void) FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_dest_scheme_offset_u16, - {"Destination Scheme Offset", "bundle.primary.destschemeoff_u16", + {"Destination Scheme Offset", "bundle.primary.destschemeoff", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_dest_scheme_offset_i32, - {"Destination Scheme Offset", "bundle.primary.destschemeoff_i32", + {"Destination Scheme Offset", "bundle.primary.destschemeoff", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_dest_ssp_offset_u16, - {"Destination SSP Offset", "bundle.primary.destssspoff_u16", + {"Destination SSP Offset", "bundle.primary.destssspoff", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_dest_ssp_offset_i32, - {"Destination SSP Offset", "bundle.primary.destssspoff_i32", + {"Destination SSP Offset", "bundle.primary.destssspoff", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_source_scheme_offset_u16, - {"Source Scheme Offset", "bundle.primary.srcschemeoff_u16", + {"Source Scheme Offset", "bundle.primary.srcschemeoff", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_source_scheme_offset_i32, - {"Source Scheme Offset", "bundle.primary.srcschemeoff_i32", + {"Source Scheme Offset", "bundle.primary.srcschemeoff", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_source_ssp_offset_u16, - {"Source SSP Offset", "bundle.primary.srcsspoff_u16", + {"Source SSP Offset", "bundle.primary.srcsspoff", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_source_ssp_offset_i32, - {"Source SSP Offset", "bundle.primary.srcsspoff_i32", + {"Source SSP Offset", "bundle.primary.srcsspoff", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_report_scheme_offset_u16, - {"Report Scheme Offset", "bundle.primary.rptschemeoff_u16", + {"Report Scheme Offset", "bundle.primary.rptschemeoff", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_report_scheme_offset_i32, - {"Report Scheme Offset", "bundle.primary.rptschemeoff_i32", + {"Report Scheme Offset", "bundle.primary.rptschemeoff", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_report_ssp_offset_u16, - {"Report SSP Offset", "bundle.primary.rptsspoff_u16", + {"Report SSP Offset", "bundle.primary.rptsspoff", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_report_ssp_offset_i32, - {"Report SSP Offset", "bundle.primary.rptsspoff_i32", + {"Report SSP Offset", "bundle.primary.rptsspoff", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_cust_scheme_offset_u16, - {"Custodian Scheme Offset", "bundle.primary.custschemeoff_u16", + {"Custodian Scheme Offset", "bundle.primary.custschemeoff", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_cust_scheme_offset_i32, - {"Custodian Scheme Offset", "bundle.primary.custschemeoff_i32", + {"Custodian Scheme Offset", "bundle.primary.custschemeoff", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_cust_ssp_offset_u16, - {"Custodian SSP Offset", "bundle.primary.custsspoff_u16", + {"Custodian SSP Offset", "bundle.primary.custsspoff", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_cust_ssp_offset_i32, - {"Custodian SSP Offset", "bundle.primary.custsspoff_i32", + {"Custodian SSP Offset", "bundle.primary.custsspoff", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_dest_scheme, @@ -2360,7 +2680,7 @@ proto_register_bundle(void) FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_lifetime_sdnv, - {"Lifetime", "bundle.primary.lifetime_sdnv", + {"Lifetime", "bundle.primary.lifetime", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_payload_length, @@ -2375,6 +2695,10 @@ proto_register_bundle(void) {"Header Type", "bundle.payload.proc.header_type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} }, + {&hf_bundle_payload_data, + {"Payload Data", "bundle.payload.data", + FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, {&hf_bundle_payload_flags_replicate_hdr, {"Replicate Header in Every Fragment", "bundle.payload.proc.replicate", FT_BOOLEAN, 8, NULL, PAYLOAD_PROCFLAGS_REPLICATE_MASK, NULL, HFILL} @@ -2396,7 +2720,7 @@ proto_register_bundle(void) FT_UINT8, BASE_DEC, VALS(admin_record_type_vals), 0xF0, NULL, HFILL} }, {&hf_bundle_admin_record_fragment, - {"Administrative Record Fragment", "bundle.admin.record_fragment", + {"Administrative Record for Fragment", "bundle.admin.record_fragment", FT_BOOLEAN, 8, TFS(&tfs_yes_no), ADMIN_REC_FLAGS_FRAGMENT, NULL, HFILL} }, {&hf_bundle_admin_statflags, @@ -2436,7 +2760,7 @@ proto_register_bundle(void) FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_admin_timestamp_seq_num64, - {"Timestamp Sequence Number", "bundle.admin.timestamp_seq_num64", + {"Timestamp Sequence Number", "bundle.admin.timestamp_seq_num", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_admin_timestamp_seq_num32, @@ -2552,9 +2876,13 @@ proto_register_bundle(void) FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL} }, {&hf_bundle_block_type_code, - {"Non-Primary Bundle Block Type Code", "bundle.block_type_code", + {"Block Type Code", "bundle.block_type_code", FT_UINT8, BASE_DEC, VALS(bundle_block_type_codes), 0x0, NULL, HFILL} }, + {&hf_bundle_unprocessed_block_data, + {"Block Data", "bundle.block_data", + FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, {&hf_ecos_flags, {"ECOS Flags", "bundle.block.ecos.flags", FT_UINT8, BASE_HEX, VALS(ecos_flags), 0x0, NULL, HFILL} @@ -2567,9 +2895,13 @@ proto_register_bundle(void) {"ECOS Streaming Flag", "bundle.block.ecos.flags.streaming", FT_BOOLEAN, 8, NULL, ECOS_FLAGS_STREAMING, NULL, HFILL} }, - {&hf_ecos_flags_ordinal, - {"ECOS Ordinal Flag", "bundle.block.ecos.flags.ordinal", - FT_BOOLEAN, 8, NULL, ECOS_FLAGS_ORDINAL, NULL, HFILL} + {&hf_ecos_flags_flowlabel, + {"ECOS Flow Label Flag", "bundle.block.ecos.flags.flowlabel", + FT_BOOLEAN, 8, NULL, ECOS_FLAGS_FLOWLABEL, NULL, HFILL} + }, + {&hf_ecos_flags_reliable, + {"ECOS Reliable Flag", "bundle.block.ecos.flags.reliable", + FT_BOOLEAN, 8, NULL, ECOS_FLAGS_RELIABLE, NULL, HFILL} }, {&hf_ecos_flow_label, {"ECOS Flow Label", "bundle.block.ecos.flow_label", @@ -2762,7 +3094,7 @@ proto_register_bundle(void) expert_register_field_array(expert_tcpcl, ei_tcpcl, array_length(ei_tcpcl)); register_init_routine(bundle_defragment_init); - register_cleanup_routine(bundle_defragment_cleanup); + register_cleanup_routine(bundle_defragment_cleanup); } void diff --git a/epan/dissectors/packet-dtn.h b/epan/dissectors/packet-dtn.h index 0d57ba98da..534515fa10 100644 --- a/epan/dissectors/packet-dtn.h +++ b/epan/dissectors/packet-dtn.h @@ -143,11 +143,21 @@ /* ECOS Flags */ #define ECOS_FLAGS_CRITICAL 0x01 #define ECOS_FLAGS_STREAMING 0x02 -#define ECOS_FLAGS_ORDINAL 0x04 +#define ECOS_FLAGS_FLOWLABEL 0x04 +#define ECOS_FLAGS_RELIABLE 0x08 +#define DTN_SCHEME_STR "dtn" #define IPN_SCHEME_STR "ipn" int evaluate_sdnv(tvbuff_t *tvb, int offset, int *bytecount); gint64 evaluate_sdnv_64(tvbuff_t *tvb, int offset, int *bytecount); +/* Special Functions to evaluate unsigned SDNVs with error indication + * bytecount returns the number bytes consumed + * value returns the actual value + * + * result is TRUE (1) on success else FALSE (0) + */ +int evaluate_sdnv32(tvbuff_t *tvb, int offset, int *bytecount, guint32 *value); +int evaluate_sdnv64(tvbuff_t *tvb, int offset, int *bytecount, guint64 *value); diff --git a/epan/dissectors/packet-ltp.c b/epan/dissectors/packet-ltp.c index d73f64f557..2a860d90ea 100644 --- a/epan/dissectors/packet-ltp.c +++ b/epan/dissectors/packet-ltp.c @@ -21,6 +21,21 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +/* + * Modifications were made to this file under designation MFS-33289-1 and + * are Copyright 2015 United States Government as represented by NASA + * Marshall Space Flight Center. All Rights Reserved. + * + * Released under the GNU GPL with NASA legal approval granted 2016-06-10. + * + * The subject software is provided "AS IS" WITHOUT ANY WARRANTY of any kind, + * either expressed, implied or statutory and this agreement does not, + * in any manner, constitute an endorsement by government agency of any + * results, designs or products resulting from use of the subject software. + * See the Agreement for the specific language governing permissions and + * limitations. + */ + /* * Licklider Transmission Protocol - RFC 5326. */ @@ -50,7 +65,6 @@ static int proto_ltp = -1; /* LTP Header variables */ static int hf_ltp_version = -1; static int hf_ltp_type = -1; -static int hf_ltp_session_id = -1; static int hf_ltp_session_orig = -1; static int hf_ltp_session_no = -1; static int hf_ltp_hdr_extn_cnt = -1; @@ -62,6 +76,8 @@ static int hf_ltp_data_offset = -1; static int hf_ltp_data_length = -1; static int hf_ltp_data_chkp = -1; static int hf_ltp_data_rpt = -1; +static int hf_ltp_data_sda_clid = -1; +static int hf_ltp_partial_packet = -1; /* static int hf_ltp_data_clidata = -1; */ /* LTP Report Segment variable */ @@ -75,6 +91,7 @@ static int hf_ltp_rpt_clm_len = -1; /* LTP Report Ack Segment Variable */ static int hf_ltp_rpt_ack_sno = -1; +static int hf_ltp_cancel_ack = -1; /* LTP Session Management Segment Variable */ static int hf_ltp_cancel_code = -1; @@ -103,6 +120,8 @@ static int hf_ltp_reassembled_length = -1; static expert_field ei_ltp_neg_reception_claim_count = EI_INIT; static expert_field ei_ltp_mal_reception_claim = EI_INIT; +static expert_field ei_ltp_sdnv_length = EI_INIT; +static expert_field ei_ltp_sno_larger_than_ccsds = EI_INIT; static dissector_handle_t bundle_handle; @@ -162,6 +181,12 @@ static const value_string extn_tag_codes[] = { {0, NULL} }; +static const value_string client_service_id_info[] = { + {0x01, "Bundle Protocol"}, + {0x02, "CCSDS LTP Service Data Aggregation"}, + {0, NULL} +}; + static guint ltp_port = 1113; @@ -204,129 +229,127 @@ static const fragment_items ltp_frag_items = { }; static int -dissect_data_segment(proto_tree *ltp_tree, tvbuff_t *tvb,packet_info *pinfo,int frame_offset,int ltp_type, guint64 session_num){ +add_sdnv64_to_tree(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, int offset, int hf_sdnv, guint64 *value, proto_item** item_ret) +{ + int sdnv_status; + int sdnv_length; + guint64 sdnv_value; + proto_item* ti; + + sdnv_status = evaluate_sdnv64(tvb, offset, &sdnv_length, &sdnv_value); + ti = proto_tree_add_uint64(tree, hf_sdnv, tvb, offset, sdnv_length, sdnv_value); + + *value = sdnv_value; + if (NULL != *item_ret) *item_ret = ti; + + if (!sdnv_status) { + expert_add_info(pinfo, ti, &ei_ltp_sdnv_length); + } + return sdnv_length; +} + +static int +dissect_data_segment(proto_tree *ltp_tree, tvbuff_t *tvb,packet_info *pinfo,int frame_offset,int ltp_type, guint64 session_num) +{ guint64 client_id; - guint64 offset; - guint64 length; + guint64 data_offset; + guint64 data_length; guint64 chkp_sno = 0; guint64 rpt_sno = 0; + guint64 sda_client_id = 0; - int segment_offset = 0; + unsigned segment_size = 0; - int client_id_size; - int offset_size; - int length_size; - int chkp_sno_size; - int rpt_sno_size; - - int data_offset = 0; - int data_length; - int bundle_size = 0; - int dissected_data_size = 0; - int data_count = 1; + int sdnv_length; + int sdnv_status; proto_tree *ltp_data_tree; - proto_tree *ltp_data_data_tree; - - tvbuff_t *datatvb; + proto_item *ti; fragment_head *frag_msg = NULL; gboolean more_frags = TRUE; tvbuff_t *new_tvb = NULL; - /* Extract the info for the data segment */ - client_id = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&client_id_size); - segment_offset+= client_id_size; - - if((unsigned)(frame_offset + segment_offset) >= tvb_captured_length(tvb)){ - /* This would mean the data segment is incomplete */ - return 0; - } - offset = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&offset_size); - segment_offset+= offset_size; - - if((unsigned)(frame_offset + segment_offset) >= tvb_captured_length(tvb)){ - /* This would mean the data segment is incomplete */ - return 0; - } - - length = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&length_size); - segment_offset+= length_size; - - if((unsigned)(frame_offset + segment_offset) >= tvb_captured_length(tvb)){ - /* This would mean the data segment is incomplete */ - return 0; - } - - if(ltp_type != 0 ) - { - chkp_sno = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&chkp_sno_size); - segment_offset+= chkp_sno_size; - - if((unsigned)(frame_offset + segment_offset) >= tvb_captured_length(tvb)){ - /* This would mean the data segment is incomplete */ - return 0; - } - - rpt_sno = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&rpt_sno_size); - segment_offset+= rpt_sno_size; - - if((unsigned)(frame_offset + segment_offset) >= tvb_captured_length(tvb)){ - /* This would mean the data segment is incomplete */ - return 0; - } - } - /* Adding size of the data */ - if ((segment_offset + (int)length < segment_offset) || (segment_offset + (int)length < (int)length)) { - /* Addition result has wrapped */ - return 0; - } - segment_offset+= (int)length; - - if ((segment_offset + frame_offset < segment_offset) || (segment_offset + frame_offset < frame_offset)) { - /* Addition result has wrapped */ - return 0; - } - if((unsigned)(frame_offset + segment_offset) > tvb_captured_length(tvb)){ - /* This would mean the data segment is incomplete */ - return 0; - } - /* Create a subtree for data segment and add the other fields under it */ - ltp_data_tree = proto_tree_add_subtree(ltp_tree, tvb,frame_offset, segment_offset, ett_data_segm, NULL, "Data Segment"); + ltp_data_tree = proto_tree_add_subtree(ltp_tree, tvb, frame_offset, tvb_captured_length(tvb), ett_data_segm, NULL, "Data Segment"); - proto_tree_add_uint64(ltp_data_tree,hf_ltp_data_clid, tvb, frame_offset,client_id_size,client_id); - frame_offset += client_id_size; - proto_tree_add_uint64(ltp_data_tree, hf_ltp_data_offset, tvb, frame_offset,offset_size, offset); - frame_offset += offset_size; - - proto_tree_add_uint64(ltp_data_tree,hf_ltp_data_length, tvb, frame_offset,length_size,length); - frame_offset += length_size; - - if(ltp_type != 0 ) - { - proto_tree_add_uint64(ltp_data_tree, hf_ltp_data_chkp, tvb, frame_offset,chkp_sno_size, chkp_sno); - frame_offset += chkp_sno_size; - - proto_tree_add_uint64(ltp_data_tree, hf_ltp_data_rpt, tvb, frame_offset,rpt_sno_size, rpt_sno); - frame_offset += rpt_sno_size; - - more_frags = FALSE; - frag_msg = fragment_add_check(<p_reassembly_table, - tvb, frame_offset, pinfo, (guint32)session_num, NULL, - (guint32)offset, (guint32)length, more_frags); + /* Client ID - 0 = Bundle Protocol, 1 = CCSDS LTP Service Data Aggregation */ + sdnv_status = evaluate_sdnv64(tvb, frame_offset, &sdnv_length, &client_id); + ti = proto_tree_add_uint64_format_value(ltp_data_tree, hf_ltp_data_clid, tvb, frame_offset, sdnv_length, client_id, + "%" G_GINT64_MODIFIER "u (%s)", client_id, + val_to_str_const((const guint32) client_id, client_service_id_info, "Invalid")); + if (!sdnv_status) { + expert_add_info(pinfo, ti, &ei_ltp_sdnv_length); + return 0; } - else + frame_offset += sdnv_length; + segment_size += sdnv_length; + + + /* data segment offset */ + if ((sdnv_length = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_offset, &data_offset, &ti)) > 0) { + frame_offset += sdnv_length; + segment_size += sdnv_length; + } else { + return 0; + } + + /* data segment length */ + if ((sdnv_length = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_length, &data_length, &ti)) > 0) { + frame_offset += sdnv_length; + segment_size += sdnv_length; + + /* add in the data length also */ + segment_size += (unsigned int) data_length; + } else { + return 0; + } + + more_frags = FALSE; + if (ltp_type != 0 && ltp_type < 4) { + /* checkpoint serial number - 32 bits per CCSDS */ + if ((sdnv_length = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_chkp, &chkp_sno, &ti)) > 0) { + frame_offset += sdnv_length; + segment_size += sdnv_length; + + if (chkp_sno > 4294967295U) { + /* just a warning - continue processing */ + expert_add_info(pinfo, ti, &ei_ltp_sno_larger_than_ccsds); + } + } else { + return 0; + } + + /* report serial number - 32 bits per CCSDS */ + if ((sdnv_length = add_sdnv64_to_tree(ltp_data_tree, tvb, pinfo, frame_offset, hf_ltp_data_rpt, &rpt_sno, &ti)) > 0) { + frame_offset += sdnv_length; + segment_size += sdnv_length; + + if (rpt_sno > 4294967295U) { + /* just a warning - continue processing */ + expert_add_info(pinfo, ti, &ei_ltp_sno_larger_than_ccsds); + } + } else { + return 0; + } + + } else if (ltp_type != 7) { more_frags = TRUE; - frag_msg = fragment_add_check(<p_reassembly_table, - tvb, frame_offset, pinfo, (guint32)session_num, NULL, - (guint32)offset, (guint32)length, more_frags); } + if (segment_size >= tvb_captured_length(tvb)) { + /* did not capture the entire packet */ + proto_tree_add_string(ltp_data_tree, hf_ltp_partial_packet, tvb, 0, 0, ""); + return tvb_captured_length(tvb); + } + + frag_msg = fragment_add_check(<p_reassembly_table, + tvb, frame_offset, pinfo, (guint32)session_num, NULL, + (guint32)data_offset, (guint32)data_length, more_frags); if(frag_msg) { @@ -334,14 +357,14 @@ dissect_data_segment(proto_tree *ltp_tree, tvbuff_t *tvb,packet_info *pinfo,int if(!(frag_msg->flags & FD_PARTIAL_REASSEMBLY)) { /* if the segment has not been fragmented, then no reassembly is needed */ - if(!more_frags && offset == 0) + if(!more_frags && data_offset == 0) { - new_tvb = tvb_new_subset_remaining(tvb,frame_offset); + new_tvb = tvb_new_subset_remaining(tvb, frame_offset); } else { new_tvb = process_reassembled_data(tvb, frame_offset, pinfo, "Reassembled LTP Segment", - frag_msg, <p_frag_items,NULL, ltp_data_tree); + frag_msg, <p_frag_items,NULL, ltp_data_tree); } } @@ -349,20 +372,51 @@ dissect_data_segment(proto_tree *ltp_tree, tvbuff_t *tvb,packet_info *pinfo,int if(new_tvb) { - data_length = tvb_captured_length(new_tvb); - while(dissected_data_size < data_length) - { - ltp_data_data_tree = proto_tree_add_subtree_format(ltp_data_tree, tvb,frame_offset, 0, - ett_data_data_segm, NULL, "Data[%d]",data_count); + int data_count = 1; - datatvb = tvb_new_subset(new_tvb, data_offset, (int)data_length - dissected_data_size, tvb_captured_length(new_tvb)); + int parse_length; + int parse_offset = 0; + parse_length = tvb_captured_length(new_tvb); + while(parse_offset < parse_length) + { + int bundle_size; + int sda_header_size; + proto_tree *ltp_data_data_tree; + tvbuff_t *datatvb; + ltp_data_data_tree = proto_tree_add_subtree_format(ltp_data_tree, tvb,frame_offset, 0, + ett_data_data_segm, NULL, "Data[%d]",data_count); + + sda_header_size = 0; + if (client_id == 2) { + sdnv_status = evaluate_sdnv64(tvb, frame_offset+parse_offset, &sdnv_length, &sda_client_id); + ti = proto_tree_add_uint64_format_value(ltp_data_data_tree, hf_ltp_data_sda_clid, tvb, frame_offset+parse_offset, sdnv_length, sda_client_id, + "%" G_GINT64_MODIFIER "u (%s)", sda_client_id, val_to_str_const((const guint32) sda_client_id, client_service_id_info, "Invalid")); + + if (!sdnv_status) { + expert_add_info(pinfo, ti, &ei_ltp_sdnv_length); + return 0; + } + + sda_header_size = sdnv_length; + + parse_offset += sdnv_length; + if (parse_offset == parse_length) { + col_set_str(pinfo->cinfo, COL_INFO, "CCSDS LTP SDA Protocol Error"); + return 0; /* Give up*/ + } + } + + datatvb = tvb_new_subset(new_tvb, parse_offset, (int)parse_length - parse_offset, tvb_captured_length(new_tvb)); bundle_size = call_dissector(bundle_handle, datatvb, pinfo, ltp_data_data_tree); if(bundle_size == 0) { /*Couldn't parse bundle*/ col_set_str(pinfo->cinfo, COL_INFO, "Dissection Failed"); return 0; /*Give up*/ } - data_offset += bundle_size; - dissected_data_size += bundle_size; + + /* update the length of the data set */ + proto_item_set_len(ltp_data_data_tree, bundle_size+sda_header_size); + + parse_offset += bundle_size; data_count++; } } @@ -379,7 +433,7 @@ dissect_data_segment(proto_tree *ltp_tree, tvbuff_t *tvb,packet_info *pinfo,int } - return segment_offset; + return segment_size; } @@ -441,11 +495,11 @@ dissect_report_segment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ltp_tree, * max number of claims we can possibly squeeze into the remaining tvbuff, then * the packet is malformed. */ - if (rcpt_clm_cnt > tvb_reported_length_remaining(tvb, frame_offset + segment_offset) / 2) { + if (rcpt_clm_cnt > tvb_captured_length_remaining(tvb, frame_offset + segment_offset) / 2) { proto_item_set_end(ltp_rpt_item, tvb, frame_offset + segment_offset); expert_add_info_format(pinfo, ltp_tree, &ei_ltp_mal_reception_claim, "Reception claim count impossibly large: %d > %d", rcpt_clm_cnt, - tvb_reported_length_remaining(tvb, frame_offset + segment_offset) / 2); + tvb_captured_length_remaining(tvb, frame_offset + segment_offset) / 2); return 0; } proto_tree_add_uint(ltp_rpt_tree, hf_ltp_rpt_clm_cnt, tvb, frame_offset + segment_offset, rcpt_clm_cnt_size, rcpt_clm_cnt); @@ -514,6 +568,7 @@ dissect_cancel_segment(proto_tree * ltp_tree, tvbuff_t *tvb,int frame_offset){ return 1; } + static int dissect_header_extn(proto_tree *ltp_tree, tvbuff_t *tvb,int frame_offset,int hdr_extn_cnt){ guint8 extn_type[LTP_MAX_HDR_EXTN]; @@ -622,8 +677,6 @@ dissect_ltp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) int frame_offset; int header_offset; int segment_offset = 0; - int hdr_extn_offset = 0; - int trl_extn_offset = 0; guint8 ltp_hdr; gint ltp_type; @@ -636,9 +689,6 @@ dissect_ltp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) int engine_id_size; int session_num_size; - proto_item *ltp_header_item = NULL; - proto_item *ltp_session_item = NULL; - proto_tree *ltp_header_tree = NULL; proto_tree *ltp_session_tree = NULL; @@ -682,8 +732,9 @@ dissect_ltp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) frame_offset++; /* Adding the session id subtree */ - ltp_session_item = proto_tree_add_item(ltp_header_item,hf_ltp_session_id,tvb,frame_offset, engine_id_size + session_num_size,ENC_NA); - ltp_session_tree = proto_item_add_subtree(ltp_session_item,ett_hdr_session); + ltp_session_tree = proto_tree_add_subtree(ltp_header_tree, tvb, frame_offset, header_offset+1, ett_hdr_session, NULL, "Session ID"); + + proto_tree_add_uint64(ltp_session_tree,hf_ltp_session_orig,tvb,frame_offset,engine_id_size,engine_id); frame_offset+=engine_id_size; proto_tree_add_uint64(ltp_session_tree,hf_ltp_session_no, tvb, frame_offset,session_num_size,session_num); @@ -700,13 +751,15 @@ dissect_ltp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(ltp_type,ltp_type_col_info,"Protocol Error")); - if((unsigned)frame_offset >= tvb_captured_length(tvb)){ - col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); - return 0; - } - /* Check if there are any header extensions */ if(hdr_extn_cnt > 0){ + int hdr_extn_offset; + + if((unsigned)frame_offset >= tvb_captured_length(tvb)){ + col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); + return 0; + } + hdr_extn_offset = dissect_header_extn(ltp_tree, tvb, frame_offset,hdr_extn_cnt); if(hdr_extn_offset == 0){ col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); @@ -715,10 +768,16 @@ dissect_ltp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) frame_offset += hdr_extn_offset; } - if((unsigned)frame_offset >= tvb_captured_length(tvb)){ + if((unsigned)frame_offset > tvb_captured_length(tvb)){ col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); return 0; } + else if((unsigned)frame_offset == tvb_captured_length(tvb)){ + if(ltp_type != 13 && ltp_type != 15){ + col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); + return 0; + } + } /* Call sub routines to handle the segment content*/ if((ltp_type >= 0) && (ltp_type < 8)){ @@ -749,6 +808,9 @@ dissect_ltp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) return 0; } } + else if(ltp_type == 13 || ltp_type == 15){ + proto_tree_add_string(ltp_tree, hf_ltp_cancel_ack, tvb, 0, 0, "(No Data)"); + } frame_offset += segment_offset; /* Check to see if there are any trailer extensions */ if(trl_extn_cnt > 0){ @@ -756,8 +818,7 @@ dissect_ltp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); return 0; } - trl_extn_offset = dissect_trailer_extn(ltp_tree, tvb, frame_offset,trl_extn_cnt); - if(trl_extn_offset == 0){ + if(0 == dissect_trailer_extn(ltp_tree, tvb, frame_offset,trl_extn_cnt)) { col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); return 0; } @@ -772,11 +833,6 @@ ltp_defragment_init(void) { &addresses_reassembly_table_functions); } -static void -ltp_defragment_cleanup(void) { - reassembly_table_destroy(<p_reassembly_table); -} - /* Register the protocol with Wireshark */ void proto_register_ltp(void) @@ -792,10 +848,6 @@ proto_register_ltp(void) {"LTP Type","ltp.type", FT_UINT8,BASE_HEX,NULL, 0x0, NULL, HFILL} }, - {&hf_ltp_session_id, - {"Session ID","ltp.session", - FT_NONE,BASE_NONE,NULL, 0x0, NULL, HFILL} - }, {&hf_ltp_session_orig, {"Session originator","ltp.session.orig", FT_UINT64,BASE_DEC,NULL, 0x0, NULL, HFILL} @@ -938,6 +990,18 @@ proto_register_ltp(void) {&hf_ltp_reassembled_length, {"LTP reassembled length", "ltp.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + {&hf_ltp_data_sda_clid, + {"Client service ID", "ltp.data.sda.client.id", + FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + {&hf_ltp_partial_packet, + {"", "ltp.partial_packet", + FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + {&hf_ltp_cancel_ack, + {"", "ltp.cancel_ack", + FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL} } }; @@ -961,6 +1025,8 @@ proto_register_ltp(void) static ei_register_info ei[] = { { &ei_ltp_neg_reception_claim_count, { "ltp.neg_reception_claim_count", PI_UNDECODED, PI_ERROR, "Negative reception claim count", EXPFILL }}, { &ei_ltp_mal_reception_claim, { "ltp.mal_reception_claim", PI_MALFORMED, PI_ERROR, "Reception claim count impossibly large", EXPFILL }}, + { &ei_ltp_sdnv_length, { "ltp.sdnv_length_invalid", PI_PROTOCOL, PI_ERROR, "SDNV length error", EXPFILL }}, + { &ei_ltp_sno_larger_than_ccsds, { "ltp.serial_number_too_large", PI_PROTOCOL, PI_WARN, "Serial number larger than CCSDS specification", EXPFILL }} }; expert_module_t* expert_ltp; @@ -981,7 +1047,6 @@ proto_register_ltp(void) "The UDP or DCCP port to accept LTP Connections", 10, <p_port); register_init_routine(ltp_defragment_init); - register_cleanup_routine(ltp_defragment_cleanup); } void