Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-amp.c
blob3e9086aa9f3144a833d2e75a8b49b14e02759c95
1 /* packet-amp.c
2 * Routines for Asynchronous management Protocol dissection
3 * Copyright 2018, Krishnamurthy Mayya (krishnamurthymayya@gmail.com)
4 * Updated to CBOR encoding: Keith Scott, 2019 (kscott@mitre.org)
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/exceptions.h>
15 #include <epan/expert.h>
16 #include <epan/packet.h>
17 #include <epan/tfs.h>
18 #include "packet-amp.h"
20 /* The AMP standard can be found here:
21 * https://tools.ietf.org/html/draft-birrane-dtn-amp-04
22 * https://tools.ietf.org/html/draft-birrane-dtn-amp-03
25 #define AMP_APID 0x000 /* TODO - To be decided. Currently, the function 'dissect_amp_as_subtree' is
26 being called from dtn.c file when required to decode the bundle protocol's
27 data-payload as AMP. Later in the future, when a dedicated field is given to
28 this, this should be filled. */
32 static void
33 add_value_time_to_tree(uint64_t value, int len, proto_tree *tree, tvbuff_t *tvb, int offset, int hf_time_format)
35 nstime_t dtn_time;
37 // If it's a relative time, just make it zero.
38 if ( value < 558230400 ) {
39 value = 0;
41 dtn_time.secs = (time_t)(value);
42 dtn_time.nsecs = 0;
43 proto_tree_add_time(tree, hf_time_format, tvb, offset, len, &dtn_time);
45 return;
48 #define AMP_HDR_RESERVED 0xC0
49 #define AMP_HDR_ACL 0x20
50 #define AMP_HDR_NACK 0x10
51 #define AMP_HDR_ACK 0x08
52 #define AMP_HDR_OPCODE 0x07
54 #define AMP_ARI_NICKNAME 0x80
55 #define AMP_ARI_PARAMETERS 0x40
56 #define AMP_ARI_ISSUER 0x20
57 #define AMP_ARI_TAG 0x10
58 #define AMP_ARI_STRUCT 0x0F
59 #define AMP_ARI_VALUE 0xF0
61 #define AMP_CBOR_UINT_SMALL 0x1F
63 #define AMP_TNVC_RESERVED 0xF0
64 #define AMP_TNVC_MIXED 0x08
65 #define AMP_TNVC_TYPE 0x04
66 #define AMP_TNVC_NAME 0x02
67 #define AMP_TNVC_VALUE 0x01
69 #define AMP_MSG_REGISTER_AGENT 0x01
70 #define AMP_MSG_DATA_REPORT 0x00
71 #define AMP_MSG_PERFORM_CONTROL 0x02
73 static dissector_handle_t amp_handle;
75 void proto_register_amp(void);
76 void proto_reg_handoff_amp(void);
78 static int hf_amp_message_header;
79 static int hf_amp_report_bytestring;
80 static int hf_amp_report_data;
81 static int hf_amp_report_integer8_small;
82 static int hf_amp_report_integer;
83 static int hf_amp_cbor_header;
84 static int hf_amp_primary_timestamp;
85 static int hf_amp_agent_name;
86 static int hf_amp_text_string;
87 static int hf_amp_ari_flags;
88 static int hf_ari_value;
89 static int hf_ari_struct;
90 static int hf_ari_nickname;
91 static int hf_ari_parameters;
92 static int hf_ari_issuer;
93 static int hf_ari_tag;
94 static int hf_amp_tnvc_flags;
95 static int hf_amp_tnvc_reserved;
96 static int hf_amp_tnvc_mixed;
97 static int hf_amp_tnvc_typed;
98 static int hf_amp_tnvc_name;
99 static int hf_amp_tnvc_values;
101 /* Initialize the protocol and registered fields */
102 static int proto_amp;
104 static int ett_amp_message_header;
105 static int ett_amp_proto;
106 static int ett_amp;
107 static int ett_amp_cbor_header;
108 static int ett_amp_message;
109 static int ett_amp_register;
110 static int ett_amp_report_set;
111 static int ett_amp_report;
112 static int ett_amp_tnvc_flags;
113 static int ett_amp_ari_flags;
115 static int hf_amp_reserved;
116 static int hf_amp_acl;
117 static int hf_amp_nack;
118 static int hf_amp_ack;
119 static int hf_amp_opcode;
120 static int hf_amp_rx_name;
122 static expert_field ei_amp_cbor_malformed;
124 static const value_string opcode[] = {
125 { 0, "Register Agent" },
126 { 1, "Report Set" },
127 { 2, "Perform Control" },
128 { 0, NULL }
131 static const value_string amp_ari_struct_type[] = {
132 { 0, "Const" },
133 { 1, "Control" },
134 { 2, "Externally Defined Data" },
135 { 3, "Macro" },
136 { 4, "Operation" },
137 { 5, "Report Template" },
138 { 6, "State-Based Rule" },
139 { 7, "Table Templates" },
140 { 8, "Time-Based Rule" },
141 { 9, "Variables" },
142 { 10, "Metadata" },
143 { 11, "Reserved" },
144 { 12, "Reserved" },
145 { 13, "Reserved" },
146 { 14, "Reserved" },
147 { 15, "Reserved" },
148 { 0, NULL }
152 /* AMP Message Header */
153 static int * const amp_message_header[] = {
154 &hf_amp_reserved,
155 &hf_amp_acl,
156 &hf_amp_nack,
157 &hf_amp_ack,
158 &hf_amp_opcode,
162 /* TNVC Flags */
163 static int * const amp_tnvc_flags[] = {
164 &hf_amp_tnvc_reserved,
165 &hf_amp_tnvc_mixed,
166 &hf_amp_tnvc_typed,
167 &hf_amp_tnvc_name,
168 &hf_amp_tnvc_values,
172 /* ARI Flags */
173 static int * const amp_ari_flags[] = {
174 &hf_ari_nickname,
175 &hf_ari_parameters,
176 &hf_ari_issuer,
177 &hf_ari_tag,
178 &hf_ari_struct,
182 /* CBOR Types */
183 typedef enum {
184 CBOR_UNKNOWN = -1,
185 CBOR_UINT = 0, // Positive, unsigned integer
186 CBOR_INT = 1, // Negative integer
187 CBOR_BYTESTRING = 2,
188 CBOR_TEXTSTRING = 3,
189 CBOR_ARRAY = 4,
190 CBOR_MAP = 5,
191 CBOR_SEMANTIC_TAG = 6,
192 CBOR_PRIMITIVE = 7
193 } CBOR_TYPE;
195 typedef struct {
196 int type;
197 int size; // for integers, the value
198 // for bytestrings and textstrings, the size of the string
199 // for arrays, the number of elements in the array
200 uint64_t totalSize; // total size (including size above and any bytestring
201 // size).
202 uint64_t uint;
203 } cborObj;
206 // Decode the CBOR object at the given offset in the tvb.
207 // The returned cborObj contains the object (with type) and the size
208 // (including the CBOR identifier).
209 static cborObj cbor_info(tvbuff_t *tvb, int offset)
211 int tmp = 0;
212 cborObj ret;
213 ret.type = CBOR_UNKNOWN;
214 ret.size = 0;
215 ret.totalSize = 0;
216 ret.uint = -1;
217 int theSize;
219 tmp = tvb_get_uint8(tvb, offset);
221 offset += 1;
222 ret.size += 1;
224 ret.type = (tmp & 0xE0)>>5; // Top 3 bits
225 theSize = (tmp & 0x1F);
227 switch ( ret.type )
229 case 0x00: // Positive / Unsigned integer
230 if ( theSize<24 ) {
231 ret.uint = (tmp & 0x1F); // May be actual size or indication of follow-on size
232 } else if (theSize==24) { // next byte is uint8_t data
233 ret.uint = tvb_get_uint8(tvb, offset);
234 ret.size += 1;
235 } else if (theSize==25) { // next 2 bytes are uint16_t data
236 ret.uint = tvb_get_uint16(tvb, offset, 0);
237 ret.size += 2;
238 } else if (theSize==26) { // next 4 bytes are uint32_t data
239 ret.uint = tvb_get_uint32(tvb, offset, 0);
240 ret.size += 4;
241 } else if (theSize==27) { // next 8 bytes are uint64_t data
242 ret.uint = tvb_get_uint64(tvb, offset, 0);
243 ret.size += 8;
245 ret.totalSize = ret.size;
246 break;
248 case 0x02: // Byte string
249 if ( theSize<24 ) { // Array size is contained in the identifier byte
250 ret.uint = (tmp & 0x1F);
251 } else if (theSize==24) { // next byte is uint8_t data (length)
252 ret.uint = tvb_get_uint8(tvb, offset);
253 ret.size += 1;
254 } else if (theSize==25) { // next 2bytes are uint16_t data (length)
255 ret.uint = tvb_get_uint16(tvb, offset, 0);
256 ret.size += 2;
257 } else if (theSize==26) { // next 4bytes are uint32_t data
258 ret.uint = tvb_get_uint32(tvb, offset, 0);
259 ret.size += 4;
260 } else if (theSize==27) { // next byte is uint64_t data
261 ret.uint = tvb_get_uint64(tvb, offset, 0);
262 ret.size += 8;
264 ret.totalSize = ret.size+ret.uint;
265 break;
267 case 0x03: // Text string
268 if ( theSize<24 ) // Array size is contained in the identifier byte
270 ret.uint = (tmp & 0x1F);
271 } else if (theSize==24) // next byte is uint8_t data
273 ret.uint = tvb_get_uint8(tvb, offset);
274 ret.size += 1;
275 } else if (theSize==25) // next 2bytes are uint16_t data
277 ret.uint = tvb_get_uint16(tvb, offset, 0);
278 ret.size += 2;
279 } else if (theSize==26) // next 4bytes are uint32_t data
281 ret.uint = tvb_get_uint32(tvb, offset, 0);
282 ret.size += 4;
283 } else if (theSize==27) // next byte is uint64_t data
285 ret.uint = tvb_get_uint64(tvb, offset, 0);
286 ret.size += 8;
288 ret.totalSize = ret.size+ret.uint;
289 break;
291 case 0x04: // Array
292 if ( theSize<24 ) // Array size is contained in the identifier byte
294 ret.uint = (tmp & 0x1F);
295 } else if (theSize==24) // next byte is uint8_t data
297 ret.uint = tvb_get_uint8(tvb, offset);
298 ret.size += 1;
299 } else if (theSize==25) // next 2bytes are uint16_t data
301 ret.uint = tvb_get_uint16(tvb, offset, 0);
302 ret.size += 2;
303 } else if (theSize==26) // next 4bytes are uint32_t data
305 ret.uint = tvb_get_uint32(tvb, offset, 0);
306 ret.size += 4;
307 } else if (theSize==27) // next byte is uint64_t data
309 ret.uint = tvb_get_uint64(tvb, offset, 0);
310 ret.size += 8;
312 // I know how many elements are in the array, but NOT the total
313 // size of the array data.
314 ret.totalSize = -1;
315 break;
317 case 0x06: // Semantic tag
318 if ( theSize<24 )
320 ret.uint = (tmp & 0x1F);
322 ret.totalSize += ret.uint;
323 break;
325 case 0x01: // Negative integer
326 case 0x07: // Primitives e.g. break, float, simple values
327 default:
328 // TODO -- not supported yet.
329 break;
331 return ret;
334 void
335 dissect_amp_as_subtree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
337 uint64_t messages = 0;
338 unsigned int i=0;
339 unsigned int j=0;
340 unsigned int k=0;
341 unsigned int numTNVCEntries = 0;
343 proto_tree *amp_tree = NULL;
344 proto_tree *amp_items_tree = NULL;
345 proto_tree *amp_register_tree = NULL;
346 proto_tree *amp_report_set_tree = NULL;
347 proto_tree *amp_report_tree = NULL;
348 proto_tree *amp_report_TNVC_tree = NULL;
349 proto_tree *amp_control_tree = NULL;
350 proto_tree *amp_table_tree = NULL;
351 proto_item *payload_item = NULL;
352 proto_tree *amp_message_tree = NULL;
353 proto_tree *amp_report_TNVC_sub_tree = NULL;
354 proto_item *amp_message = NULL;
355 proto_item *amp_register = NULL;
356 proto_item *amp_report_set = NULL;
357 proto_item *amp_report = NULL;
359 cborObj myObj;
360 cborObj tmpObj;
361 cborObj tmpObj2;
362 cborObj tmpObj3;
363 cborObj tmpObj4;
364 int reportHasTimestamp = 0;
365 int report_types_offset = 0;
367 amp_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_amp_proto,
368 &payload_item, "Payload Data: AMP Protocol");
370 // First byte is the main CBOR type (probably an array of things)
371 // e.g. 0x82 (byte array of 2 things)
372 myObj = cbor_info(tvb, offset);
373 offset += myObj.size;
374 messages = myObj.uint;
376 // Item 0 is the timestamp
377 myObj = cbor_info(tvb, offset);
378 add_value_time_to_tree((int) myObj.uint, MIN(myObj.size-1, 1), amp_tree, tvb, offset, hf_amp_primary_timestamp);
379 offset += myObj.size;
381 for ( i=1; i<messages; i++ ) {
382 // Get the bytestring object that gives the total length of the AMP chunk
383 myObj = cbor_info(tvb, offset);
384 offset += myObj.size; // Note: myObj.uint is the length of the amp chunk; used later
385 // to advance offset past this message.
387 // The first byte of this byte string (the AMP message) is going to be the message header
388 // This is just a byte, not a CBOR uint8
389 int ampHeader;
390 ampHeader = tvb_get_uint8(tvb, offset);
391 amp_message_tree = proto_tree_add_subtree(amp_tree, tvb, offset, -1,
392 ett_amp_message, &amp_message, "AMP Message");
394 proto_tree_add_bitmask(amp_message_tree, tvb, offset, hf_amp_message_header, ett_amp_message_header,
395 amp_message_header, ENC_BIG_ENDIAN);
396 offset += 1;
397 int old_offset;
399 switch ( ampHeader & 0x07)
401 case 0x00: // Register agent
402 //amp_register_sub_tree = proto_item_add_subtree(amp_message_tree, ett_amp);
403 amp_register_tree = proto_tree_add_subtree(amp_message_tree, tvb, offset-1, 1,
404 ett_amp_register, &amp_register, "Register-Agent");
405 tmpObj = cbor_info(tvb, offset); // Should come back a CBOR text string if some length.
406 offset += tmpObj.size;
407 proto_tree_add_item(amp_register_tree, hf_amp_agent_name, tvb, offset,
408 (int) tmpObj.uint, ENC_ASCII|ENC_NA);
409 old_offset = offset;
410 offset += (int) tmpObj.uint;
411 if (offset < old_offset) {
412 proto_tree_add_expert(amp_tree, pinfo, &ei_amp_cbor_malformed, tvb, offset, -1);
413 return;
415 break;
417 case 0x01: // Report set
418 amp_report_set_tree = proto_tree_add_subtree(amp_message_tree, tvb, offset-2, -1,
419 ett_amp_report_set, &amp_report_set, "Report-Set");
421 // Rx Names
422 tmpObj = cbor_info(tvb, offset); // Should come back a CBOR array of some size (Rx Names)
423 if ( tmpObj.type != 0x04 ) {
424 return;
426 offset += tmpObj.size;
427 // read rx names
428 for ( j=0; j<tmpObj.uint; j++ ) {
429 tmpObj2 = cbor_info(tvb, offset); // Should be text string of some size
430 offset += tmpObj2.size;
431 proto_tree_add_item(amp_report_set_tree, hf_amp_rx_name, tvb, offset,
432 (int) tmpObj2.uint, ENC_ASCII|ENC_NA);
433 old_offset = offset;
434 offset += (int) tmpObj2.uint;
435 if (offset < old_offset) {
436 proto_tree_add_expert(amp_tree, pinfo, &ei_amp_cbor_malformed, tvb, offset, -1);
437 return;
441 // How many reports?
442 tmpObj2 = cbor_info(tvb, offset); // Should come back a CBOR array of some size
443 offset += tmpObj.size;
445 for ( j=0; j<tmpObj2.uint; j++ ) {
446 // Internals of each report per section 8.4.7 of https://tools.ietf.org/pdf/draft-birrane-dtn-amp-07.pdf
447 // amp_report_sub_tree = proto_item_add_subtree(amp_report_set_tree, ett_amp);
448 amp_report_tree = proto_tree_add_subtree(amp_report_set_tree, tvb, offset, -1,
449 ett_amp_report, &amp_report, "Report");
451 // Each Report is a:
452 // Tempate [ARI]
453 // Timestamp [TS] (opt)
454 // Entries [TNVC] (bytestring containing a TNVC)
455 tmpObj3 = cbor_info(tvb, offset); // Should come back a CBOR array of size 2 or 3
456 offset += tmpObj3.size;
457 if ( tmpObj3.uint==3 )
459 reportHasTimestamp = 1;
460 } else
462 reportHasTimestamp = 0;
465 // Tempate (bytestring); starts with ARI
466 tmpObj3 = cbor_info(tvb, offset);
467 offset += tmpObj3.size;
468 uint8_t ariFlags;
469 ariFlags = tvb_get_uint8(tvb, offset);
471 if ( (ariFlags&0x0F)==0x03 ) {
472 // Literal
473 proto_tree_add_uint(amp_report_tree, hf_ari_value, tvb, offset, 1, ariFlags);
474 } else {
475 // NOT literal
476 proto_tree_add_bitmask(amp_report_tree, tvb, offset, hf_amp_ari_flags, ett_amp_ari_flags,
477 amp_ari_flags, ENC_BIG_ENDIAN);
480 //proto_tree_add_uint(amp_ari_tree, hf_ari_struct, tvb, offset, 1, ariFlags);
482 if ( (ariFlags & 0x0F) != 0x03 )
484 // ARI is NOT Literal
485 proto_tree_add_item(amp_report_tree, hf_amp_report_bytestring, tvb, offset+1, (int) tmpObj3.uint-1, ENC_NA);
487 old_offset = offset;
488 offset += (int) tmpObj3.uint;
489 if (offset < old_offset) {
490 proto_tree_add_expert(amp_tree, pinfo, &ei_amp_cbor_malformed, tvb, offset, -1);
491 return;
494 if ( reportHasTimestamp )
496 tmpObj3 = cbor_info(tvb, offset);
497 offset += 1;
498 add_value_time_to_tree((int) tmpObj3.uint, 4, amp_report_tree, tvb, offset, hf_amp_primary_timestamp);
499 offset += (tmpObj3.size-1);
502 // Entries [TNVC] -- This is th collection of data values that comprise the report
503 // contents in accordance with the associated Report Template.
504 // Contained in a CBOR bytestring
505 tmpObj3 = cbor_info(tvb, offset);
506 offset += tmpObj3.size;
508 // Now read array length for TNVC
509 tmpObj3 = cbor_info(tvb, offset);
510 offset += tmpObj3.size;
511 numTNVCEntries = (int) tmpObj3.uint;
513 // TNVC Flags
514 proto_tree_add_bitmask(amp_report_tree, tvb, offset, hf_amp_tnvc_flags, ett_amp_tnvc_flags,
515 amp_tnvc_flags, ENC_BIG_ENDIAN);
516 offset += 1;
518 // TNVC entries
519 amp_report_TNVC_sub_tree = proto_item_add_subtree(amp_report_tree, ett_amp);
520 amp_report_TNVC_tree = proto_tree_add_subtree(amp_report_TNVC_sub_tree, tvb, offset, -1,
521 ett_amp_message, &amp_message, "TNVC Entries");
523 // Byte string containing data types
524 tmpObj3 = cbor_info(tvb, offset);
525 offset += tmpObj3.size;
526 report_types_offset = offset;
527 offset += (int) tmpObj3.uint;
528 if (offset < report_types_offset) {
529 proto_tree_add_expert(amp_tree, pinfo, &ei_amp_cbor_malformed, tvb, offset, -1);
530 return;
533 // TNVC data items
534 for ( k=0; k<numTNVCEntries-2; k++ ) {
535 tmpObj3 = cbor_info(tvb, offset);
536 switch ( tmpObj3.type ) {
537 case 0x02: // bytestring
538 // Get the type from the type dictionary
539 switch ( tvb_get_uint8(tvb, report_types_offset+k) ) {
540 case 0x12: // string
541 // It's a text string of some size INSIDE a byte string
542 tmpObj4 = cbor_info(tvb, offset+tmpObj3.size);
543 // printf("tmpObj4.type of (%02x) is (%d)\n", tvb_get_uint8(tvb, offset+tmpObj3.size), tmpObj4.type);
544 proto_tree_add_item(amp_report_TNVC_tree, hf_amp_text_string, tvb,
545 offset+tmpObj3.size+tmpObj4.size,
546 (int) tmpObj3.uint-tmpObj4.size, 0x00);
547 break;
548 case 0x16: // uvast
549 tmpObj4 = cbor_info(tvb, offset+tmpObj3.size);
550 if ( tmpObj4.type != CBOR_UINT ) {
551 break;
553 switch ( tmpObj4.size ) {
554 case 1:
555 proto_tree_add_item(amp_report_TNVC_tree, hf_amp_report_integer8_small,
556 tvb, offset+tmpObj3.size, 1, 0x00);
557 break;
558 default: // Note: CBOR will only let these sizes be 1, 2, 4, or 8 bytes.
559 proto_tree_add_item(amp_report_TNVC_tree, hf_amp_report_integer,
560 tvb, offset+tmpObj3.size+1, tmpObj4.size-1, 0x00);
561 break;
563 break;
564 default:
565 break;
567 break;
568 default:
569 proto_tree_add_item(amp_report_TNVC_tree, hf_amp_report_data, tvb, offset+tmpObj3.size, (int) tmpObj3.uint, 0x00);
570 break;
572 if ( tmpObj3.totalSize > 0 ) {
573 DISSECTOR_ASSERT(tmpObj3.totalSize <= INT32_MAX);
574 offset += (int)tmpObj3.totalSize;
575 } else {
576 break;
581 break;
583 case 0x02: // Perform Control
584 // TODO
585 //amp_control_sub_tree = proto_item_add_subtree(amp_message_tree, ett_amp);
586 amp_control_tree = proto_tree_add_subtree(amp_message_tree, tvb, offset-1, -1,
587 ett_amp_message, &amp_message, "Perform-Control");
588 proto_tree_add_item(amp_control_tree, hf_amp_cbor_header, tvb, offset, 1, ENC_BIG_ENDIAN);
589 break;
591 case 0x03: // Table Set
592 // TODO
593 //amp_table_sub_tree = proto_item_add_subtree(amp_items_tree, ett_amp);
594 amp_table_tree = proto_tree_add_subtree(amp_items_tree, tvb, offset, -1,
595 ett_amp_message, &amp_message, "AMP Message: Table-Set");
596 proto_tree_add_item(amp_table_tree, hf_amp_cbor_header, tvb, offset, 1, ENC_BIG_ENDIAN);
597 break;
598 default:
599 break;
603 return;
606 /* Code to actually dissect the packets */
607 static int
608 dissect_amp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
610 int offset = 0;
611 proto_item *amp_packet;
612 proto_item *amp_tree;
613 int amp_packet_reported_length;
615 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AMP");
616 col_clear(pinfo->cinfo, COL_INFO);
618 amp_packet_reported_length = tvb_reported_length_remaining(tvb, 0);
620 amp_packet = proto_tree_add_item(tree, proto_amp, tvb, 0, amp_packet_reported_length, ENC_NA);
621 amp_tree = proto_item_add_subtree(amp_packet, ett_amp);
623 dissect_amp_as_subtree (tvb, pinfo, amp_tree, offset);
625 return tvb_captured_length(tvb);
628 void
629 proto_register_amp(void)
631 static hf_register_info hf[] = {
633 { &hf_amp_message_header,
634 { "AMP Message Header", "amp.message.header",
635 FT_UINT8, BASE_DEC, NULL, 0x0,
636 NULL, HFILL }
638 { &hf_amp_report_data,
639 { "Report-Data", "amp.report.data",
640 FT_BYTES, BASE_NONE, NULL, 0x0,
641 NULL, HFILL }
643 { &hf_amp_report_bytestring,
644 { "Report-Bytestring", "amp.report.bytestring",
645 FT_BYTES, BASE_NONE, NULL, 0x0,
646 NULL, HFILL }
648 { &hf_amp_report_integer8_small,
649 { "Report-Integer8_small", "amp.report.integer8_small",
650 FT_UINT8, BASE_DEC, NULL, AMP_CBOR_UINT_SMALL,
651 NULL, HFILL }
653 { &hf_amp_report_integer,
654 { "Report-Integer", "amp.report.integer",
655 FT_UINT64, BASE_DEC, NULL, 0x0,
656 NULL, HFILL }
658 { &hf_amp_cbor_header,
659 { "CBOR-Header", "amp.cbor_header",
660 FT_UINT8, BASE_HEX, NULL, 0x0,
661 NULL, HFILL }
663 { &hf_amp_primary_timestamp,
664 { "Timestamp", "amp.primary_timestamp",
665 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}
667 { &hf_amp_tnvc_flags,
668 { "TNVC Flags", "amp.tnvc.flags",
669 FT_UINT8, BASE_DEC, NULL, 0x0,
670 NULL, HFILL }
672 { &hf_amp_tnvc_reserved,
673 { "Reserved", "amp.tnvc.reserved",
674 FT_UINT8, BASE_DEC, NULL, AMP_TNVC_RESERVED,
675 NULL, HFILL }
677 { &hf_amp_tnvc_mixed,
678 { "Mixed", "amp.tnvc.mixed",
679 FT_BOOLEAN, 8, TFS(&tfs_yes_no), AMP_TNVC_MIXED,
680 NULL, HFILL }
682 { &hf_amp_tnvc_typed,
683 { "TNVC Values are Typed", "amp.tnvc.typed",
684 FT_BOOLEAN, 8, TFS(&tfs_yes_no), AMP_TNVC_TYPE,
685 NULL, HFILL }
687 { &hf_amp_tnvc_name,
688 { "Name", "amp.tnvc.name",
689 FT_BOOLEAN, 8, TFS(&tfs_yes_no), AMP_TNVC_NAME,
690 NULL, HFILL }
692 { &hf_amp_tnvc_values,
693 { "Values", "amp.tnvc.value",
694 FT_BOOLEAN, 8, TFS(&tfs_yes_no), AMP_TNVC_VALUE,
695 NULL, HFILL }
697 { &hf_ari_nickname,
698 { "Nickname", "amp.nickname",
699 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), AMP_ARI_NICKNAME,
700 NULL, HFILL }
702 { &hf_amp_ari_flags,
703 { "ARI Flags", "amp.ari.flags",
704 FT_UINT8, BASE_DEC, NULL, 0x0,
705 NULL, HFILL }
707 { &hf_ari_parameters,
708 { "Parameters", "amp.parameters",
709 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), AMP_ARI_PARAMETERS,
710 NULL, HFILL }
712 { &hf_ari_issuer,
713 { "Issuer", "amp.issuer",
714 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), AMP_ARI_ISSUER,
715 NULL, HFILL }
717 { &hf_ari_tag,
718 { "Tag", "amp.tag",
719 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), AMP_ARI_TAG,
720 NULL, HFILL }
722 { &hf_ari_value,
723 { "Value", "amp.value",
724 FT_UINT8, BASE_DEC, NULL, AMP_ARI_VALUE,
725 NULL, HFILL }
727 { &hf_ari_struct,
728 { "Struct Type", "amp.struct",
729 FT_UINT8, BASE_DEC, VALS(amp_ari_struct_type), AMP_ARI_STRUCT,
730 NULL, HFILL }
732 { &hf_amp_reserved,
733 { "Reserved", "amp.reserved",
734 FT_UINT8, BASE_DEC, NULL, AMP_HDR_RESERVED,
735 NULL, HFILL }
737 { &hf_amp_acl,
738 { "ACL", "amp.acl",
739 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), AMP_HDR_ACL,
740 NULL, HFILL }
742 { &hf_amp_nack,
743 { "NACK", "amp.nack",
744 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), AMP_HDR_NACK,
745 NULL, HFILL }
747 { &hf_amp_ack,
748 { "ACK", "amp.ack",
749 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), AMP_HDR_ACK,
750 NULL, HFILL }
752 { &hf_amp_opcode,
753 { "Opcode", "amp.opcode",
754 FT_UINT8, BASE_DEC, VALS(opcode), AMP_HDR_OPCODE,
755 NULL, HFILL }
757 {&hf_amp_agent_name,
758 {"Agent-Name", "amp.agent_name",
759 FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL}
761 {&hf_amp_text_string,
762 {"String", "amp.string",
763 FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL}
765 {&hf_amp_rx_name,
766 {"Rx-Name", "amp.rx_name",
767 FT_STRINGZPAD, BASE_NONE, NULL, 0x0, NULL, HFILL}
772 /* Setup protocol subtree array */
773 static int *ett[] = {
774 &ett_amp,
775 &ett_amp_message_header,
776 &ett_amp_cbor_header,
777 &ett_amp_message,
778 &ett_amp_register,
779 &ett_amp_report_set,
780 &ett_amp_report,
781 &ett_amp_tnvc_flags,
782 &ett_amp_ari_flags,
783 &ett_amp_proto
786 static ei_register_info ei[] = {
787 { &ei_amp_cbor_malformed, { "amp.cbor.malformed", PI_MALFORMED, PI_ERROR, "Malformed CBOR object", EXPFILL }},
790 /* Register the protocol name and description */
791 proto_amp = proto_register_protocol("AMP", "AMP", "amp");
793 /* Required function calls to register the header fields and subtrees used */
794 proto_register_field_array(proto_amp, hf, array_length(hf));
795 proto_register_subtree_array(ett, array_length(ett));
796 expert_module_t* expert_amp = expert_register_protocol(proto_amp);
797 expert_register_field_array(expert_amp, ei, array_length(ei));
799 amp_handle = register_dissector("amp", dissect_amp, proto_amp);
802 void
803 proto_reg_handoff_amp(void)
805 dissector_add_uint("ccsds.apid", AMP_APID, amp_handle);
806 dissector_add_for_decode_as_with_preference("udp.port", amp_handle);
810 * Editor modelines - http://www.wireshark.org/tools/modelines.html
812 * Local variables:
813 * c-basic-offset: 4
814 * tab-width: 8
815 * indent-tabs-mode: nil
816 * End:
818 * vi: set shiftwidth=4 tabstop=8 expandtab:
819 * :indentSize=4:tabSize=8:noTabs=true: