aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Scott <keithlscott@gmail.com>2019-08-21 07:48:56 -0400
committerAnders Broman <a.broman58@gmail.com>2019-10-04 13:10:46 +0000
commit13a9a98f956fd2b37e90e3fff29d1118a88f0aff (patch)
tree2becc7fbd7032aa3ea6708801a9b90add7eea574
parentba88d0a7cf16edd050d07c14dd0dd1d6c163ca56 (diff)
dtn: Updates to TCPCL and AMP parsers and dtn payload ids.
This patch updates the TCP Convergence Layer (TCPCL) parser, updates the Compressed Bundle Header Encoding (CBHE) BP Endpoints that identify CCSDS File Delivery Protocol (CFDP) and Asynchronous Management Protocol (AMP) payloads, and adds an AMP dissector that parses the new Compressed Bundle Header Encoding (CBOR) wire format. 1. Correctly parses the TCP Convergence Layer Length field 2. Adds support for the TCP Convergence Layer Refuse-Bundle Reason-Code Flags per RFC-7242: Section-5.4 3. Parses BP traffic between Compressed Bundle Header Encoding (CBHE) endpoints 64 and 65 as CCSDS File Delivery Protocol (CFDP) payloads. 4. Parses BP traffic beetween Compressed Bundle Header Encoding (CBHE) endpoints 5 and 6 as Asynchronous Network Management (AMP) payloads 5. Updates the AMP parser to use the new Compressed Binary Object Representation (CBOR) The AMP dissector was originally written by Krishnamurthy Mayya (krishnamurthymayya@gmail.com) against an older version of the AMP specification and updated to parse the new Compressed Binary Object Representation (CBOR) format by Keith Scott (keithlscott@gmail.com) Change-Id: I8d1eff9fb09f1a9dbdb9f4cf077448316f6a9e05 Reviewed-on: https://code.wireshark.org/review/34216 Petri-Dish: Anders Broman <a.broman58@gmail.com> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
-rw-r--r--epan/dissectors/CMakeLists.txt1
-rw-r--r--epan/dissectors/packet-amp.c845
-rw-r--r--epan/dissectors/packet-cfdp.c573
-rw-r--r--epan/dissectors/packet-dtn.c68
-rw-r--r--epan/dissectors/packet-dtn.h9
5 files changed, 1383 insertions, 113 deletions
diff --git a/epan/dissectors/CMakeLists.txt b/epan/dissectors/CMakeLists.txt
index bf14d37fd1..249a91c1ed 100644
--- a/epan/dissectors/CMakeLists.txt
+++ b/epan/dissectors/CMakeLists.txt
@@ -665,6 +665,7 @@ set(DISSECTOR_SRC
${CMAKE_CURRENT_SOURCE_DIR}/packet-ajp13.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-alcap.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-alljoyn.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/packet-amp.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-amqp.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-amr.c
${CMAKE_CURRENT_SOURCE_DIR}/packet-amt.c
diff --git a/epan/dissectors/packet-amp.c b/epan/dissectors/packet-amp.c
new file mode 100644
index 0000000000..f7f550b085
--- /dev/null
+++ b/epan/dissectors/packet-amp.c
@@ -0,0 +1,845 @@
+/* packet-amp.c
+ * Routines for Asynchronous management Protocol dissection
+ * Copyright 2018, Krishnamurthy Mayya (krishnamurthymayya@gmail.com)
+ * Updated to CBOR encoding: Keith Scott, 2019 (kscott@mitre.org)
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You can obtain a version of the GNU General Public License by writing
+ * to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "config.h"
+#include <stdio.h>
+
+#include <epan/exceptions.h>
+#include <epan/packet.h>
+
+/* The AMP standard can be found here:
+ * https://tools.ietf.org/html/draft-birrane-dtn-amp-04
+ * https://tools.ietf.org/html/draft-birrane-dtn-amp-03
+ */
+
+#define AMP_APID 0x000 /* TODO - To be decided. Currently, the function 'dissect_amp_as_subtree' is
+ being called from dtn.c file when required to decode the bundle protocol's
+ data-payload as AMP. Later in the future, when a dedicated field is given to
+ this, this should be filled. */
+
+void dissect_amp_as_subtree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+
+/*
+ */
+static void
+add_value_time_to_tree(guint64 value, int len, proto_tree *tree, tvbuff_t *tvb, int offset, int hf_time_format)
+{
+ nstime_t dtn_time;
+
+ // If it's a relative time, just make it zero.
+ if ( value < 558230400 ) {
+ value = 0;
+ }
+ dtn_time.secs = (time_t)(value);
+ dtn_time.nsecs = 0;
+ proto_tree_add_time(tree, hf_time_format, tvb, offset, len, &dtn_time);
+
+ return;
+}
+
+#define AMP_HDR_RESERVED 0xC0
+#define AMP_HDR_ACL 0x20
+#define AMP_HDR_NACK 0x10
+#define AMP_HDR_ACK 0x08
+#define AMP_HDR_OPCODE 0x07
+
+#define AMP_ARI_NICKNAME 0x80
+#define AMP_ARI_PARAMETERS 0x40
+#define AMP_ARI_ISSUER 0x20
+#define AMP_ARI_TAG 0x10
+#define AMP_ARI_STRUCT 0x0F
+#define AMP_ARI_VALUE 0xF0
+
+#define AMP_CBOR_UINT_SMALL 0x1F
+
+#define AMP_TNVC_RESERVED 0xF0
+#define AMP_TNVC_MIXED 0x08
+#define AMP_TNVC_TYPE 0x04
+#define AMP_TNVC_NAME 0x02
+#define AMP_TNVC_VALUE 0x01
+
+#define AMP_MSG_REGISTER_AGENT 0x01
+#define AMP_MSG_DATA_REPORT 0x00
+#define AMP_MSG_PERFORM_CONTROL 0x02
+
+static dissector_handle_t amp_handle;
+
+void proto_register_amp(void);
+void proto_reg_handoff_amp(void);
+
+static int hf_amp_message_header = -1;
+static int hf_amp_report_bytestring = -1;
+static int hf_amp_report_data = -1;
+static int hf_amp_report_integer8_small = -1;
+static int hf_amp_report_integer = -1;
+static int hf_amp_cbor_header = -1;
+static int hf_amp_primary_timestamp = -1;
+static int hf_amp_agent_name = -1;
+static int hf_amp_text_string = -1;
+static int hf_amp_ari_flags = -1;
+static int hf_ari_value = -1;
+static int hf_ari_struct = -1;
+static int hf_ari_nickname = -1;
+static int hf_ari_parameters = -1;
+static int hf_ari_issuer = -1;
+static int hf_ari_tag = -1;
+static int hf_amp_tnvc_flags = -1;
+static int hf_amp_tnvc_reserved = -1;
+static int hf_amp_tnvc_mixed = -1;
+static int hf_amp_tnvc_typed = -1;
+static int hf_amp_tnvc_name = -1;
+static int hf_amp_tnvc_values = -1;
+
+/* Initialize the protocol and registered fields */
+static int proto_amp = -1;
+
+static gint ett_amp_message_header = -1;
+static gint ett_amp_proto = -1;
+static gint ett_amp = -1;
+static gint ett_amp_cbor_header = -1;
+static gint ett_amp_message = -1;
+static gint ett_amp_register = -1;
+static gint ett_amp_report_set = -1;
+static gint ett_amp_report = -1;
+static gint ett_amp_tnvc_flags = -1;
+static gint ett_amp_ari_flags = -1;
+
+static int hf_amp_reserved = -1;
+static int hf_amp_acl = -1;
+static int hf_amp_nack = -1;
+static int hf_amp_ack = 0;
+static int hf_amp_opcode = -1;
+static int hf_amp_rx_name = -1;
+
+static const value_string opcode[] = {
+ { 0, "Register Agent" },
+ { 1, "Report Set" },
+ { 2, "Perform Control" },
+ { 0, NULL }
+};
+
+static const value_string tnvc_yesno[] = {
+ { 0, "no" },
+ { 1, "yes" },
+ { 0, NULL }
+};
+
+static const value_string tnvc_present_notpresent[] = {
+ { 0, "not present" },
+ { 1, "present" },
+ { 0, NULL }
+};
+
+static const value_string amp_ari_struct_type[] = {
+ { 0, "Const" },
+ { 1, "Control" },
+ { 2, "Externally Defined Data" },
+ { 3, "Macro" },
+ { 4, "Operation" },
+ { 5, "Report Template" },
+ { 6, "State-Based Rule" },
+ { 7, "Table Templates" },
+ { 8, "Time-Based Rule" },
+ { 9, "Variables" },
+ { 10, "Metadata" },
+ { 11, "Reserved" },
+ { 12, "Reserved" },
+ { 13, "Reserved" },
+ { 14, "Reserved" },
+ { 15, "Reserved" },
+ { 16, "Reserved" },
+ { 17, "Reserved" },
+ { 18, "Reserved" },
+ { 19, "Reserved" },
+ { 0, NULL }
+};
+
+
+/* AMP Message Header */
+static const int *amp_message_header[] = {
+ &hf_amp_reserved,
+ &hf_amp_acl,
+ &hf_amp_nack,
+ &hf_amp_ack,
+ &hf_amp_opcode,
+ 0
+};
+
+/* TNVC Flags */
+static const int *amp_tnvc_flags[] = {
+ &hf_amp_tnvc_reserved,
+ &hf_amp_tnvc_mixed,
+ &hf_amp_tnvc_typed,
+ &hf_amp_tnvc_name,
+ &hf_amp_tnvc_values,
+ 0
+};
+
+/* ARI Flags */
+static const int *amp_ari_flags[] = {
+ &hf_ari_nickname,
+ &hf_ari_parameters,
+ &hf_ari_issuer,
+ &hf_ari_tag,
+ &hf_ari_struct,
+ 0
+};
+
+/* CBOR Types */
+typedef enum {
+ CBOR_UNKNOWN = -1,
+ CBOR_UINT = 0, // Positive, unsigned integer
+ CBOR_INT = 1, // Negative integer
+ CBOR_BYTESTRING = 2,
+ CBOR_TEXTSTRING = 3,
+ CBOR_ARRAY = 4,
+ CBOR_MAP = 5,
+ CBOR_SEMANTIC_TAG = 6,
+ CBOR_PRIMITIVE = 7
+} CBOR_TYPE;
+
+typedef struct {
+ int type;
+ int size; // for integers, the value
+ // for bytestrings and textstrings, the size of the string
+ // for arrays, the number of elements in the array
+ guint64 totalSize; // total size (including size above and any bytestring
+ // size).
+ guint64 uint;
+} cborObj;
+
+
+// Decode the CBOR object at the given offset in the tvb.
+// The returned cborObj contains the object (with type) and the size
+// (including the CBOR identifier).
+static cborObj cbor_info(tvbuff_t *tvb, int offset)
+{
+ int tmp = 0;
+ cborObj ret;
+ ret.type = CBOR_UNKNOWN;
+ ret.size = 0;
+ ret.totalSize = 0;
+ ret.uint = -1;
+ int theSize;
+
+ tmp = tvb_get_guint8(tvb, offset);
+
+ offset += 1;
+ ret.size += 1;
+
+ ret.type = (tmp & 0xE0)>>5; // Top 3 bits
+ theSize = (tmp & 0x1F);
+
+ switch ( ret.type )
+ {
+ case 0x00: // Positive / Unsigned integer
+ if ( theSize<24 ) {
+ ret.uint = (tmp & 0x1F); // May be actual size or indication of follow-on size
+ } else if (theSize==24) { // next byte is uint8_t data
+ ret.uint = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ ret.size += 1;
+ } else if (theSize==25) { // next 2 bytes are uint16_t data
+ ret.uint = tvb_get_guint16(tvb, offset, 0);
+ offset += 2;
+ ret.size += 2;
+ } else if (theSize==26) { // next 4 bytes are uint32_t data
+ ret.uint = tvb_get_guint32(tvb, offset, 0);
+ offset += 4;
+ ret.size += 4;
+ } else if (theSize==27) { // next 8 bytes are uint64_t data
+ ret.uint = tvb_get_guint64(tvb, offset, 0);
+ offset += 8;
+ ret.size += 8;
+ }
+ ret.totalSize = ret.size;
+ break;
+
+ case 0x02: // Byte string
+ if ( theSize<24 ) { // Array size is contained in the identifier byte
+ ret.uint = (tmp & 0x1F);
+ } else if (theSize==24) { // next byte is uint8_t data (length)
+ ret.uint = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ ret.size += 1;
+ } else if (theSize==25) { // next 2bytes are uint16_t data (length)
+ ret.uint = tvb_get_guint16(tvb, offset, 0);
+ offset += 2;
+ ret.size += 2;
+ } else if (theSize==26) { // next 4bytes are uint32_t data
+ ret.uint = tvb_get_guint32(tvb, offset, 0);
+ offset += 4;
+ ret.size += 4;
+ } else if (theSize==27) { // next byte is uint64_t data
+ ret.uint = tvb_get_guint64(tvb, offset, 0);
+ offset += 8;
+ ret.size += 8;
+ }
+ ret.totalSize = ret.size+ret.uint;
+ break;
+
+ case 0x03: // Text string
+ if ( theSize<24 ) // Array size is contained in the identifier byte
+ {
+ ret.uint = (tmp & 0x1F);
+ } else if (theSize==24) // next byte is uint8_t data
+ {
+ ret.uint = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ ret.size += 1;
+ } else if (theSize==25) // next 2bytes are uint16_t data
+ {
+ ret.uint = tvb_get_guint16(tvb, offset, 0);
+ offset += 2;
+ ret.size += 2;
+ } else if (theSize==26) // next 4bytes are uint32_t data
+ {
+ ret.uint = tvb_get_guint32(tvb, offset, 0);
+ offset += 4;
+ ret.size += 4;
+ } else if (theSize==27) // next byte is uint64_t data
+ {
+ ret.uint = tvb_get_guint64(tvb, offset, 0);
+ offset += 8;
+ ret.size += 8;
+ }
+ ret.totalSize = ret.size+ret.uint;
+ break;
+
+ case 0x04: // Array
+ if ( theSize<24 ) // Array size is contained in the identifier byte
+ {
+ ret.uint = (tmp & 0x1F);
+ } else if (theSize==24) // next byte is uint8_t data
+ {
+ ret.uint = tvb_get_guint8(tvb, offset);
+ offset += 1;
+ ret.size += 1;
+ } else if (theSize==25) // next 2bytes are uint16_t data
+ {
+ ret.uint = tvb_get_guint16(tvb, offset, 0);
+ offset += 2;
+ ret.size += 2;
+ } else if (theSize==26) // next 4bytes are uint32_t data
+ {
+ ret.uint = tvb_get_guint32(tvb, offset, 0);
+ offset += 4;
+ ret.size += 4;
+ } else if (theSize==27) // next byte is uint64_t data
+ {
+ ret.uint = tvb_get_guint64(tvb, offset, 0);
+ offset += 8;
+ ret.size += 8;
+ }
+ // I know how many elements are in the array, but NOT the total
+ // size of the array data.
+ ret.totalSize = -1;
+ break;
+
+ case 0x06: // Semantic tag
+ if ( theSize<24 )
+ {
+ ret.uint = (tmp & 0x1F);
+ }
+ ret.totalSize += ret.uint;
+ break;
+
+ case 0x01: // Negative integer
+ case 0x07: // Primitives e.g. break, float, simple values
+ default:
+ // TODO -- not supported yet.
+ break;
+ }
+ return(ret);
+}
+
+void
+dissect_amp_as_subtree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ guint64 messages = 0;
+ unsigned int i=0;
+ unsigned int j=0;
+ unsigned int k=0;
+ unsigned int numTNVCEntries = 0;
+
+ proto_tree *amp_tree = NULL;
+ proto_tree *amp_items_tree = NULL;
+ proto_tree *amp_register_tree = NULL;
+ proto_tree *amp_report_set_tree = NULL;
+ proto_tree *amp_report_tree = NULL;
+ proto_tree *amp_report_TNVC_tree = NULL;
+ proto_tree *amp_control_tree = NULL;
+ proto_tree *amp_table_tree = NULL;
+ proto_item *payload_item = NULL;
+ proto_tree *amp_message_tree = NULL;
+ proto_tree *amp_report_TNVC_sub_tree = NULL;
+ proto_item *amp_message = NULL;
+ proto_item *amp_register = NULL;
+ proto_item *amp_report_set = NULL;
+ proto_item *amp_report = NULL;
+
+ cborObj myObj;
+ cborObj tmpObj;
+ cborObj tmpObj2;
+ cborObj tmpObj3;
+ cborObj tmpObj4;
+ int reportHasTimestamp = 0;
+ int report_types_offset = 0;
+
+ pinfo = pinfo;
+
+ amp_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_amp_proto,
+ &payload_item, "Payload Data: AMP Protocol");
+
+ // First byte is the main CBOR type (probably an array of things)
+ // e.g. 0x82 (byte array of 2 things)
+ myObj = cbor_info(tvb, offset);
+ offset += myObj.size;
+ messages = myObj.uint;
+
+ // Item 0 is the timestamp
+ myObj = cbor_info(tvb, offset);
+ add_value_time_to_tree((int) myObj.uint, MIN(myObj.size-1, 1), amp_tree, tvb, offset, hf_amp_primary_timestamp);
+ offset += myObj.size;
+
+ for ( i=1; i<messages; i++ ) {
+
+ // Get the bytestring object that gives the total length of the AMP chunk
+ myObj = cbor_info(tvb, offset);
+ offset += myObj.size; // Note: myObj.uint is the length of the amp chunk; used later
+ // to advance offset past this message.
+
+ // The first byte of this byte string (the AMP message) is going to be the message header
+ // This is just a byte, not a CBOR uint8
+ int ampHeader;
+ ampHeader = tvb_get_guint8(tvb, offset);
+ amp_message_tree = proto_tree_add_subtree(amp_tree, tvb, offset, -1,
+ ett_amp_message, &amp_message, "AMP Message");
+
+ proto_tree_add_bitmask(amp_message_tree, tvb, offset, hf_amp_message_header, ett_amp_message_header,
+ amp_message_header, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ switch ( ampHeader & 0x07)
+ {
+ case 0x00: // Register agent
+ //amp_register_sub_tree = proto_item_add_subtree(amp_message_tree, ett_amp);
+ amp_register_tree = proto_tree_add_subtree(amp_message_tree, tvb, offset-1, 1,
+ ett_amp_register, &amp_register, "Register-Agent");
+ tmpObj = cbor_info(tvb, offset); // Should come back a CBOR text string if some length.
+ offset += tmpObj.size;
+ proto_tree_add_item(amp_register_tree, hf_amp_agent_name, tvb, offset,
+ (int) tmpObj.uint, ENC_ASCII|ENC_NA);
+ offset += (int) tmpObj.uint;
+ break;
+
+ case 0x01: // Report set
+ amp_report_set_tree = proto_tree_add_subtree(amp_message_tree, tvb, offset-2, -1,
+ ett_amp_report_set, &amp_report_set, "Report-Set");
+
+ // Rx Names
+ tmpObj = cbor_info(tvb, offset); // Should come back a CBOR array of some size (Rx Names)
+ if ( tmpObj.type != 0x04 ) {
+ return;
+ }
+ offset += tmpObj.size;
+ // read rx names
+ for ( j=0; j<tmpObj.uint; j++ ) {
+ tmpObj2 = cbor_info(tvb, offset); // Should be text string of some size
+ offset += tmpObj2.size;
+ proto_tree_add_item(amp_report_set_tree, hf_amp_rx_name, tvb, offset,
+ (int) tmpObj2.uint, ENC_ASCII|ENC_NA);
+ offset += (int) tmpObj2.uint;
+ }
+
+ // How many reports?
+ tmpObj2 = cbor_info(tvb, offset); // Should come back a CBOR array of some size
+ offset += tmpObj.size;
+
+ for ( j=0; j<tmpObj2.uint; j++ ) {
+ // Internals of each report per section 8.4.7 of https://tools.ietf.org/pdf/draft-birrane-dtn-amp-07.pdf
+ // amp_report_sub_tree = proto_item_add_subtree(amp_report_set_tree, ett_amp);
+ amp_report_tree = proto_tree_add_subtree(amp_report_set_tree, tvb, offset, -1,
+ ett_amp_report, &amp_report, "Report");
+
+ // Each Report is a:
+ // Tempate [ARI]
+ // Timestamp [TS] (opt)
+ // Entries [TNVC] (bytestring containing a TNVC)
+ tmpObj3 = cbor_info(tvb, offset); // Should come back a CBOR array of size 2 or 3
+ offset += tmpObj3.size;
+ if ( tmpObj3.uint==3 )
+ {
+ reportHasTimestamp = 1;
+ } else
+ {
+ reportHasTimestamp = 0;
+ }
+
+ // Tempate (bytestring); starts with ARI
+ tmpObj3 = cbor_info(tvb, offset);
+ offset += tmpObj3.size;
+ guint8 ariFlags;
+ ariFlags = tvb_get_guint8(tvb, offset);
+
+ if ( (ariFlags&0x0F)==0x03 ) {
+ // Literal
+ proto_tree_add_uint(amp_report_tree, hf_ari_value, tvb, offset, 1, ariFlags);
+ } else {
+ // NOT literal
+ proto_tree_add_bitmask(amp_report_tree, tvb, offset, hf_amp_ari_flags, ett_amp_ari_flags,
+ amp_ari_flags, ENC_BIG_ENDIAN);
+
+ }
+ //proto_tree_add_uint(amp_ari_tree, hf_ari_struct, tvb, offset, 1, ariFlags);
+
+ if ( (ariFlags & 0x0F) != 0x03 )
+ {
+ // ARI is NOT Literal
+ proto_tree_add_item(amp_report_tree, hf_amp_report_bytestring, tvb, offset+1, (int) tmpObj3.uint-1, 0x00);
+ }
+ offset += (int) tmpObj3.uint;
+
+ if ( reportHasTimestamp )
+ {
+ tmpObj3 = cbor_info(tvb, offset);
+ offset += 1;
+ add_value_time_to_tree((int) tmpObj3.uint, 4, amp_report_tree, tvb, offset, hf_amp_primary_timestamp);
+ offset += (tmpObj3.size-1);
+ }
+
+ // Entries [TNVC] -- This is th collection of data values that comprise the report
+ // contents in accordance with the associated Report Template.
+ // Contained in a CBOR bytestring
+ tmpObj3 = cbor_info(tvb, offset);
+ offset += tmpObj3.size;
+
+ // Now read array length for TNVC
+ tmpObj3 = cbor_info(tvb, offset);
+ offset += tmpObj3.size;
+ numTNVCEntries = (int) tmpObj3.uint;
+
+ // TNVC Flags
+ proto_tree_add_bitmask(amp_report_tree, tvb, offset, hf_amp_tnvc_flags, ett_amp_tnvc_flags,
+ amp_tnvc_flags, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ // TNVC entries
+ amp_report_TNVC_sub_tree = proto_item_add_subtree(amp_report_tree, ett_amp);
+ amp_report_TNVC_tree = proto_tree_add_subtree(amp_report_TNVC_sub_tree, tvb, offset, -1,
+ ett_amp_message, &amp_message, "TNVC Entries");
+
+ // Byte string containing data types
+ tmpObj3 = cbor_info(tvb, offset);
+ offset += tmpObj3.size;
+ report_types_offset = offset;
+ offset += (int) tmpObj3.uint;
+
+ // TNVC data items
+ for ( k=0; k<numTNVCEntries-2; k++ ) {
+ tmpObj3 = cbor_info(tvb, offset);
+ switch ( tmpObj3.type ) {
+ case 0x02: // bytestring
+ // Get the type from the type dictionary
+ switch ( tvb_get_guint8(tvb, report_types_offset+k) ) {
+ case 0x12: // string
+ // It's a text string of some size INSIDE a byte string
+ tmpObj4 = cbor_info(tvb, offset+tmpObj3.size);
+ // printf("tmpObj4.type of (%02x) is (%d)\n", tvb_get_guint8(tvb, offset+tmpObj3.size), tmpObj4.type);
+ proto_tree_add_item(amp_report_TNVC_tree, hf_amp_text_string, tvb,
+ offset+tmpObj3.size+tmpObj4.size,
+ (int) tmpObj3.uint-tmpObj4.size, 0x00);
+ break;
+ case 0x16: // uvast
+ tmpObj4 = cbor_info(tvb, offset+tmpObj3.size);
+ if ( tmpObj4.type != CBOR_UINT ) {
+ break;
+ }
+ switch ( tmpObj4.size ) {
+ case 1:
+ proto_tree_add_item(amp_report_TNVC_tree, hf_amp_report_integer8_small,
+ tvb, offset+tmpObj3.size, 1, 0x00);
+ break;
+ default: // Note: CBOR will only let these sizes be 1, 2, 4, or 8 bytes.
+ proto_tree_add_item(amp_report_TNVC_tree, hf_amp_report_integer,
+ tvb, offset+tmpObj3.size+1, tmpObj4.size-1, 0x00);
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ proto_tree_add_item(amp_report_TNVC_tree, hf_amp_report_data, tvb, offset+tmpObj3.size, (int) tmpObj3.uint, 0x00);
+ break;
+ }
+ if ( tmpObj3.totalSize > 0 ) {
+ DISSECTOR_ASSERT(tmpObj3.totalSize <= G_MAXINT32);
+ offset += (int)tmpObj3.totalSize;
+ } else {
+ break;
+ }
+ }
+
+ }
+ break;
+
+ case 0x02: // Perform Control
+ // TODO
+ //amp_control_sub_tree = proto_item_add_subtree(amp_message_tree, ett_amp);
+ amp_control_tree = proto_tree_add_subtree(amp_message_tree, tvb, offset-1, -1,
+ ett_amp_message, &amp_message, "Perform-Control");
+ proto_tree_add_item(amp_control_tree, hf_amp_cbor_header, tvb, offset, 1, 0x00);
+ break;
+
+ case 0x03: // Table Set
+ // TODO
+ //amp_table_sub_tree = proto_item_add_subtree(amp_items_tree, ett_amp);
+ amp_table_tree = proto_tree_add_subtree(amp_items_tree, tvb, offset, -1,
+ ett_amp_message, &amp_message, "AMP Message: Table-Set");
+ proto_tree_add_item(amp_table_tree, hf_amp_cbor_header, tvb, offset, 1, 0x00);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return;
+}
+
+/* Code to actually dissect the packets */
+static int
+dissect_amp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ int offset = 0;
+ proto_item *amp_packet;
+ proto_item *amp_tree;
+ gint amp_packet_reported_length;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "AMP");
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ amp_packet_reported_length = tvb_reported_length_remaining(tvb, 0);
+
+ amp_packet = proto_tree_add_item(tree, proto_amp, tvb, 0, amp_packet_reported_length, ENC_NA);
+ amp_tree = proto_item_add_subtree(amp_packet, ett_amp);
+
+ dissect_amp_as_subtree (tvb, pinfo, amp_tree, offset);
+
+ return tvb_captured_length(tvb);
+}
+
+void
+proto_register_amp(void)
+{
+ static hf_register_info hf[] = {
+
+ { &hf_amp_message_header,
+ { "AMP Message Header", "amp.message.header",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_amp_report_data,
+ { "Report-Data", "amp.report.data",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_amp_report_bytestring,
+ { "Report-Bytestring", "amp.report.bytestring",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_amp_report_integer8_small,
+ { "Report-Integer8_small", "amp.report.integer8_small",
+ FT_UINT8, BASE_DEC, NULL, AMP_CBOR_UINT_SMALL,
+ NULL, HFILL }
+ },
+ { &hf_amp_report_integer,
+ { "Report-Integer", "amp.report.integer",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_amp_cbor_header,
+ { "CBOR-Header", "amp.cbor_header",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_amp_primary_timestamp,
+ { "Timestamp", "amp.primary_timestamp",
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
+ },
+ { &hf_amp_tnvc_flags,
+ { "TNVC Flags", "amp.tnvc.flags",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_amp_tnvc_reserved,
+ { "Reserved", "amp.tnvc.reserved",
+ FT_UINT8, BASE_DEC, NULL, AMP_TNVC_RESERVED,
+ NULL, HFILL }
+ },
+ { &hf_amp_tnvc_mixed,
+ { "Mixed", "amp.tnvc.mixed",
+ FT_UINT8, BASE_DEC, VALS(tnvc_yesno), AMP_TNVC_MIXED,
+ NULL, HFILL }
+ },
+ { &hf_amp_tnvc_typed,
+ { "TNVC Values are Typed", "amp.tnvc.typed",
+ FT_UINT8, BASE_DEC, VALS(tnvc_yesno), AMP_TNVC_TYPE,
+ NULL, HFILL }
+ },
+ { &hf_amp_tnvc_name,
+ { "Name", "amp.tnvc.name",
+ FT_UINT8, BASE_DEC, VALS(tnvc_yesno), AMP_TNVC_NAME,
+ NULL, HFILL }
+ },
+ { &hf_amp_tnvc_values,
+ { "Values", "amp.tnvc.value",
+ FT_UINT8, BASE_DEC, VALS(tnvc_yesno), AMP_TNVC_VALUE,
+ NULL, HFILL }
+ },
+ { &hf_ari_nickname,
+ { "Nickname", "amp.nickname",
+ FT_UINT8, BASE_DEC, VALS(tnvc_present_notpresent), AMP_ARI_NICKNAME,
+ NULL, HFILL }
+ },
+ { &hf_amp_ari_flags,
+ { "ARI Flags", "amp.ari.flags",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_ari_parameters,
+ { "Parameters", "amp.parameters",
+ FT_UINT8, BASE_DEC, VALS(tnvc_present_notpresent), AMP_ARI_PARAMETERS,
+ NULL, HFILL }
+ },
+ { &hf_ari_issuer,
+ { "Issuer", "amp.issuer",
+ FT_UINT8, BASE_DEC, VALS(tnvc_present_notpresent), AMP_ARI_ISSUER,
+ NULL, HFILL }
+ },
+ { &hf_ari_tag,
+ { "Tag", "amp.tag",
+ FT_UINT8, BASE_DEC, VALS(tnvc_present_notpresent), AMP_ARI_TAG,
+ NULL, HFILL }
+ },
+ { &hf_ari_value,
+ { "Value", "amp.value",
+ FT_UINT8, BASE_DEC, NULL, AMP_ARI_VALUE,
+ NULL, HFILL }
+ },
+ { &hf_ari_struct,
+ { "Struct Type", "amp.struct",
+ FT_UINT8, BASE_DEC, VALS(amp_ari_struct_type), AMP_ARI_STRUCT,
+ NULL, HFILL }
+ },
+ { &hf_amp_reserved,
+ { "Reserved", "amp.reserved",
+ FT_UINT8, BASE_DEC, NULL, AMP_HDR_RESERVED,
+ NULL, HFILL }
+ },
+ { &hf_amp_acl,
+ { "ACL", "amp.acl",
+ FT_UINT8, BASE_DEC, VALS(tnvc_present_notpresent), AMP_HDR_ACL,
+ NULL, HFILL }
+ },
+ { &hf_amp_nack,
+ { "NACK", "amp.nack",
+ FT_UINT8, BASE_DEC, VALS(tnvc_present_notpresent), AMP_HDR_NACK,
+ NULL, HFILL }
+ },
+ { &hf_amp_ack,
+ { "ACK", "amp.ack",
+ FT_UINT8, BASE_DEC, VALS(tnvc_present_notpresent), AMP_HDR_ACK,
+ NULL, HFILL }
+ },
+ { &hf_amp_opcode,
+ { "Opcode", "amp.opcode",
+ FT_UINT8, BASE_DEC, VALS(opcode), AMP_HDR_OPCODE,
+ NULL, HFILL }
+ },
+ {&hf_amp_agent_name,
+ {"Agent-Name", "amp.agent_name",
+ FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_amp_text_string,
+ {"String", "amp.string",
+ FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ {&hf_amp_rx_name,
+ {"Rx-Name", "amp.rx_name",
+ FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_amp,
+ &ett_amp_message_header,
+ &ett_amp_cbor_header,
+ &ett_amp_message,
+ &ett_amp_register,
+ &ett_amp_report_set,
+ &ett_amp_report,
+ &ett_amp_tnvc_flags,
+ &ett_amp_ari_flags,
+ &ett_amp_proto
+ };
+
+ // expert_module_t* expert_amp;
+
+ /* Register the protocol name and description */
+ proto_amp = proto_register_protocol("AMP", "AMP", "amp");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_amp, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ // expert_amp = expert_register_protocol(proto_amp);
+ // expert_register_field_array(expert_amp, ei, array_length(ei));
+
+ amp_handle = register_dissector("amp", dissect_amp, proto_amp);
+}
+
+void
+proto_reg_handoff_amp(void)
+{
+ dissector_add_uint("ccsds.apid", AMP_APID, amp_handle);
+ dissector_add_for_decode_as_with_preference("udp.port", amp_handle);
+}
+
+/*
+ * Editor modelines - http://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:
+ */
diff --git a/epan/dissectors/packet-cfdp.c b/epan/dissectors/packet-cfdp.c
index 1b52a7c487..2e2835c0a8 100644
--- a/epan/dissectors/packet-cfdp.c
+++ b/epan/dissectors/packet-cfdp.c
@@ -6,9 +6,16 @@
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
+ * Slightly updated to allow more in-depth decoding when called
+ * with the 'dissect_as_subtree' method and to leverage some
+ * of the bitfield display operations: Keith Scott
+ * <kscott@mitre.org>.
+ *
* SPDX-License-Identifier: GPL-2.0-or-later
*/
+#include <stdio.h>
+
#include "config.h"
#include <epan/packet.h>
#include <epan/expert.h>
@@ -25,6 +32,18 @@ void proto_reg_handoff_cfdp(void);
/* Initialize the protocol and registered fields */
static int proto_cfdp = -1;
+static int hf_cfdp_flags = -1;
+static int hf_cfdp_byte2 = -1;
+static int hf_cfdp_proxy_fault_hdl_overr = -1;
+static int hf_cfdp_proxy_trans_mode = -1;
+static int hf_cfdp_proxy_segment_control_byte = -1;
+static int hf_cfdp_proxy_put_resp = -1;
+static int hf_cfdp_orig_trans_id = -1;
+static int hf_cfdp_remote_stat_rep_req = -1;
+static int hf_cfdp_remote_stat_rep_resp = -1;
+static int hf_cfdp_finish_pdu_flags = -1;
+static int hf_cfdp_remote_suspend_resume_req = -1;
+static int hf_cfdp_remote_suspend_resume_resp = -1;
static int hf_cfdp_version = -1;
static int hf_cfdp_pdu_type = -1;
static int hf_cfdp_direction = -1;
@@ -32,6 +51,7 @@ static int hf_cfdp_trans_mode = -1;
static int hf_cfdp_crc_flag = -1;
static int hf_cfdp_res1 = -1;
static int hf_cfdp_data_length = -1;
+static int hf_cfdp_file_data_pdu = -1;
static int hf_cfdp_res2 = -1;
static int hf_cfdp_entid_length = -1;
static int hf_cfdp_res3 = -1;
@@ -76,7 +96,6 @@ static int hf_cfdp_status_code_6 = -1;
static int hf_cfdp_status_code_7 = -1;
static int hf_cfdp_status_code_8 = -1;
static int hf_cfdp_handler_code = -1;
-static int hf_cfdp_trans_mode_msg = -1;
static int hf_cfdp_proxy_msg_type = -1;
static int hf_cfdp_proxy_segment_control = -1;
static int hf_cfdp_proxy_delivery_code = -1;
@@ -102,8 +121,20 @@ static int hf_cfdp_user_data = -1;
/* Initialize the subtree pointers */
static gint ett_cfdp = -1;
static gint ett_cfdp_header = -1;
+static gint ett_cfdp_flags = -1;
+static gint ett_cfdp_byte2 = -1;
+static gint ett_cfdp_proxy_fault_hdl_overr = -1;
+static gint ett_cfdp_proxy_trans_mode = -1;
+static gint ett_cfdp_proxy_segment_control_byte = -1;
+static gint ett_cfdp_proxy_put_resp = -1;
+static gint ett_cfdp_orig_trans_id = -1;
+static gint ett_cfdp_remote_stat_rep_req = -1;
+static gint ett_cfdp_remote_stat_rep_resp = -1;
static gint ett_cfdp_file_directive_header = -1;
static gint ett_cfdp_file_data_header = -1;
+static gint ett_cfdp_finish_pdu_flags = -1;
+static gint ett_cfdp_remote_suspend_resume_req = -1;
+static gint ett_cfdp_remote_suspend_resume_resp = -1;
static gint ett_cfdp_fault_location = -1;
static gint ett_cfdp_crc = -1;
static gint ett_cfdp_filestore_req = -1;
@@ -111,6 +142,7 @@ static gint ett_cfdp_filestore_resp = -1;
static gint ett_cfdp_msg_to_user = -1;
static gint ett_cfdp_fault_hdl_overr = -1;
static gint ett_cfdp_flow_label = -1;
+static gint ett_cfdp_proto = -1;
static expert_field ei_cfdp_bad_length = EI_INIT;
@@ -425,6 +457,108 @@ static const value_string cfdp_directive_codes[] = {
{ 0, NULL }
};
+static const int *cfdp_flags[] = {
+ &hf_cfdp_version,
+ &hf_cfdp_pdu_type,
+ &hf_cfdp_direction,
+ &hf_cfdp_trans_mode,
+ &hf_cfdp_crc_flag,
+ &hf_cfdp_res1,
+ NULL
+};
+
+static const int *cfdp_byte2[] = {
+ &hf_cfdp_res2,
+ &hf_cfdp_entid_length,
+ &hf_cfdp_res3,
+ &hf_cfdp_transeqnum_length,
+ NULL
+};
+
+static const int *cfdp_proxy_fault_hdl_overr[] = {
+ &hf_cfdp_condition_code,
+ &hf_cfdp_handler_code,
+ NULL
+};
+
+static const int *cfdp_proxy_trans_mode [] = {
+ &hf_cfdp_spare_seven_2,
+ &hf_cfdp_trans_mode,
+ NULL
+};
+
+static const int *cfdp_proxy_segment_control_byte [] = {
+ &hf_cfdp_spare_seven_2,
+ &hf_cfdp_proxy_segment_control,
+ NULL
+};
+
+static const int *cfdp_proxy_put_resp [] = {
+ &hf_cfdp_condition_code,
+ &hf_cfdp_spare_one,
+ &hf_cfdp_condition_code,
+ &hf_cfdp_proxy_delivery_code,
+ &hf_cfdp_file_stat,
+ NULL
+};
+
+static const int *cfdp_orig_trans_id[] = {
+ &hf_cfdp_res2,
+ &hf_cfdp_entid_length,
+ &hf_cfdp_res3,
+ &hf_cfdp_transeqnum_length,
+ NULL
+};
+
+static const int *cfdp_remote_stat_rep_req[] = {
+ &hf_cfdp_res2,
+ &hf_cfdp_entid_length,
+ &hf_cfdp_res3,
+ &hf_cfdp_transeqnum_length,
+ NULL
+};
+
+static const int *cfdp_remote_stat_rep_resp[] = {
+ &hf_cfdp_trans_stat,
+ &hf_cfdp_spare_five,
+ &hf_cfdp_rep_resp_code,
+ &hf_cfdp_spare_one_2,
+ &hf_cfdp_entid_length,
+ &hf_cfdp_spare_one,
+ &hf_cfdp_transeqnum_length,
+ NULL
+};
+
+static const int *cfdp_finish_pdu_flags [] = {
+ &hf_cfdp_condition_code,
+ &hf_cfdp_end_system_stat,
+ &hf_cfdp_delivery_code,
+ &hf_cfdp_file_stat,
+ NULL
+};
+
+static const int *cfdp_remote_suspend_resume_req [] = {
+ &hf_cfdp_spare_one_2,
+ &hf_cfdp_entid_length,
+ &hf_cfdp_spare_one,
+ &hf_cfdp_transeqnum_length,
+ NULL
+};
+
+
+static const int *cfdp_remote_suspend_resume_resp [] = {
+ &hf_cfdp_suspension_ind,
+ &hf_cfdp_trans_stat_2,
+ &hf_cfdp_spare_five,
+ &hf_cfdp_spare_one_2,
+ &hf_cfdp_entid_length,
+ &hf_cfdp_spare_one,
+ &hf_cfdp_transeqnum_length,
+ NULL
+};
+
+
+
/* Dissect the Source Entity ID field */
static void
dissect_cfdp_src_entity_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint8 len_ent_id)
@@ -566,6 +700,7 @@ static guint32 dissect_cfdp_filestore_resp_tlv(tvbuff_t *tvb, proto_tree *tree,
proto_tree_add_item(cfdp_filestore_resp_tree, hf_cfdp_second_file_name, tvb, offset, aux_byte, ENC_ASCII|ENC_NA);
offset += aux_byte;
}
+
/* Filestore Message */
aux_byte = tvb_get_guint8(tvb, offset);
offset += 1;
@@ -575,7 +710,7 @@ static guint32 dissect_cfdp_filestore_resp_tlv(tvbuff_t *tvb, proto_tree *tree,
}
}
- return offset;
+ return offset+1;
}
/* Dissect the Fault Location TLV */
@@ -607,11 +742,16 @@ static guint32 dissect_cfdp_fault_location_tlv(tvbuff_t *tvb, proto_tree *tree,
/* Dissect the Message to User TLV */
static guint32 dissect_cfdp_msg_to_user_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ext_offset){
- guint8 aux_byte, tlv_type, tlv_len;
+ guint8 aux_byte;
+ guint8 tlv_type;
+ guint8 tlv_len;
proto_tree *cfdp_msg_to_user_tree;
guint32 offset = ext_offset;
guint32 msg_to_user_id;
+
+ guint64 retval;
+
int len_ent_id;
int len_tseq_num;
@@ -656,6 +796,7 @@ static guint32 dissect_cfdp_msg_to_user_tlv(tvbuff_t *tvb, packet_info *pinfo, p
tlv_len = tvb_get_guint8(tvb, offset);
offset += 1;
proto_tree_add_item(cfdp_msg_to_user_tree, hf_cfdp_message_to_user, tvb, offset, tlv_len, ENC_NA);
+ offset += tlv_len;
break;
case PROXY_FILESTORE_REQ:
@@ -663,16 +804,20 @@ static guint32 dissect_cfdp_msg_to_user_tlv(tvbuff_t *tvb, packet_info *pinfo, p
break;
case PROXY_FAULT_HDL_OVERR:
- aux_byte = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_handler_code, tvb, offset, 1, aux_byte);
+ proto_tree_add_bitmask(cfdp_msg_to_user_tree, tvb, offset,
+ hf_cfdp_proxy_fault_hdl_overr,
+ ett_cfdp_proxy_fault_hdl_overr,
+ cfdp_proxy_fault_hdl_overr,
+ ENC_BIG_ENDIAN);
offset += 1;
break;
case PROXY_TRANS_MODE:
- aux_byte = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_seven_2, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_trans_mode_msg, tvb, offset, 1, aux_byte);
+ proto_tree_add_bitmask(cfdp_msg_to_user_tree, tvb, offset,
+ hf_cfdp_proxy_trans_mode,
+ ett_cfdp_proxy_trans_mode,
+ cfdp_proxy_trans_mode,
+ ENC_BIG_ENDIAN);
offset += 1;
break;
@@ -681,19 +826,20 @@ static guint32 dissect_cfdp_msg_to_user_tlv(tvbuff_t *tvb, packet_info *pinfo, p
break;
case PROXY_SEGMENT_CONTROL:
- aux_byte = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_seven_2, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_proxy_segment_control, tvb, offset, 1, aux_byte);
+ proto_tree_add_bitmask(cfdp_msg_to_user_tree, tvb, offset,
+ hf_cfdp_proxy_segment_control_byte,
+ ett_cfdp_proxy_segment_control_byte,
+ cfdp_proxy_segment_control_byte,
+ ENC_BIG_ENDIAN);
offset += 1;
break;
case PROXY_PUT_RESP:
- aux_byte = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_proxy_delivery_code, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_file_stat, tvb, offset, 1, aux_byte);
+ proto_tree_add_bitmask(cfdp_msg_to_user_tree, tvb, offset,
+ hf_cfdp_proxy_put_resp,
+ ett_cfdp_proxy_put_resp,
+ cfdp_proxy_put_resp,
+ ENC_BIG_ENDIAN);
offset += 1;
break;
@@ -705,18 +851,19 @@ static guint32 dissect_cfdp_msg_to_user_tlv(tvbuff_t *tvb, packet_info *pinfo, p
break;
case ORIG_TRANS_ID:
- aux_byte = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_res2, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_entid_length, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_res3, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, aux_byte);
+ proto_tree_add_bitmask_ret_uint64(cfdp_msg_to_user_tree, tvb, offset,
+ hf_cfdp_orig_trans_id,
+ ett_cfdp_orig_trans_id,
+ cfdp_orig_trans_id,
+ ENC_BIG_ENDIAN,
+ &retval);
offset += 1;
- len_ent_id = ((aux_byte & HDR_LEN_ENT_ID) >> 4) + 1;
+ len_ent_id = ((retval & HDR_LEN_ENT_ID) >> 4) + 1;
dissect_cfdp_src_entity_id(tvb, pinfo, cfdp_msg_to_user_tree, offset, len_ent_id);
offset += len_ent_id;
- len_tseq_num = (aux_byte & HDR_LEN_TSEQ_NUM) +1;
+ len_tseq_num = (retval & HDR_LEN_TSEQ_NUM) +1;
dissect_cfdp_tseq_num(tvb, pinfo, cfdp_msg_to_user_tree, offset, len_tseq_num);
offset += len_tseq_num;
@@ -754,17 +901,19 @@ static guint32 dissect_cfdp_msg_to_user_tlv(tvbuff_t *tvb, packet_info *pinfo, p
case REMOTE_STAT_REP_REQ:
aux_byte = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_res2, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_entid_length, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_res3, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, aux_byte);
+ proto_tree_add_bitmask_ret_uint64(cfdp_msg_to_user_tree, tvb, offset,
+ hf_cfdp_remote_stat_rep_req,
+ ett_cfdp_remote_stat_rep_req,
+ cfdp_remote_stat_rep_req,
+ ENC_BIG_ENDIAN,
+ &retval);
offset += 1;
- len_ent_id = ((aux_byte & HDR_LEN_ENT_ID) >> 4) + 1;
+ len_ent_id = ((retval & HDR_LEN_ENT_ID) >> 4) + 1;
dissect_cfdp_src_entity_id(tvb, pinfo, cfdp_msg_to_user_tree, offset, len_ent_id);
offset += len_ent_id;
- len_tseq_num = (aux_byte & HDR_LEN_TSEQ_NUM) +1;
+ len_tseq_num = (retval & HDR_LEN_TSEQ_NUM) +1;
dissect_cfdp_tseq_num(tvb, pinfo, cfdp_msg_to_user_tree, offset, len_tseq_num);
offset += len_tseq_num;
@@ -776,66 +925,57 @@ static guint32 dissect_cfdp_msg_to_user_tlv(tvbuff_t *tvb, packet_info *pinfo, p
break;
case REMOTE_STAT_REP_RESP:
- aux_byte = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_trans_stat, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_five, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_rep_resp_code, tvb, offset, 1, aux_byte);
- offset += 1;
-
- aux_byte = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one_2, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_entid_length, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, aux_byte);
- offset += 1;
-
- len_ent_id = ((aux_byte & HDR_LEN_ENT_ID) >> 4) + 1;
+ proto_tree_add_bitmask_ret_uint64(cfdp_msg_to_user_tree, tvb, offset,
+ hf_cfdp_remote_stat_rep_resp,
+ ett_cfdp_remote_stat_rep_resp,
+ cfdp_remote_stat_rep_resp,
+ ENC_BIG_ENDIAN,
+ &retval);
+
+ len_ent_id = ((retval & (HDR_LEN_ENT_ID<<8)) >> 12) + 1;
dissect_cfdp_src_entity_id(tvb, pinfo, cfdp_msg_to_user_tree, offset, len_ent_id);
offset += len_ent_id;
- len_tseq_num = (aux_byte & HDR_LEN_TSEQ_NUM) +1;
+ len_tseq_num = (retval & HDR_LEN_TSEQ_NUM) +1;
dissect_cfdp_tseq_num(tvb, pinfo, cfdp_msg_to_user_tree, offset, len_tseq_num);
offset += len_tseq_num;
break;
case REMOTE_SUSPEND_REQ:
case REMOTE_RESUME_REQ:
- aux_byte = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one_2, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_entid_length, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, aux_byte);
+ proto_tree_add_bitmask_ret_uint64(cfdp_msg_to_user_tree, tvb, offset,
+ hf_cfdp_remote_suspend_resume_req,
+ ett_cfdp_remote_suspend_resume_req,
+ cfdp_remote_suspend_resume_req,
+ ENC_BIG_ENDIAN,
+ &retval);
+
offset += 1;
- len_ent_id = ((aux_byte & HDR_LEN_ENT_ID) >> 4) + 1;
+ len_ent_id = ((retval & HDR_LEN_ENT_ID) >> 4) + 1;
dissect_cfdp_src_entity_id(tvb, pinfo, cfdp_msg_to_user_tree, offset, len_ent_id);
offset += len_ent_id;
- len_tseq_num = (aux_byte & HDR_LEN_TSEQ_NUM) +1;
+ len_tseq_num = (retval & HDR_LEN_TSEQ_NUM) +1;
dissect_cfdp_tseq_num(tvb, pinfo, cfdp_msg_to_user_tree, offset, len_tseq_num);
offset += len_tseq_num;
break;
case REMOTE_SUSPEND_RESP:
case REMOTE_RESUME_RESP:
- aux_byte = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_suspension_ind, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_trans_stat_2, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_five, tvb, offset, 1, aux_byte);
- offset += 1;
-
- aux_byte = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one_2, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_entid_length, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_spare_one, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(cfdp_msg_to_user_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, aux_byte);
- offset += 1;
-
- len_ent_id = ((aux_byte & HDR_LEN_ENT_ID) >> 4) + 1;
+ proto_tree_add_bitmask_ret_uint64(cfdp_msg_to_user_tree, tvb, offset,
+ hf_cfdp_remote_suspend_resume_resp,
+ ett_cfdp_remote_suspend_resume_resp,
+ cfdp_remote_suspend_resume_resp,
+ ENC_BIG_ENDIAN,
+ &retval);
+ offset += 2;
+
+ len_ent_id = ((retval & HDR_LEN_ENT_ID) >> 4) + 1;
dissect_cfdp_src_entity_id(tvb, pinfo, cfdp_msg_to_user_tree, offset, len_ent_id);
offset += len_ent_id;
- len_tseq_num = (aux_byte & HDR_LEN_TSEQ_NUM) +1;
+ len_tseq_num = (retval & HDR_LEN_TSEQ_NUM) +1;
dissect_cfdp_tseq_num(tvb, pinfo, cfdp_msg_to_user_tree, offset, len_tseq_num);
offset += len_tseq_num;
break;
@@ -942,25 +1082,29 @@ static guint32 dissect_cfdp_eof_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tre
static guint32 dissect_cfdp_finished_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ext_offset, guint ext_packet_len){
guint32 offset = ext_offset;
- guint8 aux_byte, tlv_type;
-
+ guint8 tlv_type;
+ guint64 aux_byte;
- guint cfdp_packet_data_length = ext_packet_len;
+ guint cfdp_packet_data_length = offset+ext_packet_len;
- aux_byte = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(tree, hf_cfdp_condition_code, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(tree, hf_cfdp_end_system_stat, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(tree, hf_cfdp_delivery_code, tvb, offset, 1, aux_byte);
- proto_tree_add_uint(tree, hf_cfdp_file_stat, tvb, offset, 1, aux_byte);
+ proto_tree_add_bitmask_ret_uint64(tree, tvb, offset,
+ hf_cfdp_finish_pdu_flags,
+ ett_cfdp_finish_pdu_flags,
+ cfdp_finish_pdu_flags,
+ ENC_BIG_ENDIAN,
+ &aux_byte);
offset += 1;
col_add_fstr(pinfo->cinfo, COL_INFO, "Finished PDU (%s)", val_to_str_const((aux_byte & 0xF0) >> 4, cfdp_condition_codes, "Reserved Code"));
/* Add TLV fields */
- while(offset < cfdp_packet_data_length){
+ while(offset < cfdp_packet_data_length-1){
tlv_type = tvb_get_guint8(tvb, offset);
offset += 1;
switch(tlv_type){
+ case 0x00:
+ offset += 2;
+ break;
case FILESTORE_RESP:
offset = dissect_cfdp_filestore_resp_tlv(tvb, tree, offset);
break;
@@ -1108,7 +1252,7 @@ dissect_cfdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_
gint cfdp_packet_data_length;
gint length;
guint8 first_byte;
- guint8 second_byte;
+ guint64 retval;
gint len_ent_id;
gint len_tseq_num;
@@ -1119,8 +1263,6 @@ dissect_cfdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_
cfdp_packet_header_length = (tvb_get_guint8(tvb, 3) & HDR_LEN_TSEQ_NUM) + 1 + 2*(((tvb_get_guint8(tvb, 3) & HDR_LEN_ENT_ID) >>4) +1) + CFDP_HEADER_FIXED_FIELDS_LEN;
cfdp_packet_length = tvb_get_ntohs(tvb, 1) + cfdp_packet_header_length;
-
-
/* Min length is size of header plus 2 octets, whereas max length is reported length.
* If the length field in the CFDP header is outside of these bounds,
* use the value it violates. Otherwise, use the length field value.
@@ -1144,30 +1286,29 @@ dissect_cfdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_
/* CRC code is not included in the packet data length */
cfdp_packet_data_length = tvb_get_ntohs(tvb, 1)-2*((first_byte & HDR_CRCF) >>1);
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_version, tvb, offset, 1, first_byte);
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_pdu_type, tvb, offset, 1, first_byte);
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_direction, tvb, offset, 1, first_byte);
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_trans_mode, tvb, offset, 1, first_byte);
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_crc_flag, tvb, offset, 1, first_byte);
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_res1, tvb, offset, 1, first_byte);
+ proto_tree_add_bitmask(cfdp_header_tree, tvb, offset,
+ hf_cfdp_flags,
+ ett_cfdp_flags,
+ cfdp_flags,
+ ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(cfdp_header_tree, hf_cfdp_data_length, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
- second_byte = tvb_get_guint8(tvb, offset);
-
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_res2, tvb, offset, 1, second_byte);
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_entid_length, tvb, offset, 1, second_byte);
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_res3, tvb, offset, 1, second_byte);
- proto_tree_add_uint(cfdp_header_tree, hf_cfdp_transeqnum_length, tvb, offset, 1, second_byte);
- offset += 1;
+ proto_tree_add_bitmask_ret_uint64(cfdp_header_tree, tvb, offset,
+ hf_cfdp_byte2,
+ ett_cfdp_byte2,
+ cfdp_byte2,
+ ENC_BIG_ENDIAN,
+ &retval);
+ offset += 2;
- len_ent_id = ((second_byte & HDR_LEN_ENT_ID) >> 4) + 1;
+ len_ent_id = ((retval & HDR_LEN_ENT_ID) >> 4) + 1;
dissect_cfdp_src_entity_id(tvb, pinfo, cfdp_header_tree, offset, len_ent_id);
offset += len_ent_id;
- len_tseq_num = (second_byte & HDR_LEN_TSEQ_NUM) +1;
+ len_tseq_num = (retval & HDR_LEN_TSEQ_NUM) +1;
dissect_cfdp_tseq_num(tvb, pinfo, cfdp_header_tree, offset, len_tseq_num);
offset += len_tseq_num;
@@ -1261,10 +1402,208 @@ dissect_cfdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_
}
void
+dissect_cfdp_as_subtree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
+{
+ proto_tree *cfdp_header_tree = NULL;
+ proto_tree *cfdp_sub_tree = NULL;
+ proto_item *payload_item = NULL;
+ proto_tree *cfdp_tree = NULL;
+ proto_item *cfdp_header;
+ gint cfdp_data_len;
+ gint len_ent_id;
+ gint len_tseq_num;
+ guint64 first_byte;
+ guint64 retval;
+
+ cfdp_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_cfdp_proto,
+ &payload_item, "Payload Data: CFDP Protocol");
+
+ cfdp_sub_tree = proto_item_add_subtree(cfdp_tree, ett_cfdp);
+ cfdp_header_tree = proto_tree_add_subtree(cfdp_sub_tree, tvb, offset, -1,
+ ett_cfdp_header, &cfdp_header, "CFDP Header");
+
+ proto_tree_add_bitmask_ret_uint64(cfdp_header_tree, tvb, offset,
+ hf_cfdp_flags,
+ ett_cfdp_flags,
+ cfdp_flags,
+ ENC_BIG_ENDIAN,
+ &first_byte);
+ offset += 1;
+
+ guint cfdp_data_end;
+ cfdp_data_len = tvb_get_guint16 (tvb, offset, ENC_BIG_ENDIAN);
+ proto_tree_add_item(cfdp_header_tree, hf_cfdp_data_length, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_bitmask_ret_uint64(cfdp_header_tree, tvb, offset,
+ hf_cfdp_byte2,
+ ett_cfdp_byte2,
+ cfdp_byte2,
+ ENC_BIG_ENDIAN,
+ &retval);
+ offset += 1;
+
+ len_ent_id = ((retval & HDR_LEN_ENT_ID) >> 4) + 1;
+ dissect_cfdp_src_entity_id(tvb, pinfo, cfdp_header_tree, offset, len_ent_id);
+ offset += len_ent_id;
+
+ len_tseq_num = (retval & HDR_LEN_TSEQ_NUM) +1;
+ dissect_cfdp_tseq_num(tvb, pinfo, cfdp_header_tree, offset, len_tseq_num);
+ offset += len_tseq_num;
+
+ dissect_cfdp_dst_entity_id(tvb, pinfo, cfdp_header_tree, offset, len_ent_id);
+ offset += len_ent_id;
+
+ cfdp_data_end = offset+cfdp_data_len;
+
+ /* Build the File Directive or the File Data tree */
+ if(!(first_byte & HDR_TYPE_CFDP))
+ {
+ proto_item *cfdp_file_directive_header;
+ proto_tree *cfdp_file_directive_header_tree;
+ guint8 directive_code;
+
+ cfdp_file_directive_header_tree = proto_tree_add_subtree(cfdp_tree, tvb, offset, cfdp_data_len,
+ ett_cfdp_file_directive_header, &cfdp_file_directive_header,
+ "CFDP File Directive");
+
+ directive_code = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(cfdp_file_directive_header_tree, hf_cfdp_file_directive_type, tvb, offset, 1, directive_code);
+ offset += 1;
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s PDU", val_to_str(directive_code, cfdp_directive_codes, "Reserved (%d)"));
+
+ switch(directive_code)
+ {
+ case EOF_PDU:
+ offset = dissect_cfdp_eof_pdu(tvb, pinfo, cfdp_file_directive_header_tree, offset, cfdp_data_len);
+ break;
+
+ case FINISHED_PDU:
+ offset = dissect_cfdp_finished_pdu(tvb, pinfo, cfdp_file_directive_header_tree, offset, cfdp_data_len);
+ break;
+
+ case ACK_PDU:
+ offset = dissect_cfdp_ack_pdu(tvb, pinfo, cfdp_file_directive_header_tree, offset);
+ break;
+
+ case METADATA_PDU:
+ offset = dissect_cfdp_metadata_pdu(tvb, pinfo, cfdp_file_directive_header_tree, offset, cfdp_data_len);
+ break;
+
+ case PROMPT_PDU:
+ offset = dissect_cfdp_prompt_pdu(tvb, pinfo, cfdp_file_directive_header_tree, offset);
+ break;
+
+ case KEEP_ALIVE_PDU:
+ offset = dissect_cfdp_keep_alive_pdu(tvb, cfdp_file_directive_header_tree, offset);
+ break;
+
+ default:
+ break;
+ }
+
+ }else{
+ proto_tree *cfdp_file_data_header_tree;
+
+ col_add_fstr(pinfo->cinfo, COL_INFO, "File Data PDU");
+
+ cfdp_file_data_header_tree = proto_tree_add_subtree(cfdp_tree, tvb, offset, cfdp_data_len,
+ ett_cfdp_file_data_header, NULL, "CFDP File Data");
+
+ proto_tree_add_item(cfdp_file_data_header_tree, hf_cfdp_file_data_offset, tvb, offset, 4, ENC_BIG_ENDIAN);
+
+ offset += 4;
+
+ proto_tree_add_item(cfdp_file_data_header_tree, hf_cfdp_user_data, tvb, offset, cfdp_data_len-4, ENC_NA);
+ offset += cfdp_data_len-4;
+
+ }
+ if(first_byte & HDR_CRCF){
+ proto_item *cfdp_crc;
+ proto_tree *cfdp_crc_tree;
+
+ cfdp_crc_tree = proto_tree_add_subtree(cfdp_tree, tvb, offset, 2, ett_cfdp_crc, &cfdp_crc, "CRC");
+
+ proto_tree_add_item(cfdp_crc_tree, hf_cfdp_crc, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_item_set_end(cfdp_crc, tvb, offset);
+ }
+
+ if ( cfdp_data_end>(guint)offset ) {
+ proto_tree_add_string(cfdp_header_tree, hf_cfdp_file_data_pdu, tvb, offset, cfdp_data_len,
+ wmem_strdup_printf(wmem_packet_scope(), "<%d bytes>", cfdp_data_len));
+ offset = cfdp_data_end;
+ }
+ return;
+}
+
+void
proto_register_cfdp(void)
{
static hf_register_info hf[] = {
+ { &hf_cfdp_flags,
+ { "Flags", "cfdp.flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_byte2,
+ { "Byte2", "cfdp.byte2",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_proxy_fault_hdl_overr,
+ { "Proxy Fault HDL Overr", "cfdp.proxy_fault_hdl_overr",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_proxy_trans_mode,
+ { "Proxy Transmission Mode", "cfdp.proxy_trans_mode",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_proxy_segment_control_byte,
+ { "Proxy Segment Control", "cfdp.proxy_segment_control",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_proxy_put_resp,
+ { "Proxy Put Response", "cfdp.proxy_put_response",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_orig_trans_id,
+ { "Originating Transaction ID", "cfdp.orig_trans_id",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_remote_stat_rep_req,
+ { "Remote Status Report Request", "cfdp.remote_status_rep_req",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_remote_stat_rep_resp,
+ { "Remote Status Report Response", "cfdp.remote_status_rep_resp",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_finish_pdu_flags,
+ { "Finish PDU flags", "cfdp.finish_pdu_flags",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_remote_suspend_resume_req,
+ { "Remote Suspend/Resume Request", "cfdp.remote_suspend_resume_req",
+ FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_cfdp_remote_suspend_resume_resp,
+ { "Remote Suspend/Resume Response", "cfdp.remote_suspend_resume_resp",
+ FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }
+ },
{ &hf_cfdp_version,
{ "Version", "cfdp.version",
FT_UINT8, BASE_DEC, NULL, HDR_VERSION_CFDP,
@@ -1300,6 +1639,10 @@ proto_register_cfdp(void)
FT_UINT16, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
+ {&hf_cfdp_file_data_pdu,
+ {"CFDP File PDU Data", "cfdp.file_data_pdu",
+ FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
{ &hf_cfdp_res2,
{ "Bit reserved 2", "cfdp.res2",
FT_UINT8, BASE_DEC, NULL, 0x80,
@@ -1386,8 +1729,8 @@ proto_register_cfdp(void)
NULL, HFILL }
},
{ &hf_cfdp_spare_five,
- { "Spare", "cfdp.spare_five",
- FT_UINT8, BASE_DEC, NULL, 0x3E,
+ { "Spare", "cfdp.spare_five_b",
+ FT_UINT16, BASE_DEC, NULL, 0x3E00,
NULL, HFILL }
},
{ &hf_cfdp_spare_seven,
@@ -1406,13 +1749,13 @@ proto_register_cfdp(void)
NULL, HFILL }
},
{ &hf_cfdp_trans_stat,
- { "Transaction status", "cfdp.trans_stat",
- FT_UINT8, BASE_DEC, VALS(cfdp_trans_stat_ack), 0xC0,
+ { "Transaction status B", "cfdp.trans_stat_b",
+ FT_UINT16, BASE_DEC, VALS(cfdp_trans_stat_ack), 0xC000,
NULL, HFILL }
},
{ &hf_cfdp_trans_stat_2,
- { "Transaction status", "cfdp.trans_stat_2",
- FT_UINT8, BASE_DEC, VALS(cfdp_trans_stat_ack), 0x60,
+ { "Transaction status", "cfdp.trans_stat_2_b",
+ FT_UINT8, BASE_DEC, VALS(cfdp_trans_stat_ack), 0x6000,
NULL, HFILL }
},
{ &hf_cfdp_file_checksum,
@@ -1519,11 +1862,6 @@ proto_register_cfdp(void)
FT_UINT8, BASE_DEC, VALS(cfdp_handler_codes), 0x0F,
NULL, HFILL }
},
- { &hf_cfdp_trans_mode_msg,
- { "Trans. Mode", "cfdp.trans_mode_msg",
- FT_UINT8, BASE_DEC, VALS(cfdp_trans_mode), 0x01,
- NULL, HFILL }
- },
{ &hf_cfdp_proxy_msg_type,
{ "Proxy Message Type", "cfdp.proxy_msg_type",
FT_UINT8, BASE_DEC | BASE_EXT_STRING, &cfdp_proxy_msg_type_ext, 0x0,
@@ -1562,13 +1900,13 @@ proto_register_cfdp(void)
NULL, HFILL}
},
{ &hf_cfdp_rep_resp_code,
- {"Report Response Code", "cfdp.rep_resp_code",
- FT_UINT8, BASE_DEC, VALS(cfdp_rep_resp_code), 0x01,
+ {"Report Response Code", "cfdp.rep_resp_code_b",
+ FT_UINT16, BASE_DEC, VALS(cfdp_rep_resp_code), 0x0100,
NULL, HFILL}
},
{ &hf_cfdp_suspension_ind,
- {"Suspension indicator", "cfdp.suspension_ind",
- FT_UINT8, BASE_DEC, VALS(cfdp_suspension_ind), 0x80,
+ {"Suspension indicator", "cfdp.suspension_ind_b",
+ FT_UINT8, BASE_DEC, VALS(cfdp_suspension_ind), 0x8000,
NULL, HFILL}
},
@@ -1585,6 +1923,18 @@ proto_register_cfdp(void)
/* Setup protocol subtree array */
static gint *ett[] = {
&ett_cfdp,
+ &ett_cfdp_flags,
+ &ett_cfdp_byte2,
+ &ett_cfdp_proxy_fault_hdl_overr,
+ &ett_cfdp_proxy_trans_mode,
+ &ett_cfdp_proxy_segment_control_byte,
+ &ett_cfdp_proxy_put_resp,
+ &ett_cfdp_orig_trans_id,
+ &ett_cfdp_remote_suspend_resume_req,
+ &ett_cfdp_remote_suspend_resume_resp,
+ &ett_cfdp_remote_stat_rep_req,
+ &ett_cfdp_remote_stat_rep_resp,
+ &ett_cfdp_finish_pdu_flags,
&ett_cfdp_header,
&ett_cfdp_file_directive_header,
&ett_cfdp_file_data_header,
@@ -1594,7 +1944,8 @@ proto_register_cfdp(void)
&ett_cfdp_filestore_resp,
&ett_cfdp_msg_to_user,
&ett_cfdp_fault_hdl_overr,
- &ett_cfdp_flow_label
+ &ett_cfdp_flow_label,
+ &ett_cfdp_proto
};
static ei_register_info ei[] = {
diff --git a/epan/dissectors/packet-dtn.c b/epan/dissectors/packet-dtn.c
index e041c763fd..1b01c770b9 100644
--- a/epan/dissectors/packet-dtn.c
+++ b/epan/dissectors/packet-dtn.c
@@ -47,6 +47,15 @@
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_cfdp_as_subtree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+
+extern void
+dissect_amp_as_subtree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset);
+
+int add_sdnv_time_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, int hf_sdnv_time);
+
+
/* For Reassembling TCP Convergence Layer segments */
static reassembly_table msg_reassembly_table;
@@ -59,6 +68,9 @@ static int hf_bundle_pdu_version = -1;
/* TCP Convergence Header Variables */
static int hf_tcp_convergence_pkt_type = -1;
+/* Refuse-Bundle reason code */
+static int hf_dtn_refuse_bundle_reason_code = -1;
+
static int hf_contact_hdr_version = -1;
static int hf_contact_hdr_flags = -1;
static int hf_contact_hdr_keep_alive = -1;
@@ -332,6 +344,16 @@ static const value_string packet_type_vals[] = {
{((TCP_CONVERGENCE_REFUSE_BUNDLE>>4) & 0x0F), "Refuse Bundle"},
{((TCP_CONVERGENCE_KEEP_ALIVE>>4) & 0x0F), "Keep Alive"},
{((TCP_CONVERGENCE_SHUTDOWN>>4) & 0x0F), "Shutdown"},
+ {((TCP_CONVERGENCE_LENGTH>>4) & 0x0F), "Length"},
+ {0, NULL}
+};
+
+/* Refuse-Bundle Reason-Code Flags as per RFC-7242: Section-5.4 */
+static const value_string refuse_bundle_reason_code[] = {
+ {((TCP_REFUSE_BUNDLE_REASON_UNKNOWN>>4) & 0x0F), "Reason for refusal is unknown"},
+ {((TCP_REFUSE_BUNDLE_REASON_RX_COMPLETE>>4) & 0x0F), "Complete Bundle Received"},
+ {((TCP_REFUSE_BUNDLE_REASON_RX_EXHAUSTED>>4) & 0x0F), "Receiver's resources exhausted"},
+ {((TCP_REFUSE_BUNDLE_REASON_RX_RETRANSMIT>>4) & 0x0F), "Receiver expects re-transmission of bundle"},
{0, NULL}
};
@@ -480,7 +502,7 @@ add_dtn_time_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, int hf_dtn_tim
* Adds the result of SDNV which is a time since 2000 to tree.
* Returns bytes in SDNV or 0 if something goes wrong.
*/
-static int
+int
add_sdnv_time_to_tree(proto_tree *tree, tvbuff_t *tvb, int offset, int hf_sdnv_time)
{
nstime_t dtn_time;
@@ -883,6 +905,9 @@ dissect_version_4_primary_header(packet_info *pinfo, proto_tree *primary_tree, t
* 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,
@@ -993,6 +1018,7 @@ dissect_version_5_and_6_primary_header(packet_info *pinfo,
/* -- 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);
@@ -1010,6 +1036,7 @@ dissect_version_5_and_6_primary_header(packet_info *pinfo,
/* -- 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);
@@ -1230,7 +1257,26 @@ dissect_payload_header(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int
return offset;
}
} else {
- proto_tree_add_item(payload_block_tree, hf_bundle_payload_data, tvb, offset, payload_length, ENC_ASCII);
+ /* 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(wmem_packet_scope(), "<%d bytes>",payload_length));
+ }
+
offset += payload_length;
}
@@ -2210,6 +2256,14 @@ get_tcpcl_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data
}
return len;
+
+ case TCP_CONVERGENCE_LENGTH:
+ /* get length from sdnv */
+ len = evaluate_sdnv(tvb, offset+1, &bytecount);
+ if (len < 0)
+ return 0;
+ return bytecount+1;
+
}
/* This probably isn't a TCPCL/Bundle packet, so just stop dissection */
@@ -2220,6 +2274,7 @@ static int
dissect_tcpcl_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{
guint8 conv_hdr;
+ guint8 refuse_bundle_hdr;
int offset = 0;
int sdnv_length, segment_length, convergence_hdr_size;
proto_item *ci, *sub_item;
@@ -2409,6 +2464,11 @@ dissect_tcpcl_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dat
} else {
col_set_str(pinfo->cinfo, COL_INFO, "TCPL REFUSE_BUNDLE Segment");
}
+
+ refuse_bundle_hdr = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(conv_tree, hf_dtn_refuse_bundle_reason_code, tvb, offset, 1, ENC_BIG_ENDIAN);
+ col_add_str(pinfo->cinfo, COL_INFO, val_to_str_const((refuse_bundle_hdr>>4)&0xF, refuse_bundle_reason_code, "Unknown"));
+
/*No valid flags*/
processed_length = tvb_captured_length(tvb);
break;
@@ -3140,6 +3200,10 @@ proto_register_bundle(void)
{"Pkt Type", "tcpcl.pkt_type",
FT_UINT8, BASE_DEC, VALS(packet_type_vals), 0xF0, NULL, HFILL}
},
+ {&hf_dtn_refuse_bundle_reason_code,
+ {"Reason-Code", "tcpcl.refuse.reason_code",
+ FT_UINT8, BASE_DEC, VALS(refuse_bundle_reason_code), 0xF0, NULL, HFILL}
+ },
{&hf_tcp_convergence_data_procflags,
{"TCP Convergence Data Flags", "tcpcl.data.proc.flag",
FT_UINT8, BASE_HEX, NULL, TCP_CONVERGENCE_DATA_FLAGS, NULL, HFILL}
diff --git a/epan/dissectors/packet-dtn.h b/epan/dissectors/packet-dtn.h
index 59539dc88c..e2be07af27 100644
--- a/epan/dissectors/packet-dtn.h
+++ b/epan/dissectors/packet-dtn.h
@@ -29,6 +29,7 @@
#define TCP_CONVERGENCE_REFUSE_BUNDLE 0x30
#define TCP_CONVERGENCE_KEEP_ALIVE 0x40
#define TCP_CONVERGENCE_SHUTDOWN 0x50
+#define TCP_CONVERGENCE_LENGTH 0x60
/* TCP Convergence Layer - Contact Header Flags */
#define TCP_CONV_BUNDLE_ACK_FLAG 0x01
@@ -45,6 +46,14 @@
#define TCP_CONVERGENCE_SHUTDOWN_REASON 0x02
#define TCP_CONVERGENCE_SHUTDOWN_DELAY 0x01
+/* REFUSE-BUNDLE Reason-Codes */
+#define TCP_REFUSE_BUNDLE_REASON_UNKNOWN 0x00
+#define TCP_REFUSE_BUNDLE_REASON_RX_COMPLETE 0x01
+#define TCP_REFUSE_BUNDLE_REASON_RX_EXHAUSTED 0x02
+#define TCP_REFUSE_BUNDLE_REASON_RX_RETRANSMIT 0x03
+/* 0x4-0x7 - Unassigned
+ * 0x8-0xf - Reserved for future Use */
+
/*
* TCP Convergence Layer - Minimum buffer sizes
* For Data Packet require 5 bytes fixed plus