diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
commit | e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch) | |
tree | 68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-vcdu.c | |
parent | Initial commit. (diff) | |
download | wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip |
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-vcdu.c')
-rw-r--r-- | epan/dissectors/packet-vcdu.c | 676 |
1 files changed, 676 insertions, 0 deletions
diff --git a/epan/dissectors/packet-vcdu.c b/epan/dissectors/packet-vcdu.c new file mode 100644 index 00000000..b0b6b9c0 --- /dev/null +++ b/epan/dissectors/packet-vcdu.c @@ -0,0 +1,676 @@ +/* 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 + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.com> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include <epan/packet.h> +#include <epan/expert.h> +#include <epan/prefs.h> +#include <epan/to_str.h> +#include <epan/uat.h> + +void proto_register_vcdu(void); +void proto_reg_handoff_vcdu(void); + +/* 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; + +/* Generated from convert_proto_tree_add_text.pl */ +static int hf_vcdu_data = -1; +static int hf_vcdu_ground_receipt_time = -1; +static int hf_vcdu_ccsds_all_fill = -1; +static int hf_vcdu_bitream_all_fill = -1; +static int hf_vcdu_bitream_all_data = -1; +static int hf_vcdu_bitream_all_data_anomaly = -1; +static int hf_vcdu_ccsds_continuation_packet = -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 vcdu_handle; + +static dissector_handle_t ccsds_handle; + +/* Initialize the subtree pointers */ +static gint ett_vcdu = -1; +static gint ett_smex = -1; +static gint ett_vcduh = -1; + +static expert_field ei_vcdu_fhp_too_close_to_end_of_vcdu = EI_INIT; + +/* + * 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 0x07ff + +/* 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 } +}; + +/* 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 */ +}; + +typedef struct { + guint channel; +} uat_channel_t; + +static uat_channel_t *uat_bitchannels = NULL; +static uat_t *vcdu_uat = NULL; +static guint num_channels_uat = 0; + +UAT_DEC_CB_DEF(uat_bitchannels, channel, uat_channel_t) + +static bool +vcdu_uat_data_update_cb(void *p, char **err) { + uat_channel_t *ud = (uat_channel_t *)p; + + if (ud->channel >= 64) { + *err = g_strdup("Channel must be between 0-63."); + return FALSE; + } + return TRUE; +} + +static void +vcdu_prefs_apply_cb(void) +{ + guint i; + + if (num_channels_uat > 0) + { + memset(bitstream_channels, 0, sizeof(bitstream_channels)); + + for (i = 0; i < num_channels_uat; i++) + { + bitstream_channels[uat_bitchannels[i].channel] = 1; + } + } +} + +/* 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 (wmem_allocator_t *pool, int pb5_days_since_midnight_9_10_oct_1995, int pb5_seconds, int pb5_milliseconds) +{ + static int utcdiff = 0; + nstime_t t; + + 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 yr; + 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 */ + } + + t.secs = (pb5_days_since_midnight_9_10_oct_1995 * 86400) + pb5_seconds + utcdiff; + t.nsecs = pb5_milliseconds*1000000; /* msecs to nsecs */ + + return abs_time_to_str(pool, &t, ABSOLUTE_TIME_DOY_UTC, TRUE); +} + + +static int +dissect_vcdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + int offset = 0; + gboolean ccsds_tree_added = FALSE; + + proto_item *smex_header; + proto_tree *smex_tree; + + proto_tree *vcdu_tree; + proto_item *vcdu_item; + + guint16 first_word; + guint32 long_word; + + int vcid, pb5_days, pb5_seconds, pb5_milliseconds; + const char *time_string; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "VCDU"); + col_set_str(pinfo->cinfo, COL_INFO, "Virtual Channel Data Unit"); + + /* build the smex header tree */ + smex_tree = proto_tree_add_subtree(tree, tvb, offset, SMEX_HEADER_LENGTH, ett_smex, &smex_header, "SMEX Header"); + + proto_tree_add_item(smex_tree, hf_smex_gsc, tvb, offset, 8, ENC_BIG_ENDIAN); + offset += 8; + /* proto_tree_add_item(smex_tree, hf_smex_unused, tvb, offset, 2, ENC_BIG_ENDIAN); */ + 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, ENC_BIG_ENDIAN); + proto_tree_add_item(smex_tree, hf_smex_rs_error, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(smex_tree, hf_smex_crc_enable, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(smex_tree, hf_smex_crc_error, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(smex_tree, hf_smex_mcs_enable, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(smex_tree, hf_smex_mcs_num_error, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(smex_tree, hf_smex_data_inv, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(smex_tree, hf_smex_frame_sync, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(smex_tree, hf_smex_data_dir, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(smex_tree, hf_smex_data_class, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* 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, ENC_BIG_ENDIAN); + proto_tree_add_item(smex_tree, hf_smex_jday, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 1; + proto_tree_add_item(smex_tree, hf_smex_seconds, tvb, offset, 3, ENC_BIG_ENDIAN); + offset += 3; + + proto_tree_add_item(smex_tree, hf_smex_msec, tvb, offset, 2, ENC_BIG_ENDIAN); + /* proto_tree_add_item(smex_tree, hf_smex_spare, tvb, offset, 2, ENC_BIG_ENDIAN); */ + offset += 2; + + /* format ground receipt time into human readable time format for display */ + time_string = smex_time_to_string(pinfo->pool, pb5_days, pb5_seconds, pb5_milliseconds); + proto_tree_add_string(smex_tree, hf_vcdu_ground_receipt_time, tvb, offset-6, 6, time_string); + + proto_item_set_end(smex_header, tvb, offset); + + + /* build the vcdu header tree */ + vcdu_tree = proto_tree_add_subtree(tree, tvb, offset, VCDU_HEADER_LENGTH, ett_vcdu, &vcdu_item, "VCDU Header"); + + /* 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, ENC_BIG_ENDIAN); + proto_tree_add_item(vcdu_tree, hf_vcdu_sp_id, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(vcdu_tree, hf_vcdu_vc_id, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + proto_tree_add_item(vcdu_tree, hf_vcdu_seq, tvb, offset, 3, ENC_BIG_ENDIAN); + offset += 3; + proto_tree_add_item(vcdu_tree, hf_vcdu_replay, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* extract mpdu/bpdu header word */ + first_word = tvb_get_ntohs(tvb, offset); + + /* do bitstream channel processing */ + if (bitstream_channels[vcid]) + { + guint16 new_ptr; + + /* 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, ENC_BIG_ENDIAN); + + switch (new_ptr) + { + case LBP_ALL_DATA: + proto_tree_add_item(vcdu_tree, hf_vcdu_bitream_all_data, tvb, 0, -1, ENC_NA); + break; + + case LBP_ALL_DATA_ANOMALY: + proto_tree_add_item(vcdu_tree, hf_vcdu_bitream_all_data_anomaly, tvb, 0, -1, ENC_NA); + break; + + case LBP_ALL_FILL: + proto_tree_add_item(vcdu_tree, hf_vcdu_bitream_all_fill, tvb, 0, -1, ENC_NA); + break; + + default: + break; + } + } /* end of bitstream channel processing */ + + /* do ccsds channel processing */ + else + { + guint16 new_ptr; + + /* 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, ENC_BIG_ENDIAN); + + /* process special cases of first header pointer */ + if (FHP_ALL_FILL == new_ptr) + { + proto_tree_add_item(vcdu_tree, hf_vcdu_ccsds_all_fill, tvb, 0, -1, ENC_NA); + } + + else if (FHP_CONTINUATION == new_ptr) + { + proto_tree_add_item(vcdu_tree, hf_vcdu_ccsds_continuation_packet, tvb, 0, -1, ENC_NA); + } + + /* process as many ccsds packet headers as we can using the ccsds packet dissector */ + else + { + int packet_boundary; + int new_offset; + + /* compute offset and packet boundary lengths for ccsds dissector loop */ + new_offset = offset + 2 + new_ptr; + + packet_boundary = + tvb_reported_length(tvb) - VCDU_HEADER_LENGTH + - CCSDS_PRIMARY_HEADER_LENGTH - CCSDS_SECONDARY_HEADER_LENGTH; + + while ( ((new_offset-offset+2) < packet_boundary) && ((new_offset-offset+2) >= 4) ) + { + int ccsds_len; + tvbuff_t *new_tvb; + + ccsds_tree_added = TRUE; + ccsds_len = tvb_get_ntohs(tvb, new_offset+4); + + new_tvb = tvb_new_subset_remaining(tvb, new_offset); + call_dissector(ccsds_handle, new_tvb, pinfo, vcdu_tree); + + new_offset = new_offset + ccsds_len + 7; + } + + if (! ccsds_tree_added) + { + proto_tree_add_expert(vcdu_tree, pinfo, &ei_vcdu_fhp_too_close_to_end_of_vcdu, tvb, 0, -1); + } + } + + } /* 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_item, tvb, offset); + + if (! ccsds_tree_added) + { + /* add "Data" section if ccsds parsing did not do so already */ + proto_tree_add_item(vcdu_tree, hf_vcdu_data, tvb, offset, -1, ENC_NA); + } + + return tvb_captured_length(tvb); +} + + +void +proto_register_vcdu(void) +{ + module_t *vcdu_module; + + /* Setup list of header fields See Section 1.6.1 for details*/ + static hf_register_info hf[] = { + { &hf_smex_gsc, + { "Ground Sequence Counter", "vcdu.smex.gsc", + FT_UINT64, BASE_DEC, NULL, 0x0, + "SMEX Ground Sequence Counter", HFILL } + }, +#if 0 + { &hf_smex_unused, + { "Unused", "vcdu.smex.unused", + FT_UINT16, BASE_DEC, NULL, 0x0, + "SMEX Unused", HFILL } + }, +#endif + { &hf_smex_version, + { "Version", "vcdu.smex.version", + FT_UINT16, BASE_DEC, NULL, SMEX_VERSION, + "SMEX Version", HFILL } + }, + { &hf_smex_framelen, + { "Frame Length", "vcdu.smex.frame_len", + FT_UINT16, BASE_DEC, NULL, SMEX_FRAMELEN, + "SMEX Frame Length", HFILL } + }, + { &hf_smex_rs_enable, + { "RS Enable", "vcdu.smex.rs_enable", + FT_BOOLEAN, 8, NULL, 0x80, + "SMEX RS Enable", HFILL } + }, + { &hf_smex_rs_error, + { "RS Error", "vcdu.smex.rs_error", + FT_BOOLEAN, 8, NULL, 0x40, + "SMEX RS Error", HFILL } + }, + { &hf_smex_crc_enable, + { "CRC Enable", "vcdu.smex.crc_enable", + FT_BOOLEAN, 8, NULL, 0x20, + "SMEX CRC Enable", HFILL } + }, + { &hf_smex_crc_error, + { "CRC Error", "vcdu.smex.crc_error", + FT_BOOLEAN, 8, NULL, 0x10, + "SMEX CRC Error", HFILL } + }, + { &hf_smex_mcs_enable, + { "MCS Enable", "vcdu.smex.mcs_enable", + FT_BOOLEAN, 8, NULL, 0x08, + "SMEX MCS Enable", HFILL } + }, + { &hf_smex_mcs_num_error, + { "MCS Number Error", "vcdu.smex.mcs_numerr", + FT_BOOLEAN, 8, NULL, 0x04, + "SMEX MCS Number Error", HFILL } + }, + { &hf_smex_data_inv, + { "Data Inversion", "vcdu.smex.data_inv", + FT_UINT16, BASE_DEC, VALS(smex_data_inversion_type), 0x03, + "SMEX Data Inversion", HFILL } + }, + { &hf_smex_frame_sync, + { "Frame Sync", "vcdu.smex.frame_sync", + FT_UINT16, BASE_DEC, VALS(smex_frame_sync_mode), 0xc0, + "SMEX Frame Sync Flag", HFILL } + }, + { &hf_smex_data_dir, + { "Data Direction", "vcdu.smex.data_dir", + FT_UINT16, BASE_DEC, VALS(smex_data_direction), 0x20, + "SMEX Data Direction flag", HFILL } + }, + { &hf_smex_data_class, + { "Data Class", "vcdu.smex.data_class", + FT_UINT16, BASE_DEC, VALS(smex_data_class), 0x1f, + "SMEX Data Class", HFILL } + }, + { &hf_smex_pb5, + { "PB5 Flag", "vcdu.smex.pb5", + FT_UINT16, BASE_DEC, NULL, 0x8000, + "SMEX PB5 Flag", HFILL } + }, + { &hf_smex_jday, + { "Julian Day", "vcdu.smex.jday", + FT_UINT16, BASE_DEC, NULL, PB5_JULIAN_DAY_MASK, + "SMEX Julian Day", HFILL } + }, + { &hf_smex_seconds, + { "Seconds", "vcdu.smex.seconds", + FT_UINT24, BASE_DEC, NULL, PB5_SECONDS_MASK, + "SMEX Seconds", HFILL } + }, + { &hf_smex_msec, + { "Milliseconds", "vcdu.smex.msec", + FT_UINT16, BASE_DEC, NULL, PB5_MILLISECONDS_MASK, + "SMEX Milliseconds", HFILL } + }, +#if 0 + { &hf_smex_spare, + { "Spare", "vcdu.smex.spare", + FT_UINT16, BASE_DEC, NULL, 0x003f, + "SMEX Spare", HFILL } + }, +#endif + + { &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_UINT24, BASE_DEC, NULL, 0x0, + "VCDU Sequence Count", HFILL } + }, + { &hf_vcdu_replay, + { "Replay Flag", "vcdu.replay", + FT_BOOLEAN, 8, NULL, 0x80, + "VCDU Replay Flag", HFILL } + }, + + /* Generated from convert_proto_tree_add_text.pl */ + { &hf_vcdu_ground_receipt_time, { "Ground Receipt Time", "vcdu.ground_receipt_time", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_vcdu_bitream_all_data, { "Bitream ALL Data", "vcdu.bitream.all_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_vcdu_bitream_all_data_anomaly, { "Bitream ALL Data (Anomaly)", "vcdu.bitream.all_data_anomaly", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_vcdu_bitream_all_fill, { "Bitream ALL Fill", "vcdu.bitream.all_fill", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_vcdu_ccsds_all_fill, { "Ccsds ALL Fill", "vcdu.ccsds.all_fill", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_vcdu_ccsds_continuation_packet, { "Ccsds Continuation Packet", "vcdu.ccsds_continuation_packet", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_vcdu_data, { "Data", "vcdu.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, 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 } + } + }; + + static uat_field_t vcdu_uat_flds[] = { + UAT_FLD_DEC(uat_bitchannels, channel, "Bitstream Channel", "Bitstream Channel"), + UAT_END_FIELDS + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_vcdu, + &ett_smex, + &ett_vcduh, + }; + + static ei_register_info ei[] = { + { &ei_vcdu_fhp_too_close_to_end_of_vcdu, { "vcdu.fhp_too_close_to_end_of_vcdu", PI_PROTOCOL, PI_WARN, "FHP too close to end of VCDU. Incomplete Hdr Info Available - Unable to format CCSDS Hdr(s).", EXPFILL }}, + }; + + expert_module_t* expert_vcdu; + + /* 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)); + expert_vcdu = expert_register_protocol(proto_vcdu); + expert_register_field_array(expert_vcdu, ei, array_length(ei)); + + /* XX: Does this dissector need to be publicly registered ?? */ + vcdu_handle = register_dissector("vcdu", dissect_vcdu, proto_vcdu); + + vcdu_module = prefs_register_protocol(proto_vcdu, vcdu_prefs_apply_cb); + + vcdu_uat = uat_new("Bitstream Channel Table", + sizeof(uat_channel_t), + "vcdu_bitstream_channels", + TRUE, + &uat_bitchannels, + &num_channels_uat, + UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */ + NULL, + NULL, + vcdu_uat_data_update_cb, + NULL, + NULL, + NULL, + vcdu_uat_flds); + + prefs_register_uat_preference(vcdu_module, + "bitstream_channels", + "Bitstream Channel Table", + "Bitstream Channel Table", + vcdu_uat); + +} + + +void +proto_reg_handoff_vcdu(void) +{ + dissector_add_for_decode_as_with_preference("udp.port", vcdu_handle); + ccsds_handle = find_dissector_add_dependency("ccsds", proto_vcdu); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ |