aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/dissectors/packet-ccsds.c543
-rw-r--r--epan/dissectors/packet-ehs.c1924
-rw-r--r--epan/dissectors/packet-vcdu.c648
3 files changed, 3019 insertions, 96 deletions
diff --git a/epan/dissectors/packet-ccsds.c b/epan/dissectors/packet-ccsds.c
index 428ada6f15..8176193719 100644
--- a/epan/dissectors/packet-ccsds.c
+++ b/epan/dissectors/packet-ccsds.c
@@ -1,6 +1,7 @@
/* packet-ccsds.c
* Routines for CCSDS dissection
* Copyright 2000, Scott Hovis scott.hovis@ums.msfc.nasa.gov
+ * Enhanced 2008, Matt Dunkle Matthew.L.Dunkle@nasa.gov
*
* $Id$
*
@@ -32,19 +33,20 @@
#include <string.h>
#include <glib.h>
-
#include <epan/packet.h>
+
/*
* See
*
- * http://public.ccsds.org/publications/archive/133x0b1.pdf section 4.1
- *
- * for some information.
+ * http://stationpayloads.jsc.nasa.gov/J-reference/documents/ssp57002B.pdf
*/
+
/* Initialize the protocol and registered fields */
static int proto_ccsds = -1;
+
+/* primary ccsds header */
static int hf_ccsds_apid = -1;
static int hf_ccsds_version = -1;
static int hf_ccsds_secheader = -1;
@@ -52,18 +54,34 @@ static int hf_ccsds_type = -1;
static int hf_ccsds_seqnum = -1;
static int hf_ccsds_seqflag = -1;
static int hf_ccsds_length = -1;
-static int hf_ccsds_time = -1;
+
+/* common ccsds secondary header */
+static int hf_ccsds_coarse_time = -1;
+static int hf_ccsds_fine_time = -1;
static int hf_ccsds_timeid = -1;
static int hf_ccsds_checkword = -1;
+
+/* payload specific ccsds secondary header */
static int hf_ccsds_zoe = -1;
-static int hf_ccsds_packtype = -1;
+static int hf_ccsds_packet_type_unused = -1;
static int hf_ccsds_vid = -1;
static int hf_ccsds_dcc = -1;
+/* core specific ccsds secondary header */
+static int hf_ccsds_spare1 = -1;
+static int hf_ccsds_packet_type = -1;
+static int hf_ccsds_spare2 = -1;
+static int hf_ccsds_element_id = -1;
+static int hf_ccsds_cmd_data_packet = -1;
+static int hf_ccsds_format_version_id = -1;
+static int hf_ccsds_extended_format_id = -1;
+static int hf_ccsds_spare3 = -1;
+static int hf_ccsds_frame_id = -1;
+
/* Initialize the subtree pointers */
static gint ett_ccsds = -1;
-static gint ett_header = -1;
-static gint ett_header2 = -1;
+static gint ett_ccsds_primary_header = -1;
+static gint ett_ccsds_secondary_header = -1;
/*
* Bits in the first 16-bit header word
@@ -73,185 +91,518 @@ static gint ett_header2 = -1;
#define HDR_SECHDR 0x0800
#define HDR_APID 0x07ff
+/* some basic sizing parameters */
+enum
+{
+ IP_HEADER_LENGTH = 48,
+ VCDU_HEADER_LENGTH = 6,
+ CCSDS_PRIMARY_HEADER_LENGTH = 6,
+ CCSDS_SECONDARY_HEADER_LENGTH = 10
+};
+
+/* leap year macro */
+#ifndef Leap
+# define Leap(yr) ( ( 0 == (yr)%4 && 0 != (yr)%100 ) || ( 0 == (yr)%400 ) )
+#endif
+
+
+static const value_string ccsds_primary_header_sequence_flags[] = {
+ { 0, "Continuation segment" },
+ { 1, "First segment" },
+ { 2, "Last segment" },
+ { 3, "Unsegmented data" },
+ { 0, NULL }
+};
+
+static const value_string ccsds_secondary_header_type[] = {
+ { 0, "Core" },
+ { 1, "Payload" },
+ { 0, NULL }
+};
+
+static const value_string ccsds_secondary_header_packet_type[] = {
+ { 0, "UNDEFINED" },
+ { 1, "Data Dump" },
+ { 2, "UNDEFINED" },
+ { 3, "UNDEFINED" },
+ { 4, "TLM/Status" },
+ { 5, "UNDEFINED" },
+ { 6, "Payload Private/Science" },
+ { 7, "Ancillary Data" },
+ { 8, "Essential Cmd" },
+ { 9, "System Cmd" },
+ { 10, "Payload Cmd" },
+ { 11, "Data Load/File Transfer" },
+ { 12, "UNDEFINED" },
+ { 13, "UNDEFINED" },
+ { 14, "UNDEFINED" },
+ { 15, "UNDEFINED" },
+ { 0, NULL }
+};
+
+static const value_string ccsds_secondary_header_element_id[] = {
+ { 0, "NASA (Ground Test Only)" },
+ { 1, "NASA" },
+ { 2, "ESA/APM" },
+ { 3, "NASDA" },
+ { 4, "RSA" },
+ { 5, "CSA" },
+ { 6, "ESA/ATV" },
+ { 7, "ASI" },
+ { 8, "ESA/ERA" },
+ { 9, "Reserved" },
+ { 10, "RSA SPP" },
+ { 11, "NASDA HTV" },
+ { 12, "Reserved" },
+ { 13, "Reserved" },
+ { 14, "Reserved" },
+ { 15, "Reserved" },
+ { 0, NULL }
+};
+
+static const value_string ccsds_secondary_header_cmd_data_packet[] = {
+ { 0, "Command Packet" },
+ { 1, "Data Packet" },
+ { 0, NULL }
+};
+
+static const value_string ccsds_secondary_header_format_id[] = {
+ { 0, "Reserved" },
+ { 1, "Essential Telemetry" },
+ { 2, "Housekeeping Tlm - 1" },
+ { 3, "Housekeeping Tlm - 2" },
+ { 4, "PCS DDT" },
+ { 5, "CCS S-Band Command Response" },
+ { 6, "Contingency Telemetry via the SMCC" },
+ { 7, "Normal Data Dump" },
+ { 8, "Extended Data Dump" },
+ { 9, "Reserved" },
+ { 10, "Reserved" },
+ { 11, "Broadcast Ancillary Data" },
+ { 12, "Reserved" },
+ { 13, "NCS to OIU Telemetry and ECOMM Telemetry" },
+ { 14, "CCS to OIU Telemetry - Direct" },
+ { 15, "Reserved" },
+ { 16, "Normal File Dump" },
+ { 17, "Extended File Dump" },
+ { 18, "NCS to FGB Telemetry" },
+ { 19, "Reserved" },
+ { 20, "ZOE Normal Dump (S-Band)" },
+ { 21, "ZOE Extended Dump (S-Band)" },
+ { 22, "EMU S-Band TLM Packet" },
+ { 23, "Reserved" },
+ { 24, "Reserved" },
+ { 25, "Reserved" },
+ { 26, "CCS to OIU Telemetry via UHF" },
+ { 27, "OSTP Telemetry (After Flight 1E, CCS R5)" },
+ { 28, "Reserved" },
+ { 29, "Reserved" },
+ { 30, "Reserved" },
+ { 31, "Reserved" },
+ { 32, "Reserved" },
+ { 33, "Reserved" },
+ { 34, "Reserved" },
+ { 35, "Reserved" },
+ { 36, "Reserved" },
+ { 37, "Reserved" },
+ { 38, "Reserved" },
+ { 39, "Reserved" },
+ { 40, "Reserved" },
+ { 41, "Reserved" },
+ { 42, "Reserved" },
+ { 43, "Reserved" },
+ { 44, "Reserved" },
+ { 45, "Reserved" },
+ { 46, "Reserved" },
+ { 47, "Reserved" },
+ { 48, "Reserved" },
+ { 49, "Reserved" },
+ { 50, "Reserved" },
+ { 51, "Reserved" },
+ { 52, "Reserved" },
+ { 53, "Reserved" },
+ { 54, "Reserved" },
+ { 55, "Reserved" },
+ { 56, "Reserved" },
+ { 57, "Reserved" },
+ { 58, "Reserved" },
+ { 59, "Reserved" },
+ { 60, "Reserved" },
+ { 61, "Reserved" },
+ { 62, "Reserved" },
+ { 63, "Reserved" },
+ { 0, NULL }
+};
+
+
+
+
+/* convert time from utc to julian values */
+void utc_to_julian ( int utc, int* year, int* julianday, int* hour, int* minute, int* second )
+{
+ static int Days[2][13] =
+ {
+ { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+ };
+
+ int j, days_yr[2], left, secs;
+
+ /* oops... */
+ if ( ! year || ! julianday || ! hour || ! minute || ! second ) return;
+
+ *year = 1970;
+ *julianday = 0;
+ *hour = 0;
+ *minute = 0;
+ *second = 0;
+
+ days_yr[0] = days_yr[1] = 0;
+
+ for ( j=1; j < 13; ++j )
+ {
+ days_yr[0] += Days[0][j];
+ days_yr[1] += Days[1][j];
+ }
+
+ left = utc;
+ secs = days_yr[Leap(*year)] * 24 * 60 * 60;
+
+ while (left > secs)
+ {
+ ++(*year);
+ left -= secs;
+ secs = days_yr[Leap(*year)] * 24 * 60 * 60;
+ }
+
+ *julianday = (left / (24 * 60 * 60)) + 1;
+ left = left % (24 * 60 * 60);
+
+ *hour = left / (60 * 60);
+ left = left % (60 * 60);
+
+ *minute = left / 60;
+
+ *second = left % 60;
+
+}
+
+
+
+/* convert ccsds embedded time to a human readable string - NOT THREAD SAFE */
+static const char* embedded_time_to_string ( int coarse_time, int fine_time )
+{
+ static const char* fmt = "%04d/%03d:%02d:%02d:%02d.%03d";
+ static char juliantime[40];
+ static int utcdiff = 0;
+
+ int utc, yr, year, julianday, hour, minute, second, fraction;
+ int multiplier = 1000;
+
+ /* compute the static constant difference in seconds
+ * between midnight 5-6 January 1980 (GPS time) and
+ * seconds since 1/1/1970 (UTC time) just this once
+ */
+ if ( 0 == utcdiff )
+ {
+ for ( yr=1970; yr < 1980; ++yr )
+ {
+ utcdiff += ( Leap(yr) ? 366 : 365 ) * 24 * 60 * 60;
+ }
+
+ utcdiff += 5 * 24 * 60 * 60; /* five days of January 1980 */
+ }
+
+ utc = coarse_time + utcdiff;
+ utc_to_julian ( utc, &year, &julianday, &hour, &minute, &second );
+
+ fraction = ( multiplier * ( (int)fine_time & 0xff ) ) / 256;
+
+ g_snprintf ( juliantime, sizeof(juliantime), fmt, year, julianday, hour, minute, second, fraction );
+
+ return juliantime;
+
+}
+
+
/* Code to actually dissect the packets */
static void
dissect_ccsds(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
int offset = 0;
- proto_item *ti;
+ proto_item *ccsds_packet;
proto_tree *ccsds_tree;
- proto_item *header;
- proto_tree *header_tree;
+ proto_item *primary_header;
+ proto_tree *primary_header_tree;
guint16 first_word;
- proto_item *header2;
- proto_tree *header2_tree;
-
+ guint32 coarse_time;
+ guint8 fine_time;
+ proto_item *secondary_header;
+ proto_tree *secondary_header_tree;
+ const char* time_string;
+
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "CCSDS");
if (check_col(pinfo->cinfo, COL_INFO))
col_set_str(pinfo->cinfo, COL_INFO, "CCSDS Packet");
if (tree) {
- ti = proto_tree_add_item(tree, proto_ccsds, tvb, 0, -1, FALSE);
- ccsds_tree = proto_item_add_subtree(ti, ett_ccsds);
+ ccsds_packet = proto_tree_add_item(tree, proto_ccsds, tvb, 0, -1, FALSE);
+ ccsds_tree = proto_item_add_subtree(ccsds_packet, ett_ccsds);
+
+ /* build the ccsds primary header tree */
+ primary_header=proto_tree_add_text(ccsds_tree, tvb, offset, CCSDS_PRIMARY_HEADER_LENGTH, "Primary CCSDS Header");
+ primary_header_tree=proto_item_add_subtree(primary_header, ett_ccsds_primary_header);
- header=proto_tree_add_text(ccsds_tree, tvb, 0, -1,
- "Primary CCSDS Header");
- header_tree=proto_item_add_subtree(header, ett_header);
-
first_word=tvb_get_ntohs(tvb, offset);
- proto_tree_add_uint(header_tree, hf_ccsds_version, tvb, offset, 2, first_word);
- proto_tree_add_uint(header_tree, hf_ccsds_type, tvb, offset, 2, first_word);
- proto_tree_add_boolean(header_tree, hf_ccsds_secheader, tvb, offset, 2, first_word);
- proto_tree_add_uint(header_tree, hf_ccsds_apid, tvb, offset, 2, first_word);
+ proto_tree_add_uint(primary_header_tree, hf_ccsds_version, tvb, offset, 2, first_word);
+ proto_tree_add_uint(primary_header_tree, hf_ccsds_type, tvb, offset, 2, first_word);
+ proto_tree_add_boolean(primary_header_tree, hf_ccsds_secheader, tvb, offset, 2, first_word);
+ proto_tree_add_uint(primary_header_tree, hf_ccsds_apid, tvb, offset, 2, first_word);
offset += 2;
- proto_tree_add_item(header_tree, hf_ccsds_seqflag, tvb, offset, 2, FALSE);
- proto_tree_add_item(header_tree, hf_ccsds_seqnum, tvb, offset, 2, FALSE);
+ proto_tree_add_item(primary_header_tree, hf_ccsds_seqflag, tvb, offset, 2, FALSE);
+ proto_tree_add_item(primary_header_tree, hf_ccsds_seqnum, tvb, offset, 2, FALSE);
offset += 2;
- proto_tree_add_item(header_tree, hf_ccsds_length, tvb, offset, 2, FALSE);
+ proto_tree_add_item(primary_header_tree, hf_ccsds_length, tvb, offset, 2, FALSE);
offset += 2;
- proto_item_set_end(header, tvb, offset);
+ proto_item_set_end(primary_header, tvb, offset);
- if(first_word&HDR_SECHDR)
+ /* build the ccsds secondary header tree */
+ if ( first_word & HDR_SECHDR )
{
- header2=proto_tree_add_text(ccsds_tree, tvb, offset, -1,
- "Secondary CCSDS Header");
- header2_tree=proto_item_add_subtree(header2, ett_header2);
+ secondary_header=proto_tree_add_text(ccsds_tree, tvb, offset, CCSDS_SECONDARY_HEADER_LENGTH, "Secondary CCSDS Header");
+ secondary_header_tree=proto_item_add_subtree(secondary_header, ett_ccsds_secondary_header);
- proto_tree_add_item(header2_tree, hf_ccsds_time, tvb, offset, 5, FALSE);
- offset += 5;
+ /* command ccsds secondary header flags */
+ coarse_time=tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(secondary_header_tree, hf_ccsds_coarse_time, tvb, offset, 4, FALSE);
+ offset += 4;
- proto_tree_add_item(header2_tree, hf_ccsds_timeid, tvb, offset, 1, FALSE);
- proto_tree_add_item(header2_tree, hf_ccsds_checkword, tvb, offset, 1, FALSE);
- proto_tree_add_item(header2_tree, hf_ccsds_zoe, tvb, offset, 1, FALSE);
- proto_tree_add_item(header2_tree, hf_ccsds_packtype, tvb, offset, 1, FALSE);
- offset += 1;
+ fine_time=tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(secondary_header_tree, hf_ccsds_fine_time, tvb, offset, 1, FALSE);
+ ++offset;
- proto_tree_add_item(header2_tree, hf_ccsds_vid, tvb, offset, 2, FALSE);
- offset += 2;
+ time_string = embedded_time_to_string ( coarse_time, fine_time );
+ proto_tree_add_text(secondary_header_tree, tvb, offset-5, 5, "%s = Embedded Time", time_string);
- proto_tree_add_item(header2_tree, hf_ccsds_dcc, tvb, offset, 2, FALSE);
- offset += 2;
- proto_item_set_end(header2, tvb, offset);
+ proto_tree_add_item(secondary_header_tree, hf_ccsds_timeid, tvb, offset, 1, FALSE);
+ proto_tree_add_item(secondary_header_tree, hf_ccsds_checkword, tvb, offset, 1, FALSE);
+
+ /* payload specific ccsds secondary header flags */
+ if ( first_word & HDR_TYPE )
+ {
+ proto_tree_add_item(secondary_header_tree, hf_ccsds_zoe, tvb, offset, 1, FALSE);
+ proto_tree_add_item(secondary_header_tree, hf_ccsds_packet_type_unused, tvb, offset, 1, FALSE);
+ ++offset;
+
+ proto_tree_add_item(secondary_header_tree, hf_ccsds_vid, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ proto_tree_add_item(secondary_header_tree, hf_ccsds_dcc, tvb, offset, 2, FALSE);
+ offset += 2;
+ }
+
+ /* core specific ccsds secondary header flags */
+ else
+ {
+ /* proto_tree_add_item(secondary_header_tree, hf_ccsds_spare1, tvb, offset, 1, FALSE); */
+ proto_tree_add_item(secondary_header_tree, hf_ccsds_packet_type, tvb, offset, 1, FALSE);
+ ++offset;
+
+ /* proto_tree_add_item(secondary_header_tree, hf_ccsds_spare2, tvb, offset, 2, FALSE); */
+ proto_tree_add_item(secondary_header_tree, hf_ccsds_element_id, tvb, offset, 2, FALSE);
+ proto_tree_add_item(secondary_header_tree, hf_ccsds_cmd_data_packet, tvb, offset, 2, FALSE);
+ proto_tree_add_item(secondary_header_tree, hf_ccsds_format_version_id, tvb, offset, 2, FALSE);
+ proto_tree_add_item(secondary_header_tree, hf_ccsds_extended_format_id, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ /* proto_tree_add_item(secondary_header_tree, hf_ccsds_spare3, tvb, offset, 1, FALSE); */
+ ++offset;
+
+ proto_tree_add_item(secondary_header_tree, hf_ccsds_frame_id, tvb, offset, 1, FALSE);
+ ++offset;
+ }
+
+ /* finish the ccsds secondary header */
+ proto_item_set_end(secondary_header, tvb, offset);
}
- proto_tree_add_text(ccsds_tree, tvb, offset, -1,
- "Data");
+ /* everything that's left is the remainder of the packet data zone */
+ proto_tree_add_text(ccsds_tree, tvb, offset, -1, "Data");
}
}
-/* Register the protocol with Wireshark */
-/* this format is require because a script is used to build the C function
- that calls all the protocol registration.
-*/
+/* Register the protocol with Wireshark
+ * this format is require because a script is used to build the C function
+ * that calls all the protocol registration.
+ */
void
proto_register_ccsds(void)
{
-
+ /* Setup list of header fields See Section 1.6.1 for details*/
static hf_register_info hf[] = {
+
+ /* primary ccsds header flags */
{ &hf_ccsds_version,
- { "version", "ccsds.version",
+ { "Version", "ccsds.version",
FT_UINT16, BASE_DEC, NULL, HDR_VERSION,
- "version", HFILL }
+ NULL, HFILL }
},
{ &hf_ccsds_type,
- { "type", "ccsds.type",
- FT_UINT16, BASE_DEC, NULL, HDR_TYPE,
- "type", HFILL }
+ { "Type", "ccsds.type",
+ FT_UINT16, BASE_DEC, VALS(ccsds_secondary_header_type), HDR_TYPE,
+ NULL, HFILL }
},
{ &hf_ccsds_secheader,
- { "secondary header", "ccsds.secheader",
+ { "Secondary Header", "ccsds.secheader",
FT_BOOLEAN, 16, NULL, HDR_SECHDR,
- "secondary header present", HFILL }
+ "Secondary Header Present", HFILL }
},
{ &hf_ccsds_apid,
{ "APID", "ccsds.apid",
FT_UINT16, BASE_DEC, NULL, HDR_APID,
- "Represents APID", HFILL }
+ NULL, HFILL }
},
{ &hf_ccsds_seqflag,
- { "sequence flags", "ccsds.seqflag",
- FT_UINT16, BASE_DEC, NULL, 0xc000,
- "sequence flags", HFILL }
+ { "Sequence Flags", "ccsds.seqflag",
+ FT_UINT16, BASE_DEC, VALS(ccsds_primary_header_sequence_flags), 0xc000,
+ NULL, HFILL }
},
{ &hf_ccsds_seqnum,
- { "sequence number", "ccsds.seqnum",
+ { "Sequence Number", "ccsds.seqnum",
FT_UINT16, BASE_DEC, NULL, 0x3fff,
- "sequence number", HFILL }
+ NULL, HFILL }
},
{ &hf_ccsds_length,
- { "packet length", "ccsds.length",
+ { "Packet Length", "ccsds.length",
FT_UINT16, BASE_DEC, NULL, 0xffff,
- "packet length", HFILL }
+ NULL, HFILL }
+ },
+
+
+ /* common ccsds secondary header flags */
+ { &hf_ccsds_coarse_time,
+ { "Coarse Time", "ccsds.coarse_time",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }
},
- { &hf_ccsds_time,
- { "time", "ccsds.time",
- FT_BYTES, BASE_HEX, NULL, 0x0,
- "time", HFILL }
+ { &hf_ccsds_fine_time,
+ { "Fine Time", "ccsds.fine_time",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
},
{ &hf_ccsds_timeid,
- { "time identifier", "ccsds.timeid",
- FT_UINT8, BASE_DEC, NULL, 0xC0,
- "time identifier", HFILL }
+ { "Time Identifier", "ccsds.timeid",
+ FT_UINT8, BASE_DEC, NULL, 0xc0,
+ NULL, HFILL }
},
{ &hf_ccsds_checkword,
- { "checkword indicator", "ccsds.checkword",
+ { "Checkword Indicator", "ccsds.checkword",
FT_UINT8, BASE_DEC, NULL, 0x20,
- "checkword indicator", HFILL }
+ NULL, HFILL }
},
+
+
+ /* payload specific ccsds secondary header flags */
{ &hf_ccsds_zoe,
{ "ZOE TLM", "ccsds.zoe",
FT_UINT8, BASE_DEC, NULL, 0x10,
- "CONTAINS S-BAND ZOE PACKETS", HFILL }
+ "Contains S-band ZOE Packets", HFILL }
},
- { &hf_ccsds_packtype,
- { "packet type", "ccsds.packtype",
+ { &hf_ccsds_packet_type_unused,
+ { "Packet Type (unused for Ku-band)", "ccsds.packet_type",
FT_UINT8, BASE_DEC, NULL, 0x0f,
- "Packet Type - Unused in Ku-Band", HFILL }
+ NULL, HFILL }
},
{ &hf_ccsds_vid,
- { "version identifier", "ccsds.vid",
+ { "Version Identifier", "ccsds.vid",
FT_UINT16, BASE_DEC, NULL, 0x0,
- "version identifier", HFILL }
+ NULL, HFILL }
},
{ &hf_ccsds_dcc,
{ "Data Cycle Counter", "ccsds.dcc",
FT_UINT16, BASE_DEC, NULL, 0x0,
- "Data Cycle Counter", HFILL }
+ NULL, HFILL }
+ },
+
+
+ /* core specific ccsds secondary header flags */
+ { &hf_ccsds_spare1,
+ { "Spare Bit 1", "ccsds.spare1",
+ FT_UINT8, BASE_DEC, NULL, 0x10,
+ "unused spare bit 1", HFILL }
+ },
+ { &hf_ccsds_packet_type,
+ { "Packet Type", "ccsds.packet_type",
+ FT_UINT8, BASE_DEC, VALS(ccsds_secondary_header_packet_type), 0x0f,
+ NULL, HFILL }
+ },
+ { &hf_ccsds_spare2,
+ { "Spare Bit 2", "ccsds.spare2",
+ FT_UINT16, BASE_DEC, NULL, 0x8000,
+ NULL, HFILL }
},
+ { &hf_ccsds_element_id,
+ { "Element ID", "ccsds.element_id",
+ FT_UINT16, BASE_DEC, VALS(ccsds_secondary_header_element_id), 0x7800,
+ NULL, HFILL }
+ },
+ { &hf_ccsds_cmd_data_packet,
+ { "Cmd/Data Packet Indicator", "ccsds.cmd_data_packet",
+ FT_UINT16, BASE_DEC, VALS(ccsds_secondary_header_cmd_data_packet), 0x0400,
+ NULL, HFILL }
+ },
+ { &hf_ccsds_format_version_id,
+ { "Format Version ID", "ccsds.format_version_id",
+ FT_UINT16, BASE_DEC, NULL, 0x03c0,
+ NULL, HFILL }
+ },
+ { &hf_ccsds_extended_format_id,
+ { "Extended Format ID", "ccsds.extended_format_id",
+ FT_UINT16, BASE_DEC, VALS(ccsds_secondary_header_format_id), 0x003f,
+ NULL, HFILL }
+ },
+ { &hf_ccsds_spare3,
+ { "Spare Bits 3", "ccsds.spare3",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+ { &hf_ccsds_frame_id,
+ { "Frame ID", "ccsds.frame_id",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
};
-/* Setup protocol subtree array */
+ /* Setup protocol subtree array */
static gint *ett[] = {
&ett_ccsds,
- &ett_header,
- &ett_header2,
+ &ett_ccsds_primary_header,
+ &ett_ccsds_secondary_header
};
-/* Register the protocol name and description */
+ /* Register the protocol name and description */
proto_ccsds = proto_register_protocol("CCSDS", "CCSDS", "ccsds");
-/* Required function calls to register the header fields and subtrees used */
+ /* Required function calls to register the header fields and subtrees used */
proto_register_field_array(proto_ccsds, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
- register_dissector("ccsds", dissect_ccsds, proto_ccsds);
}
/* If this dissector uses sub-dissector registration add a registration routine.
- This format is required because a script is used to find these routines and
- create the code that calls these routines.
-*/
+ * This format is required because a script is used to find these routines and
+ * create the code that calls these routines.
+ */
void
proto_reg_handoff_ccsds(void)
{
- dissector_handle_t ccsds_handle;
-
- ccsds_handle = create_dissector_handle(dissect_ccsds,
- proto_ccsds);
- dissector_add_handle("udp.port", ccsds_handle);
+ register_dissector ( "ccsds", dissect_ccsds, proto_ccsds );
+ dissector_add ( "udp.port", 0, find_dissector("ccsds") );
}
+
diff --git a/epan/dissectors/packet-ehs.c b/epan/dissectors/packet-ehs.c
new file mode 100644
index 0000000000..2719b01d18
--- /dev/null
+++ b/epan/dissectors/packet-ehs.c
@@ -0,0 +1,1924 @@
+/* packet-vcdu.c
+ * Routines for VCDU dissection
+ * Copyright 2000, Scott Hovis scott.hovis@ums.msfc.nasa.gov
+ * Enhanced 2008, Matt Dunkle Matthew.L.Dunkle@nasa.gov
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.com>
+ * 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 should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+
+
+/* Initialize the protocol and registered fields */
+static int proto_ehs = -1;
+
+static int hf_ehs_ph_version = -1;
+static int hf_ehs_ph_project = -1;
+static int hf_ehs_ph_support_mode = -1;
+static int hf_ehs_ph_data_mode = -1;
+static int hf_ehs_ph_mission = -1;
+static int hf_ehs_ph_protocol = -1;
+
+static int hf_ehs_ph_year = -1; /* numeric year as years since 1900 */
+static int hf_ehs_ph_jday = -1; /* julian day of year */
+static int hf_ehs_ph_hour = -1;
+static int hf_ehs_ph_minute = -1;
+static int hf_ehs_ph_second = -1;
+static int hf_ehs_ph_tenths = -1;
+
+static int hf_ehs_ph_new_data_flag = -1; /* indicates the time has changed */
+static int hf_ehs_ph_pad1 = -1;
+static int hf_ehs_ph_hold_flag = -1; /* indicates a hold condition */
+static int hf_ehs_ph_sign_flag = -1; /* indicates pre-mission, i.e. countdown, time */
+
+static int hf_ehs_ph_pad2 = -1;
+static int hf_ehs_ph_pad3 = -1;
+static int hf_ehs_ph_pad4 = -1;
+
+static int hf_ehs_ph_hosc_packet_size = -1;
+
+/* generic ehs secondary header values */
+static int hf_ehs_sh_version = -1;
+static int hf_ehs_sh_data_status_bit_5 = -1;
+static int hf_ehs_sh_data_status_bit_4 = -1;
+static int hf_ehs_sh_data_status_bit_3 = -1;
+static int hf_ehs_sh_data_status_bit_2 = -1;
+static int hf_ehs_sh_data_status_bit_1 = -1;
+static int hf_ehs_sh_data_status_bit_0 = -1;
+
+/* other common remappings of the data status bits specific to certain secondary ehs header values */
+static int hf_ehs_sh_parent_stream_error = -1; /* data status bit 3 */
+static int hf_ehs_sh_vcdu_sequence_error = -1; /* data status bit 2 */
+static int hf_ehs_sh_packet_sequence_error = -1; /* data status bit 1 */
+
+/* common ehs secondary header values */
+static int hf_ehs_sh_vcdu_sequence_number = -1;
+static int hf_ehs_sh_data_stream_id = -1;
+static int hf_ehs_sh_pdss_reserved_1 = -1;
+static int hf_ehs_sh_pdss_reserved_2 = -1;
+static int hf_ehs_sh_pdss_reserved_3 = -1;
+static int hf_ehs_sh_gse_pkt_id = -1;
+static int hf_ehs_sh_payload_vs_core_id = -1;
+static int hf_ehs_sh_apid = -1;
+static int hf_ehs_sh_virtual_channel = -1;
+static int hf_ehs_sh_pdss_reserved_sync = -1;
+
+/* tdm ehs secondary header values */
+static int hf_ehs_sh_tdm_secondary_header_length = -1;
+
+static int hf_ehs_sh_tdm_extra_data_packet = -1;
+static int hf_ehs_sh_tdm_backup_stream_id_number = -1;
+static int hf_ehs_sh_tdm_end_of_data_flag = -1;
+static int hf_ehs_sh_tdm_parent_frame_error = -1;
+static int hf_ehs_sh_tdm_checksum_error = -1;
+static int hf_ehs_sh_tdm_fixed_value_error = -1;
+
+static int hf_ehs_sh_tdm_minor_frame_counter_error = -1;
+static int hf_ehs_sh_tdm_format_id_error = -1;
+static int hf_ehs_sh_tdm_bit_slip_error = -1;
+static int hf_ehs_sh_tdm_sync_error = -1;
+static int hf_ehs_sh_tdm_aoslos_flag = -1;
+static int hf_ehs_sh_tdm_override_errors_flag = -1;
+static int hf_ehs_sh_tdm_data_status = -1;
+
+static int hf_ehs_sh_tdm_idq = -1;
+static int hf_ehs_sh_tdm_cdq = -1;
+static int hf_ehs_sh_tdm_adq = -1;
+static int hf_ehs_sh_tdm_data_dq = -1;
+static int hf_ehs_sh_tdm_unused = -1;
+static int hf_ehs_sh_tdm_format_id = -1;
+
+static int hf_ehs_sh_tdm_major_frame_packet_index = -1;
+static int hf_ehs_sh_tdm_numpkts_per_major_frame = -1;
+static int hf_ehs_sh_tdm_num_minor_frames_per_packet = -1;
+
+static int hf_ehs_sh_tdm_cntmet_present = -1;
+static int hf_ehs_sh_tdm_obt_present = -1;
+static int hf_ehs_sh_tdm_major_frame_status_present = -1;
+static int hf_ehs_sh_tdm_reserved = -1;
+
+static int hf_ehs_sh_tdm_cnt_year = -1; /* numeric year as years since 1900 */
+static int hf_ehs_sh_tdm_cnt_jday = -1; /* julian day of year */
+static int hf_ehs_sh_tdm_cnt_hour = -1;
+static int hf_ehs_sh_tdm_cnt_minute = -1;
+static int hf_ehs_sh_tdm_cnt_second = -1;
+static int hf_ehs_sh_tdm_cnt_tenths = -1;
+
+static int hf_ehs_sh_tdm_obt_year = -1; /* numeric year as years since 1900 */
+static int hf_ehs_sh_tdm_obt_jday = -1; /* julian day of year */
+static int hf_ehs_sh_tdm_obt_hour = -1;
+static int hf_ehs_sh_tdm_obt_minute = -1;
+static int hf_ehs_sh_tdm_obt_second = -1;
+static int hf_ehs_sh_tdm_obt_tenths = -1;
+
+static int hf_ehs_sh_tdm_obt_delta_time_flag = -1;
+static int hf_ehs_sh_tdm_obt_computed_flag = -1;
+static int hf_ehs_sh_tdm_obt_not_retrieved_flag = -1;
+static int hf_ehs_sh_tdm_obt_reserved = -1;
+static int hf_ehs_sh_tdm_obt_source_apid = -1;
+
+static int hf_ehs_sh_tdm_num_major_frame_status_words = -1;
+
+static int hf_ehs_sh_tdm_mjfs_reserved = -1;
+static int hf_ehs_sh_tdm_mjfs_parent_frame_error = -1;
+static int hf_ehs_sh_tdm_mjfs_checksum_error = -1;
+static int hf_ehs_sh_tdm_mjfs_fixed_value_error = -1;
+
+static int hf_ehs_sh_tdm_mnfs_parent_frame_error = -1;
+static int hf_ehs_sh_tdm_mnfs_data_not_available = -1;
+static int hf_ehs_sh_tdm_mnfs_checksum_error = -1;
+static int hf_ehs_sh_tdm_mnfs_fixed_value_error = -1;
+static int hf_ehs_sh_tdm_mnfs_counter_error = -1;
+static int hf_ehs_sh_tdm_mnfs_format_id_error = -1;
+static int hf_ehs_sh_tdm_mnfs_bit_slip_error = -1;
+static int hf_ehs_sh_tdm_mnfs_sync_error = -1;
+
+/* pseudo ehs secondary header values */
+static int hf_ehs_sh_pseudo_unused = -1;
+static int hf_ehs_sh_pseudo_workstation_id = -1;
+static int hf_ehs_sh_pseudo_user_id = -1;
+static int hf_ehs_sh_pseudo_comp_id = -1;
+
+/* data zone values for well known protocol AOS/LOS */
+static int hf_ehs_dz_aoslos_indicator = -1;
+
+/* data zone values for well known protocol UDSM */
+static int hf_ehs_dz_udsm_ccsds_vs_bpdu = -1;
+static int hf_ehs_dz_udsm_unused1 = -1;
+
+static int hf_ehs_dz_udsm_unused2 = -1;
+
+static int hf_ehs_dz_udsm_unused3 = -1;
+static int hf_ehs_dz_udsm_gse_pkt_id = -1;
+static int hf_ehs_dz_udsm_payload_vs_core = -1;
+static int hf_ehs_dz_udsm_apid = -1;
+
+static int hf_ehs_dz_udsm_start_time_year = -1;
+static int hf_ehs_dz_udsm_start_time_jday = -1;
+static int hf_ehs_dz_udsm_start_time_hour = -1;
+static int hf_ehs_dz_udsm_start_time_minute = -1;
+static int hf_ehs_dz_udsm_start_time_second = -1;
+
+static int hf_ehs_dz_udsm_stop_time_year = -1;
+static int hf_ehs_dz_udsm_stop_time_jday = -1;
+static int hf_ehs_dz_udsm_stop_time_hour = -1;
+static int hf_ehs_dz_udsm_stop_time_minute = -1;
+static int hf_ehs_dz_udsm_stop_time_second = -1;
+
+static int hf_ehs_dz_udsm_unused4 = -1;
+
+static int hf_ehs_dz_udsm_num_pkts_xmtd = -1;
+
+static int hf_ehs_dz_udsm_num_vcdu_seqerrs = -1;
+
+static int hf_ehs_dz_udsm_num_pkt_seqerrs = -1;
+
+static int hf_ehs_dz_udsm_num_pktlen_errors = -1;
+
+static int hf_ehs_dz_udsm_event = -1;
+
+static int hf_ehs_dz_udsm_num_pkts_xmtd_rollover = -1;
+
+
+/* handle to ccsds packet dissector */
+static dissector_handle_t ccsds_handle = (dissector_handle_t)-1;
+
+/* Initialize the subtree pointers */
+static gint ett_ehs = -1;
+static gint ett_ehs_primary_header = -1;
+static gint ett_ehs_secondary_header = -1;
+static gint ett_ehs_data_zone = -1;
+
+/* EHS protocol types */
+typedef enum EHS_Protocol_Type
+{
+ EHS_PROTOCOL__ALL_PROTOCOLS,
+ EHS_PROTOCOL__TDM_TELEMETRY,
+ EHS_PROTOCOL__NASCOM_TELEMETRY,
+ EHS_PROTOCOL__PSEUDO_TELEMETRY,
+ EHS_PROTOCOL__TDS_DATA,
+ EHS_PROTOCOL__TEST_DATA,
+ EHS_PROTOCOL__GSE_DATA,
+ EHS_PROTOCOL__CUSTOM_DATA,
+ EHS_PROTOCOL__HDRS_DQ,
+ EHS_PROTOCOL__CSS,
+ EHS_PROTOCOL__AOS_LOS,
+ EHS_PROTOCOL__PDSS_PAYLOAD_CCSDS_PACKET,
+ EHS_PROTOCOL__PDSS_CORE_CCSDS_PACKET,
+ EHS_PROTOCOL__PDSS_PAYLOAD_BPDU,
+ EHS_PROTOCOL__PDSS_UDSM,
+ EHS_PROTOCOL__PDSS_RPSM,
+ NUMBER_PROTOCOLS = 15
+} EHS_Protocol_Type_t;
+
+
+/* some basic sizing parameters */
+enum
+{
+ IP_HEADER_LENGTH = 48,
+ CCSDS_PRIMARY_HEADER_LENGTH = 6,
+ CCSDS_SECONDARY_HEADER_LENGTH = 10,
+ EHS_PRIMARY_HEADER_SIZE = 16,
+ EHS_SECONDARY_HEADER_SIZE = 12
+};
+
+/* determine if a ccsds primary header indicates a secondary exists */
+#define HDR_SECHDR 0x0800
+
+
+static const value_string ehs_primary_header_project[] =
+{
+ { 0, "All" },
+ { 1, "STS" },
+ { 2, "SL" },
+ { 3, "ISS" },
+ { 4, "AXAF" },
+ { 0, NULL }
+};
+
+static const value_string ehs_primary_header_support_mode[] =
+{
+ { 0, "All" },
+ { 1, "Flight" },
+ { 2, "Test" },
+ { 3, "Sim" },
+ { 4, "Validation" },
+ { 5, "Development" },
+ { 6, "Training" },
+ { 7, "Offline" },
+ { 0, NULL }
+};
+
+static const value_string ehs_primary_header_data_mode[] =
+{
+ { 0, "Unused" },
+ { 1, "Realtime" },
+ { 2, "Dump1" },
+ { 3, "Dump2" },
+ { 4, "Dump3" },
+ { 5, "Playback1" },
+ { 6, "Playback2" },
+ { 7, "Playback3" },
+ { 8, "Playback4" },
+ { 9, "Playback5" },
+ { 10, "Playback6" },
+ { 11, "Playback7" },
+ { 12, "Playback8" },
+ { 13, "Playback9" },
+ { 14, "Playback10" },
+ { 15, "Playback11" },
+ { 16, "Mode Independent" },
+ { 0, NULL }
+};
+
+static const value_string ehs_primary_header_protocol[] =
+{
+ { 0, "All" },
+ { 1, "TDM" },
+ { 2, "NASCOM" },
+ { 3, "PSEUDO" },
+ { 4, "Time" },
+ { 5, "Test" },
+ { 6, "GSE" },
+ { 7, "Custom_Data" },
+ { 8, "HDRS_DQ" },
+ { 9, "CSS" },
+ { 10, "AOS_LOS" },
+ { 11, "PDSS_PAYLOAD_CCSDS" },
+ { 12, "PDSS_CORE_CCSDS" },
+ { 13, "PDSS_PAYLOAD_BPDU" },
+ { 14, "PDSS_UDSM" },
+ { 15, "PDSS_RPSM" },
+ { 0, NULL }
+};
+
+static const value_string ehs_secondary_header_data_stream_id[] =
+{
+ { 0, "CCSDS" },
+ { 1, "BPDU" },
+ { 0, NULL }
+};
+
+static const value_string ehs_secondary_header_payload_vs_core_id[] =
+{
+ { 0, "Core" },
+ { 1, "Payload" },
+ { 0, NULL }
+};
+
+static const value_string ehs_secondary_header_tdm_backup_stream_id[] =
+{
+ { 0, "Stream A / KMTS-A" },
+ { 1, "Stream B / KMTS-B" },
+ { 2, "SKR" },
+ { 0, NULL }
+};
+
+static const value_string ehs_secondary_header_tdm_end_of_data_flag[] =
+{
+ { 0, "OK" },
+ { 1, "Loss of Clock" },
+ { 2, "Watchdog Timeout" },
+ { 3, "Loss of Sync" },
+ { 0, NULL }
+};
+
+static const value_string ehs_secondary_header_tdm_aoslos_flag[] =
+{
+ { 0, "AOS" },
+ { 1, "LOS" },
+ { 0, NULL }
+};
+
+static const value_string ehs_secondary_header_tdm_data_status[] =
+{
+ { 0, "OK" },
+ { 1, "Suspect" },
+ { 2, "DQ Failed" },
+ { 3, "No Data" },
+ { 0, NULL }
+};
+
+static const value_string ehs_data_zone_aoslos_indicator[] =
+{
+ { 0, "S-band LOS" },
+ { 1, "S-band AOS" },
+ { 2, "Ku-band LOS" },
+ { 3, "Ku-band AOS" },
+ { 0, NULL }
+};
+
+static const value_string ehs_data_zone_udsm_ccsds_vs_bpdu[] =
+{
+ { 0, "CCSDS" },
+ { 1, "BPDU" },
+ { 0, NULL }
+};
+
+static const value_string ehs_data_zone_udsm_payload_vs_core[] =
+{
+ { 0, "Core" },
+ { 1, "Payload" },
+ { 0, NULL }
+};
+
+static const value_string ehs_data_zone_udsm_event[] =
+{
+ { 0, "Undefined" },
+ { 1, "Actual LOS" },
+ { 2, "Scheduled End of Data" },
+ { 3, "Operator Requested" },
+ { 0, NULL }
+};
+
+
+/* function to return EHS secondary header size according to protocol.
+ * the buffer pointer tvb should be pointing to the packets ehs primary
+ * header, and the offset should be set to the start of the ehs secondary
+ * header on input.
+ */
+static int ehs_secondary_header_size ( int protocol, tvbuff_t* tvb, int offset )
+{
+ /* for most protocols the ehs secondary header is a standard size */
+ int size = EHS_SECONDARY_HEADER_SIZE;
+
+ switch ( protocol )
+ {
+ case EHS_PROTOCOL__TDM_TELEMETRY:
+ /* the TDM secondary header size is variable. it's value is actually
+ * contained in the first two bytes of the secondary header itself.
+ */
+ size = tvb_get_ntohs ( tvb, offset );
+ break;
+
+ case EHS_PROTOCOL__NASCOM_TELEMETRY:
+ break;
+
+ case EHS_PROTOCOL__PSEUDO_TELEMETRY:
+ size = 8;
+ break;
+
+ case EHS_PROTOCOL__TDS_DATA:
+ break;
+
+ case EHS_PROTOCOL__TEST_DATA:
+ break;
+
+ case EHS_PROTOCOL__GSE_DATA:
+ size = 16;
+ break;
+
+ case EHS_PROTOCOL__CUSTOM_DATA:
+ break;
+
+ case EHS_PROTOCOL__HDRS_DQ:
+ break;
+
+ case EHS_PROTOCOL__CSS:
+ break;
+
+ case EHS_PROTOCOL__AOS_LOS:
+ break;
+
+ case EHS_PROTOCOL__PDSS_PAYLOAD_CCSDS_PACKET:
+ break;
+
+ case EHS_PROTOCOL__PDSS_CORE_CCSDS_PACKET:
+ break;
+
+ case EHS_PROTOCOL__PDSS_PAYLOAD_BPDU:
+ break;
+
+ case EHS_PROTOCOL__PDSS_UDSM:
+ break;
+
+ case EHS_PROTOCOL__PDSS_RPSM:
+ break;
+
+ default:
+ break;
+ }
+
+ return size;
+
+}
+
+
+/* common EHS secondary header dissector */
+static void common_secondary_header_dissector ( proto_tree* ehs_secondary_header_tree, tvbuff_t* tvb, int* offset )
+{
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_vcdu_sequence_number, tvb, *offset, 3, FALSE );
+ *offset += 3;
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_stream_id, tvb, *offset, 1, FALSE );
+ /* proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_pdss_reserved_1, tvb, *offset, 1, FALSE ); */
+ ++(*offset);
+
+ /* proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_pdss_reserved_2, tvb, *offset, 1, FALSE ); */
+ ++(*offset);
+
+ /* proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_pdss_reserved_3, tvb, *offset, 2, FALSE ); */
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_gse_pkt_id, tvb, *offset, 2, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_payload_vs_core_id, tvb, *offset, 2, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_apid, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_virtual_channel, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_pdss_reserved_sync, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+}
+
+
+/* AOS/LOS EHS secondary header dissector */
+static void aoslos_secondary_header_dissector ( proto_tree* ehs_secondary_header_tree, tvbuff_t* tvb, int* offset )
+{
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_version, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_5, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_4, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_3, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_2, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_1, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_0, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ common_secondary_header_dissector ( ehs_secondary_header_tree, tvb, offset );
+}
+
+
+/* payload ccsds secondary header dissector */
+static void payload_ccsds_secondary_header_dissector ( proto_tree* ehs_secondary_header_tree, tvbuff_t* tvb, int* offset )
+{
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_version, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_5, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_4, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_3, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_vcdu_sequence_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_packet_sequence_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_0, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ common_secondary_header_dissector ( ehs_secondary_header_tree, tvb, offset );
+}
+
+
+/* core ccsds secondary header dissector */
+static void core_ccsds_secondary_header_dissector ( proto_tree* ehs_secondary_header_tree, tvbuff_t* tvb, int* offset )
+{
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_version, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_5, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_4, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_parent_stream_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_vcdu_sequence_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_packet_sequence_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_0, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ common_secondary_header_dissector ( ehs_secondary_header_tree, tvb, offset );
+}
+
+
+/* payload bpdu secondary header dissector */
+static void payload_bpdu_secondary_header_dissector ( proto_tree* ehs_secondary_header_tree, tvbuff_t* tvb, int* offset )
+{
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_version, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_5, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_4, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_3, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_vcdu_sequence_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_1, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_0, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ common_secondary_header_dissector ( ehs_secondary_header_tree, tvb, offset );
+}
+
+
+/* udsm secondary header dissector */
+static void udsm_secondary_header_dissector ( proto_tree* ehs_secondary_header_tree, tvbuff_t* tvb, int* offset )
+{
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_version, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_5, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_4, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_3, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_2, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_1, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_data_status_bit_0, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ common_secondary_header_dissector ( ehs_secondary_header_tree, tvb, offset );
+}
+
+
+/* tdm secondary header dissector */
+static void tdm_secondary_header_dissector ( proto_tree* ehs_secondary_header_tree, tvbuff_t* tvb, int* offset )
+{
+ int j;
+ int num_major_frames = 0;
+ int num_minor_frames = 0;
+ int cntmet_present = 0;
+ int obt_present = 0;
+ int mjfs_present = 0;
+
+ int year, jday, hour, minute, second, tenths;
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_secondary_header_length, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_extra_data_packet, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_backup_stream_id_number, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_end_of_data_flag, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_parent_frame_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_checksum_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_fixed_value_error, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_minor_frame_counter_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_format_id_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_bit_slip_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_sync_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_aoslos_flag, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_override_errors_flag, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_data_status, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_idq, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_cdq, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_adq, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_data_dq, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ /* proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_unused, tvb, *offset, 2, FALSE ); */
+ *offset += 2;
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_format_id, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_major_frame_packet_index, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_numpkts_per_major_frame, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ num_minor_frames = 1 + tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_num_minor_frames_per_packet, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ cntmet_present = tvb_get_guint8 ( tvb, *offset ) & 0x80;
+ obt_present = tvb_get_guint8 ( tvb, *offset ) & 0x40;
+ mjfs_present = tvb_get_guint8 ( tvb, *offset ) & 0x20;
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_cntmet_present, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_obt_present, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_major_frame_status_present, tvb, *offset, 1, FALSE );
+ /* proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_reserved, tvb, *offset, 1, FALSE ); */
+ ++(*offset);
+
+ if ( cntmet_present )
+ {
+ year = tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_cnt_year, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ jday = tvb_get_ntohs ( tvb, *offset );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_cnt_jday, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ hour = tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_cnt_hour, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ minute = tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_cnt_minute, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ second = tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_cnt_second, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ tenths = tvb_get_guint8 ( tvb, *offset ) >> 4;
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_cnt_tenths, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ /* format a more readable time */
+ proto_tree_add_text ( ehs_secondary_header_tree, tvb, *offset-7, 7,
+ "%04d/%03d:%02d:%02d:%02d.%1d = CNT/MET Time", year + 1900, jday, hour, minute, second, tenths );
+ }
+
+
+ if ( obt_present )
+ {
+ year = tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_obt_year, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ jday = tvb_get_ntohs ( tvb, *offset );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_obt_jday, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ hour = tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_obt_hour, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ minute = tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_obt_minute, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ second = tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_obt_second, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ tenths = tvb_get_guint8 ( tvb, *offset ) >> 4;
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_obt_tenths, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ /* format a more readable time */
+ proto_tree_add_text ( ehs_secondary_header_tree, tvb, *offset-7, 7,
+ "%04d/%03d:%02d:%02d:%02d.%1d = OBT Time", year + 1900, jday, hour, minute, second, tenths );
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_obt_delta_time_flag, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_obt_computed_flag, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_obt_not_retrieved_flag, tvb, *offset, 1, FALSE );
+ /* proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_obt_reserved, tvb, *offset, 1, FALSE ); */
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_obt_source_apid, tvb, *offset, 1, FALSE );
+ }
+
+ if ( mjfs_present )
+ {
+ proto_tree_add_text ( ehs_secondary_header_tree, tvb, *offset, 0, " " );
+
+ num_major_frames = 1 + tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_num_major_frame_status_words, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ for ( j=0; j < num_major_frames; ++j )
+ {
+ proto_tree_add_text ( ehs_secondary_header_tree, tvb, *offset, 1, "Major Frame Status Byte# %d", j );
+ /* proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_mjfs_reserved, tvb, *offset, 1, FALSE ); */
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_mjfs_parent_frame_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_mjfs_checksum_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_mjfs_fixed_value_error, tvb, *offset, 1, FALSE );
+ ++(*offset);
+ }
+ }
+
+ proto_tree_add_text ( ehs_secondary_header_tree, tvb, *offset, 0, " " );
+
+ for ( j=0; j < num_minor_frames; ++j )
+ {
+ proto_tree_add_text ( ehs_secondary_header_tree, tvb, *offset, 1, "Minor Frame Status Byte# %d", j );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_mnfs_parent_frame_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_mnfs_data_not_available, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_mnfs_checksum_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_mnfs_fixed_value_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_mnfs_counter_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_mnfs_format_id_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_mnfs_bit_slip_error, tvb, *offset, 1, FALSE );
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_tdm_mnfs_sync_error, tvb, *offset, 1, FALSE );
+ ++(*offset);
+ }
+
+}
+
+
+/* pseudo secondary header dissector */
+static void pseudo_secondary_header_dissector ( proto_tree* ehs_secondary_header_tree, tvbuff_t* tvb, int* offset )
+{
+ /* proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_pseudo_unused, tvb, *offset, 2, FALSE ); */
+ *offset += 2;
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_pseudo_workstation_id, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_pseudo_user_id, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ proto_tree_add_item ( ehs_secondary_header_tree, hf_ehs_sh_pseudo_comp_id, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+}
+
+
+
+
+/* EHS secondary header dissector */
+static void ehs_secondary_header_dissector ( int protocol, proto_tree* ehs_secondary_header_tree, tvbuff_t* tvb, int* offset )
+{
+ /* the ehs secondary header structure is potentially different for each and every
+ * protocol type, including it's size. we support certain protocols but not all.
+ * for those protocols which are not supported we simply increment the offset
+ * and return. support for these other protocols can easily be added at a later
+ * time if and when it becomes necessary to do so. but for right now, we're only
+ * going to dissect those protocols that we work with on a regular basis in pdss.
+ */
+ switch ( protocol )
+ {
+ case EHS_PROTOCOL__TDM_TELEMETRY:
+ tdm_secondary_header_dissector ( ehs_secondary_header_tree, tvb, offset );
+ break;
+
+ case EHS_PROTOCOL__NASCOM_TELEMETRY:
+ *offset += ehs_secondary_header_size ( protocol, tvb, *offset );
+ break;
+
+ case EHS_PROTOCOL__PSEUDO_TELEMETRY:
+ pseudo_secondary_header_dissector ( ehs_secondary_header_tree, tvb, offset );
+ break;
+
+ case EHS_PROTOCOL__TDS_DATA:
+ *offset += ehs_secondary_header_size ( protocol, tvb, *offset );
+ break;
+
+ case EHS_PROTOCOL__TEST_DATA:
+ *offset += ehs_secondary_header_size ( protocol, tvb, *offset );
+ break;
+
+ case EHS_PROTOCOL__GSE_DATA:
+ *offset += ehs_secondary_header_size ( protocol, tvb, *offset );
+ break;
+
+ case EHS_PROTOCOL__CUSTOM_DATA:
+ *offset += ehs_secondary_header_size ( protocol, tvb, *offset );
+ break;
+
+ case EHS_PROTOCOL__HDRS_DQ:
+ *offset += ehs_secondary_header_size ( protocol, tvb, *offset );
+ break;
+
+ case EHS_PROTOCOL__CSS:
+ *offset += ehs_secondary_header_size ( protocol, tvb, *offset );
+ break;
+
+ case EHS_PROTOCOL__AOS_LOS:
+ aoslos_secondary_header_dissector ( ehs_secondary_header_tree, tvb, offset );
+ break;
+
+ case EHS_PROTOCOL__PDSS_PAYLOAD_CCSDS_PACKET:
+ payload_ccsds_secondary_header_dissector ( ehs_secondary_header_tree, tvb, offset );
+ break;
+
+ case EHS_PROTOCOL__PDSS_CORE_CCSDS_PACKET:
+ core_ccsds_secondary_header_dissector ( ehs_secondary_header_tree, tvb, offset );
+ break;
+
+ case EHS_PROTOCOL__PDSS_PAYLOAD_BPDU:
+ payload_bpdu_secondary_header_dissector ( ehs_secondary_header_tree, tvb, offset );
+ break;
+
+ case EHS_PROTOCOL__PDSS_UDSM:
+ udsm_secondary_header_dissector ( ehs_secondary_header_tree, tvb, offset );
+ break;
+
+ case EHS_PROTOCOL__PDSS_RPSM:
+ *offset += ehs_secondary_header_size ( protocol, tvb, *offset );
+ break;
+
+ default:
+ *offset += ehs_secondary_header_size ( protocol, tvb, *offset );
+ break;
+ }
+}
+
+
+/* AOS/LOS data zone dissector */
+static void aoslos_data_zone_dissector ( proto_tree* ehs_tree, tvbuff_t* tvb, int* offset, packet_info* pinfo )
+{
+ proto_item *ehs_data_zone;
+ proto_tree *ehs_data_zone_tree;
+
+ /* create the data zone tree */
+ ehs_data_zone = proto_tree_add_text ( ehs_tree, tvb, *offset, pinfo->iplen - IP_HEADER_LENGTH - *offset, "AOS/LOS Data Zone" );
+ ehs_data_zone_tree = proto_item_add_subtree ( ehs_data_zone, ett_ehs_data_zone );
+
+ /* since the aos/los EHS packet data zone is well known, format it for display as well
+ *
+ * The AOS/LOS packet data zone is only 2 bytes in
+ * length and only 2 bits in the first byte are
+ * meaningful -- Ku band or S band and AOS or LOS
+ *
+ * 7-2 - unused
+ * 1-0 - band + AOS/LOS indicator
+ *
+ * bit 1 - 0=sband 1=kuband
+ * bit 0 - 0=LOS 1=AOS
+ *
+ * 0 00 - sband LOS
+ * 1 01 - sband AOS
+ * 2 10 - kuband LOS
+ * 3 11 - kuband AOS
+ */
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_aoslos_indicator, tvb, *offset, 1, FALSE );
+ ++(*offset);
+}
+
+
+/* UDSM data zone dissector */
+static void udsm_data_zone_dissector ( proto_tree* ehs_tree, tvbuff_t* tvb, int* offset, packet_info* pinfo )
+{
+ proto_item *ehs_data_zone;
+ proto_tree *ehs_data_zone_tree;
+
+ int year, jday, hour, minute, second;
+
+ /* create the data zone tree */
+ ehs_data_zone = proto_tree_add_text ( ehs_tree, tvb, *offset, pinfo->iplen - IP_HEADER_LENGTH - *offset, "UDSM Data Zone" );
+ ehs_data_zone_tree = proto_item_add_subtree ( ehs_data_zone, ett_ehs_data_zone );
+
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_ccsds_vs_bpdu, tvb, *offset, 1, FALSE );
+ /* proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_unused1, tvb, *offset, 1, FALSE ); */
+ ++(*offset);
+
+ /* proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_unused2, tvb, *offset, 1, FALSE ); */
+ ++(*offset);
+
+ /* proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_unused3, tvb, *offset, 2, FALSE ); */
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_gse_pkt_id, tvb, *offset, 2, FALSE );
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_payload_vs_core, tvb, *offset, 2, FALSE );
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_apid, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ year = tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_start_time_year, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ jday = tvb_get_ntohs ( tvb, *offset );
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_start_time_jday, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ hour = tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_start_time_hour, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ minute = tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_start_time_minute, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ second = tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_start_time_second, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ /* format a more readable time */
+ proto_tree_add_text ( ehs_data_zone_tree, tvb, *offset-7, 7,
+ "%04d/%03d:%02d:%02d:%02d = UDSM Start Time", year + 1900, jday, hour, minute, second );
+
+ year = tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_stop_time_year, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ jday = tvb_get_ntohs ( tvb, *offset );
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_stop_time_jday, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ hour = tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_stop_time_hour, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ minute = tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_stop_time_minute, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ second = tvb_get_guint8 ( tvb, *offset );
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_stop_time_second, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ /* format a more readable time */
+ proto_tree_add_text ( ehs_data_zone_tree, tvb, *offset-7, 7,
+ "%04d/%03d:%02d:%02d:%02d = UDSM Stop Time", year + 1900, jday, hour, minute, second );
+
+ /* proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_unused4, tvb, *offset, 2, FALSE ); */
+ *offset += 2;
+
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_num_pkts_xmtd, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_num_vcdu_seqerrs, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_num_pkt_seqerrs, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_num_pktlen_errors, tvb, *offset, 2, FALSE );
+ *offset += 2;
+
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_event, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+ proto_tree_add_item ( ehs_data_zone_tree, hf_ehs_dz_udsm_num_pkts_xmtd_rollover, tvb, *offset, 1, FALSE );
+ ++(*offset);
+
+}
+
+
+/* data zone dissector */
+static void ehs_data_zone_dissector ( int protocol, proto_tree* ehs_tree, tvbuff_t* tvb, int* offset, packet_info* pinfo )
+{
+ /* the data zone of certain protocols such as AOS/LOS and UDSM is well known.
+ */
+ switch ( protocol )
+ {
+ case EHS_PROTOCOL__TDM_TELEMETRY:
+ break;
+
+ case EHS_PROTOCOL__NASCOM_TELEMETRY:
+ break;
+
+ case EHS_PROTOCOL__PSEUDO_TELEMETRY:
+ break;
+
+ case EHS_PROTOCOL__TDS_DATA:
+ break;
+
+ case EHS_PROTOCOL__TEST_DATA:
+ break;
+
+ case EHS_PROTOCOL__GSE_DATA:
+ break;
+
+ case EHS_PROTOCOL__CUSTOM_DATA:
+ break;
+
+ case EHS_PROTOCOL__HDRS_DQ:
+ break;
+
+ case EHS_PROTOCOL__CSS:
+ break;
+
+ case EHS_PROTOCOL__AOS_LOS:
+ aoslos_data_zone_dissector ( ehs_tree, tvb, offset, pinfo );
+ break;
+
+ case EHS_PROTOCOL__PDSS_PAYLOAD_CCSDS_PACKET:
+ break;
+
+ case EHS_PROTOCOL__PDSS_CORE_CCSDS_PACKET:
+ break;
+
+ case EHS_PROTOCOL__PDSS_PAYLOAD_BPDU:
+ break;
+
+ case EHS_PROTOCOL__PDSS_UDSM:
+ udsm_data_zone_dissector ( ehs_tree, tvb, offset, pinfo );
+ break;
+
+ case EHS_PROTOCOL__PDSS_RPSM:
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/* Code to actually dissect the packets */
+static void
+dissect_ehs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ int offset = 0;
+ guint16 first_word;
+
+ tvbuff_t *new_tvb;
+
+ proto_item *ehs_packet;
+ proto_tree *ehs_tree;
+
+ proto_item *ehs_primary_header;
+ proto_tree *ehs_primary_header_tree;
+
+ proto_item *ehs_secondary_header;
+ proto_tree *ehs_secondary_header_tree;
+
+ int protocol;
+ int year, jday, hour, minute, second, tenths;
+
+ if ( check_col(pinfo->cinfo, COL_PROTOCOL) )
+ col_set_str ( pinfo->cinfo, COL_PROTOCOL, "EHS" );
+ if ( check_col(pinfo->cinfo, COL_INFO) )
+ col_set_str ( pinfo->cinfo, COL_INFO, "EHS" );
+
+ if ( tree )
+ {
+ ehs_packet = proto_tree_add_item ( tree, proto_ehs, tvb, 0, -1, FALSE );
+ ehs_tree = proto_item_add_subtree ( ehs_packet, ett_ehs );
+
+ /* build the ehs primary header tree */
+ ehs_primary_header = proto_tree_add_text ( ehs_tree, tvb, offset, EHS_PRIMARY_HEADER_SIZE, "Primary EHS Header" );
+ ehs_primary_header_tree = proto_item_add_subtree ( ehs_primary_header, ett_ehs_primary_header );
+
+ proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_version, tvb, offset, 1, FALSE );
+ proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_project, tvb, offset, 1, FALSE );
+ ++offset;
+
+ proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_support_mode, tvb, offset, 1, FALSE );
+ proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_data_mode, tvb, offset, 1, FALSE );
+ ++offset;
+
+ proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_mission, tvb, offset, 1, FALSE );
+ ++offset;
+
+ /* save protocol for use later on */
+ protocol = tvb_get_guint8 ( tvb, offset );
+ proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_protocol, tvb, offset, 1, FALSE );
+ ++offset;
+
+ year = tvb_get_guint8 ( tvb, offset );
+ proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_year, tvb, offset, 1, FALSE );
+ ++offset;
+
+ jday = tvb_get_ntohs ( tvb, offset );
+ proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_jday, tvb, offset, 2, FALSE );
+ offset += 2;
+
+ hour = tvb_get_guint8 ( tvb, offset );
+ proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_hour, tvb, offset, 1, FALSE );
+ ++offset;
+
+ minute = tvb_get_guint8 ( tvb, offset );
+ proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_minute, tvb, offset, 1, FALSE );
+ ++offset;
+
+ second = tvb_get_guint8 ( tvb, offset );
+ proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_second, tvb, offset, 1, FALSE );
+ ++offset;
+
+ tenths = tvb_get_guint8 ( tvb, offset ) >> 4;
+ proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_tenths, tvb, offset, 1, FALSE );
+
+ /* format a more readable ground receipt time string */
+ proto_tree_add_text ( ehs_primary_header_tree, tvb, offset-7, 7,
+ "%04d/%03d:%02d:%02d:%02d.%1d = EHS Ground Receipt Time", year + 1900, jday, hour, minute, second, tenths );
+
+ proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_new_data_flag, tvb, offset, 1, FALSE );
+ /* proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_pad1, tvb, offset, 1, FALSE ); */
+ proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_hold_flag, tvb, offset, 1, FALSE );
+ proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_sign_flag, tvb, offset, 1, FALSE );
+ ++offset;
+
+ /* proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_pad2, tvb, offset, 1, FALSE ); */
+ ++offset;
+ /* proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_pad3, tvb, offset, 1, FALSE ); */
+ ++offset;
+ /* proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_pad4, tvb, offset, 1, FALSE ); */
+ ++offset;
+
+ proto_tree_add_item ( ehs_primary_header_tree, hf_ehs_ph_hosc_packet_size, tvb, offset, 2, FALSE );
+ offset += 2;
+
+ /* build the ehs secondary header tree */
+ ehs_secondary_header = proto_tree_add_text ( ehs_tree, tvb, offset,
+ ehs_secondary_header_size ( protocol, tvb, offset ), "Secondary EHS Header" );
+ ehs_secondary_header_tree = proto_item_add_subtree ( ehs_secondary_header, ett_ehs_secondary_header );
+
+ /* since each protocol can have a different ehs secondary header structure, we will offload
+ * this processing to lower levels of code so we don't have to insert all of that complexity
+ * directly inline here, which would no doubt make this difficult to read at best.
+ */
+ ehs_secondary_header_dissector ( protocol, ehs_secondary_header_tree, tvb, &offset );
+
+ /* for ccsds protocol types pass the remaining packet off to the ccsds packet dissector */
+ switch ( protocol )
+ {
+ case EHS_PROTOCOL__TDM_TELEMETRY:
+ case EHS_PROTOCOL__PSEUDO_TELEMETRY:
+ case EHS_PROTOCOL__AOS_LOS:
+ case EHS_PROTOCOL__PDSS_PAYLOAD_CCSDS_PACKET:
+ case EHS_PROTOCOL__PDSS_CORE_CCSDS_PACKET:
+ case EHS_PROTOCOL__PDSS_UDSM:
+ new_tvb = tvb_new_subset ( tvb, offset, -1, -1 );
+ g_assert ( ccsds_handle != NULL );
+ call_dissector ( ccsds_handle, new_tvb, pinfo, ehs_tree );
+
+ /* bump the offset to the data zone area */
+ first_word = tvb_get_ntohs ( tvb, offset );
+
+ offset += CCSDS_PRIMARY_HEADER_LENGTH;
+ if ( first_word & HDR_SECHDR ) offset += CCSDS_SECONDARY_HEADER_LENGTH;
+ break;
+
+
+ default:
+ break;
+ }
+
+ /* build the ehs data zone tree for well known protocols such as AOS/LOS and UDSM */
+ ehs_data_zone_dissector ( protocol, ehs_tree, tvb, &offset, pinfo );
+ }
+
+}
+
+
+/* Register the protocol with Wireshark
+ * this format is require because a script is used to build the C function
+ * that calls all the protocol registration.
+ */
+void
+proto_register_ehs(void)
+{
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] =
+ {
+ /* primary ehs header */
+ { &hf_ehs_ph_version,
+ { "Version", "ehs.version",
+ FT_UINT8, BASE_DEC, NULL, 0xf0,
+ NULL, HFILL }
+ },
+ { &hf_ehs_ph_project,
+ { "Project", "ehs.project",
+ FT_UINT8, BASE_DEC, VALS(ehs_primary_header_project), 0x0f,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_ph_support_mode,
+ { "Support Mode", "ehs.support_mode",
+ FT_UINT8, BASE_DEC, VALS(ehs_primary_header_support_mode), 0xf0,
+ NULL, HFILL }
+ },
+ { &hf_ehs_ph_data_mode,
+ { "Data Mode", "ehs.data_mode",
+ FT_UINT8, BASE_DEC, VALS(ehs_primary_header_data_mode), 0x0f,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_ph_mission,
+ { "Mission", "ehs.mission",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_ph_protocol,
+ { "Protocol", "ehs.protocol",
+ FT_UINT8, BASE_DEC, VALS(ehs_primary_header_protocol), 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_ph_year,
+ { "Years since 1900", "ehs.year",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_ph_jday,
+ { "Julian Day of Year", "ehs.jday",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_ph_hour,
+ { "Hour", "ehs.hour",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_ph_minute,
+ { "Minute", "ehs.minute",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_ph_second,
+ { "Second", "ehs.second",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_ph_tenths,
+ { "Tenths", "ehs.tenths",
+ FT_UINT8, BASE_DEC, NULL, 0xf0,
+ NULL, HFILL }
+ },
+ { &hf_ehs_ph_new_data_flag,
+ { "New Data Flag", "ehs.new_data_flag",
+ FT_BOOLEAN, 8, NULL, 0x08,
+ NULL, HFILL }
+ },
+ { &hf_ehs_ph_pad1,
+ { "Pad1", "ehs.pad1",
+ FT_UINT8, BASE_DEC, NULL, 0x04,
+ NULL, HFILL }
+ },
+ { &hf_ehs_ph_hold_flag,
+ { "Hold Flag", "ehs.hold_flag",
+ FT_BOOLEAN, 8, NULL, 0x02,
+ NULL, HFILL }
+ },
+ { &hf_ehs_ph_sign_flag,
+ { "Sign Flag (1->CDT)", "ehs.sign_flag",
+ FT_UINT8, BASE_DEC, NULL, 0x01,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_ph_pad2,
+ { "Pad2", "ehs.pad2",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_ph_pad3,
+ { "Pad3", "ehs.pad3",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_ph_pad4,
+ { "Pad4", "ehs.pad4",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_ph_hosc_packet_size,
+ { "HOSC Packet Size", "ehs.hosc_packet_size",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+
+ /* secondary ehs header */
+ { &hf_ehs_sh_version,
+ { "Version", "ehs2.version",
+ FT_UINT8, BASE_DEC, NULL, 0xc0,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_data_status_bit_5,
+ { "Data Status Bit 5", "ehs2.data_status_bit_5",
+ FT_UINT8, BASE_DEC, NULL, 0x20,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_data_status_bit_4,
+ { "Data Status Bit 4", "ehs2.data_status_bit_4",
+ FT_UINT8, BASE_DEC, NULL, 0x10,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_data_status_bit_3,
+ { "Data Status Bit 3", "ehs2.data_status_bit_3",
+ FT_UINT8, BASE_DEC, NULL, 0x08,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_data_status_bit_2,
+ { "Data Status Bit 2", "ehs2.data_status_bit_2",
+ FT_UINT8, BASE_DEC, NULL, 0x04,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_data_status_bit_1,
+ { "Data Status Bit 1", "ehs2.data_status_bit_1",
+ FT_UINT8, BASE_DEC, NULL, 0x02,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_data_status_bit_0,
+ { "Data Status Bit 0", "ehs2.data_status_bit_0",
+ FT_UINT8, BASE_DEC, NULL, 0x01,
+ NULL, HFILL }
+ },
+
+
+ /* other common remappings of the data status bits specific to certain secondary ehs header values */
+ { &hf_ehs_sh_parent_stream_error,
+ { "Parent Stream Error", "ehs2.parent_stream_error",
+ FT_BOOLEAN, 8, NULL, 0x08,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_vcdu_sequence_error,
+ { "VCDU Sequence Error", "ehs2.vcdu_sequence_error",
+ FT_BOOLEAN, 8, NULL, 0x04,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_packet_sequence_error,
+ { "Packet Sequence Error", "ehs2.packet_sequence_error",
+ FT_UINT8, BASE_DEC, NULL, 0x02,
+ NULL, HFILL }
+ },
+
+
+ /* common ehs secondary header values */
+ { &hf_ehs_sh_vcdu_sequence_number,
+ { "VCDU Sequence Number", "ehs2.vcdu_seqno",
+ FT_UINT24, BASE_DEC, NULL, 0xffffff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_data_stream_id,
+ { "Data Stream ID", "ehs2.data_stream_id",
+ FT_UINT8, BASE_DEC, VALS(ehs_secondary_header_data_stream_id), 0x80,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_pdss_reserved_1,
+ { "Pdss Reserved 1", "ehs2.pdss_reserved_1",
+ FT_UINT8, BASE_DEC, NULL, 0x7f,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_pdss_reserved_2,
+ { "Pdss Reserved 2", "ehs2.pdss_reserved_2",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_pdss_reserved_3,
+ { "Pdss Reserved 3", "ehs2.pdss_reserved_3",
+ FT_UINT16, BASE_DEC, NULL, 0xe000,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_gse_pkt_id,
+ { "GSE Packet ID (1=GSE)", "ehs2.gse_pkt_id",
+ FT_UINT16, BASE_DEC, NULL, 0x1000,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_payload_vs_core_id,
+ { "Payload vs Core ID", "ehs2.payload_vs_core_id",
+ FT_UINT16, BASE_DEC, VALS(ehs_secondary_header_payload_vs_core_id), 0x0800,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_apid,
+ { "APID", "ehs2.apid",
+ FT_UINT16, BASE_DEC, NULL, 0x07ff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_virtual_channel,
+ { "Virtual Channel", "ehs2.vcid",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_pdss_reserved_sync,
+ { "Pdss Reserved Sync", "ehs2.sync",
+ FT_UINT16, BASE_HEX, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+
+ /* tdm ehs secondary header values */
+ { &hf_ehs_sh_tdm_secondary_header_length,
+ { "Secondary Header Length", "ehs2.tdm_secondary_header_length",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_extra_data_packet,
+ { "Extra Data Packet", "ehs2.tdm_extra_data_packet",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_backup_stream_id_number,
+ { "Backup Stream ID Number", "ehs2.tdm_backup_stream_id_number",
+ FT_UINT8, BASE_DEC, VALS(ehs_secondary_header_tdm_backup_stream_id), 0x60,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_end_of_data_flag,
+ { "End of Data Flag", "ehs2tdm_end_of_data_flag.tdm_end_of_data_flag",
+ FT_UINT8, BASE_DEC, VALS(ehs_secondary_header_tdm_end_of_data_flag), 0x18,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_parent_frame_error,
+ { "Parent Frame Error", "ehs2.tdm_parent_frame_error",
+ FT_BOOLEAN, 8, NULL, 0x04,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_checksum_error,
+ { "Checksum Error", "ehs2.tdm_checksum_error",
+ FT_BOOLEAN, 8, NULL, 0x02,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_fixed_value_error,
+ { "Fixed Value Error", "ehs2.tdm_fixed_value_error",
+ FT_BOOLEAN, 8, NULL, 0x01,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_minor_frame_counter_error,
+ { "Minor Frame Counter Error", "ehs2.tdm_minor_frame_counter_error",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_format_id_error,
+ { "Format ID Error", "ehs2.tdm_format_id_error",
+ FT_BOOLEAN, 8, NULL, 0x40,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_bit_slip_error,
+ { "Bit Slip Error", "ehs2.tdm_bit_slip_error",
+ FT_BOOLEAN, 8, NULL, 0x20,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_sync_error,
+ { "Sync Error", "ehs2.tdm_sync_error",
+ FT_BOOLEAN, 8, NULL, 0x10,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_aoslos_flag,
+ { "AOS/LOS Flag", "ehs2.tdm_aoslos_flag",
+ FT_BOOLEAN, 8, VALS(ehs_secondary_header_tdm_aoslos_flag), 0x08,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_override_errors_flag,
+ { "Override Errors", "ehs2.tdm_override_errors_flag",
+ FT_BOOLEAN, 8, NULL, 0x04,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_data_status,
+ { "Data Status", "ehs2.tdm_data_status",
+ FT_UINT8, BASE_DEC, VALS(ehs_secondary_header_tdm_data_status), 0x03,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_idq,
+ { "IDQ", "ehs2.tdm_idq",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_cdq,
+ { "CDQ", "ehs2.tdm_cdq",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_adq,
+ { "ADQ", "ehs2.tdm_adq",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_data_dq,
+ { "Data DQ", "ehs2.tdm_data_dq",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_unused,
+ { "Unused", "ehs2.tdm_unused",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_format_id,
+ { "Format ID", "ehs2.tdm_format_id",
+ FT_UINT16, BASE_HEX, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_major_frame_packet_index,
+ { "Major Frame Packet Index", "ehs2.tdm_major_frame_packet_index",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_numpkts_per_major_frame,
+ { "Num Packets per Major Frame", "ehs2.tdm_numpkts_per_major_frame",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_num_minor_frames_per_packet,
+ { "Num Minor Frames per Packet", "ehs2.tdm_num_minor_frame_per_packet",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_cntmet_present,
+ { "CNT or MET Present", "ehs2.tdm_cntmet_present",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_obt_present,
+ { "OBT Present", "ehs2.tdm_obt_present",
+ FT_BOOLEAN, 8, NULL, 0x40,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_major_frame_status_present,
+ { "Major Frame Status Present", "ehs2.tdm_major_frame_status_present",
+ FT_BOOLEAN, 8, NULL, 0x20,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_reserved,
+ { "Reserved", "ehs2.tdm_reserved",
+ FT_UINT8, BASE_DEC, NULL, 0x1f,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_cnt_year,
+ { "CNT Years since 1900", "ehs2.tdm_cnt_year",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_cnt_jday,
+ { "CNT Julian Day of Year", "ehs2.tdm_cnt_jday",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_cnt_hour,
+ { "CNT Hour", "ehs2.tdm_cnt_hour",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_cnt_minute,
+ { "CNT Minute", "ehs2.tdm_cnt_minute",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_cnt_second,
+ { "CNT Second", "ehs2.tdm_cnt_second",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_cnt_tenths,
+ { "CNT Tenths", "ehs2.tdm_cnt_tenths",
+ FT_UINT8, BASE_DEC, NULL, 0xf0,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_obt_year,
+ { "OBT Years since 1900", "ehs2.tdm_cnt_year",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_obt_jday,
+ { "OBT Julian Day of Year", "ehs2.tdm_cnt_jday",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_obt_hour,
+ { "OBT Hour", "ehs2.tdm_cnt_hour",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_obt_minute,
+ { "OBT Minute", "ehs2.tdm_cnt_minute",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_obt_second,
+ { "OBT Second", "ehs2.tdm_cnt_second",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_obt_tenths,
+ { "OBT Tenths", "ehs2.tdm_cnt_tenths",
+ FT_UINT8, BASE_DEC, NULL, 0xf0,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_obt_delta_time_flag,
+ { "OBT is Delta Time Instead of GMT", "ehs2.tdm_obt_delta_time_flag",
+ FT_BOOLEAN, 16, NULL, 0x8000,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_obt_computed_flag,
+ { "OBT Computed", "ehs2.tdm_obt_computed_flag",
+ FT_BOOLEAN, 16, NULL, 0x4000,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_obt_not_retrieved_flag,
+ { "OBT Not Retrieved", "ehs2.tdm_obt_not_retrieved_flag",
+ FT_BOOLEAN, 16, NULL, 0x2000,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_obt_reserved,
+ { "OBT Reserved", "ehs2.tdm_obt_reserved",
+ FT_BOOLEAN, 16, NULL, 0x1800,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_obt_source_apid,
+ { "OBT Source APID", "ehs2.tdm_obt_source_apid",
+ FT_UINT16, BASE_DEC, NULL, 0x07ff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_num_major_frame_status_words,
+ { "Number of Major Frame Status Words", "ehs2.tdm_num_major_frame_status_words",
+ FT_UINT8, BASE_DEC, NULL, 0x0ff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_mjfs_reserved,
+ { "Reserved", "ehs2.tdm_mjfs_reserved",
+ FT_UINT8, BASE_DEC, NULL, 0xf8,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_mjfs_parent_frame_error,
+ { "Parent Frame Error", "ehs2.tdm_mjfs_parent_frame_error",
+ FT_BOOLEAN, 8, NULL, 0x04,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_mjfs_checksum_error,
+ { "Checksum Error", "ehs2.tdm_mjfs_checksum_error",
+ FT_BOOLEAN, 8, NULL, 0x02,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_mjfs_fixed_value_error,
+ { "Fixed Value Error", "ehs2.tdm_mjfs_fixed_value_error",
+ FT_BOOLEAN, 8, NULL, 0x01,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_sh_tdm_mnfs_parent_frame_error,
+ { "Parent Frame Error", "ehs2.tdm_mnfs_parent_frame_error",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_mnfs_data_not_available,
+ { "Data Not Available", "ehs2.tdm_mnfs_data_not_available",
+ FT_BOOLEAN, 8, NULL, 0x40,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_mnfs_checksum_error,
+ { "Checksum Error", "ehs2.tdm_mnfs_checksum_error",
+ FT_BOOLEAN, 8, NULL, 0x20,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_mnfs_fixed_value_error,
+ { "Fixed Value Error", "ehs2.tdm_mnfs_fixed_value_error",
+ FT_BOOLEAN, 8, NULL, 0x10,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_mnfs_counter_error,
+ { "Counter Error", "ehs2.tdm_mnfs_counter_error",
+ FT_BOOLEAN, 8, NULL, 0x08,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_mnfs_format_id_error,
+ { "Format ID Error", "ehs2.tdm_mnfs_format_id_error",
+ FT_BOOLEAN, 8, NULL, 0x04,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_mnfs_bit_slip_error,
+ { "Bit Slip Error", "ehs2.tdm_mnfs_bit_slip_error",
+ FT_BOOLEAN, 8, NULL, 0x02,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_tdm_mnfs_sync_error,
+ { "Sync Error", "ehs2.tdm_mnfs_sync_error",
+ FT_BOOLEAN, 8, NULL, 0x01,
+ NULL, HFILL }
+ },
+
+
+ /* pseudo secondary header */
+ { &hf_ehs_sh_pseudo_unused,
+ { "Unused", "ehs2.pseudo_unused",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_pseudo_workstation_id,
+ { "Workstation ID", "ehs2.pseudo_workstation_id",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_pseudo_user_id,
+ { "User ID", "ehs2.pseudo_user_id",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_sh_pseudo_comp_id,
+ { "Comp ID", "ehs2.pseudo_comp_id",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+
+ /* aos/los protocol data zone */
+ { &hf_ehs_dz_aoslos_indicator,
+ { "AOS/LOS Indicator", "dz.aoslos_indicator",
+ FT_UINT8, BASE_DEC, VALS(ehs_data_zone_aoslos_indicator), 0x03,
+ NULL, HFILL }
+ },
+
+
+ /* udsm protocol data zone */
+ { &hf_ehs_dz_udsm_ccsds_vs_bpdu,
+ { "CCSDS vs BPDU", "dz.udsm_ccsds_vs_bpdu",
+ FT_UINT8, BASE_DEC, VALS(ehs_data_zone_udsm_ccsds_vs_bpdu), 0x80,
+ NULL, HFILL }
+ },
+ { &hf_ehs_dz_udsm_unused1,
+ { "Unused 1", "dz.udsm_unused1",
+ FT_UINT8, BASE_DEC, NULL, 0x7f,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_dz_udsm_unused2,
+ { "Unused 2", "dz.udsm_unused2",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_dz_udsm_unused3,
+ { "Unused 3", "dz.udsm_unused3",
+ FT_UINT16, BASE_DEC, NULL, 0xe000,
+ NULL, HFILL }
+ },
+ { &hf_ehs_dz_udsm_gse_pkt_id,
+ { "GSE Pkt ID", "dz.udsm_gse_pkt_id",
+ FT_BOOLEAN, 16, NULL, 0x1000,
+ NULL, HFILL }
+ },
+ { &hf_ehs_dz_udsm_payload_vs_core,
+ { "Payload vs Core", "dz.udsm_payload_vs_core",
+ FT_UINT16, BASE_DEC, VALS(ehs_data_zone_udsm_payload_vs_core), 0x0800,
+ NULL, HFILL }
+ },
+ { &hf_ehs_dz_udsm_apid,
+ { "APID", "dz.udsm_apid",
+ FT_UINT16, BASE_DEC, NULL, 0x07ff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_dz_udsm_start_time_year,
+ { "Start Time Years since 1900", "dz.udsm_start_time_year",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_dz_udsm_start_time_jday,
+ { "Start Time Julian Day", "dz.udsm_start_time_jday",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_dz_udsm_start_time_hour,
+ { "Start Time Hour", "dz.udsm_start_time_hour",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_dz_udsm_start_time_minute,
+ { "Start Time Minute", "dz.udsm_start_time_minute",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_dz_udsm_start_time_second,
+ { "Start Time Second", "dz.udsm_start_time_second",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_dz_udsm_stop_time_year,
+ { "Stop Time Years since 1900", "dz.udsm_stop_time_year",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_dz_udsm_stop_time_jday,
+ { "Stop Time Julian Day", "dz.udsm_stop_time_jday",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_dz_udsm_stop_time_hour,
+ { "Stop Time Hour", "dz.udsm_stop_time_hour",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_dz_udsm_stop_time_minute,
+ { "Stop Time Minute", "dz.udsm_stop_time_minute",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+ { &hf_ehs_dz_udsm_stop_time_second,
+ { "Stop Time Second", "dz.udsm_stop_time_second",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_dz_udsm_unused4,
+ { "Unused 4", "dz.udsm_unused4",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_dz_udsm_num_pkts_xmtd,
+ { "Num Pkts Transmitted", "dz.udsm_num_pkts_xmtd",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_dz_udsm_num_vcdu_seqerrs,
+ { "Num VCDU Sequence Errors", "dz.udsm_num_vcdu_seqerrs",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_dz_udsm_num_pkt_seqerrs,
+ { "Num Packet Sequence Errors", "dz.udsm_num_pkt_seqerrs",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_dz_udsm_num_pktlen_errors,
+ { "Num Pkt Length Errors", "dz.udsm_num_pktlen_errors",
+ FT_UINT16, BASE_DEC, NULL, 0xffff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_dz_udsm_event,
+ { "UDSM Event Code", "dz.udsm_event",
+ FT_UINT8, BASE_DEC, VALS(ehs_data_zone_udsm_event), 0xff,
+ NULL, HFILL }
+ },
+
+ { &hf_ehs_dz_udsm_num_pkts_xmtd_rollover,
+ { "Num Pkts Transmitted Rollover Counter", "dz.udsm_num_pkts_xmtd_rollover",
+ FT_UINT8, BASE_DEC, NULL, 0xff,
+ NULL, HFILL }
+ },
+
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_ehs,
+ &ett_ehs_primary_header,
+ &ett_ehs_secondary_header,
+ &ett_ehs_data_zone
+ };
+
+ /* Register the protocol name and description */
+ proto_ehs = proto_register_protocol("EHS", "EHS", "ehs");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_ehs, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ * This format is required because a script is used to find these routines and
+ * create the code that calls these routines.
+ */
+void
+proto_reg_handoff_ehs(void)
+{
+ register_dissector ( "ehs", dissect_ehs, proto_ehs );
+ dissector_add ( "udp.port", 0, find_dissector("ehs") );
+ ccsds_handle = find_dissector ( "ccsds" );
+}
+
diff --git a/epan/dissectors/packet-vcdu.c b/epan/dissectors/packet-vcdu.c
new file mode 100644
index 0000000000..bb6fba853f
--- /dev/null
+++ b/epan/dissectors/packet-vcdu.c
@@ -0,0 +1,648 @@
+/* packet-vcdu.c
+ * Routines for VCDU dissection
+ * Copyright 2000, Scott Hovis scott.hovis@ums.msfc.nasa.gov
+ * Enhanced 2008, Matt Dunkle Matthew.L.Dunkle@nasa.gov
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.com>
+ * 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 should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/filesystem.h>
+
+
+/* Initialize the protocol and registered fields */
+static int proto_vcdu = -1;
+
+static int hf_smex_gsc = -1;
+static int hf_smex_unused = -1;
+static int hf_smex_version = -1;
+static int hf_smex_framelen = -1;
+static int hf_smex_rs_error = -1;
+static int hf_smex_rs_enable = -1;
+static int hf_smex_crc_enable = -1;
+static int hf_smex_crc_error = -1;
+static int hf_smex_mcs_enable = -1;
+static int hf_smex_mcs_num_error = -1;
+static int hf_smex_data_inv = -1;
+static int hf_smex_frame_sync = -1;
+static int hf_smex_data_dir = -1;
+static int hf_smex_data_class = -1;
+static int hf_smex_pb5 = -1;
+static int hf_smex_jday = -1;
+static int hf_smex_seconds = -1;
+static int hf_smex_msec = -1;
+static int hf_smex_spare = -1;
+
+static int hf_vcdu_version = -1;
+static int hf_vcdu_sp_id = -1;
+static int hf_vcdu_vc_id = -1;
+static int hf_vcdu_seq = -1;
+static int hf_vcdu_replay = -1;
+
+/* although technically not part of the vcdu header, the
+ * first header pointer (for ccsds), and the last bit
+ * pointer (for bitstream), are more easily processed by
+ * simply adding them to the tail end of the vcdu header
+ * branch rather than creating a distinct branch for them
+ */
+static int hf_vcdu_fhp = -1;
+static int hf_vcdu_lbp = -1;
+
+static dissector_handle_t ccsds_handle = (dissector_handle_t)-1;
+
+/* Initialize the subtree pointers */
+static gint ett_vcdu = -1;
+static gint ett_smex = -1;
+static gint ett_vcduh = -1;
+
+/*
+ * Bits in the first 16-bit header word
+ */
+#define SMEX_VERSION 0xc000
+#define SMEX_FRAMELEN 0x3fff
+
+/* some basic sizing parameters */
+#define IP_HEADER_LENGTH 48
+#define SMEX_HEADER_LENGTH 20
+#define VCDU_HEADER_LENGTH 6
+#define CCSDS_PRIMARY_HEADER_LENGTH 6
+#define CCSDS_SECONDARY_HEADER_LENGTH 10
+
+#define PB5_JULIAN_DAY_MASK 0x7ffe
+#define PB5_SECONDS_MASK 0x01ffff
+#define PB5_MILLISECONDS_MASK 0xffc0
+
+#define LBP_ALL_DATA 0x3fff
+#define LBP_ALL_DATA_ANOMALY 0x7ff
+#define LBP_ALL_FILL 0x3ffe
+
+#define FHP_ALL_FILL 0x7fe
+#define FHP_CONTINUATION 0x7ff
+
+#define LBP_MASK 0x3fff
+#define FHP_MASK 0x7ff
+
+/* leap year macro */
+#ifndef Leap
+# define Leap(yr) ( ( 0 == (yr)%4 && 0 != (yr)%100 ) || ( 0 == (yr)%400 ) )
+#endif
+
+
+static const value_string smex_data_inversion_type[] = {
+ { 0, "Data True (not inverted)" },
+ { 1, "Data Inverted (not corrected)" },
+ { 2, "Data Inversion State UNDEFINED" },
+ { 3, "Data Inverted (and corrected)" },
+ { 0, NULL }
+};
+
+static const value_string smex_frame_sync_mode[] = {
+ { 0, "Search" },
+ { 1, "Check" },
+ { 2, "Lock" },
+ { 3, "Flywheel" },
+ { 0, NULL }
+};
+
+static const value_string smex_data_direction[] = {
+ { 0, "Forward" },
+ { 1, "Reverse" },
+ { 0, NULL }
+};
+
+static const value_string smex_data_class[] = {
+ { 0, "Data Class UNDEFINED" },
+ { 1, "CCSDS Frame" },
+ { 2, "CCSDS Packet" },
+ { 3, "TDM Frame" },
+ { 4, "Stopped TDM Frame" },
+ { 0, NULL }
+};
+
+
+
+
+/* prototype of utc to julian time conversion function - see packet-ccsds.c for the full source code */
+extern void utc_to_julian ( int utc, int* year, int* julianday, int* hour, int* minute, int* second );
+
+
+/* convert smex PB5 header time to a human readable string - NOT THREAD SAFE
+ *
+ * note: this is not true PB5 time either, but a tsi specific version, although it is similar
+ */
+static const char* smex_time_to_string ( int pb5_days_since_midnight_9_10_oct_1995, int pb5_seconds, int pb5_milliseconds )
+{
+ static const char* fmt = "%04d/%03d:%02d:%02d:%02d.%03d";
+ static char juliantime[40];
+ static int utcdiff = 0;
+
+ static int Days[2][13] =
+ {
+ { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+ };
+
+ int utc, yr, year, julianday, hour, minute, second;
+ int ix, days, month;
+
+ /* compute the static constant difference in seconds
+ * between midnight 9-10 October 1995 (PB5 time) and
+ * seconds since 1/1/1970 (UTC time) just this once
+ */
+ if ( 0 == utcdiff )
+ {
+ for ( yr=1970; yr < 1995; ++yr )
+ {
+ utcdiff += ( Leap(yr) ? 366 : 365 ) * 24 * 60 * 60;
+ }
+
+ days = 0;
+ ix = ( Leap(1995) ? 1 : 0 );
+
+ for ( month=1; month < 10; ++month )
+ {
+ days += Days[ix][month];
+ }
+
+ days += 9; /* this gets us up to midnight october 9-10 */
+
+ utcdiff += days * 24 * 60 * 60; /* add days in 1995 prior to October 10 */
+ }
+
+ utc = ( pb5_days_since_midnight_9_10_oct_1995 * 86400 ) + pb5_seconds + utcdiff;
+ utc_to_julian ( utc, &year, &julianday, &hour, &minute, &second );
+
+ g_snprintf ( juliantime, sizeof(juliantime), fmt, year, julianday, hour, minute, second, pb5_milliseconds );
+
+ return juliantime;
+
+}
+
+
+/* Code to actually dissect the packets */
+static void
+dissect_vcdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ static int bitstream_channels_file_read = 0;
+
+ /* default bitstream channel assignments:
+ * the audio channels 4-6 are designated as bitstream channels
+ * the standard bitstream channels are 12 through 19
+ * the video channels 28-30 are designated as bitstream channels
+ * the fill channel 63 is designated as bitstream
+ */
+ static int bitstream_channels[] =
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* channels 0-9 */
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /* channels 10-19 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* channels 20-29 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* channels 30-39 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* channels 40-49 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* channels 50-59 */
+ 0, 0, 0, 1 /* channels 60-63 */
+ };
+
+ int packet_boundary = 0;
+ int offset = 0;
+ int new_offset=0;
+ int ccsds_tree_added = 0;
+
+ int apid = 0;
+ int ccsds_len = 0;
+
+ proto_item *smex_header = NULL;
+ proto_tree *smex_tree = NULL;
+
+ proto_item *vcdu_header = NULL;
+ proto_tree *vcdu_tree = NULL;
+
+ guint16 first_word = 0;
+ guint32 long_word = 0;
+ guint16 new_ptr = 0;
+
+ tvbuff_t *new_tvb = NULL;
+
+ int channel = 0, vcid = 0;
+ char *filename = NULL;
+ char *endptr = NULL, *cptr = NULL;
+ FILE* fp = NULL;
+ char readbuf[1024];
+
+ int pb5_days = 0, pb5_seconds = 0, pb5_milliseconds = 0;
+ const char* time_string = NULL;
+
+
+ /* if the bitstream channels file has not been read attempt to do so now.
+ * this file potentially contains a modified list of the channels that
+ * should be processed as bitstream instead of ccsds.
+ */
+ if ( ! bitstream_channels_file_read )
+ {
+ bitstream_channels_file_read = 1;
+ filename = get_persconffile_path ( ".bitstream_channels", FALSE, FALSE );
+ fp = fopen ( filename, "r" );
+
+ if ( NULL != fp )
+ {
+ if ( fgets ( readbuf, sizeof(readbuf), fp ) == readbuf )
+ {
+ memset ( bitstream_channels, 0, sizeof(bitstream_channels) );
+ cptr = readbuf;
+
+ while ( TRUE )
+ {
+ channel = strtoul ( cptr, &endptr, 0 );
+ if ( cptr == endptr ) break;
+
+ if ( channel >= 0 && channel < 64 )
+ {
+ bitstream_channels[channel] = 1;
+ }
+
+ cptr = endptr;
+ }
+ }
+
+ fclose(fp);
+ g_free(filename);
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "VCDU");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_set_str(pinfo->cinfo, COL_INFO, "Virtual Channel Data Unit");
+
+ if (tree) {
+ /* build the smex header tree */
+ smex_header=proto_tree_add_text(tree, tvb, offset, SMEX_HEADER_LENGTH, "SMEX Header");
+ smex_tree=proto_item_add_subtree(smex_header, ett_smex);
+
+ proto_tree_add_item(smex_tree, hf_smex_gsc, tvb, offset, 8, FALSE);
+ offset += 8;
+ /* proto_tree_add_uint(smex_tree, hf_smex_unused, tvb, offset, 2, FALSE); */
+ offset += 2;
+
+ first_word=tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(smex_tree, hf_smex_version, tvb, offset, 2, first_word);
+ proto_tree_add_uint(smex_tree, hf_smex_framelen, tvb, offset, 2, first_word);
+ offset += 2;
+
+ proto_tree_add_item(smex_tree, hf_smex_rs_enable, tvb, offset, 1, FALSE);
+ proto_tree_add_item(smex_tree, hf_smex_rs_error, tvb, offset, 1, FALSE);
+ proto_tree_add_item(smex_tree, hf_smex_crc_enable, tvb, offset, 1, FALSE);
+ proto_tree_add_item(smex_tree, hf_smex_crc_error, tvb, offset, 1, FALSE);
+ proto_tree_add_item(smex_tree, hf_smex_mcs_enable, tvb, offset, 1, FALSE);
+ proto_tree_add_item(smex_tree, hf_smex_mcs_num_error, tvb, offset, 1, FALSE);
+ proto_tree_add_item(smex_tree, hf_smex_data_inv, tvb, offset, 1, FALSE);
+ ++offset;
+
+ proto_tree_add_item(smex_tree, hf_smex_frame_sync, tvb, offset, 1, FALSE);
+ proto_tree_add_item(smex_tree, hf_smex_data_dir, tvb, offset, 1, FALSE);
+ proto_tree_add_item(smex_tree, hf_smex_data_class, tvb, offset, 1, FALSE);
+ ++offset;
+
+ /* extract smex ground receipt time tag */
+ long_word = tvb_get_ntohl ( tvb, offset );
+ pb5_days = ( long_word >> 17 ) & PB5_JULIAN_DAY_MASK;
+ pb5_seconds = ( long_word & PB5_SECONDS_MASK );
+
+ first_word = tvb_get_ntohs ( tvb, offset+4 );
+ pb5_milliseconds = ( first_word & PB5_MILLISECONDS_MASK ) >> 6;
+
+ proto_tree_add_item(smex_tree, hf_smex_pb5, tvb, offset, 2, FALSE);
+ proto_tree_add_item(smex_tree, hf_smex_jday, tvb, offset, 2, FALSE);
+ ++offset;
+ proto_tree_add_item(smex_tree, hf_smex_seconds, tvb, offset, 3, FALSE);
+ offset += 3;
+
+ proto_tree_add_item(smex_tree, hf_smex_msec, tvb, offset, 2, FALSE);
+ /* proto_tree_add_item(smex_tree, hf_smex_spare, tvb, offset, 2, FALSE); */
+ offset += 2;
+
+ /* format ground receipt time into human readable time format for display */
+ time_string = smex_time_to_string ( pb5_days, pb5_seconds, pb5_milliseconds );
+ proto_tree_add_text (smex_tree, tvb, offset-6, 6, "%s = Ground Receipt Time", time_string );
+
+ proto_item_set_end(smex_header, tvb, offset);
+
+
+ /* build the vcdu header tree */
+ vcdu_header=proto_tree_add_text(tree, tvb, offset, VCDU_HEADER_LENGTH, "VCDU Header");
+ vcdu_tree = proto_item_add_subtree(vcdu_header, ett_vcdu);
+
+ /* extract the virtual channel for use later on */
+ first_word=tvb_get_ntohs(tvb, offset);
+ vcid = first_word & 0x3f;
+
+ proto_tree_add_item(vcdu_tree, hf_vcdu_version, tvb, offset, 2, FALSE);
+ proto_tree_add_item(vcdu_tree, hf_vcdu_sp_id, tvb, offset, 2, FALSE);
+ proto_tree_add_item(vcdu_tree, hf_vcdu_vc_id, tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(vcdu_tree, hf_vcdu_seq, tvb, offset, 3, FALSE);
+ offset += 3;
+ proto_tree_add_item(vcdu_tree, hf_vcdu_replay, tvb, offset, 1, FALSE);
+ ++offset;
+
+ /* extract mpdu/bpdu header word */
+ first_word=tvb_get_ntohs(tvb, offset);
+
+ /* do bitstream channel processing */
+ if ( bitstream_channels[vcid] )
+ {
+ /* extract last bit pointer for bitstream channels */
+ new_ptr=first_word & LBP_MASK;
+
+ /* add last bit pointer to display tree */
+ proto_tree_add_item(vcdu_tree, hf_vcdu_lbp, tvb, offset, 2, FALSE);
+
+ switch ( new_ptr )
+ {
+ case LBP_ALL_DATA:
+ proto_tree_add_text(vcdu_tree, tvb, 0, -1, "Bitream ALL Data");
+ break;
+
+ case LBP_ALL_DATA_ANOMALY:
+ proto_tree_add_text(vcdu_tree, tvb, 0, -1, "Bitream ALL Data (Anomaly)");
+ break;
+
+ case LBP_ALL_FILL:
+ proto_tree_add_text(vcdu_tree, tvb, 0, -1, "Bitream ALL Fill");
+ break;
+
+ default:
+ break;
+ }
+ } /* end of bitstream channel processing */
+
+ /* do ccsds channel processing */
+ else
+ {
+ /* extract first header pointer for ccsds channels */
+ new_ptr=first_word & FHP_MASK;
+
+ /* add first header pointer to display tree */
+ proto_tree_add_item(vcdu_tree, hf_vcdu_fhp, tvb, offset, 2, FALSE);
+
+ /* process special cases of first header pointer */
+ if ( FHP_ALL_FILL == new_ptr )
+ {
+ proto_tree_add_text(vcdu_tree, tvb, 0, -1, "Ccsds ALL Fill");
+ }
+
+ else if ( FHP_CONTINUATION == new_ptr )
+ {
+ proto_tree_add_text(vcdu_tree, tvb, 0, -1, "Ccsds Continuation Packet");
+ }
+
+ /* process as many ccsds packet headers as we can using the ccsds packet dissector */
+ else
+ {
+ /* compute offset and packet boundary lengths for ccsds dissector loop */
+ new_offset=offset+2+new_ptr;
+
+ packet_boundary = pinfo->iplen - IP_HEADER_LENGTH - VCDU_HEADER_LENGTH - CCSDS_PRIMARY_HEADER_LENGTH - CCSDS_SECONDARY_HEADER_LENGTH;
+
+ while ( (new_offset-offset+2) < packet_boundary && (new_offset-offset+2) >= 4 )
+ {
+ ccsds_tree_added = 1;
+ ccsds_len=tvb_get_ntohs(tvb, new_offset+4);
+
+ apid=tvb_get_ntohs(tvb, new_offset);
+ apid=apid & 0x07ff;
+ /* printf ( "new_ptr=%d new_offset=%d apid=%d ccsds_len=%d\n", new_ptr, new_offset, apid, ccsds_len ); fflush(stdout); */
+
+ new_tvb = tvb_new_subset(tvb, new_offset, -1, -1);
+ g_assert(ccsds_handle != NULL);
+ call_dissector(ccsds_handle, new_tvb, pinfo, vcdu_tree);
+
+ new_offset=new_offset+ccsds_len+7;
+ }
+
+ if ( ! ccsds_tree_added )
+ {
+ proto_tree_add_text(vcdu_tree, tvb, 0, -1, "FHP too close to end of VCDU. Incomplete Hdr Info Available - Unable to format CCSDS Hdr(s)." );
+ }
+ }
+
+ } /* end of ccsds channel processing */
+
+ /* don't include the mpdu/bpdu header in the vcdu header highlighting.
+ * by skipping the offset bump the vcdu header highlighting will show
+ * just 6 bytes as it really should, and the fhp/lbp will be included
+ * in the data zone, which is technically more correct.
+ */
+ /* offset += 2; */
+ proto_item_set_end(vcdu_tree, tvb, offset);
+
+ if ( ! ccsds_tree_added )
+ {
+ /* add "Data" section if ccsds parsing did not do so already */
+ proto_tree_add_text(vcdu_tree, tvb, offset, -1, "Data");
+ }
+ }
+}
+
+
+/* Register the protocol with Wireshark
+ * this format is require because a script is used to build the C function
+ * that calls all the protocol registration.
+ */
+void
+proto_register_vcdu(void)
+{
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_smex_gsc,
+ { "Ground Sequence Counter", "smex.gsc",
+ FT_UINT64, BASE_DEC, NULL, 0x0,
+ "SMEX Ground Sequence Counter", HFILL }
+ },
+ { &hf_smex_unused,
+ { "Unused", "smex.unused",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "SMEX Unused", HFILL }
+ },
+ { &hf_smex_version,
+ { "Version", "smex.version",
+ FT_UINT16, BASE_DEC, NULL, SMEX_VERSION,
+ "SMEX Version", HFILL }
+ },
+ { &hf_smex_framelen,
+ { "Frame Length", "smex.frame_len",
+ FT_UINT16, BASE_DEC, NULL, SMEX_FRAMELEN,
+ "SMEX Frame Length", HFILL }
+ },
+ { &hf_smex_rs_enable,
+ { "RS Enable", "smex.rs_enable",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ "SMEX RS Enable", HFILL }
+ },
+ { &hf_smex_rs_error,
+ { "RS Error", "smex.rs_error",
+ FT_BOOLEAN, 8, NULL, 0x40,
+ "SMEX RS Error", HFILL }
+ },
+ { &hf_smex_crc_enable,
+ { "CRC Enable", "smex.crc_enable",
+ FT_BOOLEAN, 8, NULL, 0x20,
+ "SMEX CRC Enable", HFILL }
+ },
+ { &hf_smex_crc_error,
+ { "CRC Error", "smex.crc_error",
+ FT_BOOLEAN, 8, NULL, 0x10,
+ "SMEX CRC Error", HFILL }
+ },
+ { &hf_smex_mcs_enable,
+ { "MCS Enable", "smex.mcs_enable",
+ FT_BOOLEAN, 8, NULL, 0x08,
+ "SMEX MCS Enable", HFILL }
+ },
+ { &hf_smex_mcs_num_error,
+ { "MCS Number Error", "smex.mcs_numerr",
+ FT_BOOLEAN, 8, NULL, 0x04,
+ "SMEX MCS Number Error", HFILL }
+ },
+ { &hf_smex_data_inv,
+ { "Data Inversion", "smex.data_inv",
+ FT_UINT16, BASE_DEC, VALS(smex_data_inversion_type), 0x03,
+ "SMEX Data Inversion", HFILL }
+ },
+ { &hf_smex_frame_sync,
+ { "Frame Sync", "smex.frame_sync",
+ FT_UINT16, BASE_DEC, VALS(smex_frame_sync_mode), 0xc0,
+ "SMEX Frame Sync Flag", HFILL }
+ },
+ { &hf_smex_data_dir,
+ { "Data Direction", "smex.data_dir",
+ FT_UINT16, BASE_DEC, VALS(smex_data_direction), 0x20,
+ "SMEX Data Direction flag", HFILL }
+ },
+ { &hf_smex_data_class,
+ { "Data Class", "smex.data_class",
+ FT_UINT16, BASE_DEC, VALS(smex_data_class), 0x1f,
+ "SMEX Data Class", HFILL }
+ },
+ { &hf_smex_pb5,
+ { "PB5 Flag", "smex.pb5",
+ FT_UINT16, BASE_DEC, NULL, 0x8000,
+ "SMEX PB5 Flag", HFILL }
+ },
+ { &hf_smex_jday,
+ { "Julian Day", "smex.jday",
+ FT_UINT16, BASE_DEC, NULL, PB5_JULIAN_DAY_MASK,
+ "SMEX Julian Day", HFILL }
+ },
+ { &hf_smex_seconds,
+ { "Seconds", "smex.seconds",
+ FT_UINT24, BASE_DEC, NULL, PB5_SECONDS_MASK,
+ "SMEX Seconds", HFILL }
+ },
+ { &hf_smex_msec,
+ { "Milliseconds", "smex.msec",
+ FT_UINT16, BASE_DEC, NULL, PB5_MILLISECONDS_MASK,
+ "SMEX Milliseconds", HFILL }
+ },
+ { &hf_smex_spare,
+ { "Spare", "smex.spare",
+ FT_UINT16, BASE_DEC, NULL, 0x03f,
+ "SMEX Spare", HFILL }
+ },
+
+
+
+ { &hf_vcdu_version,
+ { "Version", "vcdu.version",
+ FT_UINT16, BASE_DEC, NULL, 0xc0,
+ "VCDU Version", HFILL }
+ },
+ { &hf_vcdu_sp_id,
+ { "Space Craft ID", "vcdu.spid",
+ FT_UINT16, BASE_DEC, NULL, 0x3fc0,
+ "VCDU Space Craft ID", HFILL }
+ },
+ { &hf_vcdu_vc_id,
+ { "Virtual Channel ID", "vcdu.vcid",
+ FT_UINT16, BASE_DEC, NULL, 0x3f,
+ "VCDU Virtual Channel ID", HFILL }
+ },
+ { &hf_vcdu_seq,
+ { "Sequence Count", "vcdu.seq",
+ FT_UINT16, BASE_DEC, NULL, 0xffffff,
+ "VCDU Sequence Count", HFILL }
+ },
+ { &hf_vcdu_replay,
+ { "Replay Flag", "vcdu.replay",
+ FT_BOOLEAN, 8, NULL, 0x80,
+ "VCDU Replay Flag", HFILL }
+ },
+
+ /* not really part of the vcdu header, but it's easier this way */
+ { &hf_vcdu_fhp,
+ { "First Header Pointer", "vcdu.fhp",
+ FT_UINT16, BASE_DEC, NULL, FHP_MASK,
+ "VCDU/MPDU First Header Pointer", HFILL }
+ },
+ { &hf_vcdu_lbp,
+ { "Last Bit Pointer", "vcdu.lbp",
+ FT_UINT16, BASE_DEC, NULL, LBP_MASK,
+ "VCDU/BPDU Last Bit Pointer", HFILL }
+ }
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_vcdu,
+ &ett_smex,
+ &ett_vcduh,
+ };
+
+ /* Register the protocol name and description */
+ proto_vcdu = proto_register_protocol("VCDU", "VCDU", "vcdu");
+
+ /* Required function calls to register the header fields and subtrees used */
+ proto_register_field_array(proto_vcdu, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+
+/* If this dissector uses sub-dissector registration add a registration routine.
+ * This format is required because a script is used to find these routines and
+ * create the code that calls these routines.
+ */
+void
+proto_reg_handoff_vcdu(void)
+{
+ register_dissector ( "vcdu", dissect_vcdu, proto_vcdu );
+ dissector_add ( "udp.port", 0, find_dissector("vcdu") );
+ ccsds_handle = find_dissector ( "ccsds" );
+}
+