NASA provided LTP and DTN updates
authordz-msfc <zollerd@gmail.com>
Thu, 3 Mar 2016 02:39:12 +0000 (20:39 -0600)
committerAnders Broman <a.broman58@gmail.com>
Thu, 23 Jun 2016 14:19:17 +0000 (14:19 +0000)
Change-Id: I49769271a41b6a7b23c6bc1d4beaadbe8819198d
Reviewed-on: https://code.wireshark.org/review/14310
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
epan/dissectors/packet-dtn.c
epan/dissectors/packet-dtn.h
epan/dissectors/packet-ltp.c

index 06cfe59a26160dd317366fb7b97d5cf341b058d1..1ad920075c89b831ea1f6e48b93c1d10b4cebf8f 100644 (file)
  * 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 <stdio.h>
 #include <epan/packet.h>
 #include <epan/prefs.h>
 #include <epan/reassemble.h>
@@ -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);
+        /* 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);
 
-        col_add_fstr(pinfo->cinfo, COL_INFO, "%s > %s", src_node, dst_node);
-        /* remember custodian, for use in checking cteb validity */
         *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
index 0d57ba98da22fcc4e999dec7c1d4dddaf301dbb2..534515fa102a72879a03b659ac6b05d09717684e 100644 (file)
 /* 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);
index d73f64f5571c1505f826cbbb3c67950b2f16764c..2a860d90ea40bbd5c2755a933a885568aa67b502 100644 (file)
  * 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;
+       /* 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, tvb_captured_length(tvb), ett_data_segm, NULL, "Data Segment");
+
 
-       if((unsigned)(frame_offset + segment_offset) >= tvb_captured_length(tvb)){
-       /* This would mean the data segment is incomplete */
+       /* 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;
        }
-       offset = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&offset_size);
-       segment_offset+= offset_size;
+       frame_offset += sdnv_length;
+       segment_size += sdnv_length;
 
-       if((unsigned)(frame_offset + segment_offset) >= tvb_captured_length(tvb)){
-       /* This would mean the data segment is incomplete */
+
+       /* 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;
        }
 
-       length = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&length_size);
-       segment_offset+= length_size;
+       /* 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;
 
-       if((unsigned)(frame_offset + segment_offset) >= tvb_captured_length(tvb)){
-       /* This would mean the data segment is incomplete */
+               /* add in the data length also */
+               segment_size += (unsigned int) data_length;
+       } else {
                return 0;
        }
 
-       if(ltp_type != 0 )
+       more_frags = FALSE;
+       if (ltp_type != 0 && ltp_type < 4)
        {
-               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 */
+               /* 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;
                }
 
-               rpt_sno = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&rpt_sno_size);
-               segment_offset+= rpt_sno_size;
+               /* 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((unsigned)(frame_offset + segment_offset) >= tvb_captured_length(tvb)){
-               /* This would mean the data segment is incomplete */
+                       if (rpt_sno > 4294967295U) {
+                               /* just a warning - continue processing */
+                               expert_add_info(pinfo, ti, &ei_ltp_sno_larger_than_ccsds);
+                       }
+               } else {
                        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");
-
-       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;
+       } else if (ltp_type != 7) {
+               more_frags = TRUE;
 
-               more_frags = FALSE;
-               frag_msg = fragment_add_check(&ltp_reassembly_table,
-                         tvb, frame_offset, pinfo, (guint32)session_num, NULL,
-                         (guint32)offset, (guint32)length, more_frags);
        }
-       else
-       {
-               more_frags = TRUE;
-               frag_msg = fragment_add_check(&ltp_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, "<increase capture size?>");
+               return tvb_captured_length(tvb);
        }
 
+       frag_msg = fragment_add_check(&ltp_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, &ltp_frag_items,NULL, ltp_data_tree);
+                                                                       frag_msg, &ltp_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)
+               int data_count = 1;
+
+               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);
+                                                                               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, data_offset, (int)data_length - dissected_data_size, tvb_captured_length(new_tvb));
+                       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(&ltp_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,
+                 {"<partial packet>", "ltp.partial_packet",
+                 FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL}
+         },
+         {&hf_ltp_cancel_ack,
+                 {"<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, &ltp_port);
        register_init_routine(ltp_defragment_init);
-       register_cleanup_routine(ltp_defragment_cleanup);
 }
 
 void