summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-bpv6.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-bpv6.c')
-rw-r--r--epan/dissectors/packet-bpv6.c2594
1 files changed, 2594 insertions, 0 deletions
diff --git a/epan/dissectors/packet-bpv6.c b/epan/dissectors/packet-bpv6.c
new file mode 100644
index 00000000..ed53a677
--- /dev/null
+++ b/epan/dissectors/packet-bpv6.c
@@ -0,0 +1,2594 @@
+/* packet-bpv6.c
+ * References:
+ * RFC 5050: https://tools.ietf.org/html/rfc5050
+ *
+ * Copyright 2006-2007 The MITRE Corporation.
+ * All Rights Reserved.
+ * Approved for Public Release; Distribution Unlimited.
+ * Tracking Number 07-0090.
+ *
+ * The US Government will not be charged any license fee and/or royalties
+ * related to this software. Neither name of The MITRE Corporation; nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Specification reference:
+ * RFC 5050
+ * https://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 <epan/packet.h>
+#include <epan/reassemble.h>
+#include <epan/expert.h>
+#include <epan/wscbor.h>
+#include "packet-bpv6.h"
+#include "packet-cfdp.h"
+
+void proto_register_bpv6(void);
+void proto_reg_handoff_bpv6(void);
+
+static int dissect_admin_record(proto_tree *primary_tree, tvbuff_t *tvb, packet_info *pinfo,
+ int offset, int payload_length, gboolean* success);
+
+extern void
+dissect_amp_as_subtree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+
+
+static int evaluate_sdnv(tvbuff_t *tvb, int offset, int *bytecount);
+
+/// Return an error_info index if not valid
+static int evaluate_sdnv_ei(tvbuff_t *tvb, int offset, int *bytecount, expert_field **error);
+
+static int add_sdnv_time_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, int hf_sdnv_time);
+
+static gint64
+evaluate_sdnv_64(tvbuff_t *tvb, int offset, int *bytecount);
+
+static int proto_bundle = -1;
+static dissector_handle_t bundle_handle = NULL;
+static dissector_handle_t bpv6_handle = NULL;
+static dissector_handle_t bpv7_handle = NULL;
+
+static int hf_bundle_pdu_version = -1;
+
+/* Primary Header Processing Flag Variables */
+static int hf_bundle_procflags = -1;
+static int hf_bundle_procflags_fragment = -1;
+static int hf_bundle_procflags_admin = -1;
+static int hf_bundle_procflags_dont_fragment = -1;
+static int hf_bundle_procflags_cust_xfer_req = -1;
+static int hf_bundle_procflags_dest_singleton = -1;
+static int hf_bundle_procflags_application_ack = -1;
+
+/* Additions for Version 5 */
+static int hf_bundle_control_flags = -1;
+static int hf_bundle_procflags_general = -1;
+static int hf_bundle_procflags_cos = -1;
+static int hf_bundle_procflags_status = -1;
+
+/* Primary Header COS Flag Variables */
+static int hf_bundle_cosflags = -1;
+static int hf_bundle_cosflags_priority = -1;
+
+/* Primary Header Status Report Request Flag Variables */
+static int hf_bundle_srrflags = -1;
+static int hf_bundle_srrflags_report_receipt = -1;
+static int hf_bundle_srrflags_report_cust_accept = -1;
+static int hf_bundle_srrflags_report_forward = -1;
+static int hf_bundle_srrflags_report_delivery = -1;
+static int hf_bundle_srrflags_report_deletion = -1;
+static int hf_bundle_srrflags_report_ack = -1;
+
+/* Primary Header Fields*/
+static int hf_bundle_primary_header_len = -1;
+static int hf_bundle_primary_dictionary_len = -1;
+static int hf_bundle_primary_timestamp = -1;
+static int hf_bundle_primary_fragment_offset = -1;
+static int hf_bundle_primary_total_adu_len = -1;
+static int hf_bundle_primary_timestamp_seq_num64 = -1;
+static int hf_bundle_primary_timestamp_seq_num32 = -1;
+
+static int hf_bundle_dest_scheme_offset_u16 = -1;
+static int hf_bundle_dest_scheme_offset_i32 = -1;
+static int hf_bundle_dest_ssp_offset_u16 = -1;
+static int hf_bundle_dest_ssp_offset_i32 = -1;
+static int hf_bundle_source_scheme_offset_u16 = -1;
+static int hf_bundle_source_scheme_offset_i32 = -1;
+static int hf_bundle_source_ssp_offset_u16 = -1;
+static int hf_bundle_source_ssp_offset_i32 = -1;
+static int hf_bundle_report_scheme_offset_u16 = -1;
+static int hf_bundle_report_scheme_offset_i32 = -1;
+static int hf_bundle_report_ssp_offset_u16 = -1;
+static int hf_bundle_report_ssp_offset_i32 = -1;
+static int hf_bundle_cust_scheme_offset_u16 = -1;
+static int hf_bundle_cust_scheme_offset_i32 = -1;
+static int hf_bundle_cust_ssp_offset_u16 = -1;
+static int hf_bundle_cust_ssp_offset_i32 = -1;
+
+/* Dictionary EIDs */
+static int hf_bundle_dest_scheme = -1;
+static int hf_bundle_dest_ssp = -1;
+static int hf_bundle_source_scheme = -1;
+static int hf_bundle_source_ssp = -1;
+static int hf_bundle_report_scheme = -1;
+static int hf_bundle_report_ssp = -1;
+static int hf_bundle_custodian_scheme = -1;
+static int hf_bundle_custodian_ssp = -1;
+
+/* Remaining Primary Header Fields */
+static int hf_bundle_creation_timestamp = -1;
+static int hf_bundle_lifetime = -1;
+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;
+static int hf_bundle_payload_flags_discard_on_fail = -1;
+static int hf_bundle_payload_flags_last_header = -1;
+
+/* Block Processing Control Flag Variables (Version 5) */
+static int hf_block_control_flags = -1;
+static int hf_block_control_flags_sdnv = -1;
+static int hf_block_control_replicate = -1;
+static int hf_block_control_transmit_status = -1;
+static int hf_block_control_delete_bundle = -1;
+static int hf_block_control_last_block = -1;
+static int hf_block_control_discard_block = -1;
+static int hf_block_control_not_processed = -1;
+static int hf_block_control_eid_reference = -1;
+static int hf_block_control_block_length = -1;
+static int hf_block_control_block_cteb_custody_id = -1;
+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_flowlabel = -1;
+static int hf_ecos_flags_reliable = -1;
+static int hf_ecos_flow_label = -1;
+
+static int hf_ecos_ordinal = -1;
+
+/* Administrative Record Variables */
+static int hf_bundle_admin_record_type = -1;
+static int hf_bundle_admin_record_fragment = -1;
+static int hf_bundle_admin_statflags = -1;
+static int hf_bundle_admin_rcvd = -1;
+static int hf_bundle_admin_accepted = -1;
+static int hf_bundle_admin_forwarded = -1;
+static int hf_bundle_admin_delivered = -1;
+static int hf_bundle_admin_deleted = -1;
+static int hf_bundle_admin_acked = -1;
+static int hf_bundle_admin_fragment_offset = -1;
+static int hf_bundle_admin_fragment_length = -1;
+static int hf_bundle_admin_timestamp_seq_num64 = -1;
+static int hf_bundle_admin_timestamp_seq_num32 = -1;
+static int hf_bundle_admin_endpoint_length = -1;
+static int hf_bundle_admin_endpoint_id = -1;
+
+static int hf_bundle_admin_receipt_time = -1;
+static int hf_bundle_admin_accept_time = -1;
+static int hf_bundle_admin_forward_time = -1;
+static int hf_bundle_admin_delivery_time = -1;
+static int hf_bundle_admin_delete_time = -1;
+static int hf_bundle_admin_ack_time = -1;
+static int hf_bundle_admin_timestamp_copy = -1;
+static int hf_bundle_admin_signal_time = -1;
+static int hf_bundle_status_report_reason_code = -1;
+static int hf_bundle_custody_trf_succ_flg = -1;
+static int hf_bundle_custody_signal_reason = -1;
+static int hf_bundle_custody_id_range_start = -1;
+static int hf_bundle_custody_id_range_end = -1;
+
+static int hf_bundle_age_extension_block_code = -1;
+static int hf_bundle_block_previous_hop_scheme = -1;
+static int hf_bundle_block_previous_hop_eid = -1;
+
+/* Security Block Variables */
+static int hf_bundle_target_block_type = -1;
+static int hf_bundle_target_block_occurrence = -1;
+static int hf_bundle_ciphersuite_type = -1;
+static int hf_bundle_ciphersuite_flags = -1;
+static int hf_block_ciphersuite_params = -1;
+static int hf_block_ciphersuite_params_length = -1;
+static int hf_block_ciphersuite_params_item_length = -1;
+static int hf_block_ciphersuite_param_type = -1;
+static int hf_block_ciphersuite_param_data = -1;
+static int hf_block_ciphersuite_result_length = -1;
+static int hf_block_ciphersuite_result_item_length = -1;
+static int hf_block_ciphersuite_result_type = -1;
+static int hf_block_ciphersuite_result_data = -1;
+static int hf_block_ciphersuite_range_offset = -1;
+static int hf_block_ciphersuite_range_length = -1;
+
+/* Tree Node Variables */
+static gint ett_bundle = -1;
+static gint ett_bundle_hdr = -1;
+static gint ett_primary_hdr = -1;
+static gint ett_proc_flags = -1;
+static gint ett_gen_flags = -1;
+static gint ett_cos_flags = -1;
+static gint ett_srr_flags = -1;
+static gint ett_dictionary = -1;
+static gint ett_payload_hdr = -1;
+static gint ett_payload_flags = -1;
+static gint ett_block_flags = -1;
+static gint ett_admin_record = -1;
+static gint ett_admin_rec_status = -1;
+static gint ett_metadata_hdr = -1;
+static gint ett_sec_block_param_data = -1;
+
+static expert_field ei_bundle_payload_length = EI_INIT;
+static expert_field ei_bundle_control_flags_length = EI_INIT;
+static expert_field ei_bundle_block_control_flags = EI_INIT;
+static expert_field ei_bundle_sdnv_length = EI_INIT;
+static expert_field ei_bundle_timestamp_seq_num = EI_INIT;
+static expert_field ei_bundle_offset_error = EI_INIT;
+static expert_field ei_block_control_block_cteb_invalid = EI_INIT;
+static expert_field ei_block_control_block_cteb_valid = EI_INIT;
+
+
+typedef struct dictionary_data {
+ int bundle_header_dict_length;
+
+ int dest_scheme_offset;
+ int dst_scheme_pos;
+ int dst_scheme_len;
+ int source_scheme_offset;
+ int src_scheme_pos;
+ int src_scheme_len;
+ int report_scheme_offset;
+ int rpt_scheme_pos;
+ int rpt_scheme_len;
+ int cust_scheme_offset;
+ int cust_scheme_pos;
+ int cust_scheme_len;
+ int dest_ssp_offset;
+ int dst_ssp_len;
+ int source_ssp_offset;
+ int src_ssp_len;
+ int report_ssp_offset;
+ int rpt_ssp_len;
+ int cust_ssp_offset;
+ int cust_ssp_len;
+
+} dictionary_data_t;
+
+
+static const value_string admin_record_type_vals[] = {
+ {ADMIN_REC_TYPE_STATUS_REPORT, "Bundle Status Report"},
+ {ADMIN_REC_TYPE_CUSTODY_SIGNAL, "Custody Signal"},
+ {ADMIN_REC_TYPE_AGGREGATE_CUSTODY_SIGNAL, "Aggregate Custody Signal"},
+ {ADMIN_REC_TYPE_ANNOUNCE_BUNDLE, "Announce Record (Contact)"},
+ {0, NULL}
+};
+
+static const value_string custody_signal_reason_codes[] = {
+ {0x0, "No Additional Information"},
+ {0x3, "Redundant Reception"},
+ {0x4, "Depleted Storage"},
+ {0x5, "Destination Endpoint ID Unintelligible"},
+ {0x6, "No Known Route to Destination"},
+ {0x7, "No Timely Contact with Next Node on Route"},
+ {0x8, "Header Unintelligible"},
+ {0, NULL}
+};
+
+static const value_string status_report_reason_codes[] = {
+ {0x0, "No Additional Information"},
+ {0x1, "Lifetime Expired"},
+ {0x2, "Forwarded over Unidirectional Link"},
+ {0x3, "Transmission Cancelled"},
+ {0x4, "Depleted Storage"},
+ {0x5, "Destination Endpoint ID Unintelligible"},
+ {0x6, "No Known Route to Destination"},
+ {0x7, "No Timely Contact with Next Node on Route"},
+ {0x8, "Header Unintelligible"},
+ {0, NULL}
+};
+
+static const value_string bundle_block_type_codes[] = {
+ {0x01, "Bundle Payload Block"},
+ {0x02, "Bundle Authentication Block"},
+ {0x03, "Block Integrity Block"},
+ {0x04, "Block Confidentiality Block"},
+ {0x05, "Previous-Hop Insertion Block"},
+ {0x08, "Metadata Extension Block"},
+ {0x09, "Extension Security Block"},
+ {0x0a, "Custody Transfer Enhancement Block"},
+ {0x13, "Extended Class of Service Block"},
+ {0x14, "Bundle Age Extension Block"},
+ {0, NULL}
+};
+
+static const value_string cosflags_priority_vals[] = {
+ {0x00, "Bulk"},
+ {0x01, "Normal"},
+ {0x02, "Expedited"},
+ {0x03, "Invalid (Reserved)"},
+ {0, NULL}
+};
+
+static const value_string ciphersuite_types[] = {
+ {0x01, "HMAC_SHA1"},
+ {0x05, "HMAC_SHA256"},
+ {0x06, "ARC4_AES128"},
+ {0xD1, "HMAC_SHA384"},
+ {0xD2, "ECDSA_SHA256"},
+ {0xD3, "ECDSA_SHA384"},
+ {0xD4, "SHA256_AES128"},
+ {0xD5, "SHA384_AES256"},
+ {0, NULL}
+};
+
+static const value_string res_params_types[] = {
+ {0x01, "Initialization Vector"},
+ {0x03, "Key Information"},
+ {0x04, "Content Range"},
+ {0x05, "Integrity Signature"},
+ {0x07, "Salt"},
+ {0x08, "BCB Integrity Check Value"},
+ {0, NULL}
+};
+
+/*
+ * Adds the result of 2 SDNVs to tree: First SDNV is seconds, next is nanoseconds.
+ * Returns bytes in both SDNVs or 0 if something goes wrong.
+ */
+static int
+add_dtn_time_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, int hf_dtn_time)
+{
+ 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) {
+ return 0;
+ }
+
+ dtn_time.secs = (time_t)(sdnv_value + 946684800);
+ offset += sdnv_length;
+
+ dtn_time.nsecs = evaluate_sdnv(tvb, offset, &sdnv2_length);
+ if (dtn_time.nsecs < 0) {
+ return 0;
+ }
+
+ proto_tree_add_time(tree, hf_dtn_time, tvb, orig_offset, sdnv_length + sdnv2_length, &dtn_time);
+
+ return (sdnv_length + sdnv2_length);
+}
+
+/*
+ * Adds the result of SDNV which is a time since 2000 to tree.
+ * Returns bytes in SDNV or 0 if something goes wrong.
+ */
+int
+add_sdnv_time_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, int hf_sdnv_time)
+{
+ nstime_t dtn_time;
+ int sdnv_length;
+ int sdnv_value;
+
+ sdnv_value = evaluate_sdnv(tvb, offset, &sdnv_length);
+ if (sdnv_value < 0) {
+ return 0;
+ }
+
+ dtn_time.secs = (time_t)(sdnv_value + 946684800);
+ dtn_time.nsecs = 0;
+ proto_tree_add_time(tree, hf_sdnv_time, tvb, offset, sdnv_length, &dtn_time);
+
+ return sdnv_length;
+}
+
+static int
+add_sdnv_to_tree(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, int offset, int hf_sdnv)
+{
+ proto_item *ti;
+ int sdnv_length;
+ int sdnv_value;
+
+ sdnv_value = evaluate_sdnv(tvb, offset, &sdnv_length);
+ ti = proto_tree_add_int(tree, hf_sdnv, tvb, offset, sdnv_length, sdnv_value);
+ if (sdnv_value < 0) {
+ expert_add_info(pinfo, ti, &ei_bundle_sdnv_length);
+ return 0;
+ }
+ return sdnv_length;
+}
+
+/*
+ * Pull out stuff from the dictionary
+ */
+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, int creation_timestamp, int timestamp_sequence)
+{
+ proto_tree *dict_tree;
+ 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");
+
+ /*
+ * If the dictionary length is 0, then the CBHE block compression method is applied. (RFC6260)
+ * So the scheme offset is the node number and the ssp offset is the service number.
+ * If destination scheme offset is 2 and destination ssp offset is 1, then the EID is
+ * ipn:2.1
+ */
+ if (dict_data->bundle_header_dict_length == 0)
+ {
+ const gchar *src_node, *dst_node;
+
+ /*
+ * Destination info
+ */
+ 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, "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(pinfo->pool, "%d.%d",dict_data->dest_scheme_offset,dict_data->dest_ssp_offset));
+
+ dst_node = wmem_strdup_printf(pinfo->pool, "%s:%d.%d", IPN_SCHEME_STR,
+ dict_data->dest_scheme_offset, dict_data->dest_ssp_offset);
+ }
+
+ /*
+ * Source info
+ */
+ 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, "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(pinfo->pool, "%d.%d", dict_data->source_scheme_offset, dict_data->source_ssp_offset));
+
+ src_node = wmem_strdup_printf(pinfo->pool, "%s:%d.%d", IPN_SCHEME_STR,
+ dict_data->source_scheme_offset, dict_data->source_ssp_offset);
+ }
+
+ /*
+ * Report to info
+ */
+ 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, "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(pinfo->pool, "%d.%d", dict_data->report_scheme_offset, dict_data->report_ssp_offset));
+ }
+
+ /*
+ * Custodian info
+ */
+ 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, "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(pinfo->pool, "%d.%d", dict_data->cust_scheme_offset, dict_data->cust_ssp_offset));
+ }
+
+ /* remember custodian, for use in checking cteb validity */
+ col_set_writable(pinfo->cinfo, COL_INFO, TRUE);
+ 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(pinfo->pool, "%s:%d.%d", IPN_SCHEME_STR,
+ dict_data->cust_scheme_offset, dict_data->cust_ssp_offset);
+ }
+
+ /*
+ * This pointer can be made to address outside the packet boundaries so we
+ * need to check for improperly formatted strings (no null termination).
+ */
+
+ else
+ {
+ /*
+ * Destination info
+ */
+
+ proto_tree_add_item(dict_tree, hf_bundle_dest_scheme,
+ tvb, offset + dict_data->dest_scheme_offset, -1, ENC_ASCII);
+ proto_tree_add_item(dict_tree, hf_bundle_dest_ssp,
+ tvb, offset + dict_data->dest_ssp_offset, -1, ENC_ASCII);
+
+ /*
+ * Source info
+ */
+
+ proto_tree_add_item(dict_tree, hf_bundle_source_scheme,
+ tvb, offset + dict_data->source_scheme_offset, -1, ENC_ASCII);
+ proto_tree_add_item(dict_tree, hf_bundle_source_ssp,
+ tvb, offset + dict_data->source_ssp_offset, -1, ENC_ASCII);
+
+ /*
+ * Report to info
+ */
+
+ proto_tree_add_item(dict_tree, hf_bundle_report_scheme,
+ tvb, offset + dict_data->report_scheme_offset, -1, ENC_ASCII);
+ proto_tree_add_item(dict_tree, hf_bundle_report_ssp,
+ tvb, offset + dict_data->report_ssp_offset, -1, ENC_ASCII);
+
+ /*
+ * Custodian info
+ */
+
+ proto_tree_add_item(dict_tree, hf_bundle_custodian_scheme, tvb, offset + dict_data->cust_scheme_offset, -1, ENC_ASCII);
+ proto_tree_add_item(dict_tree, hf_bundle_custodian_ssp, tvb, offset + dict_data->cust_ssp_offset, -1, ENC_ASCII);
+
+ /*
+ * Add Source/Destination to INFO Field
+ */
+
+ col_set_writable(pinfo->cinfo, COL_INFO, TRUE);
+ 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(pinfo->pool, tvb, offset + dict_data->source_scheme_offset, NULL, ENC_ASCII),
+ tvb_get_stringz_enc(pinfo->pool, tvb, offset + dict_data->source_ssp_offset, NULL, ENC_ASCII),
+ tvb_get_stringz_enc(pinfo->pool, tvb, offset + dict_data->dest_scheme_offset, NULL, ENC_ASCII),
+ tvb_get_stringz_enc(pinfo->pool, 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(pinfo->pool,
+ "%s:%s",
+ tvb_get_stringz_enc(pinfo->pool,
+ tvb, offset + dict_data->cust_scheme_offset,
+ NULL, ENC_ASCII),
+ tvb_get_stringz_enc(pinfo->pool,
+ tvb, offset + dict_data->cust_ssp_offset,
+ NULL, ENC_ASCII));
+ }
+ offset += dict_data->bundle_header_dict_length; /*Skip over dictionary*/
+
+ /*
+ * Do this only if Fragment Flag is set
+ */
+
+ 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;
+ }
+ offset += sdnv_length;
+
+ sdnv_length = add_sdnv_to_tree(tree, tvb, pinfo, offset, hf_bundle_primary_total_adu_len);
+ if (sdnv_length < 0) {
+ return 0;
+ }
+ offset += sdnv_length;
+ }
+
+ return offset;
+}
+
+/*
+ * This routine returns 0 if header decoding fails, otherwise the length of the primary
+ * header, starting right after version number.
+ */
+static int
+dissect_version_4_primary_header(packet_info *pinfo, proto_tree *primary_tree, tvbuff_t *tvb,
+ guint8* pri_hdr_procflags, gchar **bundle_custodian)
+{
+ int bundle_header_length;
+ int offset = 1; /* Version Number already displayed */
+ int sdnv_length;
+ dictionary_data_t dict_data;
+
+ proto_item *ti;
+ proto_tree *srr_flag_tree, *proc_flag_tree, *cos_flag_tree;
+
+ /* Primary Header Processing Flags */
+ *pri_hdr_procflags = tvb_get_guint8(tvb, offset);
+ ti = proto_tree_add_item(primary_tree, hf_bundle_procflags, tvb,
+ offset, 1, ENC_BIG_ENDIAN);
+ proc_flag_tree = proto_item_add_subtree(ti, ett_proc_flags);
+ proto_tree_add_item(proc_flag_tree, hf_bundle_procflags_fragment,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(proc_flag_tree, hf_bundle_procflags_admin,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(proc_flag_tree, hf_bundle_procflags_dont_fragment,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(proc_flag_tree, hf_bundle_procflags_cust_xfer_req,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(proc_flag_tree, hf_bundle_procflags_dest_singleton,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+
+ /* Primary Header COS Flags */
+ ++offset;
+ ti = proto_tree_add_item(primary_tree, hf_bundle_cosflags, tvb,
+ offset, 1, ENC_BIG_ENDIAN);
+ cos_flag_tree = proto_item_add_subtree(ti, ett_cos_flags);
+ proto_tree_add_item(cos_flag_tree, hf_bundle_cosflags_priority,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ /* Status Report Request Flags */
+ ++offset;
+ ti = proto_tree_add_item(primary_tree, hf_bundle_srrflags, tvb,
+ offset, 1, ENC_BIG_ENDIAN);
+ srr_flag_tree = proto_item_add_subtree(ti, ett_srr_flags);
+
+ proto_tree_add_item(srr_flag_tree, hf_bundle_srrflags_report_receipt,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(srr_flag_tree, hf_bundle_srrflags_report_cust_accept,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(srr_flag_tree, hf_bundle_srrflags_report_forward,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(srr_flag_tree, hf_bundle_srrflags_report_delivery,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(srr_flag_tree, hf_bundle_srrflags_report_deletion,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(srr_flag_tree, hf_bundle_srrflags_report_ack,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ ++offset;
+
+ bundle_header_length = evaluate_sdnv(tvb, offset, &sdnv_length);
+ ti = proto_tree_add_int(primary_tree, hf_bundle_primary_header_len, tvb, offset, sdnv_length,
+ bundle_header_length);
+ if (bundle_header_length < 0) {
+ expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "Bundle Header Length Error");
+ return tvb_reported_length_remaining(tvb, offset);
+ }
+
+ offset += sdnv_length;
+
+ /* Ensure all fields have been initialized */
+ memset(&dict_data, 0, sizeof(dict_data));
+
+ /*
+ * Pick up offsets into dictionary (8 of them)
+ */
+
+ dict_data.dest_scheme_offset = tvb_get_ntohs(tvb, offset);
+ dict_data.dst_scheme_pos = offset;
+ dict_data.dst_scheme_len = 2;
+ proto_tree_add_item(primary_tree, hf_bundle_dest_scheme_offset_u16,
+ tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ dict_data.dest_ssp_offset = tvb_get_ntohs(tvb, offset);
+ dict_data.dst_ssp_len = 2;
+ proto_tree_add_item(primary_tree, hf_bundle_dest_ssp_offset_u16,
+ tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ dict_data.source_scheme_offset = tvb_get_ntohs(tvb, offset);
+ dict_data.src_scheme_pos = offset;
+ dict_data.src_scheme_len = 2;
+ proto_tree_add_item(primary_tree, hf_bundle_source_scheme_offset_u16,
+ tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ dict_data.source_ssp_offset = tvb_get_ntohs(tvb, offset);
+ dict_data.src_ssp_len = 2;
+ proto_tree_add_item(primary_tree, hf_bundle_source_ssp_offset_u16,
+ tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ dict_data.report_scheme_offset = tvb_get_ntohs(tvb, offset);
+ dict_data.rpt_scheme_pos = offset;
+ dict_data.rpt_scheme_len = 2;
+ proto_tree_add_item(primary_tree, hf_bundle_report_scheme_offset_u16,
+ tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ dict_data.report_ssp_offset = tvb_get_ntohs(tvb, offset);
+ dict_data.rpt_ssp_len = 2;
+ proto_tree_add_item(primary_tree, hf_bundle_report_ssp_offset_u16,
+ tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ dict_data.cust_scheme_offset = tvb_get_ntohs(tvb, offset);
+ dict_data.cust_scheme_pos = offset;
+ dict_data.cust_scheme_len = 2;
+ proto_tree_add_item(primary_tree, hf_bundle_cust_scheme_offset_u16,
+ tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ dict_data.cust_ssp_offset = tvb_get_ntohs(tvb, offset);
+ dict_data.cust_ssp_len = 2;
+ proto_tree_add_item(primary_tree, hf_bundle_cust_ssp_offset_u16,
+ tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(primary_tree, hf_bundle_creation_timestamp,
+ tvb, offset, 8, ENC_BIG_ENDIAN);
+ offset += 8;
+
+ proto_tree_add_item(primary_tree, hf_bundle_lifetime, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ dict_data.bundle_header_dict_length = evaluate_sdnv(tvb, offset, &sdnv_length);
+ ti = proto_tree_add_int(primary_tree, hf_bundle_primary_dictionary_len, tvb, offset, sdnv_length,
+ dict_data.bundle_header_dict_length);
+ if (dict_data.bundle_header_dict_length < 0) {
+ expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "Dictionary Header Length Error");
+ return tvb_reported_length_remaining(tvb, offset);
+ }
+ offset += sdnv_length;
+
+ offset = dissect_dictionary(pinfo, primary_tree, tvb, offset, &dict_data, *pri_hdr_procflags, bundle_custodian, 0, 0);
+ return offset;
+}
+
+
+/*
+ * This routine returns 0 if header decoding fails, otherwise the length of the primary
+ * header, starting right after version number.
+ */
+
+static int src_ssp;
+static int dst_ssp;
+
+static int
+dissect_version_5_and_6_primary_header(packet_info *pinfo,
+ proto_tree *primary_tree, tvbuff_t *tvb,
+ guint8* pri_hdr_procflags, gchar **bundle_custodian)
+{
+ guint64 bundle_processing_control_flags;
+ guint8 cosflags;
+ int bundle_header_length;
+ int offset = 1; /* Version Number already displayed */
+ 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 int * const pri_flags[] = {
+ &hf_bundle_procflags_fragment,
+ &hf_bundle_procflags_admin,
+ &hf_bundle_procflags_dont_fragment,
+ &hf_bundle_procflags_cust_xfer_req,
+ &hf_bundle_procflags_dest_singleton,
+ &hf_bundle_procflags_application_ack,
+ NULL
+ };
+
+ static int * const srr_flags[] = {
+ &hf_bundle_srrflags_report_receipt,
+ &hf_bundle_srrflags_report_cust_accept,
+ &hf_bundle_srrflags_report_forward,
+ &hf_bundle_srrflags_report_delivery,
+ &hf_bundle_srrflags_report_deletion,
+ NULL
+ };
+
+ bundle_processing_control_flags = evaluate_sdnv_64(tvb, offset, &sdnv_length);
+
+ /* Primary Header Processing Flags */
+ *pri_hdr_procflags = (guint8) (bundle_processing_control_flags & 0x7f);
+
+ if (sdnv_length < 1 || sdnv_length > 8) {
+ expert_add_info_format(pinfo, primary_tree, &ei_bundle_control_flags_length,
+ "Wrong bundle control flag length: %d", sdnv_length);
+ return 0;
+ }
+ ti = proto_tree_add_item(primary_tree, hf_bundle_control_flags, tvb,
+ offset, sdnv_length, ENC_BIG_ENDIAN);
+ proc_flag_tree = proto_item_add_subtree(ti, ett_proc_flags);
+
+ ti = proto_tree_add_uint(proc_flag_tree, hf_bundle_procflags_general, tvb, offset,
+ sdnv_length, *pri_hdr_procflags);
+ gen_flag_tree = proto_item_add_subtree(ti, ett_gen_flags);
+
+ /* With the variability of sdnv_length, proto_tree_add_bitmask_value
+ can't be used */
+
+ proto_tree_add_bitmask_list_value(gen_flag_tree, tvb, offset, sdnv_length, pri_flags, *pri_hdr_procflags);
+
+ /* Primary Header COS Flags */
+ cosflags = (guint8) ((bundle_processing_control_flags >> 7) & 0x7f);
+ ti = proto_tree_add_uint(proc_flag_tree, hf_bundle_procflags_cos, tvb, offset,
+ sdnv_length, cosflags);
+ cos_flag_tree = proto_item_add_subtree(ti, ett_cos_flags);
+ proto_tree_add_uint(cos_flag_tree, hf_bundle_cosflags_priority, tvb, offset,
+ sdnv_length, cosflags);
+
+ /* Status Report Request Flags */
+ srrflags = (guint8) ((bundle_processing_control_flags >> 14) & 0x7f);
+ ti = proto_tree_add_uint(proc_flag_tree, hf_bundle_procflags_status, tvb, offset,
+ sdnv_length, srrflags);
+ srr_flag_tree = proto_item_add_subtree(ti, ett_srr_flags);
+
+ proto_tree_add_bitmask_list_value(srr_flag_tree, tvb, offset, sdnv_length, srr_flags, srrflags);
+ offset += sdnv_length;
+
+ /* -- hdr_length -- */
+ bundle_header_length = evaluate_sdnv(tvb, offset, &sdnv_length);
+ ti = proto_tree_add_int(primary_tree, hf_bundle_primary_header_len, tvb, offset, sdnv_length,
+ bundle_header_length);
+ if (bundle_header_length < 0) {
+ expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "Bundle Header Length Error");
+ return tvb_reported_length_remaining(tvb, offset);
+ }
+
+ offset += sdnv_length;
+
+ /*
+ * Pick up offsets into dictionary (8 of them). Do rough sanity check that SDNV
+ * hasn't told us to access way past the Primary Header.
+ */
+
+ /* Ensure all fields have been initialized */
+ memset(&dict_data, 0, sizeof(dict_data));
+
+ /* -- dest_scheme -- */
+ dict_data.dest_scheme_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
+ dict_data.dst_scheme_pos = offset;
+ dict_data.dst_scheme_len = 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);
+ offset += sdnv_length;
+
+ /* -- dest_ssp -- */
+ dict_data.dest_ssp_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
+ dict_data.dst_ssp_len = sdnv_length;
+ dst_ssp = dict_data.dest_ssp_offset;
+
+ 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);
+ offset += sdnv_length;
+
+ /* -- source_scheme -- */
+ dict_data.source_scheme_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
+ dict_data.src_scheme_pos = offset;
+ dict_data.src_scheme_len = 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);
+ offset += sdnv_length;
+
+ /* -- source_ssp -- */
+ dict_data.source_ssp_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
+ dict_data.src_ssp_len = sdnv_length;
+ src_ssp = dict_data.source_ssp_offset;
+
+ 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);
+ offset += sdnv_length;
+
+ /* -- report_scheme -- */
+ dict_data.report_scheme_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
+ dict_data.rpt_scheme_pos = offset;
+ dict_data.rpt_scheme_len = sdnv_length;
+
+ 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);
+ offset += sdnv_length;
+
+ /* -- report_ssp -- */
+ dict_data.report_ssp_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
+ dict_data.rpt_ssp_len = 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);
+ offset += sdnv_length;
+
+
+ /* -- cust_scheme -- */
+ dict_data.cust_scheme_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
+ dict_data.cust_scheme_pos = offset;
+ dict_data.cust_scheme_len = 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);
+ offset += sdnv_length;
+
+ /* -- cust_ssp -- */
+ dict_data.cust_ssp_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
+ dict_data.cust_ssp_len = 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);
+ 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;
+
+ offset += sdnv_length;
+
+ /* -- timestamp_sequence -- */
+ timestamp_sequence = evaluate_sdnv(tvb, offset, &sdnv_length);
+ if (timestamp_sequence < 0) {
+ gint64 ts_seq = evaluate_sdnv_64(tvb, offset, &sdnv_length);
+
+ ti = proto_tree_add_int64(primary_tree, hf_bundle_primary_timestamp_seq_num64,
+ tvb, offset, sdnv_length, ts_seq);
+ if (ts_seq < 0) {
+ expert_add_info(pinfo, ti, &ei_bundle_timestamp_seq_num);
+ }
+ }
+ else {
+ proto_tree_add_int(primary_tree, hf_bundle_primary_timestamp_seq_num32,
+ tvb, offset, sdnv_length, timestamp_sequence);
+ }
+ offset += sdnv_length;
+
+ /* -- lifetime -- */
+ sdnv_length = add_sdnv_to_tree(primary_tree, tvb, pinfo, offset, hf_bundle_lifetime_sdnv);
+ offset += sdnv_length;
+
+ /* -- dict_length -- */
+ dict_data.bundle_header_dict_length = evaluate_sdnv(tvb, offset, &sdnv_length);
+ ti = proto_tree_add_int(primary_tree, hf_bundle_primary_dictionary_len, tvb, offset, sdnv_length,
+ dict_data.bundle_header_dict_length);
+ if (dict_data.bundle_header_dict_length < 0) {
+ expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "Dictionary Header Length Error");
+ return tvb_reported_length_remaining(tvb, offset);
+ }
+ offset += sdnv_length;
+
+ 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;
+}
+
+/*
+ * offset is where the header starts.
+ * Return new offset, and set lastheader if failure.
+ */
+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_block, *payload_item, *ti;
+ proto_tree *payload_block_tree, *payload_tree;
+ int sdnv_length, payload_length;
+
+ 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;
+
+ /* Add tree for processing flags */
+ /* This is really a SDNV but there are only 7 bits defined so leave it this way*/
+
+ if (version == 4) {
+ static int * const flags[] = {
+ &hf_bundle_payload_flags_replicate_hdr,
+ &hf_bundle_payload_flags_xmit_report,
+ &hf_bundle_payload_flags_discard_on_fail,
+ &hf_bundle_payload_flags_last_header,
+ NULL
+ };
+ guint8 procflags;
+
+ procflags = tvb_get_guint8(tvb, offset);
+ if (procflags & HEADER_PROCFLAGS_LAST_HEADER) {
+ *lastheader = TRUE;
+ }
+ else {
+ *lastheader = FALSE;
+ }
+ proto_tree_add_bitmask(payload_tree, tvb, offset, hf_bundle_payload_flags,
+ ett_payload_flags, flags, ENC_BIG_ENDIAN);
+ ++offset;
+ }
+ else { /*Bundle Protocol Version 5*/
+ int control_flags;
+ proto_item *block_flag_item;
+ proto_tree *block_flag_tree;
+
+ control_flags = evaluate_sdnv(tvb, offset, &sdnv_length);
+ if (control_flags & BLOCK_CONTROL_LAST_BLOCK) {
+ *lastheader = TRUE;
+ }
+ else {
+ *lastheader = FALSE;
+ }
+ block_flag_item = proto_tree_add_item(payload_tree, hf_block_control_flags, tvb,
+ offset, sdnv_length, ENC_BIG_ENDIAN);
+ block_flag_tree = proto_item_add_subtree(block_flag_item, ett_block_flags);
+
+ proto_tree_add_item(block_flag_tree, hf_block_control_replicate,
+ tvb, offset, sdnv_length, ENC_BIG_ENDIAN);
+ proto_tree_add_item(block_flag_tree, hf_block_control_transmit_status,
+ tvb, offset, sdnv_length, ENC_BIG_ENDIAN);
+ proto_tree_add_item(block_flag_tree, hf_block_control_delete_bundle,
+ tvb, offset, sdnv_length, ENC_BIG_ENDIAN);
+ proto_tree_add_item(block_flag_tree, hf_block_control_last_block,
+ tvb, offset, sdnv_length, ENC_BIG_ENDIAN);
+ proto_tree_add_item(block_flag_tree, hf_block_control_discard_block,
+ tvb, offset, sdnv_length, ENC_BIG_ENDIAN);
+ proto_tree_add_item(block_flag_tree, hf_block_control_not_processed,
+ tvb, offset, sdnv_length, ENC_BIG_ENDIAN);
+ proto_tree_add_item(block_flag_tree, hf_block_control_eid_reference,
+ tvb, offset, sdnv_length, ENC_BIG_ENDIAN);
+ offset += sdnv_length;
+ }
+
+ payload_length = evaluate_sdnv(tvb, offset, &sdnv_length);
+ ti = proto_tree_add_int(payload_tree, hf_bundle_payload_length, tvb, offset, sdnv_length, payload_length);
+ if (payload_length < 0) {
+ expert_add_info(pinfo, ti, &ei_bundle_payload_length);
+ /* Force quiting */
+ *lastheader = TRUE;
+ return offset;
+ }
+
+ 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) {
+ gboolean success = FALSE;
+
+ /*
+ * XXXX - Have not allowed for admin record spanning multiple segments!
+ */
+
+ offset = dissect_admin_record(payload_block_tree, tvb, pinfo, offset, payload_length, &success);
+ if (!success) {
+ /* Force quiting */
+ *lastheader = TRUE;
+ return offset;
+ }
+ } else {
+ /* If Source SSP Offset is 64 and Destination SSP offset is 65, then
+ interpret the payload-data part as CFDP. */
+ if (src_ssp == 0x40 &&
+ dst_ssp == 0x41)
+ {
+ dissect_cfdp_as_subtree (tvb, pinfo, payload_block_tree, offset);
+ }
+ /* If Source SSP Offset is 5 and Destination SSP offset is 6, then
+ interpret the payload-data part as AMP. */
+ else if ((src_ssp == 0x5 && dst_ssp == 0x6) ||
+ (dst_ssp == 0x5 && src_ssp == 0x6))
+ {
+ dissect_amp_as_subtree (tvb, pinfo, payload_block_tree, offset);
+ }
+ else
+ {
+ proto_tree_add_string(payload_block_tree, hf_bundle_payload_data, tvb, offset, payload_length,
+ wmem_strdup_printf(pinfo->pool, "<%d bytes>",payload_length));
+ }
+
+ offset += payload_length;
+ }
+
+ return offset;
+}
+
+/*
+ * Return the offset after the Administrative Record or set success = FALSE if analysis fails.
+ */
+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;
+ proto_tree *admin_record_tree;
+ proto_item *timestamp_sequence_item;
+ guint8 record_type;
+ guint8 status;
+ int start_offset = offset;
+ int sdnv_length;
+ int timestamp_sequence;
+ int endpoint_length;
+
+ *success = FALSE;
+ admin_record_tree = proto_tree_add_subtree(primary_tree, tvb, offset, -1,
+ ett_admin_record, &admin_record_item, "Administrative Record");
+ record_type = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_item(admin_record_tree, hf_bundle_admin_record_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+
+ switch ((record_type >> 4) & 0xf)
+ {
+ case ADMIN_REC_TYPE_STATUS_REPORT:
+ {
+ proto_item *status_flag_item;
+ proto_tree *status_flag_tree;
+
+ proto_tree_add_item(admin_record_tree, hf_bundle_admin_record_fragment, tvb, offset, 1, ENC_NA);
+ ++offset;
+
+ /* Decode Bundle Status Report Flags */
+ status = tvb_get_guint8(tvb, offset);
+ status_flag_item = proto_tree_add_item(admin_record_tree,
+ hf_bundle_admin_statflags, tvb, offset, 1, ENC_BIG_ENDIAN);
+ status_flag_tree = proto_item_add_subtree(status_flag_item,
+ ett_admin_rec_status);
+ proto_tree_add_item(status_flag_tree, hf_bundle_admin_rcvd,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(status_flag_tree, hf_bundle_admin_accepted,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(status_flag_tree, hf_bundle_admin_forwarded,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(status_flag_tree, hf_bundle_admin_delivered,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(status_flag_tree, hf_bundle_admin_deleted,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(status_flag_tree, hf_bundle_admin_acked,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ ++offset;
+
+ proto_tree_add_item(admin_record_tree, hf_bundle_status_report_reason_code, tvb, offset, 1, ENC_BIG_ENDIAN);
+ ++offset;
+
+ if (record_type & ADMIN_REC_FLAGS_FRAGMENT) {
+ sdnv_length = add_sdnv_to_tree(admin_record_tree, tvb, pinfo, offset, hf_bundle_admin_fragment_offset);
+ if (sdnv_length <= 0) {
+ return offset;
+ }
+ offset += sdnv_length;
+ sdnv_length = add_sdnv_to_tree(admin_record_tree, tvb, pinfo, offset, hf_bundle_admin_fragment_length);
+ if (sdnv_length <= 0) {
+ return offset;
+ }
+ offset += sdnv_length;
+ }
+ if (status & ADMIN_STATUS_FLAGS_RECEIVED) {
+ sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_receipt_time);
+ if (sdnv_length <= 0) {
+ return offset;
+ }
+ offset += sdnv_length;
+ }
+ if (status & ADMIN_STATUS_FLAGS_ACCEPTED) {
+ sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_accept_time);
+ if (sdnv_length <= 0) {
+ return offset;
+ }
+ offset += sdnv_length;
+ }
+ if (status & ADMIN_STATUS_FLAGS_FORWARDED) {
+ sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_forward_time);
+ if (sdnv_length <= 0) {
+ return offset;
+ }
+ offset += sdnv_length;
+ }
+ if (status & ADMIN_STATUS_FLAGS_DELIVERED) {
+ sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_delivery_time);
+ if (sdnv_length <= 0) {
+ return offset;
+ }
+ offset += sdnv_length;
+ }
+ if (status & ADMIN_STATUS_FLAGS_DELETED) {
+ sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_delete_time);
+ if (sdnv_length <= 0) {
+ return offset;
+ }
+ offset += sdnv_length;
+ }
+ if (status & ADMIN_STATUS_FLAGS_ACKNOWLEDGED) {
+ sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_ack_time);
+ if (sdnv_length <= 0) {
+ return offset;
+ }
+ offset += sdnv_length;
+ }
+
+ /* Get 2 SDNVs for Creation Timestamp */
+ sdnv_length = add_sdnv_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_timestamp_copy);
+ if (sdnv_length <= 0) {
+ return offset;
+ }
+ offset += sdnv_length;
+
+ timestamp_sequence = evaluate_sdnv(tvb, offset, &sdnv_length);
+ if (timestamp_sequence < 0) {
+ gint64 ts_seq = evaluate_sdnv_64(tvb, offset, &sdnv_length);
+
+ timestamp_sequence_item = proto_tree_add_int64(admin_record_tree, hf_bundle_admin_timestamp_seq_num64,
+ tvb, offset, sdnv_length, ts_seq);
+ if (ts_seq < 0) {
+ expert_add_info(pinfo, timestamp_sequence_item, &ei_bundle_timestamp_seq_num);
+ return offset;
+ }
+ }
+ else {
+ proto_tree_add_int(admin_record_tree, hf_bundle_admin_timestamp_seq_num32,
+ tvb, offset, sdnv_length, timestamp_sequence);
+ }
+ offset += sdnv_length;
+
+ endpoint_length = evaluate_sdnv(tvb, offset, &sdnv_length);
+ if (endpoint_length < 0) {
+ return tvb_reported_length_remaining(tvb, offset);
+ }
+ proto_tree_add_int(admin_record_tree, hf_bundle_admin_endpoint_length, tvb, offset, sdnv_length, endpoint_length);
+ offset += sdnv_length;
+
+ /*
+ * Endpoint name may not be null terminated. This routine is supposed
+ * to add the null at the end of the string buffer.
+ */
+ proto_tree_add_item(admin_record_tree, hf_bundle_admin_endpoint_id, tvb, offset, endpoint_length, ENC_NA|ENC_ASCII);
+ offset += endpoint_length;
+
+ break;
+ } /* case ADMIN_REC_TYPE_STATUS_REPORT */
+ case ADMIN_REC_TYPE_CUSTODY_SIGNAL:
+ {
+ proto_tree_add_item(admin_record_tree, hf_bundle_admin_record_fragment, tvb, offset, 1, ENC_NA);
+ ++offset;
+
+ proto_tree_add_item(admin_record_tree, hf_bundle_custody_trf_succ_flg, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(admin_record_tree, hf_bundle_custody_signal_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
+ ++offset;
+
+ if (record_type & ADMIN_REC_FLAGS_FRAGMENT) {
+ sdnv_length = add_sdnv_to_tree(admin_record_tree, tvb, pinfo, offset, hf_bundle_admin_fragment_offset);
+ if (sdnv_length <= 0) {
+ return offset;
+ }
+ offset += sdnv_length;
+ sdnv_length = add_sdnv_to_tree(admin_record_tree, tvb, pinfo, offset, hf_bundle_admin_fragment_length);
+ if (sdnv_length <= 0) {
+ return offset;
+ }
+ offset += sdnv_length;
+ }
+
+ /* Signal Time */
+ sdnv_length = add_dtn_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_signal_time);
+ if (sdnv_length <= 0) {
+ return offset;
+ }
+ offset += sdnv_length;
+
+ /* Timestamp copy */
+ sdnv_length = add_sdnv_time_to_tree(admin_record_tree, tvb, offset, hf_bundle_admin_timestamp_copy);
+ if (sdnv_length <= 0) {
+ return offset;
+ }
+ offset += sdnv_length;
+
+ timestamp_sequence = evaluate_sdnv(tvb, offset, &sdnv_length);
+ if (timestamp_sequence < 0) {
+ gint64 ts_seq = evaluate_sdnv_64(tvb, offset, &sdnv_length);
+
+ timestamp_sequence_item = proto_tree_add_int64(admin_record_tree, hf_bundle_admin_timestamp_seq_num64,
+ tvb, offset, sdnv_length, ts_seq);
+ if (ts_seq < 0) {
+ expert_add_info(pinfo, timestamp_sequence_item, &ei_bundle_timestamp_seq_num);
+ return offset;
+ }
+ }
+ else {
+ proto_tree_add_int(admin_record_tree, hf_bundle_admin_timestamp_seq_num32,
+ tvb, offset, sdnv_length, timestamp_sequence);
+ }
+ offset += sdnv_length;
+
+ endpoint_length = evaluate_sdnv(tvb, offset, &sdnv_length);
+ if (endpoint_length < 0) {
+ return tvb_reported_length_remaining(tvb, offset);
+ }
+ proto_tree_add_int(admin_record_tree, hf_bundle_admin_endpoint_length, tvb, offset, sdnv_length, endpoint_length);
+ offset += sdnv_length;
+ proto_tree_add_item(admin_record_tree, hf_bundle_admin_endpoint_id, tvb, offset, endpoint_length, ENC_NA|ENC_ASCII);
+ offset += endpoint_length;
+ break;
+ } /* 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;
+ int fill_length = -1;
+ int sdnv_length_start = -1;
+ int sdnv_length_gap = -1;
+ int sdnv_length_length = -1;
+
+ proto_tree_add_item(admin_record_tree, hf_bundle_admin_record_fragment, tvb, offset, 1, ENC_NA);
+ ++offset;
+ ++payload_bytes_processed;
+
+ proto_tree_add_item(admin_record_tree, hf_bundle_custody_trf_succ_flg, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(admin_record_tree, hf_bundle_custody_signal_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
+ ++offset;
+ ++payload_bytes_processed;
+
+ /* process the first fill */
+ fill_start = evaluate_sdnv(tvb, offset, &sdnv_length_start);
+ ti = proto_tree_add_int(admin_record_tree, hf_bundle_custody_id_range_start, tvb, offset, sdnv_length_start, fill_start);
+ if (fill_start < 0 || sdnv_length_start < 0) {
+ expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "ACS: Unable to process CTEB Custody ID Range start SDNV");
+ return offset;
+ }
+ fill_length = evaluate_sdnv(tvb, offset + sdnv_length_start, &sdnv_length_length);
+ ti = proto_tree_add_int(admin_record_tree, hf_bundle_custody_id_range_end, tvb, offset,
+ sdnv_length_start + sdnv_length_length, fill_start + fill_length - 1);
+ if (fill_length < 0 || sdnv_length_length < 0) {
+ expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "ACS: Unable to process CTEB Custody ID Range length SDNV");
+ return tvb_reported_length_remaining(tvb, offset);
+ }
+
+ right_edge = fill_start + fill_length;
+ offset += sdnv_length_start + sdnv_length_length;
+ payload_bytes_processed += sdnv_length_start + sdnv_length_length;
+
+ /* 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) {
+ expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "ACS: Unable to process CTEB Custody ID Range gap SDNV");
+ return offset;
+ }
+ fill_length = evaluate_sdnv(tvb, offset + sdnv_length_gap, &sdnv_length_length);
+ ti = proto_tree_add_int(admin_record_tree, hf_bundle_custody_id_range_end, tvb, offset,
+ sdnv_length_gap + sdnv_length_length, right_edge + fill_gap + fill_length - 1);
+ if (fill_length < 0 || sdnv_length_length < 0) {
+ expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "ACS: Unable to process CTEB Custody ID Range length SDNV");
+ return tvb_reported_length_remaining(tvb, offset);
+ }
+
+ right_edge += fill_gap + fill_length;
+ offset += sdnv_length_gap + sdnv_length_length;
+ payload_bytes_processed += sdnv_length_gap + sdnv_length_length;
+ }
+
+ if (payload_bytes_processed > payload_length) {
+ expert_add_info_format(pinfo, ti, &ei_bundle_offset_error, "ACS: CTEB Custody ID Range data extends past payload length");
+ return offset;
+ }
+
+ break;
+ } /* case ADMIN_REC_TYPE_AGGREGATE_CUSTODY_SIGNAL */
+ case ADMIN_REC_TYPE_ANNOUNCE_BUNDLE:
+ default:
+ offset++;
+ break;
+ } /* End Switch */
+
+ proto_item_set_len(admin_record_item, offset - start_offset);
+ *success = TRUE;
+ return offset;
+}
+
+static int
+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;
+ int bundle_age;
+ 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, "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) {
+ *lastheader = TRUE;
+ } else {
+ *lastheader = FALSE;
+ }
+ block_flag_item = proto_tree_add_uint(block_tree, hf_block_control_flags_sdnv, tvb,
+ offset, sdnv_length, control_flags);
+ block_flag_tree = proto_item_add_subtree(block_flag_item, ett_block_flags);
+ block_flag_replicate_item = proto_tree_add_boolean(block_flag_tree, hf_block_control_replicate,
+ tvb, offset, sdnv_length, control_flags);
+ proto_tree_add_boolean(block_flag_tree, hf_block_control_transmit_status,
+ tvb, offset, sdnv_length, control_flags);
+ proto_tree_add_boolean(block_flag_tree, hf_block_control_delete_bundle,
+ tvb, offset, sdnv_length, control_flags);
+ proto_tree_add_boolean(block_flag_tree, hf_block_control_last_block,
+ tvb, offset, sdnv_length, control_flags);
+ proto_tree_add_boolean(block_flag_tree, hf_block_control_discard_block,
+ tvb, offset, sdnv_length, control_flags);
+ proto_tree_add_boolean(block_flag_tree, hf_block_control_not_processed,
+ tvb, offset, sdnv_length, control_flags);
+ 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) {
+ int i;
+ int num_eid_ref;
+
+ num_eid_ref = evaluate_sdnv(tvb, offset, &sdnv_length);
+ offset += sdnv_length;
+ block_overhead += sdnv_length;
+
+ for (i = 0; i < num_eid_ref; i++)
+ {
+ if (evaluate_sdnv(tvb, offset, &sdnv_length) < 0)
+ break;
+ offset += sdnv_length;
+ block_overhead += sdnv_length;
+
+ if (evaluate_sdnv(tvb, offset, &sdnv_length) < 0)
+ break;
+ offset += sdnv_length;
+ block_overhead += sdnv_length;
+ }
+ }
+
+ block_length = evaluate_sdnv(tvb, offset, &sdnv_length);
+ ti = proto_tree_add_int(block_tree, hf_block_control_block_length, tvb, offset, sdnv_length, block_length);
+ if (block_length < 0) {
+ expert_add_info_format(pinfo, ti, &ei_bundle_offset_error, "Metadata Block Length Error");
+ /* Force quitting */
+ *lastheader = TRUE;
+ 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, block_overhead + block_length);
+
+ switch (type)
+ {
+ case BUNDLE_BLOCK_TYPE_AUTHENTICATION:
+ 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;
+ }
+ case BUNDLE_BLOCK_TYPE_BUNDLE_AGE:
+ {
+ bundle_age = evaluate_sdnv(tvb, offset, &sdnv_length);
+ proto_tree_add_int(block_tree, hf_bundle_age_extension_block_code, tvb, offset, sdnv_length, bundle_age/1000000);
+ offset += block_length;
+ break;
+ }
+ case BUNDLE_BLOCK_TYPE_PREVIOUS_HOP_INSERT:
+ {
+ int scheme_length;
+
+ proto_tree_add_item_ret_length(block_tree, hf_bundle_block_previous_hop_scheme, tvb, offset, 4, ENC_ASCII, &scheme_length);
+ offset += scheme_length;
+ proto_tree_add_item(block_tree, hf_bundle_block_previous_hop_eid, tvb, offset, block_length-scheme_length, ENC_ASCII);
+ if (block_length - scheme_length < 1) {
+ expert_add_info_format(pinfo, ti, &ei_bundle_offset_error, "Metadata Block Length Error");
+ *lastheader = TRUE;
+ return offset;
+ }
+ offset += block_length - scheme_length;
+
+ break;
+ }
+ case BUNDLE_BLOCK_TYPE_INTEGRITY:
+ case BUNDLE_BLOCK_TYPE_CONFIDENTIALITY:
+ {
+ int target_block_type;
+ int target_block_occurrence;
+ int ciphersuite_type;
+ unsigned int ciphersuite_flags;
+
+ target_block_type = evaluate_sdnv(tvb, offset, &sdnv_length);
+ proto_tree_add_int(block_tree, hf_bundle_target_block_type, tvb, offset, sdnv_length, target_block_type);
+ offset += sdnv_length;
+
+ target_block_occurrence = evaluate_sdnv(tvb, offset, &sdnv_length);
+ proto_tree_add_int(block_tree, hf_bundle_target_block_occurrence, tvb, offset, sdnv_length, target_block_occurrence);
+ offset += sdnv_length;
+
+ ciphersuite_type = evaluate_sdnv(tvb, offset, &sdnv_length);
+ proto_tree_add_int(block_tree, hf_bundle_ciphersuite_type, tvb, offset, sdnv_length, ciphersuite_type);
+ offset += sdnv_length;
+
+ ciphersuite_flags = (unsigned int)evaluate_sdnv(tvb, offset, &sdnv_length);
+ block_flag_item = proto_tree_add_uint(block_tree, hf_bundle_ciphersuite_flags, tvb, offset, sdnv_length, ciphersuite_flags);
+ block_flag_tree = proto_item_add_subtree(block_flag_item, ett_block_flags);
+ proto_tree_add_boolean(block_flag_tree, hf_block_ciphersuite_params, tvb, offset, sdnv_length, ciphersuite_flags);
+ offset += sdnv_length;
+
+ int range_offset;
+ int range_length;
+ if (ciphersuite_flags & BLOCK_CIPHERSUITE_PARAMS) {
+ /* Decode cipher suite parameters */
+ int params_length;
+ int param_type;
+ int item_length;
+ proto_tree *param_tree;
+ expert_field *ei = NULL;
+
+ params_length = evaluate_sdnv_ei(tvb, offset, &sdnv_length, &ei);
+ if (ei) {
+ proto_tree_add_expert(block_tree, pinfo, ei, tvb, offset, -1);
+ *lastheader = TRUE;
+ return offset;
+ }
+ param_tree = proto_tree_add_subtree(block_tree, tvb, offset, params_length+1, ett_sec_block_param_data, NULL, "Ciphersuite Parameters Data");
+ proto_tree_add_int(param_tree, hf_block_ciphersuite_params_length, tvb, offset, sdnv_length, params_length);
+ offset += sdnv_length;
+
+ for(int i = 0; i < params_length; i+=item_length+2)
+ {
+ param_type = evaluate_sdnv(tvb, offset, &sdnv_length);
+ proto_tree_add_int(param_tree, hf_block_ciphersuite_param_type, tvb, offset, sdnv_length, param_type);
+ offset += sdnv_length;
+
+ ei = NULL;
+ item_length = evaluate_sdnv_ei(tvb, offset, &sdnv_length, &ei);
+ proto_tree_add_int(param_tree, hf_block_ciphersuite_params_item_length, tvb, offset, sdnv_length, item_length);
+ if (ei) {
+ proto_tree_add_expert(param_tree, pinfo, ei, tvb, offset, -1);
+ *lastheader = TRUE;
+ return offset;
+ }
+
+ offset += sdnv_length;
+
+ //display item data
+ switch (param_type)
+ {
+ case 1:
+ case 3:
+ case 5:
+ case 7:
+ case 8:
+ proto_tree_add_item(param_tree, hf_block_ciphersuite_param_data, tvb, offset, item_length, ENC_NA);
+ offset += item_length;
+ break;
+ case 4:
+ //pair of sdnvs offset and length
+ range_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
+ proto_tree_add_int(param_tree, hf_block_ciphersuite_range_offset, tvb, offset, sdnv_length, range_offset);
+ offset += sdnv_length;
+
+ range_length = evaluate_sdnv(tvb, offset, &sdnv_length);
+ proto_tree_add_int(param_tree, hf_block_ciphersuite_range_length, tvb, offset, sdnv_length, range_length);
+ offset += sdnv_length;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ /* Decode cipher suite results */
+ int result_length;
+ int result_type;
+ int result_item_length;
+ proto_tree *result_tree;
+
+ result_length = evaluate_sdnv(tvb, offset, &sdnv_length);
+ result_tree = proto_tree_add_subtree(block_tree, tvb, offset, result_length+1, ett_sec_block_param_data, NULL, "Security Results Data");
+ proto_tree_add_int(result_tree, hf_block_ciphersuite_result_length, tvb, offset, sdnv_length, result_length);
+ offset += sdnv_length;
+
+ for(int i = 0; i < result_length; i+=result_item_length+2)
+ {
+ result_type = evaluate_sdnv(tvb, offset, &sdnv_length);
+ proto_tree_add_int(result_tree, hf_block_ciphersuite_result_type, tvb, offset, sdnv_length, result_type);
+ offset += sdnv_length;
+
+ expert_field *ei = NULL;
+ result_item_length = evaluate_sdnv_ei(tvb, offset, &sdnv_length, &ei);
+ proto_tree_add_int(result_tree, hf_block_ciphersuite_result_item_length, tvb, offset, sdnv_length, result_item_length);
+ if (ei) {
+ proto_tree_add_expert(result_tree, pinfo, ei, tvb, offset, -1);
+ *lastheader = TRUE;
+ return offset;
+ }
+ offset += sdnv_length;
+
+ //display item data
+ switch (result_type)
+ {
+ case 1:
+ case 3:
+ case 5:
+ case 7:
+ case 8:
+ proto_tree_add_item(result_tree, hf_block_ciphersuite_result_data, tvb, offset, result_item_length, ENC_NA);
+ offset += result_item_length;
+ break;
+ case 4:
+ //pair of sdnvs offset and length
+ range_offset = evaluate_sdnv(tvb, offset, &sdnv_length);
+ proto_tree_add_int(result_tree, hf_block_ciphersuite_range_offset, tvb, offset, sdnv_length, range_offset);
+ offset += sdnv_length;
+
+ range_length = evaluate_sdnv(tvb, offset, &sdnv_length);
+ proto_tree_add_int(result_tree, hf_block_ciphersuite_range_length, tvb, offset, sdnv_length, range_length);
+ offset += sdnv_length;
+ break;
+ default:
+ break;
+ }
+
+ }
+ break;
+
+ }
+ case BUNDLE_BLOCK_TYPE_CUSTODY_TRANSFER:
+ {
+ int custody_id;
+ const guint8 *cteb_creator_custodian_eid;
+ int cteb_creator_custodian_eid_length;
+
+ /* check requirements for Block Processing Control Flags */
+ if ((control_flags & BLOCK_CONTROL_REPLICATE) != 0) {
+ expert_add_info_format(pinfo, block_flag_replicate_item, &ei_bundle_block_control_flags, "ERROR: Replicate must be clear for CTEB");
+ }
+ if ((control_flags & BLOCK_CONTROL_EID_REFERENCE) != 0) {
+ expert_add_info_format(pinfo, block_flag_eid_reference_item, &ei_bundle_block_control_flags, "ERROR: EID-Reference must be clear for CTEB");
+ }
+
+ /* there are two elements in a CTEB, first is the custody ID */
+ custody_id = evaluate_sdnv(tvb, offset, &sdnv_length);
+ proto_tree_add_int(block_tree, hf_block_control_block_cteb_custody_id, tvb, offset, sdnv_length, custody_id);
+ offset += sdnv_length;
+
+ /* and second is the creator custodian EID */
+ if (block_length - sdnv_length < 1) {
+ expert_add_info_format(pinfo, ti, &ei_bundle_offset_error, "Metadata Block Length Error");
+ *lastheader = TRUE;
+ return offset;
+ }
+ cteb_creator_custodian_eid_length = block_length - sdnv_length;
+ ti = proto_tree_add_item_ret_string(block_tree, hf_block_control_block_cteb_creator_custodian_eid, tvb, offset,
+ cteb_creator_custodian_eid_length, ENC_ASCII, pinfo->pool, &cteb_creator_custodian_eid);
+
+ /* also check if CTEB is valid, i.e. custodians match */
+ if (bundle_custodian == NULL) {
+ expert_add_info_format(pinfo, ti, &ei_block_control_block_cteb_invalid,
+ "CTEB Is NOT Valid (Bundle Custodian NULL)");
+ }
+ else if (strlen(cteb_creator_custodian_eid) != strlen(bundle_custodian)) {
+ expert_add_info_format(pinfo, ti, &ei_block_control_block_cteb_invalid,
+ "CTEB Is NOT Valid (Bundle Custodian [%s] != CTEB Custodian [%s])",
+ bundle_custodian, cteb_creator_custodian_eid);
+ }
+ else if (memcmp(cteb_creator_custodian_eid, bundle_custodian, strlen(bundle_custodian)) != 0) {
+ expert_add_info_format(pinfo, ti, &ei_block_control_block_cteb_invalid,
+ "CTEB Is NOT Valid (Bundle Custodian [%s] != CTEB Custodian [%s])",
+ bundle_custodian, cteb_creator_custodian_eid);
+ }
+ else {
+ expert_add_info(pinfo, ti, &ei_block_control_block_cteb_valid);
+ }
+ offset += cteb_creator_custodian_eid_length;
+
+ break;
+ }
+ case BUNDLE_BLOCK_TYPE_EXTENDED_COS:
+ {
+ int flags;
+ static int * const ecos_flags_fields[] = {
+ &hf_ecos_flags_critical,
+ &hf_ecos_flags_streaming,
+ &hf_ecos_flags_flowlabel,
+ &hf_ecos_flags_reliable,
+ NULL
+ };
+
+ /* check requirements for Block Processing Control Flags */
+ if ((control_flags & BLOCK_CONTROL_REPLICATE) == 0) {
+ expert_add_info_format(pinfo, block_flag_replicate_item, &ei_bundle_block_control_flags, "ERROR: Replicate must be set for ECOS");
+ }
+ if ((control_flags & BLOCK_CONTROL_EID_REFERENCE) != 0) {
+ expert_add_info_format(pinfo, block_flag_eid_reference_item, &ei_bundle_block_control_flags, "ERROR: EID-Reference must be clear for ECOS");
+ }
+
+ /* flags byte */
+ flags = (int)tvb_get_guint8(tvb, offset);
+ proto_tree_add_bitmask(block_tree, tvb, offset, hf_ecos_flags, ett_block_flags, ecos_flags_fields, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ /* ordinal byte */
+ proto_tree_add_item(block_tree, hf_ecos_ordinal, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ /* optional flow label sdnv */
+ 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) {
+ expert_add_info_format(pinfo, ti, &ei_bundle_sdnv_length, "ECOS Flow Label Error");
+ /* Force quitting */
+ *lastheader = TRUE;
+ return offset;
+ }
+ offset += sdnv_length;
+ }
+
+ break;
+ }
+ 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;
+ }
+ }
+
+ return offset;
+}
+
+/*3rd arg is number of bytes in field (returned)*/
+static int
+evaluate_sdnv(tvbuff_t *tvb, int offset, int *bytecount)
+{
+ guint64 value = 0;
+ *bytecount = tvb_get_varint(tvb, offset, FT_VARINT_MAX_LEN, &value, ENC_VARINT_SDNV);
+
+ if (*bytecount == 0) {
+ return -1;
+ }
+ if (value > G_MAXINT) {
+ ws_warning("evaluate_sdnv decoded a value too large to fit in an int, truncating");
+ return G_MAXINT;
+ }
+ return (int)value;
+}
+
+static int
+evaluate_sdnv_ei(tvbuff_t *tvb, int offset, int *bytecount, expert_field **error) {
+ int value = evaluate_sdnv(tvb, offset, bytecount);
+ *error = (value < 0) ? &ei_bundle_sdnv_length : NULL;
+ return value;
+}
+
+/* Special Function to evaluate 64 bit SDNVs */
+/*3rd arg is number of bytes in field (returned)*/
+static gint64
+evaluate_sdnv_64(tvbuff_t *tvb, int offset, int *bytecount)
+{
+ guint64 val = 0;
+ *bytecount = tvb_get_varint(tvb, offset, FT_VARINT_MAX_LEN, &val, ENC_VARINT_SDNV);
+
+ if (*bytecount == 0) {
+ return -1;
+ }
+ return val & G_MAXINT64;
+}
+
+static int
+dissect_bpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ proto_item *ti, *ti_bundle_protocol;
+ proto_tree *bundle_tree, *primary_tree;
+ int primary_header_size;
+ gboolean lastheader = FALSE;
+ int offset = 0;
+ guint8 version, pri_hdr_procflags;
+ /* 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;
+ }
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Bundle");
+ /* Clear out stuff in the info column */
+ col_clear(pinfo->cinfo,COL_INFO);
+
+ ti_bundle_protocol = proto_tree_add_item(tree, proto_bundle, tvb, offset, -1, ENC_NA);
+ // identify parent proto version
+ proto_item_append_text(ti_bundle_protocol, " Version %d", version);
+
+ bundle_tree = proto_item_add_subtree(ti_bundle_protocol, ett_bundle);
+
+ 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) {
+ primary_header_size = dissect_version_4_primary_header(pinfo, primary_tree, tvb,
+ &pri_hdr_procflags, &bundle_custodian);
+ }
+ else {
+ primary_header_size = dissect_version_5_and_6_primary_header(pinfo, primary_tree, tvb,
+ &pri_hdr_procflags, &bundle_custodian);
+ }
+
+ if (primary_header_size == 0) { /*Couldn't parse primary header*/
+ col_add_str(pinfo->cinfo, COL_INFO, "Protocol Error");
+ return(0); /*Give up*/
+ }
+
+ proto_item_set_len(ti, primary_header_size);
+ offset = primary_header_size;
+
+ /*
+ * Done with primary header; decode the remaining headers
+ */
+
+ while (lastheader == FALSE) {
+ guint8 next_header_type;
+
+ next_header_type = tvb_get_guint8(tvb, offset);
+ if (next_header_type == BUNDLE_BLOCK_TYPE_PAYLOAD) {
+
+ /*
+ * Returns payload size or 0 if can't parse payload
+ */
+ offset = dissect_payload_header(bundle_tree, tvb, pinfo, offset, version, pri_hdr_procflags, &lastheader);
+ }
+ else { /*Assume anything else is a Metadata Block*/
+ offset = display_extension_block(bundle_tree, tvb, pinfo, offset, bundle_custodian, &lastheader);
+ }
+ }
+
+ proto_item_set_len(ti_bundle_protocol, offset);
+
+ return(offset);
+}
+
+/// Introspect the data to choose a dissector version
+static int
+dissect_bundle(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ gint offset = 0;
+
+ {
+ // Primary Header Version octet
+ guint8 version = tvb_get_guint8(tvb, offset);
+ if ((version == 4) || (version == 5) || (version == 6)) {
+ return call_dissector(bpv6_handle, tvb, pinfo, tree);
+ }
+ }
+
+ wscbor_chunk_t *frame = wscbor_chunk_read(pinfo->pool, tvb, &offset);
+ if (frame->type_major == CBOR_TYPE_ARRAY) {
+ wscbor_chunk_t *primary = wscbor_chunk_read(pinfo->pool, tvb, &offset);
+ if (primary->type_major == CBOR_TYPE_ARRAY) {
+ wscbor_chunk_t *version = wscbor_chunk_read(pinfo->pool, tvb, &offset);
+ if (version->type_major == CBOR_TYPE_UINT) {
+ guint64 vers_val = version->head_value;
+ if (vers_val == 7) {
+ return call_dissector(bpv7_handle, tvb, pinfo, tree);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+void
+proto_register_bpv6(void)
+{
+
+ static hf_register_info hf[] = {
+ {&hf_bundle_pdu_version,
+ {"Bundle Version", "bundle.version",
+ FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_procflags,
+ {"Primary Header Processing Flags", "bundle.primary.proc.flag",
+ FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_procflags_fragment,
+ {"Bundle is a Fragment", "bundle.primary.proc.frag",
+ FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_FRAG_MASK, NULL, HFILL}
+ },
+ {&hf_bundle_procflags_admin,
+ {"Administrative Record", "bundle.primary.proc.admin",
+ FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_ADMIN_MASK, NULL, HFILL}
+ },
+ {&hf_bundle_procflags_dont_fragment,
+ {"Do Not Fragment Bundle", "bundle.primary.proc.dontfrag",
+ FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_DONTFRAG_MASK, NULL, HFILL}
+ },
+ {&hf_bundle_procflags_cust_xfer_req,
+ {"Request Custody Transfer", "bundle.primary.proc.xferreq",
+ FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_XFERREQ_MASK, NULL, HFILL}
+ },
+ {&hf_bundle_procflags_dest_singleton,
+ {"Destination is Singleton", "bundle.primary.proc.single",
+ FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_SINGLETON_MASK, NULL, HFILL}
+ },
+ {&hf_bundle_procflags_application_ack,
+ {"Request Acknowledgement by Application", "bundle.primary.proc.ack",
+ FT_BOOLEAN, 8, NULL, BUNDLE_PROCFLAGS_APP_ACK_MASK, NULL, HFILL}
+ },
+ {&hf_bundle_control_flags,
+ {"Bundle Processing Control Flags", "bundle.primary.processing.control.flag",
+ FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_procflags_general,
+ {"General Flags", "bundle.primary.proc.gen",
+ FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_procflags_cos,
+ {"Class of Service Flags", "bundle.primary.proc.cos",
+ FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_procflags_status,
+ {"Status Report Flags", "bundle.primary.proc.status",
+ FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_cosflags,
+ {"Primary Header COS Flags", "bundle.primary.cos.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_cosflags_priority,
+ {"Priority", "bundle.primary.cos.priority",
+ FT_UINT8, BASE_DEC, VALS(cosflags_priority_vals), BUNDLE_COSFLAGS_PRIORITY_MASK, NULL, HFILL}
+ },
+ {&hf_bundle_srrflags,
+ {"Primary Header Report Request Flags", "bundle.primary.srr.flag",
+ FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_srrflags_report_receipt,
+ {"Request Reception Report", "bundle.primary.srr.report",
+ FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_REPORT_MASK, NULL, HFILL}
+ },
+ {&hf_bundle_srrflags_report_cust_accept,
+ {"Request Report of Custody Acceptance", "bundle.primary.srr.custaccept",
+ FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_CUSTODY_MASK, NULL, HFILL}
+ },
+ {&hf_bundle_srrflags_report_forward,
+ {"Request Report of Bundle Forwarding", "bundle.primary.srr.forward",
+ FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_FORWARD_MASK, NULL, HFILL}
+ },
+ {&hf_bundle_srrflags_report_delivery,
+ {"Request Report of Bundle Delivery", "bundle.primary.srr.delivery",
+ FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_DELIVERY_MASK, NULL, HFILL}
+ },
+ {&hf_bundle_srrflags_report_deletion,
+ {"Request Report of Bundle Deletion", "bundle.primary.srr.delete",
+ FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_DELETION_MASK, NULL, HFILL}
+ },
+ {&hf_bundle_srrflags_report_ack,
+ {"Request Report of Application Ack", "bundle.primary.srr.ack",
+ FT_BOOLEAN, 8, NULL, BUNDLE_SRRFLAGS_ACK_MASK, NULL, HFILL}
+ },
+ {&hf_bundle_primary_header_len,
+ {"Bundle Header Length", "bundle.primary.len",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_primary_dictionary_len,
+ {"Dictionary Length", "bundle.primary.dictionary_len",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_primary_fragment_offset,
+ {"Fragment Offset", "bundle.primary.fragment_offset",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_primary_total_adu_len,
+ {"Total Application Data Unit Length", "bundle.primary.total_adu_len",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_primary_timestamp_seq_num64,
+ {"Timestamp Sequence Number", "bundle.primary.timestamp_seq_num64",
+ FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_primary_timestamp_seq_num32,
+ {"Timestamp Sequence Number", "bundle.primary.timestamp_seq_num32",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_primary_timestamp,
+ {"Timestamp", "bundle.primary.timestamp",
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_dest_scheme_offset_u16,
+ {"Destination Scheme Offset", "bundle.primary.destschemeoffu16",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_dest_scheme_offset_i32,
+ {"Destination Scheme Offset", "bundle.primary.destschemeoffi32",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_dest_ssp_offset_u16,
+ {"Destination SSP Offset", "bundle.primary.destssspoffu16",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_dest_ssp_offset_i32,
+ {"Destination SSP Offset", "bundle.primary.destssspoffi32",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_source_scheme_offset_u16,
+ {"Source Scheme Offset", "bundle.primary.srcschemeoffu16",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_source_scheme_offset_i32,
+ {"Source Scheme Offset", "bundle.primary.srcschemeoffi32",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_source_ssp_offset_u16,
+ {"Source SSP Offset", "bundle.primary.srcsspoffu16",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_source_ssp_offset_i32,
+ {"Source SSP Offset", "bundle.primary.srcsspoffi32",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_report_scheme_offset_u16,
+ {"Report Scheme Offset", "bundle.primary.rptschemeoffu16",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_report_scheme_offset_i32,
+ {"Report Scheme Offset", "bundle.primary.rptschemeoffi32",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_report_ssp_offset_u16,
+ {"Report SSP Offset", "bundle.primary.rptsspoffu16",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_report_ssp_offset_i32,
+ {"Report SSP Offset", "bundle.primary.rptsspoffi32",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_cust_scheme_offset_u16,
+ {"Custodian Scheme Offset", "bundle.primary.custschemeoffu16",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_cust_scheme_offset_i32,
+ {"Custodian Scheme Offset", "bundle.primary.custschemeoffi32",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_cust_ssp_offset_u16,
+ {"Custodian SSP Offset", "bundle.primary.custsspoffu16",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_cust_ssp_offset_i32,
+ {"Custodian SSP Offset", "bundle.primary.custsspoffi32",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_dest_scheme,
+ {"Destination Scheme", "bundle.primary.destination_scheme",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_dest_ssp,
+ {"Destination", "bundle.primary.destination",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_source_scheme,
+ {"Source Scheme", "bundle.primary.source_scheme",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_source_ssp,
+ {"Source", "bundle.primary.source",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_report_scheme,
+ {"Report Scheme", "bundle.primary.report_scheme",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_report_ssp,
+ {"Report", "bundle.primary.report",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_custodian_scheme,
+ {"Custodian Scheme", "bundle.primary.custodian_scheme",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_custodian_ssp,
+ {"Custodian", "bundle.primary.custodian",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_creation_timestamp,
+ {"Creation Timestamp", "bundle.primary.creation_timestamp",
+ FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_lifetime,
+ {"Lifetime", "bundle.primary.lifetime",
+ FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_lifetime_sdnv,
+ {"Lifetime", "bundle.primary.lifetime_sdnv",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_payload_length,
+ {"Payload Length", "bundle.payload.length",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_payload_flags,
+ {"Payload Header Processing Flags", "bundle.payload.proc.flag",
+ FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_payload_header_type,
+ {"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}
+ },
+ {&hf_bundle_payload_flags_xmit_report,
+ {"Report if Can't Process Header", "bundle.payload.proc.report",
+ FT_BOOLEAN, 8, NULL, PAYLOAD_PROCFLAGS_XMIT_STATUS, NULL, HFILL}
+ },
+ {&hf_bundle_payload_flags_discard_on_fail,
+ {"Discard if Can't Process Header", "bundle.payload.proc.discard",
+ FT_BOOLEAN, 8, NULL, PAYLOAD_PROCFLAGS_DISCARD_FAILURE, NULL, HFILL}
+ },
+ {&hf_bundle_payload_flags_last_header,
+ {"Last Header", "bundle.payload.proc.lastheader",
+ FT_BOOLEAN, 8, NULL, PAYLOAD_PROCFLAGS_LAST_HEADER, NULL, HFILL}
+ },
+ {&hf_bundle_admin_record_type,
+ {"Administrative Record Type", "bundle.admin.record_type",
+ FT_UINT8, BASE_DEC, VALS(admin_record_type_vals), 0xF0, NULL, HFILL}
+ },
+ {&hf_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,
+ {"Administrative Record Status Flags", "bundle.admin.status.flag",
+ FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_admin_rcvd,
+ {"Reporting Node Received Bundle", "bundle.admin.status.rcvd",
+ FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_RECEIVED, NULL, HFILL}
+ },
+ {&hf_bundle_admin_accepted,
+ {"Reporting Node Accepted Custody", "bundle.admin.status.accept",
+ FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_ACCEPTED, NULL, HFILL}
+ },
+ {&hf_bundle_admin_forwarded,
+ {"Reporting Node Forwarded Bundle", "bundle.admin.status.forward",
+ FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_FORWARDED, NULL, HFILL}
+ },
+ {&hf_bundle_admin_delivered,
+ {"Reporting Node Delivered Bundle", "bundle.admin.status.delivered",
+ FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_DELIVERED, NULL, HFILL}
+ },
+ {&hf_bundle_admin_deleted,
+ {"Reporting Node Deleted Bundle", "bundle.admin.status.delete",
+ FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_DELETED, NULL, HFILL}
+ },
+ {&hf_bundle_admin_acked,
+ {"Acknowledged by Application", "bundle.admin.status.ack",
+ FT_BOOLEAN, 8, NULL, ADMIN_STATUS_FLAGS_ACKNOWLEDGED, NULL, HFILL}
+ },
+ {&hf_bundle_admin_fragment_offset,
+ {"Fragment Offset", "bundle.admin.fragment_offset",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_admin_fragment_length,
+ {"Fragment Length", "bundle.admin.fragment_length",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_admin_timestamp_seq_num64,
+ {"Timestamp Sequence Number", "bundle.admin.timestamp_seq_num64",
+ FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_admin_timestamp_seq_num32,
+ {"Timestamp Sequence Number", "bundle.admin.timestamp_seq_num32",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_admin_endpoint_length,
+ {"Endpoint Length", "bundle.admin.endpoint_length",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_admin_endpoint_id,
+ {"Bundle Endpoint ID", "bundle.admin.endpoint_id",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_admin_receipt_time,
+ {"Bundle Received Time", "bundle.admin.status.receipttime",
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_admin_accept_time,
+ {"Bundle Accepted Time", "bundle.admin.status.accepttime",
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_admin_forward_time,
+ {"Bundle Forwarded Time", "bundle.admin.status.forwardtime",
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_admin_delivery_time,
+ {"Bundle Delivered Time", "bundle.admin.status.deliverytime",
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_admin_delete_time,
+ {"Bundle Deleted Time", "bundle.admin.status.deletetime",
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_admin_ack_time,
+ {"Bundle Acknowledged Time", "bundle.admin.status.acktime",
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_admin_timestamp_copy,
+ {"Bundle Creation Timestamp", "bundle.admin.status.timecopy",
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_admin_signal_time,
+ {"Bundle Signal Time", "bundle.admin.signal.time",
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_block_control_flags,
+ {"Block Processing Control Flags", "bundle.block.control.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_block_control_flags_sdnv,
+ {"Block Processing Control Flags", "bundle.block.control.flags",
+ FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_block_control_block_length,
+ {"Block Length", "bundle.block.length",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_block_control_block_cteb_custody_id,
+ {"CTEB Custody ID", "bundle.block.cteb_custody_id",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_block_control_block_cteb_creator_custodian_eid,
+ {"CTEB Creator Custodian EID", "bundle.block.cteb_creator_custodian_eid",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_block_control_replicate,
+ {"Replicate Block in Every Fragment", "bundle.block.control.replicate",
+ FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_REPLICATE, NULL, HFILL}
+ },
+ {&hf_block_control_transmit_status,
+ {"Transmit Status if Block Can't be Processed", "bundle.block.control.status",
+ FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_TRANSMIT_STATUS, NULL, HFILL}
+ },
+ {&hf_block_control_delete_bundle,
+ {"Delete Bundle if Block Can't be Processed", "bundle.block.control.delete",
+ FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_DELETE_BUNDLE, NULL, HFILL}
+ },
+ {&hf_block_control_last_block,
+ {"Last Block", "bundle.block.control.last",
+ FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_LAST_BLOCK, NULL, HFILL}
+ },
+ {&hf_block_control_discard_block,
+ {"Discard Block If Can't Process", "bundle.block.control.discard",
+ FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_DISCARD_BLOCK, NULL, HFILL}
+ },
+ {&hf_block_control_not_processed,
+ {"Block Was Forwarded Without Processing", "bundle.block.control.process",
+ FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_NOT_PROCESSED, NULL, HFILL}
+ },
+ {&hf_block_control_eid_reference,
+ {"Block Contains an EID-reference Field", "bundle.block.control.eid",
+ FT_BOOLEAN, 8, NULL, BLOCK_CONTROL_EID_REFERENCE, NULL, HFILL}
+ },
+ {&hf_bundle_status_report_reason_code,
+ {"Status Report Reason Code", "bundle.status_report_reason_code",
+ FT_UINT8, BASE_DEC, VALS(status_report_reason_codes), 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_custody_trf_succ_flg,
+ {"Custody Transfer Succeeded Flag", "bundle.custody_trf_succ_flg",
+ FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL}
+ },
+ {&hf_bundle_custody_signal_reason,
+ {"Custody Signal Reason Code", "bundle.custody_signal_reason_code",
+ FT_UINT8, BASE_DEC, VALS(custody_signal_reason_codes), ADMIN_REC_CUSTODY_REASON_MASK, NULL, HFILL}
+ },
+ {&hf_bundle_custody_id_range_start,
+ {"CTEB Custody ID Range Start", "bundle.custody_id_range_start",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_custody_id_range_end,
+ {"CTEB Custody ID Range End", "bundle.custody_id_range_end",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_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, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_ecos_flags_critical,
+ {"Critical", "bundle.block.ecos.flags.critical",
+ FT_BOOLEAN, 8, NULL, ECOS_FLAGS_CRITICAL, NULL, HFILL}
+ },
+ {&hf_ecos_flags_streaming,
+ {"Streaming", "bundle.block.ecos.flags.streaming",
+ FT_BOOLEAN, 8, NULL, ECOS_FLAGS_STREAMING, NULL, HFILL}
+ },
+ {&hf_ecos_flags_flowlabel,
+ {"Flow Label", "bundle.block.ecos.flags.flowlabel",
+ FT_BOOLEAN, 8, NULL, ECOS_FLAGS_FLOWLABEL, NULL, HFILL}
+ },
+ {&hf_ecos_flags_reliable,
+ {"Reliable", "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",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_ecos_ordinal,
+ {"ECOS Ordinal", "bundle.block.ecos.ordinal",
+ FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_age_extension_block_code,
+ {"Bundle Age in seconds", "bundle.age_extension_block_code",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_block_previous_hop_scheme,
+ {"Previous Hop Scheme", "bundle.block.previous_hop_scheme",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_block_previous_hop_eid,
+ {"Previous Hop EID", "bundle.block.previous_hop_eid",
+ FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_target_block_type,
+ {"Target Block Type", "bundle.target_block_type",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_target_block_occurrence,
+ {"Target Block Occurrence", "bundle.target_block_occurrence",
+ FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_ciphersuite_type,
+ {"Ciphersuite Type", "bundle.ciphersuite_type",
+ FT_INT32, BASE_DEC, VALS(ciphersuite_types), 0x0, NULL, HFILL}
+ },
+ {&hf_bundle_ciphersuite_flags,
+ {"Ciphersuite Flags", "bundle.ciphersuite_flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_block_ciphersuite_params,
+ {"Block Contains Ciphersuite Parameters", "bundle.block.ciphersuite_params",
+ FT_BOOLEAN, 8, NULL, BLOCK_CIPHERSUITE_PARAMS, NULL, HFILL}
+ },
+ {&hf_block_ciphersuite_params_length,
+ {"Ciphersuite Parameters Length", "bundle.block.ciphersuite_params_length",
+ FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_block_ciphersuite_params_item_length,
+ {"Parameter Length", "bundle.block.ciphersuite_params_item_length",
+ FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_block_ciphersuite_param_type,
+ {"Ciphersuite Parameter Type", "bundle.block.ciphersuite_param_type",
+ FT_INT8, BASE_DEC, VALS(res_params_types), 0x0, NULL, HFILL}
+ },
+ {&hf_block_ciphersuite_param_data,
+ {"Ciphersuite Parameter Data", "bundle.block.ciphersuite_param_data",
+ FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_block_ciphersuite_result_length,
+ {"Security Results Length", "bundle.block.ciphersuite_result_length",
+ FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_block_ciphersuite_result_item_length,
+ {"Security Result Item Length", "bundle.block.ciphersuite_result_item_length",
+ FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_block_ciphersuite_result_type,
+ {"Security Result Item Type", "bundle.block.ciphersuite_result_type",
+ FT_INT8, BASE_DEC, VALS(res_params_types), 0x0, NULL, HFILL}
+ },
+ {&hf_block_ciphersuite_result_data,
+ {"Security Result Item Data", "bundle.block.ciphersuite_result_data",
+ FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_block_ciphersuite_range_offset,
+ {"Content Range Offset", "bundle.block.ciphersuite_range_offset",
+ FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_block_ciphersuite_range_length,
+ {"Content Range Length", "bundle.block.ciphersuite_range_length",
+ FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ };
+
+ static gint *ett[] = {
+ &ett_bundle,
+ &ett_bundle_hdr,
+ &ett_primary_hdr,
+ &ett_proc_flags,
+ &ett_gen_flags,
+ &ett_cos_flags,
+ &ett_srr_flags,
+ &ett_dictionary,
+ &ett_payload_hdr,
+ &ett_payload_flags,
+ &ett_block_flags,
+ &ett_admin_record,
+ &ett_admin_rec_status,
+ &ett_metadata_hdr,
+ &ett_sec_block_param_data
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_bundle_control_flags_length,
+ { "bundle.block.control.flags.length", PI_UNDECODED, PI_WARN, "Wrong bundle control flag length", EXPFILL }
+ },
+ { &ei_bundle_payload_length,
+ { "bundle.payload.length.invalid", PI_PROTOCOL, PI_ERROR, "Payload length error", EXPFILL }
+ },
+ { &ei_bundle_sdnv_length,
+ { "bundle.sdnv_length_invalid", PI_PROTOCOL, PI_ERROR, "SDNV length error", EXPFILL }
+ },
+ { &ei_bundle_timestamp_seq_num,
+ { "bundle.timestamp_seq_num_invalid", PI_PROTOCOL, PI_ERROR, "Timestamp Sequence Number error", EXPFILL }
+ },
+ { &ei_bundle_offset_error,
+ { "bundle.offset_error", PI_PROTOCOL, PI_WARN, "Offset field error", EXPFILL }
+ },
+ { &ei_bundle_block_control_flags,
+ { "bundle.block.control.flags.error", PI_PROTOCOL, PI_WARN, "Control flag error", EXPFILL }
+ },
+ { &ei_block_control_block_cteb_invalid,
+ { "bundle.block.control.cteb_invalid", PI_PROTOCOL, PI_WARN, "CTEB Is Invalid", EXPFILL }
+ },
+ { &ei_block_control_block_cteb_valid,
+ { "bundle.block.control.cteb_valid", PI_PROTOCOL, PI_NOTE, "CTEB Is Valid", EXPFILL }
+ },
+ };
+
+ expert_module_t *expert_bundle;
+
+ proto_bundle = proto_register_protocol("Bundle Protocol", "BP", "bundle");
+ bpv6_handle = register_dissector("bpv6", dissect_bpv6, proto_bundle);
+ bundle_handle = register_dissector("bundle", dissect_bundle, proto_bundle);
+
+ proto_register_field_array(proto_bundle, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ expert_bundle = expert_register_protocol(proto_bundle);
+ expert_register_field_array(expert_bundle, ei, array_length(ei));
+}
+
+void
+proto_reg_handoff_bpv6(void)
+{
+ bpv7_handle = find_dissector("bpv7");
+
+ dissector_add_uint_with_preference("udp.port", BUNDLE_PORT, bundle_handle);
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */