6 This file is auto generated, do not edit!
7 See tools/asterix/README.md for details.
17 * Routines for ASTERIX decoding
18 * By Marko Hrastovec <marko.hrastovec@sloveniacontrol.si>
20 * Wireshark - Network traffic analyzer
21 * By Gerald Combs <gerald@wireshark.org>
22 * Copyright 1998 Gerald Combs
24 * SPDX-License-Identifier: GPL-2.0-or-later
28 * ASTERIX (All-purpose structured EUROCONTROL surveillances
29 * information exchange) is a protocol related to air traffic control.
31 * The specifications can be downloaded from
32 * http://www.eurocontrol.int/services/asterix
37 #include <wsutil/bits_ctz.h>
39 #include <epan/packet.h>
40 #include <epan/prefs.h>
41 #include <epan/proto_data.h>
43 void proto_register_asterix(void);
44 void proto_reg_handoff_asterix(void);
46 #define PROTO_TAG_ASTERIX "ASTERIX"
47 #define ASTERIX_PORT 8600
49 #define MAX_DISSECT_STR 1024
50 #define MAX_BUFFER 256
52 static int proto_asterix
;
54 static int hf_asterix_category
;
55 static int hf_asterix_length
;
56 static int hf_asterix_message
;
57 static int hf_asterix_fspec
;
58 static int hf_re_field_len
;
60 static int hf_counter
;
63 static int ett_asterix
;
64 static int ett_asterix_category
;
65 static int ett_asterix_length
;
66 static int ett_asterix_message
;
67 static int ett_asterix_subtree
;
69 static dissector_handle_t asterix_handle
;
70 /* The following defines tell us how to decode the length of
71 * fields and how to construct their display structure */
80 #define EXP 9 /* Explicit (RE or SP) */
82 /* The following defines tell us how to
83 * decode and display individual fields. */
84 #define FIELD_PART_INT 0
85 #define FIELD_PART_UINT 1
86 #define FIELD_PART_FLOAT 2
87 #define FIELD_PART_UFLOAT 3
88 #define FIELD_PART_SQUAWK 4
89 #define FIELD_PART_CALLSIGN 5
90 #define FIELD_PART_ASCII 6
91 #define FIELD_PART_FX 7
92 #define FIELD_PART_HEX 8
93 #define FIELD_PART_IAS_IM 9
94 #define FIELD_PART_IAS_ASPD 10
96 typedef struct FieldPart_s FieldPart
;
98 uint16_t bit_length
; /* length of field in bits */
99 double scaling_factor
; /* scaling factor of the field (for instance: 1/128) */
100 uint8_t type
; /* Pre-defined type for proper presentation */
101 int *hf
; /* Pointer to hf representing this kind of data */
102 const char *format_string
; /* format string for showing float values */
105 typedef struct AsterixField_s AsterixField
;
106 struct AsterixField_s
{
107 uint8_t type
; /* type of field */
108 unsigned length
; /* fixed length */
109 unsigned repetition_counter_size
; /* size of repetition counter, length of one item is in length */
110 unsigned header_length
; /* the size is in first header_length bytes of the field */
111 int *hf
; /* pointer to Wireshark hf_register_info */
112 const FieldPart
* const *part
; /* Look declaration and description of FieldPart above. */
113 const AsterixField
* const field
[]; /* subfields */
116 static void dissect_asterix_packet (tvbuff_t
*, packet_info
*pinfo
, proto_tree
*);
117 static void dissect_asterix_data_block (tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned, proto_tree
*, uint8_t, int);
118 static int dissect_asterix_fields (tvbuff_t
*, packet_info
*pinfo
, unsigned, proto_tree
*, uint8_t, const AsterixField
* const []);
120 static void asterix_build_subtree (tvbuff_t
*, packet_info
*pinfo
, unsigned, proto_tree
*, const AsterixField
*);
121 static void twos_complement (int64_t *, int);
122 static uint8_t asterix_bit (uint8_t, uint8_t);
123 static unsigned asterix_fspec_len (tvbuff_t
*, unsigned);
124 static uint8_t asterix_field_exists (tvbuff_t
*, unsigned, int);
125 static uint8_t asterix_get_active_uap (tvbuff_t
*, unsigned, uint8_t);
126 static int asterix_field_length (tvbuff_t
*, unsigned, const AsterixField
* const);
127 static int asterix_field_offset (tvbuff_t
*, unsigned, const AsterixField
* const [], int);
128 static int asterix_message_length (tvbuff_t
*, unsigned, uint8_t, uint8_t);
130 static const char AISCode
[] = { ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
131 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', ' ', ' ', ' ', ' ',
132 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
133 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', ' ', ' ', ' ', ' ', ' ' };
135 static const value_string valstr_XXX_FX
[] = {
136 { 0, "End of data item" },
137 { 1, "Extension into next extent" },
140 static const FieldPart IXXX_FX
= { 1, 1.0, FIELD_PART_FX
, &hf_XXX_FX
, NULL
};
141 static const FieldPart IXXX_1bit_spare
= { 1, 1.0, FIELD_PART_UINT
, NULL
, NULL
};
142 static const FieldPart IXXX_2bit_spare
= { 2, 1.0, FIELD_PART_UINT
, NULL
, NULL
};
143 static const FieldPart IXXX_3bit_spare
= { 3, 1.0, FIELD_PART_UINT
, NULL
, NULL
};
144 static const FieldPart IXXX_4bit_spare
= { 4, 1.0, FIELD_PART_UINT
, NULL
, NULL
};
145 static const FieldPart IXXX_5bit_spare
= { 5, 1.0, FIELD_PART_UINT
, NULL
, NULL
};
146 static const FieldPart IXXX_6bit_spare
= { 6, 1.0, FIELD_PART_UINT
, NULL
, NULL
};
147 static const FieldPart IXXX_7bit_spare
= { 7, 1.0, FIELD_PART_UINT
, NULL
, NULL
};
150 static const AsterixField IX_SPARE
= { FIXED
, 0, 0, 0, &hf_spare
, NULL
, { NULL
} };
156 /* settings which category version to use for each ASTERIX category */
157 static int global_categories_version
[] = {
416 static int dissect_asterix (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
418 col_set_str (pinfo
->cinfo
, COL_PROTOCOL
, "ASTERIX");
419 col_clear (pinfo
->cinfo
, COL_INFO
);
421 if (tree
) { /* we are being asked for details */
422 dissect_asterix_packet (tvb
, pinfo
, tree
);
425 return tvb_captured_length(tvb
);
428 static void dissect_asterix_packet (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
433 proto_item
*asterix_packet_item
;
434 proto_tree
*asterix_packet_tree
;
436 for (i
= 0; i
< tvb_reported_length (tvb
); i
+= length
+ 3) {
437 /* all ASTERIX messages have the same structure:
441 * 1 byte category even though a category is referenced as I019,
442 * this is just stored as decimal 19 (i.e. 0x13)
443 * 2 bytes length the total length of this ASTERIX message, the
444 * length includes the size of the header.
446 * Note that the there was a structural change at
447 * one point that changes whether multiple
448 * records can occur after the header or not
449 * (each category specifies this explicitly. All
450 * of the currently supported categories can have
451 * multiple records so this implementation just
452 * assumes that is always the case)
454 * record (multiple records can exists):
456 * n bytes FSPEC the field specifier is a bit mask where the
457 * lowest bit of each byte is called the FX bit.
458 * When the FX bit is set this indicates that
459 * the FSPEC extends into the next byte.
460 * Any other bit indicates the presence of the
461 * field that owns that bit (as per the User
462 * Application Profile (UAP)).
463 * X bytes Field Y X is as per the specification for field Y.
466 * The User Application Profile (UAP) is simply a mapping from the
467 * FSPEC to fields. Each category has its own UAP.
469 category
= tvb_get_uint8 (tvb
, i
);
470 length
= (tvb_get_uint8 (tvb
, i
+ 1) << 8) + tvb_get_uint8 (tvb
, i
+ 2) - 3; /* -3 for category and length */
472 asterix_packet_item
= proto_tree_add_item (tree
, proto_asterix
, tvb
, i
, length
+ 3, ENC_NA
);
473 proto_item_append_text (asterix_packet_item
, ", Category %03d", category
);
474 asterix_packet_tree
= proto_item_add_subtree (asterix_packet_item
, ett_asterix
);
475 proto_tree_add_item (asterix_packet_tree
, hf_asterix_category
, tvb
, i
, 1, ENC_BIG_ENDIAN
);
476 proto_tree_add_item (asterix_packet_tree
, hf_asterix_length
, tvb
, i
+ 1, 2, ENC_BIG_ENDIAN
);
478 dissect_asterix_data_block (tvb
, pinfo
, i
+ 3, asterix_packet_tree
, category
, length
);
482 static void dissect_asterix_data_block (tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*tree
, uint8_t category
, int length
)
485 int fspec_len
, inner_offset
, size
, counter
;
486 proto_item
*asterix_message_item
= NULL
;
487 proto_tree
*asterix_message_tree
= NULL
;
489 for (counter
= 1, inner_offset
= 0; inner_offset
< length
; counter
++) {
491 /* This loop handles parsing of each ASTERIX record */
493 active_uap
= asterix_get_active_uap (tvb
, offset
+ inner_offset
, category
);
494 size
= asterix_message_length (tvb
, offset
+ inner_offset
, category
, active_uap
);
496 asterix_message_item
= proto_tree_add_item (tree
, hf_asterix_message
, tvb
, offset
+ inner_offset
, size
, ENC_NA
);
497 proto_item_append_text (asterix_message_item
, ", #%02d, length: %d", counter
, size
);
498 asterix_message_tree
= proto_item_add_subtree (asterix_message_item
, ett_asterix_message
);
499 fspec_len
= asterix_fspec_len (tvb
, offset
+ inner_offset
);
500 /*show_fspec (tvb, asterix_message_tree, offset + inner_offset, fspec_len);*/
501 proto_tree_add_item (asterix_message_tree
, hf_asterix_fspec
, tvb
, offset
+ inner_offset
, fspec_len
, ENC_NA
);
503 size
= dissect_asterix_fields (tvb
, pinfo
, offset
+ inner_offset
, asterix_message_tree
, category
, categories
[category
][global_categories_version
[category
]][active_uap
]);
505 inner_offset
+= size
+ fspec_len
;
508 inner_offset
= length
;
513 // We're transported over UDP and our offset always advances.
514 // NOLINTNEXTLINE(misc-no-recursion)
515 static int dissect_asterix_fields (tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*tree
, uint8_t category
, const AsterixField
* const current_uap
[])
517 unsigned i
, j
, size
, start
, len
, inner_offset
, fspec_len
;
519 proto_item
*asterix_field_item
= NULL
;
520 proto_tree
*asterix_field_tree
= NULL
;
521 proto_item
*asterix_field_item2
= NULL
;
522 proto_tree
*asterix_field_tree2
= NULL
;
524 if (current_uap
== NULL
)
527 for (i
= 0, size
= 0; current_uap
[i
] != NULL
; i
++) {
528 start
= asterix_field_offset (tvb
, offset
, current_uap
, i
);
530 len
= asterix_field_length (tvb
, offset
+ start
, current_uap
[i
]);
532 switch(current_uap
[i
]->type
) {
534 asterix_field_item
= proto_tree_add_item (tree
, *current_uap
[i
]->hf
, tvb
, offset
+ start
, len
, ENC_NA
);
535 asterix_field_tree
= proto_item_add_subtree (asterix_field_item
, ett_asterix_subtree
);
536 fspec_len
= asterix_fspec_len (tvb
, offset
+ start
);
537 proto_tree_add_item (asterix_field_tree
, hf_asterix_fspec
, tvb
, offset
+ start
, fspec_len
, ENC_NA
);
538 dissect_asterix_fields (tvb
, pinfo
, offset
+ start
, asterix_field_tree
, category
, current_uap
[i
]->field
);
541 asterix_field_item
= proto_tree_add_item (tree
, *current_uap
[i
]->hf
, tvb
, offset
+ start
, len
, ENC_NA
);
542 asterix_field_tree
= proto_item_add_subtree (asterix_field_item
, ett_asterix_subtree
);
543 for (j
= 0, counter
= 0; j
< current_uap
[i
]->repetition_counter_size
; j
++) {
544 counter
= (counter
<< 8) + tvb_get_uint8 (tvb
, offset
+ start
+ j
);
546 proto_tree_add_item (asterix_field_tree
, hf_counter
, tvb
, offset
+ start
, current_uap
[i
]->repetition_counter_size
, ENC_BIG_ENDIAN
);
547 for (j
= 0, inner_offset
= 0; j
< counter
; j
++, inner_offset
+= current_uap
[i
]->length
) {
548 asterix_field_item2
= proto_tree_add_item (asterix_field_tree
, *current_uap
[i
]->hf
, tvb
, offset
+ start
+ current_uap
[i
]->repetition_counter_size
+ inner_offset
, current_uap
[i
]->length
, ENC_NA
);
549 asterix_field_tree2
= proto_item_add_subtree (asterix_field_item2
, ett_asterix_subtree
);
550 asterix_build_subtree (tvb
, pinfo
, offset
+ start
+ current_uap
[i
]->repetition_counter_size
+ inner_offset
, asterix_field_tree2
, current_uap
[i
]);
553 /* currently not generated from asterix-spec*/
555 asterix_field_item = proto_tree_add_item (tree, *current_uap[i]->hf, tvb, offset + start, len, ENC_NA);
556 asterix_field_tree = proto_item_add_subtree (asterix_field_item, ett_asterix_subtree);
557 proto_tree_add_item (asterix_field_tree, hf_re_field_len, tvb, offset + start, 1, ENC_BIG_ENDIAN);
559 fspec_len = asterix_fspec_len (tvb, offset + start);
560 proto_tree_add_item (asterix_field_tree, hf_asterix_fspec, tvb, offset + start, fspec_len, ENC_NA);
561 dissect_asterix_fields (tvb, pinfo, offset + start, asterix_field_tree, category, current_uap[i]->field);
563 default: /* FIXED, FX, FX_1, FX_UAP */
564 asterix_field_item
= proto_tree_add_item (tree
, *current_uap
[i
]->hf
, tvb
, offset
+ start
, len
, ENC_NA
);
565 asterix_field_tree
= proto_item_add_subtree (asterix_field_item
, ett_asterix_subtree
);
566 asterix_build_subtree (tvb
, pinfo
, offset
+ start
, asterix_field_tree
, current_uap
[i
]);
574 static void asterix_build_subtree (tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
, proto_tree
*parent
, const AsterixField
*field
)
576 header_field_info
* hfi
;
577 int bytes_in_type
, byte_offset_of_mask
;
578 int i
, inner_offset
, offset_in_tvb
, length_in_tvb
;
581 char *str_buffer
= NULL
;
582 double scaling_factor
= 1.0;
583 uint8_t *air_speed_im_bit
;
584 if (field
->part
!= NULL
) {
585 for (i
= 0, inner_offset
= 0, go_on
= 1; go_on
&& field
->part
[i
] != NULL
; i
++) {
586 value
= tvb_get_bits64 (tvb
, offset
* 8 + inner_offset
, field
->part
[i
]->bit_length
, ENC_BIG_ENDIAN
);
587 if (field
->part
[i
]->hf
!= NULL
) {
588 offset_in_tvb
= offset
+ inner_offset
/ 8;
589 length_in_tvb
= (inner_offset
% 8 + field
->part
[i
]->bit_length
+ 7) / 8;
590 switch (field
->part
[i
]->type
) {
592 if (!value
) go_on
= 0;
595 case FIELD_PART_UINT
:
597 case FIELD_PART_ASCII
:
598 case FIELD_PART_SQUAWK
:
599 hfi
= proto_registrar_get_nth (*field
->part
[i
]->hf
);
602 // for a small bit field to decode correctly with
603 // a mask that belongs to a large(r) one we need to
604 // re-adjust offset_in_tvb and length_in_tvb to
605 // correctly align with the given hf mask.
607 // E.g. the following would not decode correctly:
608 // { &hf_020_050_V, ... FT_UINT16, ... 0x8000, ...
609 // instead one would have to use
610 // { &hf_020_050_V, ... FT_UINT8, ... 0x80, ...
612 bytes_in_type
= ftype_wire_size(hfi
->type
);
613 if (bytes_in_type
> 1)
615 byte_offset_of_mask
= bytes_in_type
- (ws_ilog2 (hfi
->bitmask
) + 8)/8;
616 if (byte_offset_of_mask
>= 0)
618 offset_in_tvb
-= byte_offset_of_mask
;
619 length_in_tvb
= bytes_in_type
;
623 proto_tree_add_item (parent
, *field
->part
[i
]->hf
, tvb
, offset_in_tvb
, length_in_tvb
, ENC_BIG_ENDIAN
);
625 case FIELD_PART_FLOAT
:
626 twos_complement (&value
, field
->part
[i
]->bit_length
);
628 case FIELD_PART_UFLOAT
:
629 scaling_factor
= field
->part
[i
]->scaling_factor
;
630 if (field
->part
[i
]->format_string
!= NULL
)
631 proto_tree_add_double_format_value (parent
, *field
->part
[i
]->hf
, tvb
, offset_in_tvb
, length_in_tvb
, value
* scaling_factor
, field
->part
[i
]->format_string
, value
* scaling_factor
);
633 proto_tree_add_double (parent
, *field
->part
[i
]->hf
, tvb
, offset_in_tvb
, length_in_tvb
, value
* scaling_factor
);
635 case FIELD_PART_CALLSIGN
:
636 str_buffer
= wmem_strdup_printf(
639 AISCode
[(value
>> 42) & 63],
640 AISCode
[(value
>> 36) & 63],
641 AISCode
[(value
>> 30) & 63],
642 AISCode
[(value
>> 24) & 63],
643 AISCode
[(value
>> 18) & 63],
644 AISCode
[(value
>> 12) & 63],
645 AISCode
[(value
>> 6) & 63],
646 AISCode
[value
& 63]);
647 proto_tree_add_string (parent
, *field
->part
[i
]->hf
, tvb
, offset_in_tvb
, length_in_tvb
, str_buffer
);
649 case FIELD_PART_IAS_IM
:
650 /* special processing for I021/150 and I062/380#4 because Air Speed depends on IM subfield */
651 air_speed_im_bit
= wmem_new (pinfo
->pool
, uint8_t);
652 *air_speed_im_bit
= (tvb_get_uint8 (tvb
, offset_in_tvb
) & 0x80) >> 7;
653 /* Save IM info for the packet. key = 21150. */
654 p_add_proto_data (pinfo
->pool
, pinfo
, proto_asterix
, 21150, air_speed_im_bit
);
655 proto_tree_add_item (parent
, *field
->part
[i
]->hf
, tvb
, offset_in_tvb
, length_in_tvb
, ENC_BIG_ENDIAN
);
657 case FIELD_PART_IAS_ASPD
:
658 /* special processing for I021/150 and I062/380#4 because Air Speed depends on IM subfield */
659 air_speed_im_bit
= (uint8_t *)p_get_proto_data (pinfo
->pool
, pinfo
, proto_asterix
, 21150);
660 if (!air_speed_im_bit
|| *air_speed_im_bit
== 0)
661 scaling_factor
= 1.0/16384.0;
663 scaling_factor
= 0.001;
664 proto_tree_add_double (parent
, *field
->part
[i
]->hf
, tvb
, offset_in_tvb
, length_in_tvb
, value
* scaling_factor
);
668 inner_offset
+= field
->part
[i
]->bit_length
;
673 static uint8_t asterix_bit (uint8_t b
, uint8_t bitNo
)
675 return bitNo
< 8 && (b
& (0x80 >> bitNo
)) > 0;
678 /* Function makes int64_t two's complement.
679 * Only the bit_len bit are set in int64_t. All more significant
680 * bits need to be set to have proper two's complement.
681 * If the number is negative, all other bits must be set to 1.
682 * If the number is positive, all other bits must remain 0. */
683 static void twos_complement (int64_t *v
, int bit_len
)
685 if (*v
& (UINT64_C(1) << (bit_len
- 1))) {
686 *v
|= (UINT64_C(0xffffffffffffffff) << bit_len
);
690 static unsigned asterix_fspec_len (tvbuff_t
*tvb
, unsigned offset
)
693 unsigned max_length
= tvb_reported_length (tvb
) - offset
;
694 for (i
= 0; (tvb_get_uint8 (tvb
, offset
+ i
) & 1) && i
< max_length
; i
++);
698 static uint8_t asterix_field_exists (tvbuff_t
*tvb
, unsigned offset
, int bitIndex
)
701 bitNo
= bitIndex
+ bitIndex
/ 7;
702 for (i
= 0; i
< bitNo
/ 8; i
++) {
703 if (!(tvb_get_uint8 (tvb
, offset
+ i
) & 1)) return 0;
705 return asterix_bit (tvb_get_uint8 (tvb
, offset
+ i
), bitNo
% 8);
708 // We're transported over UDP and our offset always advances.
709 // NOLINTNEXTLINE(misc-no-recursion)
710 static int asterix_field_length (tvbuff_t
*tvb
, unsigned offset
, const AsterixField
* const field
)
719 switch(field
->type
) {
721 size
= field
->length
;
724 for (i
= 0, count
= 0; i
< field
->repetition_counter_size
&& i
< sizeof (count
); i
++)
725 count
= (count
<< 8) + tvb_get_uint8 (tvb
, offset
+ i
);
726 size
= (unsigned)(field
->repetition_counter_size
+ count
* field
->length
);
729 for (i
= 0, bit_size
= 0; field
->part
[i
] != NULL
; i
++) {
730 // We don't need to shift value as FX bits are always at the end
731 should_break
= field
->part
[i
]->type
== FIELD_PART_FX
&& !(tvb_get_uint8 (tvb
, offset
+ bit_size
/ 8) & 1);
732 bit_size
+= field
->part
[i
]->bit_length
;
733 if (should_break
) break;
738 for (i
= 0, size
= 0; i
< field
->header_length
; i
++) {
739 size
= (size
<< 8) + tvb_get_uint8 (tvb
, offset
+ i
);
744 for (size
= 0; tvb_get_uint8 (tvb
, offset
+ size
) & 1; size
++);
747 for (i
= 0; field
->field
[i
] != NULL
; i
++) {
748 if (asterix_field_exists (tvb
, offset
, i
))
749 size
+= asterix_field_length (tvb
, offset
+ size
, field
->field
[i
]);
756 /* This works for category 001. For other it may require changes. */
757 static uint8_t asterix_get_active_uap (tvbuff_t
*tvb
, unsigned offset
, uint8_t category
)
760 AsterixField
const * const *current_uap
;
762 if ((category
== 1) && (categories
[category
] != NULL
)) { /* if category is supported */
763 if (categories
[category
][global_categories_version
[category
]][1] != NULL
) { /* if exists another uap */
764 current_uap
= categories
[category
][global_categories_version
[category
]][0];
765 if (current_uap
!= NULL
) {
766 inner_offset
= asterix_fspec_len (tvb
, offset
);
767 for (i
= 0; current_uap
[i
] != NULL
; i
++) {
768 if (asterix_field_exists (tvb
, offset
, i
)) {
769 if (i
== 1) { /* uap selector (I001/020) is always at index '1' */
770 return tvb_get_uint8 (tvb
, offset
+ inner_offset
) >> 7;
772 inner_offset
+= asterix_field_length (tvb
, offset
+ inner_offset
, current_uap
[i
]);
781 static int asterix_field_offset (tvbuff_t
*tvb
, unsigned offset
, const AsterixField
* const current_uap
[], int field_index
)
785 if (asterix_field_exists (tvb
, offset
, field_index
)) {
786 inner_offset
= asterix_fspec_len (tvb
, offset
);
787 for (i
= 0; i
< field_index
; i
++) {
788 if (asterix_field_exists (tvb
, offset
, i
))
789 inner_offset
+= asterix_field_length (tvb
, offset
+ inner_offset
, current_uap
[i
]);
795 static int asterix_message_length (tvbuff_t
*tvb
, unsigned offset
, uint8_t category
, uint8_t active_uap
)
798 AsterixField
const * const *current_uap
;
800 if (categories
[category
] != NULL
) { /* if category is supported */
801 current_uap
= categories
[category
][global_categories_version
[category
]][active_uap
];
802 if (current_uap
!= NULL
) {
803 size
= asterix_fspec_len (tvb
, offset
);
804 for (i
= 0; current_uap
[i
] != NULL
; i
++) {
805 if (asterix_field_exists (tvb
, offset
, i
)) {
806 size
+= asterix_field_length (tvb
, offset
+ size
, current_uap
[i
]);
815 void proto_register_asterix (void)
817 static hf_register_info hf
[] = {
818 { &hf_asterix_category
, { "Category", "asterix.category", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
819 { &hf_asterix_length
, { "Length", "asterix.length", FT_UINT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
820 { &hf_asterix_message
, { "Asterix message", "asterix.message", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
821 { &hf_asterix_fspec
, { "FSPEC", "asterix.fspec", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
822 { &hf_re_field_len
, { "RE LEN", "asterix.re_field_len", FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
823 { &hf_spare
, { "Spare", "asterix.spare", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
824 { &hf_counter
, { "Counter", "asterix.counter", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
825 { &hf_XXX_FX
, { "FX", "asterix.FX", FT_UINT8
, BASE_DEC
, VALS (valstr_XXX_FX
), 0x01, "Extension into next extent", HFILL
} },
831 /* Setup protocol subtree array */
832 static int *ett
[] = {
834 &ett_asterix_category
,
836 &ett_asterix_message
,
840 module_t
*asterix_prefs_module
;
842 proto_asterix
= proto_register_protocol (
843 "ASTERIX packet", /* name */
844 "ASTERIX", /* short name */
845 "asterix" /* abbrev */
848 proto_register_field_array (proto_asterix
, hf
, array_length (hf
));
849 proto_register_subtree_array (ett
, array_length (ett
));
851 asterix_handle
= register_dissector ("asterix", dissect_asterix
, proto_asterix
);
853 asterix_prefs_module
= prefs_register_protocol (proto_asterix
, NULL
);
860 void proto_reg_handoff_asterix (void)
862 dissector_add_uint_with_preference("udp.port", ASTERIX_PORT
, asterix_handle
);
866 * Editor modelines - https://www.wireshark.org/tools/modelines.html
871 * indent-tabs-mode: nil
874 * vi: set shiftwidth=4 tabstop=8 expandtab:
875 * :indentSize=4:tabSize=8:noTabs=true: