2 * Routines for VCDU dissection
3 * Copyright 2000, Scott Hovis scott.hovis@ums.msfc.nasa.gov
4 * Enhanced 2008, Matt Dunkle Matthew.L.Dunkle@nasa.gov
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.com>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <epan/packet.h>
16 #include <epan/expert.h>
17 #include <epan/prefs.h>
18 #include <epan/to_str.h>
21 void proto_register_vcdu(void);
22 void proto_reg_handoff_vcdu(void);
24 /* Initialize the protocol and registered fields */
25 static int proto_vcdu
;
27 static int hf_smex_gsc
;
28 /* static int hf_smex_unused; */
29 static int hf_smex_version
;
30 static int hf_smex_framelen
;
31 static int hf_smex_rs_error
;
32 static int hf_smex_rs_enable
;
33 static int hf_smex_crc_enable
;
34 static int hf_smex_crc_error
;
35 static int hf_smex_mcs_enable
;
36 static int hf_smex_mcs_num_error
;
37 static int hf_smex_data_inv
;
38 static int hf_smex_frame_sync
;
39 static int hf_smex_data_dir
;
40 static int hf_smex_data_class
;
41 static int hf_smex_pb5
;
42 static int hf_smex_jday
;
43 static int hf_smex_seconds
;
44 static int hf_smex_msec
;
45 /* static int hf_smex_spare; */
47 static int hf_vcdu_version
;
48 static int hf_vcdu_sp_id
;
49 static int hf_vcdu_vc_id
;
50 static int hf_vcdu_seq
;
51 static int hf_vcdu_replay
;
53 /* Generated from convert_proto_tree_add_text.pl */
54 static int hf_vcdu_data
;
55 static int hf_vcdu_ground_receipt_time
;
56 static int hf_vcdu_ccsds_all_fill
;
57 static int hf_vcdu_bitream_all_fill
;
58 static int hf_vcdu_bitream_all_data
;
59 static int hf_vcdu_bitream_all_data_anomaly
;
60 static int hf_vcdu_ccsds_continuation_packet
;
62 /* although technically not part of the vcdu header, the
63 * first header pointer (for ccsds), and the last bit
64 * pointer (for bitstream), are more easily processed by
65 * simply adding them to the tail end of the vcdu header
66 * branch rather than creating a distinct branch for them
68 static int hf_vcdu_fhp
;
69 static int hf_vcdu_lbp
;
71 static dissector_handle_t vcdu_handle
;
73 static dissector_handle_t ccsds_handle
;
75 /* Initialize the subtree pointers */
80 static expert_field ei_vcdu_fhp_too_close_to_end_of_vcdu
;
83 * Bits in the first 16-bit header word
85 #define SMEX_VERSION 0xc000
86 #define SMEX_FRAMELEN 0x3fff
88 /* some basic sizing parameters */
89 #define IP_HEADER_LENGTH 48
90 #define SMEX_HEADER_LENGTH 20
91 #define VCDU_HEADER_LENGTH 6
92 #define CCSDS_PRIMARY_HEADER_LENGTH 6
93 #define CCSDS_SECONDARY_HEADER_LENGTH 10
95 #define PB5_JULIAN_DAY_MASK 0x7ffe
96 #define PB5_SECONDS_MASK 0x01ffff
97 #define PB5_MILLISECONDS_MASK 0xffc0
99 #define LBP_ALL_DATA 0x3fff
100 #define LBP_ALL_DATA_ANOMALY 0x7ff
101 #define LBP_ALL_FILL 0x3ffe
103 #define FHP_ALL_FILL 0x7fe
104 #define FHP_CONTINUATION 0x7ff
106 #define LBP_MASK 0x3fff
107 #define FHP_MASK 0x07ff
109 /* leap year macro */
111 # define Leap(yr) ( ( 0 == (yr)%4 && 0 != (yr)%100 ) || ( 0 == (yr)%400 ) )
115 static const value_string smex_data_inversion_type
[] = {
116 { 0, "Data True (not inverted)" },
117 { 1, "Data Inverted (not corrected)" },
118 { 2, "Data Inversion State UNDEFINED" },
119 { 3, "Data Inverted (and corrected)" },
123 static const value_string smex_frame_sync_mode
[] = {
131 static const value_string smex_data_direction
[] = {
137 static const value_string smex_data_class
[] = {
138 { 0, "Data Class UNDEFINED" },
139 { 1, "CCSDS Frame" },
140 { 2, "CCSDS Packet" },
142 { 4, "Stopped TDM Frame" },
146 /* default bitstream channel assignments:
147 * the audio channels 4-6 are designated as bitstream channels
148 * the standard bitstream channels are 12 through 19
149 * the video channels 28-30 are designated as bitstream channels
150 * the fill channel 63 is designated as bitstream
152 static int bitstream_channels
[] =
154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* channels 0-9 */
155 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /* channels 10-19 */
156 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* channels 20-29 */
157 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* channels 30-39 */
158 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* channels 40-49 */
159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* channels 50-59 */
160 0, 0, 0, 1 /* channels 60-63 */
167 static uat_channel_t
*uat_bitchannels
;
168 static uat_t
*vcdu_uat
;
169 static unsigned num_channels_uat
;
171 UAT_DEC_CB_DEF(uat_bitchannels
, channel
, uat_channel_t
)
174 vcdu_uat_data_update_cb(void *p
, char **err
) {
175 uat_channel_t
*ud
= (uat_channel_t
*)p
;
177 if (ud
->channel
>= 64) {
178 *err
= g_strdup("Channel must be between 0-63.");
185 vcdu_prefs_apply_cb(void)
189 if (num_channels_uat
> 0)
191 memset(bitstream_channels
, 0, sizeof(bitstream_channels
));
193 for (i
= 0; i
< num_channels_uat
; i
++)
195 bitstream_channels
[uat_bitchannels
[i
].channel
] = 1;
200 /* convert smex PB5 header time to a human readable string - NOT THREAD SAFE
202 * note: this is not true PB5 time either, but a tsi specific version, although it is similar
205 smex_time_to_string (wmem_allocator_t
*pool
, int pb5_days_since_midnight_9_10_oct_1995
, int pb5_seconds
, int pb5_milliseconds
)
207 static int utcdiff
= 0;
210 static int Days
[2][13] =
212 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
213 { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
219 /* compute the static constant difference in seconds
220 * between midnight 9-10 October 1995 (PB5 time) and
221 * seconds since 1/1/1970 (UTC time) just this once
225 for (yr
=1970; yr
< 1995; ++yr
)
227 utcdiff
+= (Leap(yr
) ? 366 : 365) * 24 * 60 * 60;
231 ix
= (Leap(1995) ? 1 : 0);
233 for (month
=1; month
< 10; ++month
)
235 days
+= Days
[ix
][month
];
238 days
+= 9; /* this gets us up to midnight october 9-10 */
240 utcdiff
+= days
* 24 * 60 * 60; /* add days in 1995 prior to October 10 */
243 t
.secs
= (pb5_days_since_midnight_9_10_oct_1995
* 86400) + pb5_seconds
+ utcdiff
;
244 t
.nsecs
= pb5_milliseconds
*1000000; /* msecs to nsecs */
246 return abs_time_to_str(pool
, &t
, ABSOLUTE_TIME_DOY_UTC
, true);
251 dissect_vcdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
254 bool ccsds_tree_added
= false;
256 proto_item
*smex_header
;
257 proto_tree
*smex_tree
;
259 proto_tree
*vcdu_tree
;
260 proto_item
*vcdu_item
;
265 int vcid
, pb5_days
, pb5_seconds
, pb5_milliseconds
;
266 const char *time_string
;
268 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "VCDU");
269 col_set_str(pinfo
->cinfo
, COL_INFO
, "Virtual Channel Data Unit");
271 /* build the smex header tree */
272 smex_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, SMEX_HEADER_LENGTH
, ett_smex
, &smex_header
, "SMEX Header");
274 proto_tree_add_item(smex_tree
, hf_smex_gsc
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
276 /* proto_tree_add_item(smex_tree, hf_smex_unused, tvb, offset, 2, ENC_BIG_ENDIAN); */
279 first_word
= tvb_get_ntohs(tvb
, offset
);
280 proto_tree_add_uint(smex_tree
, hf_smex_version
, tvb
, offset
, 2, first_word
);
281 proto_tree_add_uint(smex_tree
, hf_smex_framelen
, tvb
, offset
, 2, first_word
);
284 proto_tree_add_item(smex_tree
, hf_smex_rs_enable
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
285 proto_tree_add_item(smex_tree
, hf_smex_rs_error
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
286 proto_tree_add_item(smex_tree
, hf_smex_crc_enable
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
287 proto_tree_add_item(smex_tree
, hf_smex_crc_error
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
288 proto_tree_add_item(smex_tree
, hf_smex_mcs_enable
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
289 proto_tree_add_item(smex_tree
, hf_smex_mcs_num_error
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
290 proto_tree_add_item(smex_tree
, hf_smex_data_inv
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
293 proto_tree_add_item(smex_tree
, hf_smex_frame_sync
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
294 proto_tree_add_item(smex_tree
, hf_smex_data_dir
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
295 proto_tree_add_item(smex_tree
, hf_smex_data_class
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
298 /* extract smex ground receipt time tag */
299 long_word
= tvb_get_ntohl(tvb
, offset
);
300 pb5_days
= (long_word
>> 17) & PB5_JULIAN_DAY_MASK
;
301 pb5_seconds
= (long_word
& PB5_SECONDS_MASK
);
303 first_word
= tvb_get_ntohs(tvb
, offset
+4);
304 pb5_milliseconds
= (first_word
& PB5_MILLISECONDS_MASK
) >> 6;
306 proto_tree_add_item(smex_tree
, hf_smex_pb5
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
307 proto_tree_add_item(smex_tree
, hf_smex_jday
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
309 proto_tree_add_item(smex_tree
, hf_smex_seconds
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
312 proto_tree_add_item(smex_tree
, hf_smex_msec
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
313 /* proto_tree_add_item(smex_tree, hf_smex_spare, tvb, offset, 2, ENC_BIG_ENDIAN); */
316 /* format ground receipt time into human readable time format for display */
317 time_string
= smex_time_to_string(pinfo
->pool
, pb5_days
, pb5_seconds
, pb5_milliseconds
);
318 proto_tree_add_string(smex_tree
, hf_vcdu_ground_receipt_time
, tvb
, offset
-6, 6, time_string
);
320 proto_item_set_end(smex_header
, tvb
, offset
);
323 /* build the vcdu header tree */
324 vcdu_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, VCDU_HEADER_LENGTH
, ett_vcdu
, &vcdu_item
, "VCDU Header");
326 /* extract the virtual channel for use later on */
327 first_word
= tvb_get_ntohs(tvb
, offset
);
328 vcid
= first_word
& 0x3f;
330 proto_tree_add_item(vcdu_tree
, hf_vcdu_version
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
331 proto_tree_add_item(vcdu_tree
, hf_vcdu_sp_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
332 proto_tree_add_item(vcdu_tree
, hf_vcdu_vc_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
334 proto_tree_add_item(vcdu_tree
, hf_vcdu_seq
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
336 proto_tree_add_item(vcdu_tree
, hf_vcdu_replay
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
339 /* extract mpdu/bpdu header word */
340 first_word
= tvb_get_ntohs(tvb
, offset
);
342 /* do bitstream channel processing */
343 if (bitstream_channels
[vcid
])
347 /* extract last bit pointer for bitstream channels */
348 new_ptr
= first_word
& LBP_MASK
;
350 /* add last bit pointer to display tree */
351 proto_tree_add_item(vcdu_tree
, hf_vcdu_lbp
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
356 proto_tree_add_item(vcdu_tree
, hf_vcdu_bitream_all_data
, tvb
, 0, -1, ENC_NA
);
359 case LBP_ALL_DATA_ANOMALY
:
360 proto_tree_add_item(vcdu_tree
, hf_vcdu_bitream_all_data_anomaly
, tvb
, 0, -1, ENC_NA
);
364 proto_tree_add_item(vcdu_tree
, hf_vcdu_bitream_all_fill
, tvb
, 0, -1, ENC_NA
);
370 } /* end of bitstream channel processing */
372 /* do ccsds channel processing */
377 /* extract first header pointer for ccsds channels */
378 new_ptr
= first_word
& FHP_MASK
;
380 /* add first header pointer to display tree */
381 proto_tree_add_item(vcdu_tree
, hf_vcdu_fhp
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
383 /* process special cases of first header pointer */
384 if (FHP_ALL_FILL
== new_ptr
)
386 proto_tree_add_item(vcdu_tree
, hf_vcdu_ccsds_all_fill
, tvb
, 0, -1, ENC_NA
);
389 else if (FHP_CONTINUATION
== new_ptr
)
391 proto_tree_add_item(vcdu_tree
, hf_vcdu_ccsds_continuation_packet
, tvb
, 0, -1, ENC_NA
);
394 /* process as many ccsds packet headers as we can using the ccsds packet dissector */
400 /* compute offset and packet boundary lengths for ccsds dissector loop */
401 new_offset
= offset
+ 2 + new_ptr
;
404 tvb_reported_length(tvb
) - VCDU_HEADER_LENGTH
405 - CCSDS_PRIMARY_HEADER_LENGTH
- CCSDS_SECONDARY_HEADER_LENGTH
;
407 while ( ((new_offset
-offset
+2) < packet_boundary
) && ((new_offset
-offset
+2) >= 4) )
412 ccsds_tree_added
= true;
413 ccsds_len
= tvb_get_ntohs(tvb
, new_offset
+4);
415 new_tvb
= tvb_new_subset_remaining(tvb
, new_offset
);
416 call_dissector(ccsds_handle
, new_tvb
, pinfo
, vcdu_tree
);
418 new_offset
= new_offset
+ ccsds_len
+ 7;
421 if (! ccsds_tree_added
)
423 proto_tree_add_expert(vcdu_tree
, pinfo
, &ei_vcdu_fhp_too_close_to_end_of_vcdu
, tvb
, 0, -1);
427 } /* end of ccsds channel processing */
429 /* don't include the mpdu/bpdu header in the vcdu header highlighting.
430 * by skipping the offset bump the vcdu header highlighting will show
431 * just 6 bytes as it really should, and the fhp/lbp will be included
432 * in the data zone, which is technically more correct.
435 proto_item_set_end(vcdu_item
, tvb
, offset
);
437 if (! ccsds_tree_added
)
439 /* add "Data" section if ccsds parsing did not do so already */
440 proto_tree_add_item(vcdu_tree
, hf_vcdu_data
, tvb
, offset
, -1, ENC_NA
);
443 return tvb_captured_length(tvb
);
448 proto_register_vcdu(void)
450 module_t
*vcdu_module
;
452 /* Setup list of header fields See Section 1.6.1 for details*/
453 static hf_register_info hf
[] = {
455 { "Ground Sequence Counter", "vcdu.smex.gsc",
456 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
457 "SMEX Ground Sequence Counter", HFILL
}
461 { "Unused", "vcdu.smex.unused",
462 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
463 "SMEX Unused", HFILL
}
467 { "Version", "vcdu.smex.version",
468 FT_UINT16
, BASE_DEC
, NULL
, SMEX_VERSION
,
469 "SMEX Version", HFILL
}
472 { "Frame Length", "vcdu.smex.frame_len",
473 FT_UINT16
, BASE_DEC
, NULL
, SMEX_FRAMELEN
,
474 "SMEX Frame Length", HFILL
}
476 { &hf_smex_rs_enable
,
477 { "RS Enable", "vcdu.smex.rs_enable",
478 FT_BOOLEAN
, 8, NULL
, 0x80,
479 "SMEX RS Enable", HFILL
}
482 { "RS Error", "vcdu.smex.rs_error",
483 FT_BOOLEAN
, 8, NULL
, 0x40,
484 "SMEX RS Error", HFILL
}
486 { &hf_smex_crc_enable
,
487 { "CRC Enable", "vcdu.smex.crc_enable",
488 FT_BOOLEAN
, 8, NULL
, 0x20,
489 "SMEX CRC Enable", HFILL
}
491 { &hf_smex_crc_error
,
492 { "CRC Error", "vcdu.smex.crc_error",
493 FT_BOOLEAN
, 8, NULL
, 0x10,
494 "SMEX CRC Error", HFILL
}
496 { &hf_smex_mcs_enable
,
497 { "MCS Enable", "vcdu.smex.mcs_enable",
498 FT_BOOLEAN
, 8, NULL
, 0x08,
499 "SMEX MCS Enable", HFILL
}
501 { &hf_smex_mcs_num_error
,
502 { "MCS Number Error", "vcdu.smex.mcs_numerr",
503 FT_BOOLEAN
, 8, NULL
, 0x04,
504 "SMEX MCS Number Error", HFILL
}
507 { "Data Inversion", "vcdu.smex.data_inv",
508 FT_UINT16
, BASE_DEC
, VALS(smex_data_inversion_type
), 0x03,
509 "SMEX Data Inversion", HFILL
}
511 { &hf_smex_frame_sync
,
512 { "Frame Sync", "vcdu.smex.frame_sync",
513 FT_UINT16
, BASE_DEC
, VALS(smex_frame_sync_mode
), 0xc0,
514 "SMEX Frame Sync Flag", HFILL
}
517 { "Data Direction", "vcdu.smex.data_dir",
518 FT_UINT16
, BASE_DEC
, VALS(smex_data_direction
), 0x20,
519 "SMEX Data Direction flag", HFILL
}
521 { &hf_smex_data_class
,
522 { "Data Class", "vcdu.smex.data_class",
523 FT_UINT16
, BASE_DEC
, VALS(smex_data_class
), 0x1f,
524 "SMEX Data Class", HFILL
}
527 { "PB5 Flag", "vcdu.smex.pb5",
528 FT_UINT16
, BASE_DEC
, NULL
, 0x8000,
529 "SMEX PB5 Flag", HFILL
}
532 { "Julian Day", "vcdu.smex.jday",
533 FT_UINT16
, BASE_DEC
, NULL
, PB5_JULIAN_DAY_MASK
,
534 "SMEX Julian Day", HFILL
}
537 { "Seconds", "vcdu.smex.seconds",
538 FT_UINT24
, BASE_DEC
, NULL
, PB5_SECONDS_MASK
,
539 "SMEX Seconds", HFILL
}
542 { "Milliseconds", "vcdu.smex.msec",
543 FT_UINT16
, BASE_DEC
, NULL
, PB5_MILLISECONDS_MASK
,
544 "SMEX Milliseconds", HFILL
}
548 { "Spare", "vcdu.smex.spare",
549 FT_UINT16
, BASE_DEC
, NULL
, 0x003f,
550 "SMEX Spare", HFILL
}
555 { "Version", "vcdu.version",
556 FT_UINT16
, BASE_DEC
, NULL
, 0xc0,
557 "VCDU Version", HFILL
}
560 { "Space Craft ID", "vcdu.spid",
561 FT_UINT16
, BASE_DEC
, NULL
, 0x3fc0,
562 "VCDU Space Craft ID", HFILL
}
565 { "Virtual Channel ID", "vcdu.vcid",
566 FT_UINT16
, BASE_DEC
, NULL
, 0x3f,
567 "VCDU Virtual Channel ID", HFILL
}
570 { "Sequence Count", "vcdu.seq",
571 FT_UINT24
, BASE_DEC
, NULL
, 0x0,
572 "VCDU Sequence Count", HFILL
}
575 { "Replay Flag", "vcdu.replay",
576 FT_BOOLEAN
, 8, NULL
, 0x80,
577 "VCDU Replay Flag", HFILL
}
580 /* Generated from convert_proto_tree_add_text.pl */
581 { &hf_vcdu_ground_receipt_time
, { "Ground Receipt Time", "vcdu.ground_receipt_time", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
582 { &hf_vcdu_bitream_all_data
, { "Bitream ALL Data", "vcdu.bitream.all_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
583 { &hf_vcdu_bitream_all_data_anomaly
, { "Bitream ALL Data (Anomaly)", "vcdu.bitream.all_data_anomaly", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
584 { &hf_vcdu_bitream_all_fill
, { "Bitream ALL Fill", "vcdu.bitream.all_fill", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
585 { &hf_vcdu_ccsds_all_fill
, { "Ccsds ALL Fill", "vcdu.ccsds.all_fill", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
586 { &hf_vcdu_ccsds_continuation_packet
, { "Ccsds Continuation Packet", "vcdu.ccsds_continuation_packet", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
587 { &hf_vcdu_data
, { "Data", "vcdu.data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
589 /* not really part of the vcdu header, but it's easier this way */
591 { "First Header Pointer", "vcdu.fhp",
592 FT_UINT16
, BASE_DEC
, NULL
, FHP_MASK
,
593 "VCDU/MPDU First Header Pointer", HFILL
}
596 { "Last Bit Pointer", "vcdu.lbp",
597 FT_UINT16
, BASE_DEC
, NULL
, LBP_MASK
,
598 "VCDU/BPDU Last Bit Pointer", HFILL
}
602 static uat_field_t vcdu_uat_flds
[] = {
603 UAT_FLD_DEC(uat_bitchannels
, channel
, "Bitstream Channel", "Bitstream Channel"),
607 /* Setup protocol subtree array */
608 static int *ett
[] = {
614 static ei_register_info ei
[] = {
615 { &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
}},
618 expert_module_t
* expert_vcdu
;
620 /* Register the protocol name and description */
621 proto_vcdu
= proto_register_protocol("VCDU", "VCDU", "vcdu");
623 /* Required function calls to register the header fields and subtrees used */
624 proto_register_field_array(proto_vcdu
, hf
, array_length(hf
));
625 proto_register_subtree_array(ett
, array_length(ett
));
626 expert_vcdu
= expert_register_protocol(proto_vcdu
);
627 expert_register_field_array(expert_vcdu
, ei
, array_length(ei
));
629 /* XX: Does this dissector need to be publicly registered ?? */
630 vcdu_handle
= register_dissector("vcdu", dissect_vcdu
, proto_vcdu
);
632 vcdu_module
= prefs_register_protocol(proto_vcdu
, vcdu_prefs_apply_cb
);
634 vcdu_uat
= uat_new("Bitstream Channel Table",
635 sizeof(uat_channel_t
),
636 "vcdu_bitstream_channels",
640 UAT_AFFECTS_DISSECTION
, /* affects dissection of packets, but not set of named fields */
643 vcdu_uat_data_update_cb
,
649 prefs_register_uat_preference(vcdu_module
,
650 "bitstream_channels",
651 "Bitstream Channel Table",
652 "Bitstream Channel Table",
659 proto_reg_handoff_vcdu(void)
661 dissector_add_for_decode_as_with_preference("udp.port", vcdu_handle
);
662 ccsds_handle
= find_dissector_add_dependency("ccsds", proto_vcdu
);
666 * Editor modelines - https://www.wireshark.org/tools/modelines.html
671 * indent-tabs-mode: nil
674 * vi: set shiftwidth=4 tabstop=8 expandtab:
675 * :indentSize=4:tabSize=8:noTabs=true: