2 * Routines for protocol tree
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
12 #define WS_LOG_DOMAIN LOG_DOMAIN_EPAN
22 #include <epan/unit_strings.h>
24 #include <wsutil/array.h>
25 #include <wsutil/bits_ctz.h>
26 #include <wsutil/bits_count_ones.h>
27 #include <wsutil/sign_ext.h>
28 #include <wsutil/utf8_entities.h>
29 #include <wsutil/json_dumper.h>
30 #include <wsutil/wslog.h>
31 #include <wsutil/ws_assert.h>
32 #include <wsutil/unicode-utils.h>
34 #include <ftypes/ftypes.h>
37 #include "exceptions.h"
38 #include "ptvcursor.h"
40 #include "addr_resolv.h"
41 #include "address_types.h"
44 #include "epan_dissect.h"
45 #include "dfilter/dfilter.h"
47 #include <epan/wmem_scopes.h>
49 #include "column-info.h"
51 #include "osi-utils.h"
53 #include "show_exception.h"
55 #include "register-int.h"
57 #include <wsutil/crash_info.h>
58 #include <wsutil/epochs.h>
60 /* Ptvcursor limits */
61 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
62 #define SUBTREE_MAX_LEVELS 256
64 typedef struct __subtree_lvl
{
71 wmem_allocator_t
*scope
;
72 subtree_lvl
*pushed_tree
;
73 uint8_t pushed_tree_index
;
74 uint8_t pushed_tree_max
;
80 #define cVALS(x) (const value_string*)(x)
82 /** See inlined comments.
83 @param tree the tree to append this item to
84 @param free_block a code block to call to free resources if this returns
85 @return NULL if 'tree' is null */
86 #define CHECK_FOR_NULL_TREE_AND_FREE(tree, free_block) \
92 /** See inlined comments.
93 @param tree the tree to append this item to
94 @param free_block a code block to call to free resources if this returns
95 @return NULL if 'tree' is null */
96 #define CHECK_FOR_NULL_TREE(tree) \
97 CHECK_FOR_NULL_TREE_AND_FREE(tree, ((void)0))
99 /** See inlined comments.
100 @param length the length of this item
101 @param cleanup_block a code block to call to free resources if this returns
102 @return NULL if 'length' is lower -1 or equal 0 */
103 #define CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length, cleanup_block) \
104 if (length < -1 || length == 0 ) { \
109 /** See inlined comments.
110 @param length the length of this item
111 @return NULL if 'length' is lower -1 or equal 0 */
112 #define CHECK_FOR_ZERO_OR_MINUS_LENGTH(length) \
113 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length, ((void)0))
115 /** See inlined comments.
116 @param tree the tree to append this item to
117 @param hfindex field index
118 @param hfinfo header_field
119 @param free_block a code block to call to free resources if this returns
120 @return the header field matching 'hfinfo' */
121 #define TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, free_block) \
122 /* If the tree is not visible and this item is not referenced \
123 we don't have to do much work at all but we should still \
124 return a node so that referenced field items below this node \
125 (think proto_item_add_subtree()) will still have somewhere \
126 to attach to or else filtering will not work (they would be \
127 ignored since tree would be NULL). \
128 DON'T try to fake a node where PTREE_FINFO(tree) is NULL \
129 since dissectors that want to do proto_item_set_len() or \
130 other operations that dereference this would crash. \
131 DON'T try to fake a node where PTREE_FINFO(tree) is visible \
132 because that means we can change its length or repr, and we \
133 don't want to do so with calls intended for this faked new \
134 item, so this item needs a new (hidden) child node. \
135 (PROTO_ITEM_IS_HIDDEN(tree) checks both conditions.) \
136 We fake FT_PROTOCOL unless some clients have requested us \
139 PTREE_DATA(tree)->count++; \
140 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
141 if (PTREE_DATA(tree)->count > prefs.gui_max_tree_items) { \
143 if (wireshark_abort_on_too_many_items) \
144 ws_error("Adding %s would put more than %d items in the tree -- possible infinite loop (max number of items can be increased in advanced preferences)", \
145 hfinfo->abbrev, prefs.gui_max_tree_items); \
146 /* Let the exception handler add items to the tree */ \
147 PTREE_DATA(tree)->count = 0; \
148 THROW_MESSAGE(DissectorError, \
149 wmem_strdup_printf(PNODE_POOL(tree), \
150 "Adding %s would put more than %d items in the tree -- possible infinite loop (max number of items can be increased in advanced preferences)", \
151 hfinfo->abbrev, prefs.gui_max_tree_items)); \
153 if (!(PTREE_DATA(tree)->visible)) { \
154 if (PROTO_ITEM_IS_HIDDEN(tree)) { \
155 if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
156 && (hfinfo->ref_type != HF_REF_TYPE_PRINT) \
157 && (hfinfo->type != FT_PROTOCOL || \
158 PTREE_DATA(tree)->fake_protocols)) { \
160 /* just return tree back to the caller */\
166 /** See inlined comments.
167 @param tree the tree to append this item to
168 @param hfindex field index
169 @param hfinfo header_field
170 @return the header field matching 'hfinfo' */
171 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
172 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, ((void)0))
175 /** See inlined comments.
176 @param pi the created protocol item we're about to return */
177 #define TRY_TO_FAKE_THIS_REPR(pi) \
179 if (!(PTREE_DATA(pi)->visible) && \
180 PROTO_ITEM_IS_HIDDEN(pi)) { \
181 /* If the tree (GUI) or item isn't visible it's pointless for \
182 * us to generate the protocol item's string representation */ \
185 /* Same as above but returning void */
186 #define TRY_TO_FAKE_THIS_REPR_VOID(pi) \
189 if (!(PTREE_DATA(pi)->visible) && \
190 PROTO_ITEM_IS_HIDDEN(pi)) { \
191 /* If the tree (GUI) or item isn't visible it's pointless for \
192 * us to generate the protocol item's string representation */ \
195 /* Similar to above, but allows a NULL tree */
196 #define TRY_TO_FAKE_THIS_REPR_NESTED(pi) \
197 if ((pi == NULL) || (!(PTREE_DATA(pi)->visible) && \
198 PROTO_ITEM_IS_HIDDEN(pi))) { \
199 /* If the tree (GUI) or item isn't visible it's pointless for \
200 * us to generate the protocol item's string representation */ \
204 #ifdef ENABLE_CHECK_FILTER
205 #define CHECK_HF_VALUE(type, spec, start_values) \
207 const type *current; \
209 current = start_values; \
210 for (n=0; current; n++, current++) { \
211 /* Drop out if we reached the end. */ \
212 if ((current->value == 0) && (current->strptr == NULL)) { \
215 /* Check value against all previous */ \
216 for (m=0; m < n; m++) { \
217 /* There are lots of duplicates with the same string, \
218 so only report if different... */ \
219 if ((start_values[m].value == current->value) && \
220 (strcmp(start_values[m].strptr, current->strptr) != 0)) { \
221 ws_warning("Field '%s' (%s) has a conflicting entry in its" \
222 " value_string: %" spec " is at indices %u (%s) and %u (%s)", \
223 hfinfo->name, hfinfo->abbrev, \
224 current->value, m, start_values[m].strptr, n, current->strptr); \
231 /* The longest NUMBER-like field label we have is for BASE_OUI, which
232 * can have up to 64 bytes for the manufacturer name if resolved plus
233 * 11 bytes for the "XX:XX:XX ()" part = 75 octets.
235 #define NUMBER_LABEL_LENGTH 80
237 static const char *hf_try_val_to_str(uint32_t value
, const header_field_info
*hfinfo
);
238 static const char *hf_try_val64_to_str(uint64_t value
, const header_field_info
*hfinfo
);
239 static const char *hf_try_val_to_str_const(uint32_t value
, const header_field_info
*hfinfo
, const char *unknown_str
);
240 static const char *hf_try_val64_to_str_const(uint64_t value
, const header_field_info
*hfinfo
, const char *unknown_str
);
241 static int hfinfo_bitoffset(const header_field_info
*hfinfo
);
242 static int hfinfo_mask_bitwidth(const header_field_info
*hfinfo
);
243 static int hfinfo_container_bitwidth(const header_field_info
*hfinfo
);
245 #define label_concat(dst, pos, src) \
246 ws_label_strcpy(dst, ITEM_LABEL_LENGTH, pos, src, 0)
248 static void mark_truncated(char *label_str
, size_t name_pos
, const size_t size
, size_t *value_pos
);
249 static void label_mark_truncated(char *label_str
, size_t name_pos
, size_t *value_pos
);
250 #define LABEL_MARK_TRUNCATED_START(label_str, value_pos) label_mark_truncated(label_str, 0, value_pos)
252 static void fill_label_boolean(const field_info
*fi
, char *label_str
, size_t *value_pos
);
253 static void fill_label_bitfield_char(const field_info
*fi
, char *label_str
, size_t *value_pos
);
254 static void fill_label_bitfield(const field_info
*fi
, char *label_str
, size_t *value_pos
, bool is_signed
);
255 static void fill_label_bitfield64(const field_info
*fi
, char *label_str
, size_t *value_pos
, bool is_signed
);
256 static void fill_label_char(const field_info
*fi
, char *label_str
, size_t *value_pos
);
257 static void fill_label_number(const field_info
*fi
, char *label_str
, size_t *value_pos
, bool is_signed
);
258 static void fill_label_number64(const field_info
*fi
, char *label_str
, size_t *value_pos
, bool is_signed
);
260 static size_t fill_display_label_float(const field_info
*fi
, char *label_str
);
261 static void fill_label_float(const field_info
*fi
, char *label_str
, size_t *value_pos
);
263 static const char *hfinfo_number_value_format_display(const header_field_info
*hfinfo
, int display
, char buf
[NUMBER_LABEL_LENGTH
], uint32_t value
);
264 static const char *hfinfo_number_value_format_display64(const header_field_info
*hfinfo
, int display
, char buf
[NUMBER_LABEL_LENGTH
], uint64_t value
);
265 static const char *hfinfo_char_vals_format(const header_field_info
*hfinfo
, char buf
[32], uint32_t value
);
266 static const char *hfinfo_number_vals_format(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint32_t value
);
267 static const char *hfinfo_number_vals_format64(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint64_t value
);
268 static const char *hfinfo_number_value_format(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint32_t value
);
269 static const char *hfinfo_number_value_format64(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint64_t value
);
270 static const char *hfinfo_char_value_format(const header_field_info
*hfinfo
, char buf
[32], uint32_t value
);
271 static const char *hfinfo_numeric_value_format(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint32_t value
);
272 static const char *hfinfo_numeric_value_format64(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint64_t value
);
274 static void proto_cleanup_base(void);
277 proto_tree_add_node(proto_tree
*tree
, field_info
*fi
);
280 get_hfi_length(header_field_info
*hfinfo
, tvbuff_t
*tvb
, const int start
, int *length
,
281 int *item_length
, const unsigned encoding
);
284 get_full_length(header_field_info
*hfinfo
, tvbuff_t
*tvb
, const int start
,
285 int length
, unsigned item_length
, const int encoding
);
288 new_field_info(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
,
289 const int start
, const int item_length
);
292 proto_tree_add_pi(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
,
293 int start
, int *length
);
296 proto_tree_set_representation_value(proto_item
*pi
, const char *format
, va_list ap
);
298 proto_tree_set_representation(proto_item
*pi
, const char *format
, va_list ap
);
301 proto_tree_set_protocol_tvb(field_info
*fi
, tvbuff_t
*tvb
, const char* field_data
, int length
);
303 proto_tree_set_bytes(field_info
*fi
, const uint8_t* start_ptr
, int length
);
305 proto_tree_set_bytes_tvb(field_info
*fi
, tvbuff_t
*tvb
, int offset
, int length
);
307 proto_tree_set_bytes_gbytearray(field_info
*fi
, const GByteArray
*value
);
309 proto_tree_set_time(field_info
*fi
, const nstime_t
*value_ptr
);
311 proto_tree_set_string(field_info
*fi
, const char* value
);
313 proto_tree_set_ax25(field_info
*fi
, const uint8_t* value
);
315 proto_tree_set_ax25_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
);
317 proto_tree_set_vines(field_info
*fi
, const uint8_t* value
);
319 proto_tree_set_vines_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
);
321 proto_tree_set_ether(field_info
*fi
, const uint8_t* value
);
323 proto_tree_set_ether_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
);
325 proto_tree_set_ipxnet(field_info
*fi
, uint32_t value
);
327 proto_tree_set_ipv4(field_info
*fi
, ws_in4_addr value
);
329 proto_tree_set_ipv6(field_info
*fi
, const ws_in6_addr
* value
);
331 proto_tree_set_ipv6_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, int length
);
333 proto_tree_set_fcwwn_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, int length
);
335 proto_tree_set_guid(field_info
*fi
, const e_guid_t
*value_ptr
);
337 proto_tree_set_guid_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, const unsigned encoding
);
339 proto_tree_set_oid(field_info
*fi
, const uint8_t* value_ptr
, int length
);
341 proto_tree_set_oid_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, int length
);
343 proto_tree_set_system_id(field_info
*fi
, const uint8_t* value_ptr
, int length
);
345 proto_tree_set_system_id_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, int length
);
347 proto_tree_set_boolean(field_info
*fi
, uint64_t value
);
349 proto_tree_set_float(field_info
*fi
, float value
);
351 proto_tree_set_double(field_info
*fi
, double value
);
353 proto_tree_set_uint(field_info
*fi
, uint32_t value
);
355 proto_tree_set_int(field_info
*fi
, int32_t value
);
357 proto_tree_set_uint64(field_info
*fi
, uint64_t value
);
359 proto_tree_set_int64(field_info
*fi
, int64_t value
);
361 proto_tree_set_eui64(field_info
*fi
, const uint64_t value
);
363 proto_tree_set_eui64_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, const unsigned encoding
);
365 /* Handle type length mismatch (now filterable) expert info */
366 static int proto_type_length_mismatch
;
367 static expert_field ei_type_length_mismatch_error
;
368 static expert_field ei_type_length_mismatch_warn
;
369 static void register_type_length_mismatch(void);
371 /* Handle byte array string decoding errors with expert info */
372 static int proto_byte_array_string_decoding_error
;
373 static expert_field ei_byte_array_string_decoding_failed_error
;
374 static void register_byte_array_string_decodinws_error(void);
376 /* Handle date and time string decoding errors with expert info */
377 static int proto_date_time_string_decoding_error
;
378 static expert_field ei_date_time_string_decoding_failed_error
;
379 static void register_date_time_string_decodinws_error(void);
381 /* Handle string errors expert info */
382 static int proto_string_errors
;
383 static expert_field ei_string_trailing_characters
;
384 static void register_string_errors(void);
386 static int proto_register_field_init(header_field_info
*hfinfo
, const int parent
);
388 /* special-case header field used within proto.c */
389 static header_field_info hfi_text_only
=
390 { "Text item", "text", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
};
393 /* Structure for information about a protocol */
395 const char *name
; /* long description */
396 const char *short_name
; /* short description */
397 const char *filter_name
; /* name of this protocol in filters */
398 GPtrArray
*fields
; /* fields for this protocol */
399 int proto_id
; /* field ID for this protocol */
400 bool is_enabled
; /* true if protocol is enabled */
401 bool enabled_by_default
; /* true if protocol is enabled by default */
402 bool can_toggle
; /* true if is_enabled can be changed */
403 int parent_proto_id
; /* Used to identify "pino"s (Protocol In Name Only).
404 For dissectors that need a protocol name so they
405 can be added to a dissector table, but use the
406 parent_proto_id for things like enable/disable */
407 GList
*heur_list
; /* Heuristic dissectors associated with this protocol */
410 /* List of all protocols */
411 static GList
*protocols
;
413 /* Structure stored for deregistered g_slice */
414 struct g_slice_data
{
419 /* Deregistered fields */
420 static GPtrArray
*deregistered_fields
;
421 static GPtrArray
*deregistered_data
;
422 static GPtrArray
*deregistered_slice
;
424 /* indexed by prefix, contains initializers */
425 static GHashTable
* prefixes
;
427 /* Contains information about a field when a dissector calls
428 * proto_tree_add_item. */
429 #define FIELD_INFO_NEW(pool, fi) fi = wmem_new(pool, field_info)
430 #define FIELD_INFO_FREE(pool, fi) wmem_free(pool, fi)
432 /* Contains the space for proto_nodes. */
433 #define PROTO_NODE_INIT(node) \
434 node->first_child = NULL; \
435 node->last_child = NULL; \
438 #define PROTO_NODE_FREE(pool, node) \
439 wmem_free(pool, node)
441 /* String space for protocol and field items for the GUI */
442 #define ITEM_LABEL_NEW(pool, il) \
443 il = wmem_new(pool, item_label_t); \
446 #define ITEM_LABEL_FREE(pool, il) \
449 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
450 if((hfindex == 0 || (unsigned)hfindex > gpa_hfinfo.len) && wireshark_abort_on_dissector_bug) \
451 ws_error("Unregistered hf! index=%d", hfindex); \
452 DISSECTOR_ASSERT_HINT(hfindex > 0 && (unsigned)hfindex < gpa_hfinfo.len, "Unregistered hf!"); \
453 DISSECTOR_ASSERT_HINT(gpa_hfinfo.hfi[hfindex] != NULL, "Unregistered hf!"); \
454 hfinfo = gpa_hfinfo.hfi[hfindex];
456 /* List which stores protocols and fields that have been registered */
457 typedef struct _gpa_hfinfo_t
{
459 uint32_t allocated_len
;
460 header_field_info
**hfi
;
463 static gpa_hfinfo_t gpa_hfinfo
;
465 /* Hash table of abbreviations and IDs */
466 static GHashTable
*gpa_name_map
;
467 static header_field_info
*same_name_hfinfo
;
469 /* Hash table protocol aliases. const char * -> const char * */
470 static GHashTable
*gpa_protocol_aliases
;
473 * We're called repeatedly with the same field name when sorting a column.
474 * Cache our last gpa_name_map hit for faster lookups.
476 static char *last_field_name
;
477 static header_field_info
*last_hfinfo
;
479 static void save_same_name_hfinfo(void *data
)
481 same_name_hfinfo
= (header_field_info
*)data
;
484 /* Points to the first element of an array of bits, indexed by
485 a subtree item type; that array element is true if subtrees of
486 an item of that type are to be expanded. */
487 static uint32_t *tree_is_expanded
;
489 /* Number of elements in that array. The entry with index 0 is not used. */
490 int num_tree_types
= 1;
492 /* Name hashtables for fast detection of duplicate names */
493 static GHashTable
* proto_names
;
494 static GHashTable
* proto_short_names
;
495 static GHashTable
* proto_filter_names
;
497 static const char *reserved_filter_names
[] = {
498 /* Display filter keywords. */
527 static GHashTable
*proto_reserved_filter_names
;
530 proto_compare_name(const void *p1_arg
, const void *p2_arg
)
532 const protocol_t
*p1
= (const protocol_t
*)p1_arg
;
533 const protocol_t
*p2
= (const protocol_t
*)p2_arg
;
535 return g_ascii_strcasecmp(p1
->short_name
, p2
->short_name
);
538 static GSList
*dissector_plugins
;
542 proto_register_plugin(const proto_plugin
*plug
)
544 dissector_plugins
= g_slist_prepend(dissector_plugins
, (proto_plugin
*)plug
);
546 #else /* HAVE_PLUGINS */
548 proto_register_plugin(const proto_plugin
*plug _U_
)
550 ws_warning("proto_register_plugin: built without support for binary plugins");
552 #endif /* HAVE_PLUGINS */
555 call_plugin_register_protoinfo(void *data
, void *user_data _U_
)
557 proto_plugin
*plug
= (proto_plugin
*)data
;
559 if (plug
->register_protoinfo
) {
560 plug
->register_protoinfo();
565 call_plugin_register_handoff(void *data
, void *user_data _U_
)
567 proto_plugin
*plug
= (proto_plugin
*)data
;
569 if (plug
->register_handoff
) {
570 plug
->register_handoff();
574 /* initialize data structures and register protocols and fields */
576 proto_init(GSList
*register_all_plugin_protocols_list
,
577 GSList
*register_all_plugin_handoffs_list
,
581 proto_cleanup_base();
583 proto_names
= g_hash_table_new(g_str_hash
, g_str_equal
);
584 proto_short_names
= g_hash_table_new(g_str_hash
, g_str_equal
);
585 proto_filter_names
= g_hash_table_new(g_str_hash
, g_str_equal
);
587 proto_reserved_filter_names
= g_hash_table_new(g_str_hash
, g_str_equal
);
588 for (const char **ptr
= reserved_filter_names
; *ptr
!= NULL
; ptr
++) {
589 /* GHashTable has no key destructor so the cast is safe. */
590 g_hash_table_add(proto_reserved_filter_names
, *(char **)ptr
);
594 gpa_hfinfo
.allocated_len
= 0;
595 gpa_hfinfo
.hfi
= NULL
;
596 gpa_name_map
= g_hash_table_new_full(g_str_hash
, g_str_equal
, NULL
, save_same_name_hfinfo
);
597 gpa_protocol_aliases
= g_hash_table_new(g_str_hash
, g_str_equal
);
598 deregistered_fields
= g_ptr_array_new();
599 deregistered_data
= g_ptr_array_new();
600 deregistered_slice
= g_ptr_array_new();
602 /* Initialize the ftype subsystem */
605 /* Initialize the address type subsystem */
606 address_types_initialize();
608 /* Register one special-case FT_TEXT_ONLY field for use when
609 converting wireshark to new-style proto_tree. These fields
610 are merely strings on the GUI tree; they are not filterable */
611 hf_text_only
= proto_register_field_init(&hfi_text_only
, -1);
613 /* Register the pseudo-protocols used for exceptions. */
614 register_show_exception();
615 register_type_length_mismatch();
616 register_byte_array_string_decodinws_error();
617 register_date_time_string_decodinws_error();
618 register_string_errors();
619 ftypes_register_pseudofields();
620 col_register_protocol();
622 /* Have each built-in dissector register its protocols, fields,
623 dissector tables, and dissectors to be called through a
624 handle, and do whatever one-time initialization it needs to
626 register_all_protocols(cb
, client_data
);
628 /* Now call the registration routines for all epan plugins. */
629 for (GSList
*l
= register_all_plugin_protocols_list
; l
!= NULL
; l
= l
->next
) {
630 ((void (*)(register_cb
, void *))l
->data
)(cb
, client_data
);
633 /* Now call the registration routines for all dissector plugins. */
635 (*cb
)(RA_PLUGIN_REGISTER
, NULL
, client_data
);
636 g_slist_foreach(dissector_plugins
, call_plugin_register_protoinfo
, NULL
);
638 /* Now call the "handoff registration" routines of all built-in
639 dissectors; those routines register the dissector in other
640 dissectors' handoff tables, and fetch any dissector handles
642 register_all_protocol_handoffs(cb
, client_data
);
644 /* Now do the same with epan plugins. */
645 for (GSList
*l
= register_all_plugin_handoffs_list
; l
!= NULL
; l
= l
->next
) {
646 ((void (*)(register_cb
, void *))l
->data
)(cb
, client_data
);
649 /* Now do the same with dissector plugins. */
651 (*cb
)(RA_PLUGIN_HANDOFF
, NULL
, client_data
);
652 g_slist_foreach(dissector_plugins
, call_plugin_register_handoff
, NULL
);
654 /* sort the protocols by protocol name */
655 protocols
= g_list_sort(protocols
, proto_compare_name
);
657 /* sort the dissector handles in dissector tables (for -G reports
658 * and -d error messages. The GUI sorts the handles itself.) */
659 packet_all_tables_sort_handles();
661 /* We've assigned all the subtree type values; allocate the array
662 for them, and zero it out. */
663 tree_is_expanded
= g_new0(uint32_t, (num_tree_types
/32)+1);
667 proto_cleanup_base(void)
669 protocol_t
*protocol
;
670 header_field_info
*hfinfo
;
672 /* Free the abbrev/ID hash table */
674 g_hash_table_destroy(gpa_name_map
);
677 if (gpa_protocol_aliases
) {
678 g_hash_table_destroy(gpa_protocol_aliases
);
679 gpa_protocol_aliases
= NULL
;
681 g_free(last_field_name
);
682 last_field_name
= NULL
;
685 protocol
= (protocol_t
*)protocols
->data
;
686 PROTO_REGISTRAR_GET_NTH(protocol
->proto_id
, hfinfo
);
687 DISSECTOR_ASSERT(protocol
->proto_id
== hfinfo
->id
);
689 g_slice_free(header_field_info
, hfinfo
);
690 if (protocol
->parent_proto_id
!= -1) {
692 DISSECTOR_ASSERT(protocol
->fields
== NULL
); //helpers should not have any registered fields
693 DISSECTOR_ASSERT(protocol
->heur_list
== NULL
); //helpers should not have a heuristic list
695 if (protocol
->fields
) {
696 g_ptr_array_free(protocol
->fields
, true);
698 g_list_free(protocol
->heur_list
);
700 protocols
= g_list_remove(protocols
, protocol
);
705 g_hash_table_destroy(proto_names
);
709 if (proto_short_names
) {
710 g_hash_table_destroy(proto_short_names
);
711 proto_short_names
= NULL
;
714 if (proto_filter_names
) {
715 g_hash_table_destroy(proto_filter_names
);
716 proto_filter_names
= NULL
;
719 if (proto_reserved_filter_names
) {
720 g_hash_table_destroy(proto_reserved_filter_names
);
721 proto_reserved_filter_names
= NULL
;
724 if (gpa_hfinfo
.allocated_len
) {
726 gpa_hfinfo
.allocated_len
= 0;
727 g_free(gpa_hfinfo
.hfi
);
728 gpa_hfinfo
.hfi
= NULL
;
731 if (deregistered_fields
) {
732 g_ptr_array_free(deregistered_fields
, true);
733 deregistered_fields
= NULL
;
736 if (deregistered_data
) {
737 g_ptr_array_free(deregistered_data
, true);
738 deregistered_data
= NULL
;
741 if (deregistered_slice
) {
742 g_ptr_array_free(deregistered_slice
, true);
743 deregistered_slice
= NULL
;
746 g_free(tree_is_expanded
);
747 tree_is_expanded
= NULL
;
750 g_hash_table_destroy(prefixes
);
756 proto_free_deregistered_fields();
757 proto_cleanup_base();
759 g_slist_free(dissector_plugins
);
760 dissector_plugins
= NULL
;
764 // NOLINTNEXTLINE(misc-no-recursion)
765 proto_tree_traverse_pre_order(proto_tree
*tree
, proto_tree_traverse_func func
,
768 proto_node
*pnode
= tree
;
772 if (func(pnode
, data
))
775 child
= pnode
->first_child
;
776 while (child
!= NULL
) {
778 * The routine we call might modify the child, e.g. by
779 * freeing it, so we get the child's successor before
780 * calling that routine.
783 child
= current
->next
;
784 // We recurse here, but we're limited by prefs.gui_max_tree_depth
785 if (proto_tree_traverse_pre_order((proto_tree
*)current
, func
, data
))
793 proto_tree_children_foreach(proto_tree
*tree
, proto_tree_foreach_func func
,
796 proto_node
*node
= tree
;
802 node
= node
->first_child
;
803 while (node
!= NULL
) {
805 node
= current
->next
;
806 func((proto_tree
*)current
, data
);
811 free_GPtrArray_value(void *key
, void *value
, void *user_data _U_
)
813 GPtrArray
*ptrs
= (GPtrArray
*)value
;
814 int hfid
= GPOINTER_TO_UINT(key
);
815 header_field_info
*hfinfo
;
817 PROTO_REGISTRAR_GET_NTH(hfid
, hfinfo
);
818 if (hfinfo
->ref_type
!= HF_REF_TYPE_NONE
) {
819 /* when a field is referenced by a filter this also
820 affects the refcount for the parent protocol so we need
821 to adjust the refcount for the parent as well
823 if (hfinfo
->parent
!= -1) {
824 header_field_info
*parent_hfinfo
;
825 PROTO_REGISTRAR_GET_NTH(hfinfo
->parent
, parent_hfinfo
);
826 parent_hfinfo
->ref_type
= HF_REF_TYPE_NONE
;
828 hfinfo
->ref_type
= HF_REF_TYPE_NONE
;
831 g_ptr_array_free(ptrs
, true);
835 proto_tree_free_node(proto_node
*node
, void *data _U_
)
837 field_info
*finfo
= PNODE_FINFO(node
);
839 proto_tree_children_foreach(node
, proto_tree_free_node
, NULL
);
841 fvalue_free(finfo
->value
);
846 proto_tree_reset(proto_tree
*tree
)
848 tree_data_t
*tree_data
= PTREE_DATA(tree
);
850 proto_tree_children_foreach(tree
, proto_tree_free_node
, NULL
);
853 if (tree_data
->interesting_hfids
) {
854 /* Free all the GPtrArray's in the interesting_hfids hash. */
855 g_hash_table_foreach(tree_data
->interesting_hfids
,
856 free_GPtrArray_value
, NULL
);
858 /* And then remove all values. */
859 g_hash_table_remove_all(tree_data
->interesting_hfids
);
862 /* Reset track of the number of children */
863 tree_data
->count
= 0;
865 PROTO_NODE_INIT(tree
);
868 /* frees the resources that the dissection a proto_tree uses */
870 proto_tree_free(proto_tree
*tree
)
872 tree_data_t
*tree_data
= PTREE_DATA(tree
);
874 proto_tree_children_foreach(tree
, proto_tree_free_node
, NULL
);
877 if (tree_data
->interesting_hfids
) {
878 /* Free all the GPtrArray's in the interesting_hfids hash. */
879 g_hash_table_foreach(tree_data
->interesting_hfids
,
880 free_GPtrArray_value
, NULL
);
882 /* And then destroy the hash. */
883 g_hash_table_destroy(tree_data
->interesting_hfids
);
886 g_slice_free(tree_data_t
, tree_data
);
888 g_slice_free(proto_tree
, tree
);
891 /* Is the parsing being done for a visible proto_tree or an invisible one?
892 * By setting this correctly, the proto_tree creation is sped up by not
893 * having to call vsnprintf and copy strings around.
896 proto_tree_set_visible(proto_tree
*tree
, bool visible
)
898 bool old_visible
= PTREE_DATA(tree
)->visible
;
900 PTREE_DATA(tree
)->visible
= visible
;
906 proto_tree_set_fake_protocols(proto_tree
*tree
, bool fake_protocols
)
909 PTREE_DATA(tree
)->fake_protocols
= fake_protocols
;
912 /* Assume dissector set only its protocol fields.
913 This function is called by dissectors and allows the speeding up of filtering
914 in wireshark; if this function returns false it is safe to reset tree to NULL
915 and thus skip calling most of the expensive proto_tree_add_...()
917 If the tree is visible we implicitly assume the field is referenced.
920 proto_field_is_referenced(proto_tree
*tree
, int proto_id
)
922 register header_field_info
*hfinfo
;
928 if (PTREE_DATA(tree
)->visible
)
931 PROTO_REGISTRAR_GET_NTH(proto_id
, hfinfo
);
932 if (hfinfo
->ref_type
!= HF_REF_TYPE_NONE
)
935 if (hfinfo
->type
== FT_PROTOCOL
&& !PTREE_DATA(tree
)->fake_protocols
)
942 /* Finds a record in the hfinfo array by id. */
944 proto_registrar_get_nth(unsigned hfindex
)
946 register header_field_info
*hfinfo
;
948 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
953 /* Prefix initialization
954 * this allows for a dissector to register a display filter name prefix
955 * so that it can delay the initialization of the hf array as long as
959 /* compute a hash for the part before the dot of a display filter */
961 prefix_hash (const void *key
) {
962 /* end the string at the dot and compute its hash */
963 char* copy
= g_strdup((const char *)key
);
974 tmp
= g_str_hash(copy
);
979 /* are both strings equal up to the end or the dot? */
981 prefix_equal (const void *ap
, const void *bp
) {
982 const char* a
= (const char *)ap
;
983 const char* b
= (const char *)bp
;
989 if ( (ac
== '.' || ac
== '\0') && (bc
== '.' || bc
== '\0') ) return TRUE
;
991 if ( (ac
== '.' || ac
== '\0') && ! (bc
== '.' || bc
== '\0') ) return FALSE
;
992 if ( (bc
== '.' || bc
== '\0') && ! (ac
== '.' || ac
== '\0') ) return FALSE
;
994 if (ac
!= bc
) return FALSE
;
1000 /* Register a new prefix for "delayed" initialization of field arrays */
1002 proto_register_prefix(const char *prefix
, prefix_initializer_t pi
) {
1004 prefixes
= g_hash_table_new(prefix_hash
, prefix_equal
);
1007 g_hash_table_insert(prefixes
, (void *)prefix
, (void *)pi
);
1010 /* helper to call all prefix initializers */
1012 initialize_prefix(void *k
, void *v
, void *u _U_
) {
1013 ((prefix_initializer_t
)v
)((const char *)k
);
1017 /** Initialize every remaining uninitialized prefix. */
1019 proto_initialize_all_prefixes(void) {
1020 g_hash_table_foreach_remove(prefixes
, initialize_prefix
, NULL
);
1023 /* Finds a record in the hfinfo array by name.
1024 * If it fails to find it in the already registered fields,
1025 * it tries to find and call an initializer in the prefixes
1026 * table and if so it looks again.
1030 proto_registrar_get_byname(const char *field_name
)
1032 header_field_info
*hfinfo
;
1033 prefix_initializer_t pi
;
1038 if (g_strcmp0(field_name
, last_field_name
) == 0) {
1042 hfinfo
= (header_field_info
*)g_hash_table_lookup(gpa_name_map
, field_name
);
1045 g_free(last_field_name
);
1046 last_field_name
= g_strdup(field_name
);
1047 last_hfinfo
= hfinfo
;
1054 if ((pi
= (prefix_initializer_t
)g_hash_table_lookup(prefixes
, field_name
) ) != NULL
) {
1056 g_hash_table_remove(prefixes
, field_name
);
1061 hfinfo
= (header_field_info
*)g_hash_table_lookup(gpa_name_map
, field_name
);
1064 g_free(last_field_name
);
1065 last_field_name
= g_strdup(field_name
);
1066 last_hfinfo
= hfinfo
;
1072 proto_registrar_get_byalias(const char *alias_name
)
1078 /* Find our aliased protocol. */
1079 char *an_copy
= g_strdup(alias_name
);
1080 char *dot
= strchr(an_copy
, '.');
1084 const char *proto_pfx
= (const char *) g_hash_table_lookup(gpa_protocol_aliases
, an_copy
);
1090 /* Construct our aliased field and look it up. */
1091 GString
*filter_name
= g_string_new(proto_pfx
);
1093 g_string_append_printf(filter_name
, ".%s", dot
+1);
1095 header_field_info
*hfinfo
= proto_registrar_get_byname(filter_name
->str
);
1097 g_string_free(filter_name
, TRUE
);
1103 proto_registrar_get_id_byname(const char *field_name
)
1105 header_field_info
*hfinfo
;
1107 hfinfo
= proto_registrar_get_byname(field_name
);
1116 label_strcat_flags(const header_field_info
*hfinfo
)
1118 if (FIELD_DISPLAY(hfinfo
->display
) & BASE_STR_WSP
)
1119 return FORMAT_LABEL_REPLACE_SPACE
;
1125 format_bytes_hfinfo_maxlen(wmem_allocator_t
*scope
, const header_field_info
*hfinfo
,
1126 const uint8_t *bytes
, unsigned length
, size_t max_str_len
)
1133 if (hfinfo
->display
& BASE_SHOW_UTF_8_PRINTABLE
) {
1135 * If all bytes are valid and printable UTF-8, show the
1136 * bytes as a string - in quotes to indicate that it's
1139 if (isprint_utf8_string(bytes
, length
)) {
1140 str
= wmem_strdup_printf(scope
, "\"%.*s\"",
1141 (int)length
, bytes
);
1144 } else if (hfinfo
->display
& BASE_SHOW_ASCII_PRINTABLE
) {
1146 * Check whether all bytes are printable.
1148 is_printable
= true;
1149 for (p
= bytes
; p
< bytes
+length
; p
++) {
1150 if (!g_ascii_isprint(*p
)) {
1151 /* Not printable. */
1152 is_printable
= false;
1158 * If all bytes are printable ASCII, show the bytes
1159 * as a string - in quotes to indicate that it's
1163 str
= wmem_strdup_printf(scope
, "\"%.*s\"",
1164 (int)length
, bytes
);
1170 * Either it's not printable ASCII, or we don't care whether
1171 * it's printable ASCII; show it as hex bytes.
1173 switch (FIELD_DISPLAY(hfinfo
->display
)) {
1175 str
= bytes_to_str_punct_maxlen(scope
, bytes
, length
, '.', max_str_len
/3);
1178 str
= bytes_to_str_punct_maxlen(scope
, bytes
, length
, '-', max_str_len
/3);
1181 str
= bytes_to_str_punct_maxlen(scope
, bytes
, length
, ':', max_str_len
/3);
1184 str
= bytes_to_str_punct_maxlen(scope
, bytes
, length
, ' ', max_str_len
/3);
1188 if (prefs
.display_byte_fields_with_spaces
) {
1189 str
= bytes_to_str_punct_maxlen(scope
, bytes
, length
, ' ', max_str_len
/3);
1191 str
= bytes_to_str_maxlen(scope
, bytes
, length
, max_str_len
/2);
1197 if (hfinfo
->display
& BASE_ALLOW_ZERO
) {
1198 str
= wmem_strdup(scope
, "<none>");
1200 str
= wmem_strdup(scope
, "<MISSING>");
1207 format_bytes_hfinfo(wmem_allocator_t
*scope
, const header_field_info
*hfinfo
,
1208 const uint8_t *bytes
, unsigned length
)
1210 return format_bytes_hfinfo_maxlen(scope
, hfinfo
, bytes
, length
, ITEM_LABEL_LENGTH
);
1214 ptvcursor_new_subtree_levels(ptvcursor_t
*ptvc
)
1216 subtree_lvl
*pushed_tree
;
1218 DISSECTOR_ASSERT(ptvc
->pushed_tree_max
<= SUBTREE_MAX_LEVELS
-SUBTREE_ONCE_ALLOCATION_NUMBER
);
1219 ptvc
->pushed_tree_max
+= SUBTREE_ONCE_ALLOCATION_NUMBER
;
1221 pushed_tree
= (subtree_lvl
*)wmem_realloc(ptvc
->scope
, (void *)ptvc
->pushed_tree
, sizeof(subtree_lvl
) * ptvc
->pushed_tree_max
);
1222 DISSECTOR_ASSERT(pushed_tree
!= NULL
);
1223 ptvc
->pushed_tree
= pushed_tree
;
1227 ptvcursor_free_subtree_levels(ptvcursor_t
*ptvc
)
1229 ptvc
->pushed_tree
= NULL
;
1230 ptvc
->pushed_tree_max
= 0;
1231 DISSECTOR_ASSERT(ptvc
->pushed_tree_index
== 0);
1232 ptvc
->pushed_tree_index
= 0;
1235 /* Allocates an initializes a ptvcursor_t with 3 variables:
1236 * proto_tree, tvbuff, and offset. */
1238 ptvcursor_new(wmem_allocator_t
*scope
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
1242 ptvc
= wmem_new(scope
, ptvcursor_t
);
1243 ptvc
->scope
= scope
;
1246 ptvc
->offset
= offset
;
1247 ptvc
->pushed_tree
= NULL
;
1248 ptvc
->pushed_tree_max
= 0;
1249 ptvc
->pushed_tree_index
= 0;
1254 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
1256 ptvcursor_free(ptvcursor_t
*ptvc
)
1258 ptvcursor_free_subtree_levels(ptvc
);
1262 /* Returns tvbuff. */
1264 ptvcursor_tvbuff(ptvcursor_t
*ptvc
)
1269 /* Returns current offset. */
1271 ptvcursor_current_offset(ptvcursor_t
*ptvc
)
1273 return ptvc
->offset
;
1277 ptvcursor_tree(ptvcursor_t
*ptvc
)
1286 ptvcursor_set_tree(ptvcursor_t
*ptvc
, proto_tree
*tree
)
1291 /* creates a subtree, sets it as the working tree and pushes the old working tree */
1293 ptvcursor_push_subtree(ptvcursor_t
*ptvc
, proto_item
*it
, int ett_subtree
)
1295 subtree_lvl
*subtree
;
1296 if (ptvc
->pushed_tree_index
>= ptvc
->pushed_tree_max
)
1297 ptvcursor_new_subtree_levels(ptvc
);
1299 subtree
= ptvc
->pushed_tree
+ ptvc
->pushed_tree_index
;
1300 subtree
->tree
= ptvc
->tree
;
1302 ptvc
->pushed_tree_index
++;
1303 return ptvcursor_set_subtree(ptvc
, it
, ett_subtree
);
1306 /* pops a subtree */
1308 ptvcursor_pop_subtree(ptvcursor_t
*ptvc
)
1310 subtree_lvl
*subtree
;
1312 if (ptvc
->pushed_tree_index
<= 0)
1315 ptvc
->pushed_tree_index
--;
1316 subtree
= ptvc
->pushed_tree
+ ptvc
->pushed_tree_index
;
1317 if (subtree
->it
!= NULL
)
1318 proto_item_set_len(subtree
->it
, ptvcursor_current_offset(ptvc
) - subtree
->cursor_offset
);
1320 ptvc
->tree
= subtree
->tree
;
1323 /* saves the current tvb offset and the item in the current subtree level */
1325 ptvcursor_subtree_set_item(ptvcursor_t
*ptvc
, proto_item
*it
)
1327 subtree_lvl
*subtree
;
1329 DISSECTOR_ASSERT(ptvc
->pushed_tree_index
> 0);
1331 subtree
= ptvc
->pushed_tree
+ ptvc
->pushed_tree_index
- 1;
1333 subtree
->cursor_offset
= ptvcursor_current_offset(ptvc
);
1336 /* Creates a subtree and adds it to the cursor as the working tree but does not
1337 * save the old working tree */
1339 ptvcursor_set_subtree(ptvcursor_t
*ptvc
, proto_item
*it
, int ett_subtree
)
1341 ptvc
->tree
= proto_item_add_subtree(it
, ett_subtree
);
1346 ptvcursor_add_subtree_item(ptvcursor_t
*ptvc
, proto_item
*it
, int ett_subtree
, int length
)
1348 ptvcursor_push_subtree(ptvc
, it
, ett_subtree
);
1349 if (length
== SUBTREE_UNDEFINED_LENGTH
)
1350 ptvcursor_subtree_set_item(ptvc
, it
);
1351 return ptvcursor_tree(ptvc
);
1354 /* Add an item to the tree and create a subtree
1355 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1356 * In this case, when the subtree will be closed, the parent item length will
1357 * be equal to the advancement of the cursor since the creation of the subtree.
1360 ptvcursor_add_with_subtree(ptvcursor_t
*ptvc
, int hfindex
, int length
,
1361 const unsigned encoding
, int ett_subtree
)
1365 it
= ptvcursor_add_no_advance(ptvc
, hfindex
, length
, encoding
);
1366 return ptvcursor_add_subtree_item(ptvc
, it
, ett_subtree
, length
);
1370 proto_tree_add_text_node(proto_tree
*tree
, tvbuff_t
*tvb
, int start
, int length
);
1372 /* Add a text node to the tree and create a subtree
1373 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1374 * In this case, when the subtree will be closed, the item length will be equal
1375 * to the advancement of the cursor since the creation of the subtree.
1378 ptvcursor_add_text_with_subtree(ptvcursor_t
*ptvc
, int length
,
1379 int ett_subtree
, const char *format
, ...)
1383 header_field_info
*hfinfo
;
1386 tree
= ptvcursor_tree(ptvc
);
1388 CHECK_FOR_NULL_TREE(tree
);
1390 TRY_TO_FAKE_THIS_ITEM(tree
, hf_text_only
, hfinfo
);
1392 pi
= proto_tree_add_text_node(tree
, ptvcursor_tvbuff(ptvc
),
1393 ptvcursor_current_offset(ptvc
), length
);
1395 TRY_TO_FAKE_THIS_REPR(pi
);
1397 va_start(ap
, format
);
1398 proto_tree_set_representation(pi
, format
, ap
);
1401 return ptvcursor_add_subtree_item(ptvc
, pi
, ett_subtree
, length
);
1404 /* Add a text-only node, leaving it to our caller to fill the text in */
1406 proto_tree_add_text_node(proto_tree
*tree
, tvbuff_t
*tvb
, int start
, int length
)
1413 pi
= proto_tree_add_pi(tree
, &hfi_text_only
, tvb
, start
, &length
);
1418 /* (INTERNAL USE ONLY) Add a text-only node to the proto_tree */
1420 proto_tree_add_text_internal(proto_tree
*tree
, tvbuff_t
*tvb
, int start
, int length
,
1421 const char *format
, ...)
1425 header_field_info
*hfinfo
;
1428 length
= tvb_captured_length(tvb
) ? tvb_ensure_captured_length_remaining(tvb
, start
) : 0;
1430 tvb_ensure_bytes_exist(tvb
, start
, length
);
1433 CHECK_FOR_NULL_TREE(tree
);
1435 TRY_TO_FAKE_THIS_ITEM(tree
, hf_text_only
, hfinfo
);
1437 pi
= proto_tree_add_text_node(tree
, tvb
, start
, length
);
1439 TRY_TO_FAKE_THIS_REPR(pi
);
1441 va_start(ap
, format
);
1442 proto_tree_set_representation(pi
, format
, ap
);
1448 /* (INTERNAL USE ONLY) Add a text-only node to the proto_tree (va_list version) */
1450 proto_tree_add_text_valist_internal(proto_tree
*tree
, tvbuff_t
*tvb
, int start
,
1451 int length
, const char *format
, va_list ap
)
1454 header_field_info
*hfinfo
;
1456 /* proto_tree_add_text_node calls proto_tree_add_pi() with the
1457 * FT_NONE hf_text_only, which calls get_hfi_length, which adjusts
1458 * the length to be what's in the tvbuff if length is -1, and the
1459 * minimum of length and what's in the tvbuff if not.
1462 CHECK_FOR_NULL_TREE(tree
);
1464 TRY_TO_FAKE_THIS_ITEM(tree
, hf_text_only
, hfinfo
);
1466 pi
= proto_tree_add_text_node(tree
, tvb
, start
, length
);
1468 TRY_TO_FAKE_THIS_REPR(pi
);
1470 proto_tree_set_representation(pi
, format
, ap
);
1475 /* Add a text-only node that creates a subtree underneath.
1478 proto_tree_add_subtree(proto_tree
*tree
, tvbuff_t
*tvb
, int start
, int length
, int idx
, proto_item
**tree_item
, const char *text
)
1480 return proto_tree_add_subtree_format(tree
, tvb
, start
, length
, idx
, tree_item
, "%s", text
);
1483 /* Add a text-only node that creates a subtree underneath.
1486 proto_tree_add_subtree_format(proto_tree
*tree
, tvbuff_t
*tvb
, int start
, int length
, int idx
, proto_item
**tree_item
, const char *format
, ...)
1492 va_start(ap
, format
);
1493 pi
= proto_tree_add_text_valist_internal(tree
, tvb
, start
, length
, format
, ap
);
1496 if (tree_item
!= NULL
)
1499 pt
= proto_item_add_subtree(pi
, idx
);
1504 /* Add a text-only node for debugging purposes. The caller doesn't need
1505 * to worry about tvbuff, start, or length. Debug message gets sent to
1508 proto_tree_add_debug_text(proto_tree
*tree
, const char *format
, ...)
1513 pi
= proto_tree_add_text_node(tree
, NULL
, 0, 0);
1516 va_start(ap
, format
);
1517 proto_tree_set_representation(pi
, format
, ap
);
1520 va_start(ap
, format
);
1521 vprintf(format
, ap
);
1529 proto_tree_add_format_text(proto_tree
*tree
, tvbuff_t
*tvb
, int start
, int length
)
1532 header_field_info
*hfinfo
;
1534 CHECK_FOR_NULL_TREE(tree
);
1536 TRY_TO_FAKE_THIS_ITEM(tree
, hf_text_only
, hfinfo
);
1538 pi
= proto_tree_add_text_node(tree
, tvb
, start
, length
);
1540 TRY_TO_FAKE_THIS_REPR(pi
);
1542 proto_item_set_text(pi
, "%s", tvb_format_text(tree
->tree_data
->pinfo
->pool
, tvb
, start
, length
));
1548 proto_tree_add_format_wsp_text(proto_tree
*tree
, tvbuff_t
*tvb
, int start
, int length
)
1551 header_field_info
*hfinfo
;
1554 CHECK_FOR_NULL_TREE(tree
);
1556 TRY_TO_FAKE_THIS_ITEM(tree
, hf_text_only
, hfinfo
);
1558 pi
= proto_tree_add_text_node(tree
, tvb
, start
, length
);
1560 TRY_TO_FAKE_THIS_REPR(pi
);
1562 str
= tvb_format_text_wsp(NULL
, tvb
, start
, length
);
1563 proto_item_set_text(pi
, "%s", str
);
1564 wmem_free(NULL
, str
);
1569 void proto_report_dissector_bug(const char *format
, ...)
1573 if (wireshark_abort_on_dissector_bug
) {
1575 * Try to have the error message show up in the crash
1578 va_start(args
, format
);
1579 ws_vadd_crash_info(format
, args
);
1583 * Print the error message.
1585 va_start(args
, format
);
1586 vfprintf(stderr
, format
, args
);
1595 va_start(args
, format
);
1596 VTHROW_FORMATTED(DissectorError
, format
, args
);
1601 /* We could probably get away with changing is_error to a minimum length value. */
1603 report_type_length_mismatch(proto_tree
*tree
, const char *descr
, int length
, bool is_error
)
1606 expert_add_info_format(NULL
, tree
, &ei_type_length_mismatch_error
, "Trying to fetch %s with length %d", descr
, length
);
1608 expert_add_info_format(NULL
, tree
, &ei_type_length_mismatch_warn
, "Trying to fetch %s with length %d", descr
, length
);
1612 THROW(ReportedBoundsError
);
1617 get_uint_value(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int length
, const unsigned encoding
)
1625 value
= tvb_get_uint8(tvb
, offset
);
1626 if (encoding
& ENC_ZIGBEE
) {
1627 if (value
== 0xFF) { /* Invalid Zigbee length, set to 0 */
1634 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letohs(tvb
, offset
)
1635 : tvb_get_ntohs(tvb
, offset
);
1636 if (encoding
& ENC_ZIGBEE
) {
1637 if (value
== 0xFFFF) { /* Invalid Zigbee length, set to 0 */
1644 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letoh24(tvb
, offset
)
1645 : tvb_get_ntoh24(tvb
, offset
);
1649 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letohl(tvb
, offset
)
1650 : tvb_get_ntohl(tvb
, offset
);
1655 length_error
= true;
1658 length_error
= false;
1659 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letohl(tvb
, offset
)
1660 : tvb_get_ntohl(tvb
, offset
);
1662 report_type_length_mismatch(tree
, "an unsigned integer", length
, length_error
);
1668 static inline uint64_t
1669 get_uint64_value(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, unsigned length
, const unsigned encoding
)
1677 value
= tvb_get_uint8(tvb
, offset
);
1681 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letohs(tvb
, offset
)
1682 : tvb_get_ntohs(tvb
, offset
);
1686 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letoh24(tvb
, offset
)
1687 : tvb_get_ntoh24(tvb
, offset
);
1691 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letohl(tvb
, offset
)
1692 : tvb_get_ntohl(tvb
, offset
);
1696 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letoh40(tvb
, offset
)
1697 : tvb_get_ntoh40(tvb
, offset
);
1701 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letoh48(tvb
, offset
)
1702 : tvb_get_ntoh48(tvb
, offset
);
1706 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letoh56(tvb
, offset
)
1707 : tvb_get_ntoh56(tvb
, offset
);
1711 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letoh64(tvb
, offset
)
1712 : tvb_get_ntoh64(tvb
, offset
);
1717 length_error
= true;
1720 length_error
= false;
1721 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letoh64(tvb
, offset
)
1722 : tvb_get_ntoh64(tvb
, offset
);
1724 report_type_length_mismatch(tree
, "an unsigned integer", length
, length_error
);
1731 get_int_value(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int length
, const unsigned encoding
)
1739 value
= tvb_get_int8(tvb
, offset
);
1743 value
= encoding
? tvb_get_letohis(tvb
, offset
)
1744 : tvb_get_ntohis(tvb
, offset
);
1748 value
= encoding
? tvb_get_letohi24(tvb
, offset
)
1749 : tvb_get_ntohi24(tvb
, offset
);
1753 value
= encoding
? tvb_get_letohil(tvb
, offset
)
1754 : tvb_get_ntohil(tvb
, offset
);
1759 length_error
= true;
1762 length_error
= false;
1763 value
= encoding
? tvb_get_letohil(tvb
, offset
)
1764 : tvb_get_ntohil(tvb
, offset
);
1766 report_type_length_mismatch(tree
, "a signed integer", length
, length_error
);
1772 /* Note: this returns an unsigned int64, but with the appropriate bit(s) set to
1773 * be cast-able as a int64_t. This is weird, but what the code has always done.
1775 static inline uint64_t
1776 get_int64_value(proto_tree
*tree
, tvbuff_t
*tvb
, int start
, unsigned length
, const unsigned encoding
)
1778 uint64_t value
= get_uint64_value(tree
, tvb
, start
, length
, encoding
);
1782 value
= ws_sign_ext64(value
, 56);
1785 value
= ws_sign_ext64(value
, 48);
1788 value
= ws_sign_ext64(value
, 40);
1791 value
= ws_sign_ext64(value
, 32);
1794 value
= ws_sign_ext64(value
, 24);
1797 value
= ws_sign_ext64(value
, 16);
1800 value
= ws_sign_ext64(value
, 8);
1808 static inline const uint8_t *
1809 get_string_value(wmem_allocator_t
*scope
, tvbuff_t
*tvb
, int start
,
1810 int length
, int *ret_length
, const unsigned encoding
)
1813 length
= tvb_ensure_captured_length_remaining(tvb
, start
);
1815 *ret_length
= length
;
1816 return tvb_get_string_enc(scope
, tvb
, start
, length
, encoding
);
1819 /* For FT_STRINGZ */
1820 static inline const uint8_t *
1821 get_stringz_value(wmem_allocator_t
*scope
, proto_tree
*tree
, tvbuff_t
*tvb
,
1822 int start
, int length
, int *ret_length
, const unsigned encoding
)
1824 const uint8_t *value
;
1827 report_type_length_mismatch(tree
, "a string", length
, true);
1830 /* This can throw an exception */
1831 value
= tvb_get_stringz_enc(scope
, tvb
, start
, &length
, encoding
);
1833 /* In this case, length signifies the length of the string.
1835 * This could either be a null-padded string, which doesn't
1836 * necessarily have a '\0' at the end, or a null-terminated
1837 * string, with a trailing '\0'. (Yes, there are cases
1838 * where you have a string that's both counted and null-
1841 * In the first case, we must allocate a buffer of length
1842 * "length+1", to make room for a trailing '\0'.
1844 * In the second case, we don't assume that there is a
1845 * trailing '\0' there, as the packet might be malformed.
1846 * (XXX - should we throw an exception if there's no
1847 * trailing '\0'?) Therefore, we allocate a buffer of
1848 * length "length+1", and put in a trailing '\0', just to
1851 * (XXX - this would change if we made string values counted
1852 * rather than null-terminated.)
1854 value
= tvb_get_string_enc(scope
, tvb
, start
, length
, encoding
);
1856 *ret_length
= length
;
1860 /* For FT_UINT_STRING */
1861 static inline const uint8_t *
1862 get_uint_string_value(wmem_allocator_t
*scope
, proto_tree
*tree
,
1863 tvbuff_t
*tvb
, int start
, int length
, int *ret_length
,
1864 const unsigned encoding
)
1867 const uint8_t *value
;
1869 /* I believe it's ok if this is called with a NULL tree */
1870 n
= get_uint_value(tree
, tvb
, start
, length
, encoding
& ~ENC_CHARENCODING_MASK
);
1871 value
= tvb_get_string_enc(scope
, tvb
, start
+ length
, n
, encoding
);
1873 *ret_length
= length
;
1877 /* For FT_STRINGZPAD */
1878 static inline const uint8_t *
1879 get_stringzpad_value(wmem_allocator_t
*scope
, tvbuff_t
*tvb
, int start
,
1880 int length
, int *ret_length
, const unsigned encoding
)
1883 * XXX - currently, string values are null-
1884 * terminated, so a "zero-padded" string
1885 * isn't special. If we represent string
1886 * values as something that includes a counted
1887 * array of bytes, we'll need to strip the
1891 length
= tvb_ensure_captured_length_remaining(tvb
, start
);
1893 *ret_length
= length
;
1894 return tvb_get_string_enc(scope
, tvb
, start
, length
, encoding
);
1897 /* For FT_STRINGZTRUNC */
1898 static inline const uint8_t *
1899 get_stringztrunc_value(wmem_allocator_t
*scope
, tvbuff_t
*tvb
, int start
,
1900 int length
, int *ret_length
, const unsigned encoding
)
1903 * XXX - currently, string values are null-
1904 * terminated, so a "zero-truncated" string
1905 * isn't special. If we represent string
1906 * values as something that includes a counted
1907 * array of bytes, we'll need to strip everything
1908 * starting with the terminating NUL.
1911 length
= tvb_ensure_captured_length_remaining(tvb
, start
);
1913 *ret_length
= length
;
1914 return tvb_get_string_enc(scope
, tvb
, start
, length
, encoding
);
1918 * Deltas between the epochs for various non-UN*X time stamp formats and
1919 * the January 1, 1970, 00:00:00 (proleptic?) UTC epoch for the UN*X time
1924 * NTP Era 0: the epoch is January 1, 1900, 00:00:00 (proleptic?) UTC.
1925 * XXX - if it's OK if this is unsigned, can we just use
1926 * EPOCH_DELTA_1900_01_01_00_00_00_UTC?
1928 #define NTP_TIMEDIFF1900TO1970SEC INT64_C(2208988800)
1931 * NTP Era 1: the epoch is February 7, 2036, 06:28:16 UTC.
1933 #define NTP_TIMEDIFF1970TO2036SEC INT64_C(2085978496)
1935 /* this can be called when there is no tree, so tree may be null */
1937 get_time_value(proto_tree
*tree
, tvbuff_t
*tvb
, const int start
,
1938 const int length
, const unsigned encoding
, nstime_t
*time_stamp
,
1939 const bool is_relative
)
1947 case ENC_TIME_SECS_NSECS
|ENC_BIG_ENDIAN
:
1949 * If the length is 16, 8-byte seconds, followed
1950 * by 8-byte fractional time in nanoseconds,
1953 * If the length is 12, 8-byte seconds, followed
1954 * by 4-byte fractional time in nanoseconds,
1957 * If the length is 8, 4-byte seconds, followed
1958 * by 4-byte fractional time in nanoseconds,
1961 * For absolute times, the seconds are seconds
1962 * since the UN*X epoch.
1965 time_stamp
->secs
= (time_t)tvb_get_ntoh64(tvb
, start
);
1966 time_stamp
->nsecs
= (uint32_t)tvb_get_ntoh64(tvb
, start
+8);
1967 } else if (length
== 12) {
1968 time_stamp
->secs
= (time_t)tvb_get_ntoh64(tvb
, start
);
1969 time_stamp
->nsecs
= tvb_get_ntohl(tvb
, start
+8);
1970 } else if (length
== 8) {
1971 time_stamp
->secs
= (time_t)tvb_get_ntohl(tvb
, start
);
1972 time_stamp
->nsecs
= tvb_get_ntohl(tvb
, start
+4);
1973 } else if (length
== 4) {
1975 * Backwards compatibility.
1976 * ENC_TIME_SECS_NSECS is 0; using
1977 * ENC_BIG_ENDIAN by itself with a 4-byte
1978 * time-in-seconds value was done in the
1981 time_stamp
->secs
= (time_t)tvb_get_ntohl(tvb
, start
);
1982 time_stamp
->nsecs
= 0;
1984 time_stamp
->secs
= 0;
1985 time_stamp
->nsecs
= 0;
1986 report_type_length_mismatch(tree
, "a timespec", length
, (length
< 4));
1990 case ENC_TIME_SECS_NSECS
|ENC_LITTLE_ENDIAN
:
1992 * If the length is 16, 8-byte seconds, followed
1993 * by 8-byte fractional time in nanoseconds,
1994 * both little-endian.
1996 * If the length is 12, 8-byte seconds, followed
1997 * by 4-byte fractional time in nanoseconds,
1998 * both little-endian.
2000 * If the length is 8, 4-byte seconds, followed
2001 * by 4-byte fractional time in nanoseconds,
2002 * both little-endian.
2004 * For absolute times, the seconds are seconds
2005 * since the UN*X epoch.
2008 time_stamp
->secs
= (time_t)tvb_get_letoh64(tvb
, start
);
2009 time_stamp
->nsecs
= (uint32_t)tvb_get_letoh64(tvb
, start
+8);
2010 } else if (length
== 12) {
2011 time_stamp
->secs
= (time_t)tvb_get_letoh64(tvb
, start
);
2012 time_stamp
->nsecs
= tvb_get_letohl(tvb
, start
+8);
2013 } else if (length
== 8) {
2014 time_stamp
->secs
= (time_t)tvb_get_letohl(tvb
, start
);
2015 time_stamp
->nsecs
= tvb_get_letohl(tvb
, start
+4);
2016 } else if (length
== 4) {
2018 * Backwards compatibility.
2019 * ENC_TIME_SECS_NSECS is 0; using
2020 * ENC_LITTLE_ENDIAN by itself with a 4-byte
2021 * time-in-seconds value was done in the
2024 time_stamp
->secs
= (time_t)tvb_get_letohl(tvb
, start
);
2025 time_stamp
->nsecs
= 0;
2027 time_stamp
->secs
= 0;
2028 time_stamp
->nsecs
= 0;
2029 report_type_length_mismatch(tree
, "a timespec", length
, (length
< 4));
2033 case ENC_TIME_NTP
|ENC_BIG_ENDIAN
:
2035 * NTP time stamp, big-endian.
2036 * Only supported for absolute times.
2038 DISSECTOR_ASSERT(!is_relative
);
2040 /* We need a temporary variable here so the unsigned math
2041 * works correctly (for years > 2036 according to RFC 2030
2044 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2045 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2046 * If bit 0 is not set, the time is in the range 2036-2104 and
2047 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2049 tmpsecs
= tvb_get_ntohl(tvb
, start
);
2050 if ((tmpsecs
& 0x80000000) != 0)
2051 time_stamp
->secs
= (time_t)((int64_t)tmpsecs
- NTP_TIMEDIFF1900TO1970SEC
);
2053 time_stamp
->secs
= (time_t)((int64_t)tmpsecs
+ NTP_TIMEDIFF1970TO2036SEC
);
2056 tmp64secs
= tvb_get_ntoh64(tvb
, start
);
2057 if (tmp64secs
== 0) {
2058 //This is "NULL" time
2059 time_stamp
->secs
= 0;
2060 time_stamp
->nsecs
= 0;
2063 * Convert 1/2^32s of a second to
2066 time_stamp
->nsecs
= (int)(1000000000*(tvb_get_ntohl(tvb
, start
+4)/4294967296.0));
2068 } else if (length
== 4) {
2070 * Backwards compatibility.
2073 //This is "NULL" time
2074 time_stamp
->secs
= 0;
2076 time_stamp
->nsecs
= 0;
2078 time_stamp
->secs
= 0;
2079 time_stamp
->nsecs
= 0;
2080 report_type_length_mismatch(tree
, "an NTP time stamp", length
, (length
< 4));
2084 case ENC_TIME_NTP
|ENC_LITTLE_ENDIAN
:
2086 * NTP time stamp, little-endian.
2087 * Only supported for absolute times.
2089 * NTP doesn't use this, because it's an Internet format
2090 * and hence big-endian. Any implementation must decide
2091 * whether the NTP timestamp is a 64-bit unsigned fixed
2092 * point number (RFC 1305, RFC 4330) or a 64-bit struct
2093 * with a 32-bit unsigned seconds field followed by a
2094 * 32-bit fraction field (cf. RFC 5905, which obsoletes
2095 * the previous two).
2097 * XXX: We do the latter, but no dissector uses this format.
2098 * OTOH, ERF timestamps do the former, so perhaps we
2099 * should switch the interpretation so that packet-erf.c
2100 * could use this directly?
2102 DISSECTOR_ASSERT(!is_relative
);
2104 /* We need a temporary variable here so the unsigned math
2105 * works correctly (for years > 2036 according to RFC 2030
2108 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2109 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2110 * If bit 0 is not set, the time is in the range 2036-2104 and
2111 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2113 tmpsecs
= tvb_get_letohl(tvb
, start
);
2114 if ((tmpsecs
& 0x80000000) != 0)
2115 time_stamp
->secs
= (time_t)((int64_t)tmpsecs
- NTP_TIMEDIFF1900TO1970SEC
);
2117 time_stamp
->secs
= (time_t)((int64_t)tmpsecs
+ NTP_TIMEDIFF1970TO2036SEC
);
2120 tmp64secs
= tvb_get_letoh64(tvb
, start
);
2121 if (tmp64secs
== 0) {
2122 //This is "NULL" time
2123 time_stamp
->secs
= 0;
2124 time_stamp
->nsecs
= 0;
2127 * Convert 1/2^32s of a second to
2130 time_stamp
->nsecs
= (int)(1000000000*(tvb_get_letohl(tvb
, start
+4)/4294967296.0));
2132 } else if (length
== 4) {
2134 * Backwards compatibility.
2137 //This is "NULL" time
2138 time_stamp
->secs
= 0;
2140 time_stamp
->nsecs
= 0;
2142 time_stamp
->secs
= 0;
2143 time_stamp
->nsecs
= 0;
2144 report_type_length_mismatch(tree
, "an NTP time stamp", length
, (length
< 4));
2148 case ENC_TIME_TOD
|ENC_BIG_ENDIAN
:
2150 * S/3x0 and z/Architecture TOD clock time stamp,
2151 * big-endian. The epoch is January 1, 1900,
2152 * 00:00:00 (proleptic?) UTC.
2154 * Only supported for absolute times.
2156 DISSECTOR_ASSERT(!is_relative
);
2157 DISSECTOR_ASSERT(length
== 8);
2160 todusecs
= tvb_get_ntoh64(tvb
, start
) >> 12;
2161 time_stamp
->secs
= (time_t)((todusecs
/ 1000000) - EPOCH_DELTA_1900_01_01_00_00_00_UTC
);
2162 time_stamp
->nsecs
= (int)((todusecs
% 1000000) * 1000);
2164 time_stamp
->secs
= 0;
2165 time_stamp
->nsecs
= 0;
2166 report_type_length_mismatch(tree
, "a TOD clock time stamp", length
, (length
< 4));
2170 case ENC_TIME_TOD
|ENC_LITTLE_ENDIAN
:
2172 * S/3x0 and z/Architecture TOD clock time stamp,
2173 * little-endian. The epoch is January 1, 1900,
2174 * 00:00:00 (proleptic?) UTC.
2176 * Only supported for absolute times.
2178 DISSECTOR_ASSERT(!is_relative
);
2181 todusecs
= tvb_get_letoh64(tvb
, start
) >> 12 ;
2182 time_stamp
->secs
= (time_t)((todusecs
/ 1000000) - EPOCH_DELTA_1900_01_01_00_00_00_UTC
);
2183 time_stamp
->nsecs
= (int)((todusecs
% 1000000) * 1000);
2185 time_stamp
->secs
= 0;
2186 time_stamp
->nsecs
= 0;
2187 report_type_length_mismatch(tree
, "a TOD clock time stamp", length
, (length
< 4));
2191 case ENC_TIME_RTPS
|ENC_BIG_ENDIAN
:
2193 * Time stamp using the same seconds/fraction format
2194 * as NTP, but with the origin of the time stamp being
2195 * the UNIX epoch rather than the NTP epoch; big-
2198 * Only supported for absolute times.
2200 DISSECTOR_ASSERT(!is_relative
);
2203 time_stamp
->secs
= (time_t)tvb_get_ntohl(tvb
, start
);
2205 * Convert 1/2^32s of a second to nanoseconds.
2207 time_stamp
->nsecs
= (int)(1000000000*(tvb_get_ntohl(tvb
, start
+4)/4294967296.0));
2209 time_stamp
->secs
= 0;
2210 time_stamp
->nsecs
= 0;
2211 report_type_length_mismatch(tree
, "an RTPS time stamp", length
, (length
< 4));
2215 case ENC_TIME_RTPS
|ENC_LITTLE_ENDIAN
:
2217 * Time stamp using the same seconds/fraction format
2218 * as NTP, but with the origin of the time stamp being
2219 * the UNIX epoch rather than the NTP epoch; little-
2222 * Only supported for absolute times.
2224 * The RTPS specification explicitly supports Little
2225 * Endian encoding. In one place, it states that its
2226 * Time_t representation "is the one defined by ...
2227 * RFC 1305", but in another explicitly defines it as
2228 * a struct consisting of an 32 bit unsigned seconds
2229 * field and a 32 bit unsigned fraction field, not a 64
2230 * bit fixed point, so we do that here.
2231 * https://www.omg.org/spec/DDSI-RTPS/2.5/PDF
2233 DISSECTOR_ASSERT(!is_relative
);
2236 time_stamp
->secs
= (time_t)tvb_get_letohl(tvb
, start
);
2238 * Convert 1/2^32s of a second to nanoseconds.
2240 time_stamp
->nsecs
= (int)(1000000000*(tvb_get_letohl(tvb
, start
+4)/4294967296.0));
2242 time_stamp
->secs
= 0;
2243 time_stamp
->nsecs
= 0;
2244 report_type_length_mismatch(tree
, "an RTPS time stamp", length
, (length
< 4));
2248 case ENC_TIME_MIP6
| ENC_BIG_ENDIAN
:
2250 * MIP6 time stamp, big-endian.
2251 * A 64-bit unsigned integer field containing a timestamp. The
2252 * value indicates the number of seconds since January 1, 1970,
2253 * 00:00 UTC, by using a fixed point format. In this format, the
2254 * integer number of seconds is contained in the first 48 bits of
2255 * the field, and the remaining 16 bits indicate the number of
2256 * 1/65536 fractions of a second.
2258 * Only supported for absolute times.
2260 DISSECTOR_ASSERT(!is_relative
);
2263 /* We need a temporary variable here so the casting and fractions
2264 * of a second work correctly.
2266 tmp64secs
= tvb_get_ntoh48(tvb
, start
);
2267 tmpsecs
= tvb_get_ntohs(tvb
, start
+ 6);
2270 if ((tmp64secs
== 0) && (tmpsecs
== 0)) {
2271 //This is "NULL" time
2272 time_stamp
->secs
= 0;
2273 time_stamp
->nsecs
= 0;
2275 time_stamp
->secs
= (time_t)tmp64secs
;
2276 time_stamp
->nsecs
= (int)((tmpsecs
/ 4294967296.0) * 1000000000);
2279 time_stamp
->secs
= 0;
2280 time_stamp
->nsecs
= 0;
2281 report_type_length_mismatch(tree
, "an NTP time stamp", length
, (length
!= 8));
2285 case ENC_TIME_SECS_USECS
|ENC_BIG_ENDIAN
:
2287 * If the length is 16, 8-byte seconds, followed
2288 * by 8-byte fractional time in microseconds,
2291 * If the length is 12, 8-byte seconds, followed
2292 * by 4-byte fractional time in microseconds,
2295 * If the length is 8, 4-byte seconds, followed
2296 * by 4-byte fractional time in microseconds,
2299 * For absolute times, the seconds are seconds
2300 * since the UN*X epoch.
2303 time_stamp
->secs
= (time_t)tvb_get_ntoh64(tvb
, start
);
2304 time_stamp
->nsecs
= (uint32_t)tvb_get_ntoh64(tvb
, start
+8)*1000;
2305 } else if (length
== 12) {
2306 time_stamp
->secs
= (time_t)tvb_get_ntoh64(tvb
, start
);
2307 time_stamp
->nsecs
= tvb_get_ntohl(tvb
, start
+8)*1000;
2308 } else if (length
== 8) {
2309 time_stamp
->secs
= (time_t)tvb_get_ntohl(tvb
, start
);
2310 time_stamp
->nsecs
= tvb_get_ntohl(tvb
, start
+4)*1000;
2312 time_stamp
->secs
= 0;
2313 time_stamp
->nsecs
= 0;
2314 report_type_length_mismatch(tree
, "a timeval", length
, (length
< 4));
2318 case ENC_TIME_SECS_USECS
|ENC_LITTLE_ENDIAN
:
2320 * If the length is 16, 8-byte seconds, followed
2321 * by 8-byte fractional time in microseconds,
2322 * both little-endian.
2324 * If the length is 12, 8-byte seconds, followed
2325 * by 4-byte fractional time in microseconds,
2326 * both little-endian.
2328 * If the length is 8, 4-byte seconds, followed
2329 * by 4-byte fractional time in microseconds,
2330 * both little-endian.
2332 * For absolute times, the seconds are seconds
2333 * since the UN*X epoch.
2336 time_stamp
->secs
= (time_t)tvb_get_letoh64(tvb
, start
);
2337 time_stamp
->nsecs
= (uint32_t)tvb_get_letoh64(tvb
, start
+8)*1000;
2338 } else if (length
== 12) {
2339 time_stamp
->secs
= (time_t)tvb_get_letoh64(tvb
, start
);
2340 time_stamp
->nsecs
= tvb_get_letohl(tvb
, start
+8)*1000;
2341 } else if (length
== 8) {
2342 time_stamp
->secs
= (time_t)tvb_get_letohl(tvb
, start
);
2343 time_stamp
->nsecs
= tvb_get_letohl(tvb
, start
+4)*1000;
2345 time_stamp
->secs
= 0;
2346 time_stamp
->nsecs
= 0;
2347 report_type_length_mismatch(tree
, "a timeval", length
, (length
< 4));
2351 case ENC_TIME_SECS
|ENC_BIG_ENDIAN
:
2352 case ENC_TIME_SECS
|ENC_LITTLE_ENDIAN
:
2354 * Seconds, 1 to 8 bytes.
2355 * For absolute times, it's seconds since the
2358 if (length
>= 1 && length
<= 8) {
2359 time_stamp
->secs
= (time_t)get_uint64_value(tree
, tvb
, start
, length
, encoding
);
2360 time_stamp
->nsecs
= 0;
2362 time_stamp
->secs
= 0;
2363 time_stamp
->nsecs
= 0;
2364 report_type_length_mismatch(tree
, "a time-in-seconds time stamp", length
, (length
< 4));
2368 case ENC_TIME_MSECS
|ENC_BIG_ENDIAN
:
2369 case ENC_TIME_MSECS
|ENC_LITTLE_ENDIAN
:
2371 * Milliseconds, 1 to 8 bytes.
2372 * For absolute times, it's milliseconds since the
2375 if (length
>= 1 && length
<= 8) {
2378 msecs
= get_uint64_value(tree
, tvb
, start
, length
, encoding
);
2379 time_stamp
->secs
= (time_t)(msecs
/ 1000);
2380 time_stamp
->nsecs
= (int)(msecs
% 1000)*1000000;
2382 time_stamp
->secs
= 0;
2383 time_stamp
->nsecs
= 0;
2384 report_type_length_mismatch(tree
, "a time-in-milliseconds time stamp", length
, (length
< 4));
2388 case ENC_TIME_USECS
|ENC_BIG_ENDIAN
:
2389 case ENC_TIME_USECS
|ENC_LITTLE_ENDIAN
:
2391 * Microseconds, 1 to 8 bytes.
2392 * For absolute times, it's microseconds since the
2395 if (length
>= 1 && length
<= 8) {
2398 usecs
= get_uint64_value(tree
, tvb
, start
, length
, encoding
);
2399 time_stamp
->secs
= (time_t)(usecs
/ 1000000);
2400 time_stamp
->nsecs
= (int)(usecs
% 1000000)*1000;
2402 time_stamp
->secs
= 0;
2403 time_stamp
->nsecs
= 0;
2404 report_type_length_mismatch(tree
, "a time-in-microseconds time stamp", length
, (length
< 4));
2408 case ENC_TIME_NSECS
|ENC_BIG_ENDIAN
:
2409 case ENC_TIME_NSECS
|ENC_LITTLE_ENDIAN
:
2411 * nanoseconds, 1 to 8 bytes.
2412 * For absolute times, it's nanoseconds since the
2416 if (length
>= 1 && length
<= 8) {
2419 nsecs
= get_uint64_value(tree
, tvb
, start
, length
, encoding
);
2420 time_stamp
->secs
= (time_t)(nsecs
/ 1000000000);
2421 time_stamp
->nsecs
= (int)(nsecs
% 1000000000);
2423 time_stamp
->secs
= 0;
2424 time_stamp
->nsecs
= 0;
2425 report_type_length_mismatch(tree
, "a time-in-nanoseconds time stamp", length
, (length
< 4));
2429 case ENC_TIME_RFC_3971
|ENC_BIG_ENDIAN
:
2431 * 1/64ths of a second since the UN*X epoch,
2434 * Only supported for absolute times.
2436 DISSECTOR_ASSERT(!is_relative
);
2440 * The upper 48 bits are seconds since the
2443 time_stamp
->secs
= (time_t)tvb_get_ntoh48(tvb
, start
);
2445 * The lower 16 bits are 1/2^16s of a second;
2446 * convert them to nanoseconds.
2448 * XXX - this may give the impression of higher
2449 * precision than you actually get.
2451 time_stamp
->nsecs
= (int)(1000000000*(tvb_get_ntohs(tvb
, start
+6)/65536.0));
2453 time_stamp
->secs
= 0;
2454 time_stamp
->nsecs
= 0;
2455 report_type_length_mismatch(tree
, "an RFC 3971-style time stamp", length
, (length
< 4));
2459 case ENC_TIME_RFC_3971
|ENC_LITTLE_ENDIAN
:
2461 * 1/64ths of a second since the UN*X epoch,
2464 * Only supported for absolute times.
2466 DISSECTOR_ASSERT(!is_relative
);
2470 * XXX - this is assuming that, if anybody
2471 * were ever to use this format - RFC 3971
2472 * doesn't, because that's an Internet
2473 * protocol, and those use network byte
2474 * order, i.e. big-endian - they'd treat it
2475 * as a 64-bit count of 1/2^16s of a second,
2476 * putting the upper 48 bits at the end.
2478 * The lower 48 bits are seconds since the
2481 time_stamp
->secs
= (time_t)tvb_get_letoh48(tvb
, start
+2);
2483 * The upper 16 bits are 1/2^16s of a second;
2484 * convert them to nanoseconds.
2486 * XXX - this may give the impression of higher
2487 * precision than you actually get.
2489 time_stamp
->nsecs
= (int)(1000000000*(tvb_get_letohs(tvb
, start
)/65536.0));
2491 time_stamp
->secs
= 0;
2492 time_stamp
->nsecs
= 0;
2493 report_type_length_mismatch(tree
, "an RFC 3971-style time stamp", length
, (length
< 4));
2497 case ENC_TIME_SECS_NTP
|ENC_BIG_ENDIAN
:
2499 * NTP time stamp, with 1-second resolution (i.e.,
2500 * seconds since the NTP epoch), big-endian.
2501 * Only supported for absolute times.
2503 DISSECTOR_ASSERT(!is_relative
);
2507 * We need a temporary variable here so the unsigned math
2508 * works correctly (for years > 2036 according to RFC 2030
2511 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2512 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2513 * If bit 0 is not set, the time is in the range 2036-2104 and
2514 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2516 tmpsecs
= tvb_get_ntohl(tvb
, start
);
2517 if ((tmpsecs
& 0x80000000) != 0)
2518 time_stamp
->secs
= (time_t)((int64_t)tmpsecs
- NTP_TIMEDIFF1900TO1970SEC
);
2520 time_stamp
->secs
= (time_t)((int64_t)tmpsecs
+ NTP_TIMEDIFF1970TO2036SEC
);
2521 time_stamp
->nsecs
= 0;
2523 time_stamp
->secs
= 0;
2524 time_stamp
->nsecs
= 0;
2525 report_type_length_mismatch(tree
, "an NTP seconds-only time stamp", length
, (length
< 4));
2529 case ENC_TIME_SECS_NTP
|ENC_LITTLE_ENDIAN
:
2531 * NTP time stamp, with 1-second resolution (i.e.,
2532 * seconds since the NTP epoch), little-endian.
2533 * Only supported for absolute times.
2535 DISSECTOR_ASSERT(!is_relative
);
2538 * We need a temporary variable here so the unsigned math
2539 * works correctly (for years > 2036 according to RFC 2030
2542 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2543 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2544 * If bit 0 is not set, the time is in the range 2036-2104 and
2545 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2548 tmpsecs
= tvb_get_letohl(tvb
, start
);
2549 if ((tmpsecs
& 0x80000000) != 0)
2550 time_stamp
->secs
= (time_t)((int64_t)tmpsecs
- NTP_TIMEDIFF1900TO1970SEC
);
2552 time_stamp
->secs
= (time_t)((int64_t)tmpsecs
+ NTP_TIMEDIFF1970TO2036SEC
);
2553 time_stamp
->nsecs
= 0;
2555 time_stamp
->secs
= 0;
2556 time_stamp
->nsecs
= 0;
2557 report_type_length_mismatch(tree
, "an NTP seconds-only time stamp", length
, (length
< 4));
2561 case ENC_TIME_MSEC_NTP
| ENC_BIG_ENDIAN
:
2563 * Milliseconds, 6 to 8 bytes.
2564 * For absolute times, it's milliseconds since the
2567 * ETSI TS 129.274 8.119 defines this as:
2568 * "a 48 bit unsigned integer in network order format
2569 * ...encoded as the number of milliseconds since
2570 * 00:00:00 January 1, 1900 00:00 UTC, i.e. as the
2571 * rounded value of 1000 x the value of the 64-bit
2572 * timestamp (Seconds + (Fraction / (1<<32))) defined
2573 * in clause 6 of IETF RFC 5905."
2575 * Taken literally, the part after "i.e." would
2576 * mean that the value rolls over before reaching
2577 * 2^32 * 1000 = 4294967296000 = 0x3e800000000
2578 * when the 64 bit timestamp rolls over, and we have
2579 * to pick an NTP Era equivalence class to support
2580 * (such as 1968-01-20 to 2104-02-06).
2582 * OTOH, the extra room might be used to store Era
2583 * information instead, in which case times until
2584 * 10819-08-03 can be represented with 6 bytes without
2585 * ambiguity. We handle both implementations, and assume
2586 * that times before 1968-01-20 are not represented.
2588 * Only 6 bytes or more makes sense as an absolute
2589 * time. 5 bytes or fewer could express a span of
2590 * less than 35 years, either 1900-1934 or 2036-2070.
2592 if (length
>= 6 && length
<= 8) {
2595 msecs
= get_uint64_value(tree
, tvb
, start
, length
, encoding
);
2596 tmp64secs
= (msecs
/ 1000);
2598 * Assume that times in the first half of NTP
2599 * Era 0 really represent times in the NTP
2602 if (tmp64secs
>= 0x80000000)
2603 time_stamp
->secs
= (time_t)((int64_t)tmp64secs
- NTP_TIMEDIFF1900TO1970SEC
);
2605 time_stamp
->secs
= (time_t)((int64_t)tmp64secs
+ NTP_TIMEDIFF1970TO2036SEC
);
2606 time_stamp
->nsecs
= (int)(msecs
% 1000)*1000000;
2609 time_stamp
->secs
= 0;
2610 time_stamp
->nsecs
= 0;
2611 report_type_length_mismatch(tree
, "a time-in-milliseconds NTP time stamp", length
, (length
< 6));
2615 case ENC_TIME_MP4_FILE_SECS
|ENC_BIG_ENDIAN
:
2617 * MP4 file time stamps, big-endian.
2618 * Only supported for absolute times.
2620 DISSECTOR_ASSERT(!is_relative
);
2623 tmp64secs
= tvb_get_ntoh64(tvb
, start
);
2624 time_stamp
->secs
= (time_t)(int64_t)(tmp64secs
- EPOCH_DELTA_1904_01_01_00_00_00_UTC
);
2625 time_stamp
->nsecs
= 0;
2626 } else if (length
== 4) {
2627 tmpsecs
= tvb_get_ntohl(tvb
, start
);
2628 time_stamp
->secs
= (time_t)(int32_t)(tmpsecs
- EPOCH_DELTA_1904_01_01_00_00_00_UTC
);
2629 time_stamp
->nsecs
= 0;
2631 time_stamp
->secs
= 0;
2632 time_stamp
->nsecs
= 0;
2633 report_type_length_mismatch(tree
, "an MP4 time stamp", length
, (length
< 4));
2637 case ENC_TIME_ZBEE_ZCL
| ENC_BIG_ENDIAN
:
2639 * Zigbee ZCL time stamps, big-endian.
2640 * Only supported for absolute times.
2642 DISSECTOR_ASSERT(!is_relative
);
2645 tmp64secs
= tvb_get_ntoh64(tvb
, start
);
2646 time_stamp
->secs
= (time_t)(int64_t)(tmp64secs
- EPOCH_DELTA_2000_01_01_00_00_00_UTC
);
2647 time_stamp
->nsecs
= 0;
2648 } else if (length
== 4) {
2649 tmpsecs
= tvb_get_ntohl(tvb
, start
);
2650 time_stamp
->secs
= (time_t)(int32_t)(tmpsecs
- EPOCH_DELTA_2000_01_01_00_00_00_UTC
);
2651 time_stamp
->nsecs
= 0;
2653 time_stamp
->secs
= 0;
2654 time_stamp
->nsecs
= 0;
2655 report_type_length_mismatch(tree
, "a Zigbee ZCL time stamp", length
, (length
< 4));
2659 case ENC_TIME_ZBEE_ZCL
| ENC_LITTLE_ENDIAN
:
2661 * Zigbee ZCL time stamps, little-endian.
2662 * Only supported for absolute times.
2664 DISSECTOR_ASSERT(!is_relative
);
2667 tmp64secs
= tvb_get_letoh64(tvb
, start
);
2668 time_stamp
->secs
= (time_t)(int64_t)(tmp64secs
- EPOCH_DELTA_2000_01_01_00_00_00_UTC
);
2669 time_stamp
->nsecs
= 0;
2670 } else if (length
== 4) {
2671 tmpsecs
= tvb_get_letohl(tvb
, start
);
2672 time_stamp
->secs
= (time_t)(int32_t)(tmpsecs
- EPOCH_DELTA_2000_01_01_00_00_00_UTC
);
2673 time_stamp
->nsecs
= 0;
2675 time_stamp
->secs
= 0;
2676 time_stamp
->nsecs
= 0;
2677 report_type_length_mismatch(tree
, "a Zigbee ZCL time stamp", length
, (length
< 4));
2682 DISSECTOR_ASSERT_NOT_REACHED();
2688 tree_data_add_maybe_interesting_field(tree_data_t
*tree_data
, field_info
*fi
)
2690 const header_field_info
*hfinfo
= fi
->hfinfo
;
2692 if (hfinfo
->ref_type
== HF_REF_TYPE_DIRECT
|| hfinfo
->ref_type
== HF_REF_TYPE_PRINT
) {
2693 GPtrArray
*ptrs
= NULL
;
2695 if (tree_data
->interesting_hfids
== NULL
) {
2696 /* Initialize the hash because we now know that it is needed */
2697 tree_data
->interesting_hfids
=
2698 g_hash_table_new(g_direct_hash
, NULL
/* g_direct_equal */);
2699 } else if (g_hash_table_size(tree_data
->interesting_hfids
)) {
2700 ptrs
= (GPtrArray
*)g_hash_table_lookup(tree_data
->interesting_hfids
,
2701 GINT_TO_POINTER(hfinfo
->id
));
2705 /* First element triggers the creation of pointer array */
2706 ptrs
= g_ptr_array_new();
2707 g_hash_table_insert(tree_data
->interesting_hfids
,
2708 GINT_TO_POINTER(hfinfo
->id
), ptrs
);
2711 g_ptr_array_add(ptrs
, fi
);
2717 * Validates that field length bytes are available starting from
2718 * start (pos/neg). Throws an exception if they aren't.
2721 test_length(header_field_info
*hfinfo
, tvbuff_t
*tvb
,
2722 int start
, int length
, const unsigned encoding
)
2729 if ((hfinfo
->type
== FT_STRINGZ
) ||
2730 ((encoding
& ENC_VARINT_MASK
) &&
2731 (FT_IS_UINT(hfinfo
->type
) || FT_IS_INT(hfinfo
->type
)))) {
2732 /* If we're fetching until the end of the TVB, only validate
2733 * that the offset is within range.
2739 tvb_ensure_bytes_exist(tvb
, start
, size
);
2743 detect_trailing_stray_characters(unsigned encoding
, const char *string
, int length
, proto_item
*pi
)
2745 bool found_stray_character
= false;
2750 switch (encoding
& ENC_CHARENCODING_MASK
) {
2753 for (int i
= (int)strlen(string
); i
< length
; i
++) {
2754 if (string
[i
] != '\0') {
2755 found_stray_character
= true;
2765 if (found_stray_character
) {
2766 expert_add_info(NULL
, pi
, &ei_string_trailing_characters
);
2771 free_fvalue_cb(void *data
)
2773 fvalue_t
*fv
= (fvalue_t
*)data
;
2777 /* Add an item to a proto_tree, using the text label registered to that item;
2778 the item is extracted from the tvbuff handed to it. */
2780 proto_tree_new_item(field_info
*new_fi
, proto_tree
*tree
,
2781 tvbuff_t
*tvb
, int start
, int length
,
2787 ws_in4_addr ipv4_value
;
2790 const char *stringval
= NULL
;
2791 nstime_t time_stamp
;
2794 /* Ensure that the newly created fvalue_t is freed if we throw an
2795 * exception before adding it to the tree. (gcc creates clobbering
2796 * when it optimizes the equivalent TRY..EXCEPT implementation.)
2797 * XXX: Move the new_field_info() call inside here?
2799 CLEANUP_PUSH(free_fvalue_cb
, new_fi
->value
);
2801 switch (new_fi
->hfinfo
->type
) {
2803 /* no value to set for FT_NONE */
2807 proto_tree_set_protocol_tvb(new_fi
, tvb
, new_fi
->hfinfo
->name
, length
);
2811 proto_tree_set_bytes_tvb(new_fi
, tvb
, start
, length
);
2815 n
= get_uint_value(tree
, tvb
, start
, length
, encoding
);
2816 proto_tree_set_bytes_tvb(new_fi
, tvb
, start
+ length
, n
);
2818 /* Instead of calling proto_item_set_len(), since we don't yet
2819 * have a proto_item, we set the field_info's length ourselves. */
2820 new_fi
->length
= n
+ length
;
2825 * Map all non-zero values to little-endian for
2826 * backwards compatibility.
2829 encoding
= ENC_LITTLE_ENDIAN
;
2830 proto_tree_set_boolean(new_fi
,
2831 get_uint64_value(tree
, tvb
, start
, length
, encoding
));
2835 /* XXX - make these just FT_UINT? */
2840 if (encoding
& ENC_VARINT_MASK
) {
2841 new_fi
->length
= tvb_get_varint(tvb
, start
, (length
== -1) ? FT_VARINT_MAX_LEN
: length
, &value64
, encoding
);
2842 value
= (uint32_t)value64
;
2843 if (!(encoding
& ENC_VARINT_QUIC
)) {
2844 new_fi
->flags
|= FI_VARINT
;
2849 * Map all non-zero values to little-endian for
2850 * backwards compatibility.
2853 encoding
= ENC_LITTLE_ENDIAN
;
2855 value
= get_uint_value(tree
, tvb
, start
, length
, encoding
);
2857 proto_tree_set_uint(new_fi
, value
);
2864 if (encoding
& ENC_VARINT_MASK
) {
2865 new_fi
->length
= tvb_get_varint(tvb
, start
, (length
== -1) ? FT_VARINT_MAX_LEN
: length
, &value64
, encoding
);
2866 if (!(encoding
& ENC_VARINT_QUIC
)) {
2867 new_fi
->flags
|= FI_VARINT
;
2872 * Map all other non-zero values to little-endian for
2873 * backwards compatibility.
2876 encoding
= ENC_LITTLE_ENDIAN
;
2878 value64
= get_uint64_value(tree
, tvb
, start
, length
, encoding
);
2880 proto_tree_set_uint64(new_fi
, value64
);
2883 /* XXX - make these just FT_INT? */
2889 * Map all non-zero values to little-endian for
2890 * backwards compatibility.
2893 encoding
= ENC_LITTLE_ENDIAN
;
2894 proto_tree_set_int(new_fi
,
2895 get_int_value(tree
, tvb
, start
, length
, encoding
));
2903 * Map all non-zero values to little-endian for
2904 * backwards compatibility.
2907 encoding
= ENC_LITTLE_ENDIAN
;
2908 proto_tree_set_int64(new_fi
,
2909 get_int64_value(tree
, tvb
, start
, length
, encoding
));
2914 * Map all non-zero values to little-endian for
2915 * backwards compatibility.
2918 encoding
= ENC_LITTLE_ENDIAN
;
2919 if (length
!= FT_IPv4_LEN
) {
2920 length_error
= length
< FT_IPv4_LEN
? true : false;
2921 report_type_length_mismatch(tree
, "an IPv4 address", length
, length_error
);
2923 ipv4_value
= tvb_get_ipv4(tvb
, start
);
2925 * NOTE: to support code written when
2926 * proto_tree_add_item() took a bool as its
2927 * last argument, with false meaning "big-endian"
2928 * and true meaning "little-endian", we treat any
2929 * non-zero value of "encoding" as meaning
2932 proto_tree_set_ipv4(new_fi
, encoding
? GUINT32_SWAP_LE_BE(ipv4_value
) : ipv4_value
);
2936 if (length
!= FT_IPXNET_LEN
) {
2937 length_error
= length
< FT_IPXNET_LEN
? true : false;
2938 report_type_length_mismatch(tree
, "an IPXNET address", length
, length_error
);
2940 proto_tree_set_ipxnet(new_fi
,
2941 get_uint_value(tree
, tvb
, start
, FT_IPXNET_LEN
, ENC_BIG_ENDIAN
));
2945 if (length
!= FT_IPv6_LEN
) {
2946 length_error
= length
< FT_IPv6_LEN
? true : false;
2947 report_type_length_mismatch(tree
, "an IPv6 address", length
, length_error
);
2949 proto_tree_set_ipv6_tvb(new_fi
, tvb
, start
, length
);
2953 if (length
!= FT_FCWWN_LEN
) {
2954 length_error
= length
< FT_FCWWN_LEN
? true : false;
2955 report_type_length_mismatch(tree
, "an FCWWN address", length
, length_error
);
2957 proto_tree_set_fcwwn_tvb(new_fi
, tvb
, start
, length
);
2962 length_error
= length
< 7 ? true : false;
2963 report_type_length_mismatch(tree
, "an AX.25 address", length
, length_error
);
2965 proto_tree_set_ax25_tvb(new_fi
, tvb
, start
);
2969 if (length
!= VINES_ADDR_LEN
) {
2970 length_error
= length
< VINES_ADDR_LEN
? true : false;
2971 report_type_length_mismatch(tree
, "a Vines address", length
, length_error
);
2973 proto_tree_set_vines_tvb(new_fi
, tvb
, start
);
2977 if (length
!= FT_ETHER_LEN
) {
2978 length_error
= length
< FT_ETHER_LEN
? true : false;
2979 report_type_length_mismatch(tree
, "a MAC address", length
, length_error
);
2981 proto_tree_set_ether_tvb(new_fi
, tvb
, start
);
2986 * Map all non-zero values to little-endian for
2987 * backwards compatibility.
2990 encoding
= ENC_LITTLE_ENDIAN
;
2991 if (length
!= FT_EUI64_LEN
) {
2992 length_error
= length
< FT_EUI64_LEN
? true : false;
2993 report_type_length_mismatch(tree
, "an EUI-64 address", length
, length_error
);
2995 proto_tree_set_eui64_tvb(new_fi
, tvb
, start
, encoding
);
2999 * Map all non-zero values to little-endian for
3000 * backwards compatibility.
3003 encoding
= ENC_LITTLE_ENDIAN
;
3004 if (length
!= FT_GUID_LEN
) {
3005 length_error
= length
< FT_GUID_LEN
? true : false;
3006 report_type_length_mismatch(tree
, "a GUID", length
, length_error
);
3008 proto_tree_set_guid_tvb(new_fi
, tvb
, start
, encoding
);
3013 proto_tree_set_oid_tvb(new_fi
, tvb
, start
, length
);
3017 proto_tree_set_system_id_tvb(new_fi
, tvb
, start
, length
);
3022 * NOTE: to support code written when
3023 * proto_tree_add_item() took a bool as its
3024 * last argument, with false meaning "big-endian"
3025 * and true meaning "little-endian", we treat any
3026 * non-zero value of "encoding" as meaning
3029 * At some point in the future, we might
3030 * support non-IEEE-binary floating-point
3031 * formats in the encoding as well
3032 * (IEEE decimal, System/3x0, VAX).
3035 encoding
= ENC_LITTLE_ENDIAN
;
3037 length_error
= length
< 4 ? true : false;
3038 report_type_length_mismatch(tree
, "a single-precision floating point number", length
, length_error
);
3041 floatval
= tvb_get_letohieee_float(tvb
, start
);
3043 floatval
= tvb_get_ntohieee_float(tvb
, start
);
3044 proto_tree_set_float(new_fi
, floatval
);
3049 * NOTE: to support code written when
3050 * proto_tree_add_item() took a bool as its
3051 * last argument, with false meaning "big-endian"
3052 * and true meaning "little-endian", we treat any
3053 * non-zero value of "encoding" as meaning
3056 * At some point in the future, we might
3057 * support non-IEEE-binary floating-point
3058 * formats in the encoding as well
3059 * (IEEE decimal, System/3x0, VAX).
3061 if (encoding
== true)
3062 encoding
= ENC_LITTLE_ENDIAN
;
3064 length_error
= length
< 8 ? true : false;
3065 report_type_length_mismatch(tree
, "a double-precision floating point number", length
, length_error
);
3068 doubleval
= tvb_get_letohieee_double(tvb
, start
);
3070 doubleval
= tvb_get_ntohieee_double(tvb
, start
);
3071 proto_tree_set_double(new_fi
, doubleval
);
3075 stringval
= get_string_value(PNODE_POOL(tree
),
3076 tvb
, start
, length
, &length
, encoding
);
3077 proto_tree_set_string(new_fi
, stringval
);
3079 /* Instead of calling proto_item_set_len(), since we
3080 * don't yet have a proto_item, we set the
3081 * field_info's length ourselves.
3083 * XXX - our caller can't use that length to
3084 * advance an offset unless they arrange that
3085 * there always be a protocol tree into which
3086 * we're putting this item.
3088 new_fi
->length
= length
;
3092 stringval
= get_stringz_value(PNODE_POOL(tree
),
3093 tree
, tvb
, start
, length
, &length
, encoding
);
3094 proto_tree_set_string(new_fi
, stringval
);
3096 /* Instead of calling proto_item_set_len(),
3097 * since we don't yet have a proto_item, we
3098 * set the field_info's length ourselves.
3100 * XXX - our caller can't use that length to
3101 * advance an offset unless they arrange that
3102 * there always be a protocol tree into which
3103 * we're putting this item.
3105 new_fi
->length
= length
;
3108 case FT_UINT_STRING
:
3110 * NOTE: to support code written when
3111 * proto_tree_add_item() took a bool as its
3112 * last argument, with false meaning "big-endian"
3113 * and true meaning "little-endian", if the
3114 * encoding value is true, treat that as
3115 * ASCII with a little-endian length.
3117 * This won't work for code that passes
3118 * arbitrary non-zero values; that code
3119 * will need to be fixed.
3121 if (encoding
== true)
3122 encoding
= ENC_ASCII
|ENC_LITTLE_ENDIAN
;
3123 stringval
= get_uint_string_value(PNODE_POOL(tree
),
3124 tree
, tvb
, start
, length
, &length
, encoding
);
3125 proto_tree_set_string(new_fi
, stringval
);
3127 /* Instead of calling proto_item_set_len(), since we
3128 * don't yet have a proto_item, we set the
3129 * field_info's length ourselves.
3131 * XXX - our caller can't use that length to
3132 * advance an offset unless they arrange that
3133 * there always be a protocol tree into which
3134 * we're putting this item.
3136 new_fi
->length
= length
;
3140 stringval
= get_stringzpad_value(PNODE_POOL(tree
),
3141 tvb
, start
, length
, &length
, encoding
);
3142 proto_tree_set_string(new_fi
, stringval
);
3144 /* Instead of calling proto_item_set_len(), since we
3145 * don't yet have a proto_item, we set the
3146 * field_info's length ourselves.
3148 * XXX - our caller can't use that length to
3149 * advance an offset unless they arrange that
3150 * there always be a protocol tree into which
3151 * we're putting this item.
3153 new_fi
->length
= length
;
3156 case FT_STRINGZTRUNC
:
3157 stringval
= get_stringztrunc_value(PNODE_POOL(tree
),
3158 tvb
, start
, length
, &length
, encoding
);
3159 proto_tree_set_string(new_fi
, stringval
);
3161 /* Instead of calling proto_item_set_len(), since we
3162 * don't yet have a proto_item, we set the
3163 * field_info's length ourselves.
3165 * XXX - our caller can't use that length to
3166 * advance an offset unless they arrange that
3167 * there always be a protocol tree into which
3168 * we're putting this item.
3170 new_fi
->length
= length
;
3173 case FT_ABSOLUTE_TIME
:
3175 * Absolute times can be in any of a number of
3176 * formats, and they can be big-endian or
3179 * Historically FT_TIMEs were only timespecs;
3180 * the only question was whether they were stored
3181 * in big- or little-endian format.
3183 * For backwards compatibility, we interpret an
3184 * encoding of 1 as meaning "little-endian timespec",
3185 * so that passing true is interpreted as that.
3187 if (encoding
== true)
3188 encoding
= ENC_TIME_SECS_NSECS
|ENC_LITTLE_ENDIAN
;
3190 get_time_value(tree
, tvb
, start
, length
, encoding
, &time_stamp
, false);
3192 proto_tree_set_time(new_fi
, &time_stamp
);
3195 case FT_RELATIVE_TIME
:
3197 * Relative times can be in any of a number of
3198 * formats, and they can be big-endian or
3201 * Historically FT_TIMEs were only timespecs;
3202 * the only question was whether they were stored
3203 * in big- or little-endian format.
3205 * For backwards compatibility, we interpret an
3206 * encoding of 1 as meaning "little-endian timespec",
3207 * so that passing true is interpreted as that.
3209 if (encoding
== true)
3210 encoding
= ENC_TIME_SECS_NSECS
|ENC_LITTLE_ENDIAN
;
3212 get_time_value(tree
, tvb
, start
, length
, encoding
, &time_stamp
, true);
3214 proto_tree_set_time(new_fi
, &time_stamp
);
3216 case FT_IEEE_11073_SFLOAT
:
3218 encoding
= ENC_LITTLE_ENDIAN
;
3220 length_error
= length
< 2 ? true : false;
3221 report_type_length_mismatch(tree
, "a IEEE 11073 SFLOAT", length
, length_error
);
3224 fvalue_set_uinteger(new_fi
->value
, tvb_get_uint16(tvb
, start
, encoding
));
3227 case FT_IEEE_11073_FLOAT
:
3229 encoding
= ENC_LITTLE_ENDIAN
;
3231 length_error
= length
< 4 ? true : false;
3232 report_type_length_mismatch(tree
, "a IEEE 11073 FLOAT", length
, length_error
);
3237 REPORT_DISSECTOR_BUG("field %s is of unknown type %d (%s)",
3238 new_fi
->hfinfo
->abbrev
,
3239 new_fi
->hfinfo
->type
,
3240 ftype_name(new_fi
->hfinfo
->type
));
3243 FI_SET_FLAG(new_fi
, (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
);
3245 /* Don't add new node to proto_tree until now so that any exceptions
3246 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
3247 /* XXX. wouldn't be better to add this item to tree, with some special
3248 * flag (FI_EXCEPTION?) to know which item caused exception? For
3249 * strings and bytes, we would have to set new_fi->value to something
3250 * non-NULL, or otherwise ensure that proto_item_fill_display_label
3251 * could handle NULL values. */
3253 pi
= proto_tree_add_node(tree
, new_fi
);
3255 switch (new_fi
->hfinfo
->type
) {
3258 /* XXX: trailing stray character detection should be done
3259 * _before_ conversion to UTF-8, because conversion can change
3260 * the length, or else get_string_length should return a value
3261 * for the "length in bytes of the string after conversion
3262 * including internal nulls." (Noting that we do, for other
3263 * reasons, still need the "length in bytes in the field",
3264 * especially for FT_STRINGZ.)
3266 * This is true even for ASCII and UTF-8, because
3267 * substituting REPLACEMENT CHARACTERS for illegal characters
3268 * can also do so (and for UTF-8 possibly even make the
3269 * string _shorter_).
3271 detect_trailing_stray_characters(encoding
, stringval
, length
, pi
);
3282 proto_tree_add_item_ret_int(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3283 const int start
, int length
,
3284 const unsigned encoding
, int32_t *retval
)
3286 header_field_info
*hfinfo
;
3290 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3292 switch (hfinfo
->type
) {
3299 REPORT_DISSECTOR_BUG("64-bit signed integer field %s used with proto_tree_add_item_ret_int()",
3302 REPORT_DISSECTOR_BUG("Non-signed-integer field %s used with proto_tree_add_item_ret_int()",
3306 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length
,
3314 if (encoding
& ENC_STRING
) {
3315 REPORT_DISSECTOR_BUG("wrong encoding");
3317 /* I believe it's ok if this is called with a NULL tree */
3318 value
= get_int_value(tree
, tvb
, start
, length
, encoding
);
3323 if (hfinfo
->bitmask
) {
3324 /* Mask out irrelevant portions */
3325 *retval
&= (uint32_t)(hfinfo
->bitmask
);
3327 *retval
>>= hfinfo_bitshift(hfinfo
);
3329 no_of_bits
= ws_count_ones(hfinfo
->bitmask
);
3330 *retval
= ws_sign_ext32(*retval
, no_of_bits
);
3333 CHECK_FOR_NULL_TREE(tree
);
3335 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3337 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3339 proto_tree_set_int(new_fi
, value
);
3341 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
3343 return proto_tree_add_node(tree
, new_fi
);
3347 proto_tree_add_item_ret_uint(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3348 const int start
, int length
,
3349 const unsigned encoding
, uint32_t *retval
)
3351 header_field_info
*hfinfo
;
3355 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3357 switch (hfinfo
->type
) {
3365 REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
3369 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length
,
3377 if (encoding
& ENC_STRING
) {
3378 REPORT_DISSECTOR_BUG("wrong encoding");
3380 /* I believe it's ok if this is called with a NULL tree */
3381 /* XXX - modify if we ever support EBCDIC FT_CHAR */
3382 if (encoding
& ENC_VARINT_MASK
) {
3384 tvb_get_varint(tvb
, start
, length
, &temp64
, encoding
);
3385 value
= (uint32_t)temp64
;
3387 value
= get_uint_value(tree
, tvb
, start
, length
, encoding
);
3392 if (hfinfo
->bitmask
) {
3393 /* Mask out irrelevant portions */
3394 *retval
&= (uint32_t)(hfinfo
->bitmask
);
3396 *retval
>>= hfinfo_bitshift(hfinfo
);
3400 CHECK_FOR_NULL_TREE(tree
);
3402 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3404 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3406 proto_tree_set_uint(new_fi
, value
);
3408 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
3409 if (encoding
& (ENC_VARINT_PROTOBUF
|ENC_VARINT_ZIGZAG
|ENC_VARINT_SDNV
)) {
3410 new_fi
->flags
|= FI_VARINT
;
3412 return proto_tree_add_node(tree
, new_fi
);
3415 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3416 * and returns proto_item* and uint value retreived*/
3418 ptvcursor_add_ret_uint(ptvcursor_t
*ptvc
, int hfindex
, int length
,
3419 const unsigned encoding
, uint32_t *retval
)
3422 header_field_info
*hfinfo
;
3427 offset
= ptvc
->offset
;
3428 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3430 switch (hfinfo
->type
) {
3438 REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
3442 get_hfi_length(hfinfo
, ptvc
->tvb
, offset
, &length
, &item_length
, encoding
);
3443 test_length(hfinfo
, ptvc
->tvb
, offset
, item_length
, encoding
);
3445 /* I believe it's ok if this is called with a NULL tree */
3446 /* XXX - modify if we ever support EBCDIC FT_CHAR */
3447 value
= get_uint_value(ptvc
->tree
, ptvc
->tvb
, offset
, item_length
, encoding
);
3451 if (hfinfo
->bitmask
) {
3452 /* Mask out irrelevant portions */
3453 *retval
&= (uint32_t)(hfinfo
->bitmask
);
3455 *retval
>>= hfinfo_bitshift(hfinfo
);
3459 ptvc
->offset
+= get_full_length(hfinfo
, ptvc
->tvb
, offset
, length
,
3460 item_length
, encoding
);
3462 CHECK_FOR_NULL_TREE(ptvc
->tree
);
3464 /* Coast clear. Try and fake it */
3465 TRY_TO_FAKE_THIS_ITEM(ptvc
->tree
, hfindex
, hfinfo
);
3467 new_fi
= new_field_info(ptvc
->tree
, hfinfo
, ptvc
->tvb
, offset
, item_length
);
3469 return proto_tree_new_item(new_fi
, ptvc
->tree
, ptvc
->tvb
,
3470 offset
, length
, encoding
);
3473 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3474 * and returns proto_item* and int value retreived*/
3476 ptvcursor_add_ret_int(ptvcursor_t
*ptvc
, int hfindex
, int length
,
3477 const unsigned encoding
, int32_t *retval
)
3480 header_field_info
*hfinfo
;
3485 offset
= ptvc
->offset
;
3486 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3488 switch (hfinfo
->type
) {
3495 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
3499 get_hfi_length(hfinfo
, ptvc
->tvb
, offset
, &length
, &item_length
, encoding
);
3500 test_length(hfinfo
, ptvc
->tvb
, offset
, item_length
, encoding
);
3502 /* I believe it's ok if this is called with a NULL tree */
3503 /* XXX - modify if we ever support EBCDIC FT_CHAR */
3504 value
= get_int_value(ptvc
->tree
, ptvc
->tvb
, offset
, item_length
, encoding
);
3509 if (hfinfo
->bitmask
) {
3510 /* Mask out irrelevant portions */
3511 *retval
&= (uint32_t)(hfinfo
->bitmask
);
3513 *retval
>>= hfinfo_bitshift(hfinfo
);
3515 no_of_bits
= ws_count_ones(hfinfo
->bitmask
);
3516 *retval
= ws_sign_ext32(*retval
, no_of_bits
);
3519 ptvc
->offset
+= get_full_length(hfinfo
, ptvc
->tvb
, offset
, length
,
3520 item_length
, encoding
);
3522 CHECK_FOR_NULL_TREE(ptvc
->tree
);
3524 /* Coast clear. Try and fake it */
3525 TRY_TO_FAKE_THIS_ITEM(ptvc
->tree
, hfindex
, hfinfo
);
3527 new_fi
= new_field_info(ptvc
->tree
, hfinfo
, ptvc
->tvb
, offset
, item_length
);
3529 return proto_tree_new_item(new_fi
, ptvc
->tree
, ptvc
->tvb
,
3530 offset
, length
, encoding
);
3533 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3534 * and returns proto_item* and string value retreived */
3536 ptvcursor_add_ret_string(ptvcursor_t
* ptvc
, int hf
, int length
, const unsigned encoding
, wmem_allocator_t
*scope
, const uint8_t **retval
)
3538 header_field_info
*hfinfo
;
3540 const uint8_t *value
;
3544 offset
= ptvc
->offset
;
3546 PROTO_REGISTRAR_GET_NTH(hf
, hfinfo
);
3548 switch (hfinfo
->type
) {
3550 value
= get_string_value(scope
, ptvc
->tvb
, offset
, length
, &item_length
, encoding
);
3553 value
= get_stringz_value(scope
, ptvc
->tree
, ptvc
->tvb
, offset
, length
, &item_length
, encoding
);
3555 case FT_UINT_STRING
:
3556 value
= get_uint_string_value(scope
, ptvc
->tree
, ptvc
->tvb
, offset
, length
, &item_length
, encoding
);
3559 value
= get_stringzpad_value(scope
, ptvc
->tvb
, offset
, length
, &item_length
, encoding
);
3561 case FT_STRINGZTRUNC
:
3562 value
= get_stringztrunc_value(scope
, ptvc
->tvb
, offset
, length
, &item_length
, encoding
);
3565 REPORT_DISSECTOR_BUG("field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, FT_STRINGZPAD, or FT_STRINGZTRUNC",
3572 ptvc
->offset
+= item_length
;
3574 CHECK_FOR_NULL_TREE(ptvc
->tree
);
3576 TRY_TO_FAKE_THIS_ITEM(ptvc
->tree
, hfinfo
->id
, hfinfo
);
3578 new_fi
= new_field_info(ptvc
->tree
, hfinfo
, ptvc
->tvb
, offset
, item_length
);
3580 return proto_tree_new_item(new_fi
, ptvc
->tree
, ptvc
->tvb
,
3581 offset
, length
, encoding
);
3584 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3585 * and returns proto_item* and boolean value retreived */
3587 ptvcursor_add_ret_boolean(ptvcursor_t
* ptvc
, int hfindex
, int length
, const unsigned encoding
, bool *retval
)
3589 header_field_info
*hfinfo
;
3593 uint64_t value
, bitval
;
3595 offset
= ptvc
->offset
;
3596 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3598 if (hfinfo
->type
!= FT_BOOLEAN
) {
3599 REPORT_DISSECTOR_BUG("field %s is not of type FT_BOOLEAN",
3603 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length
,
3611 if (encoding
& ENC_STRING
) {
3612 REPORT_DISSECTOR_BUG("wrong encoding");
3615 get_hfi_length(hfinfo
, ptvc
->tvb
, offset
, &length
, &item_length
, encoding
);
3616 test_length(hfinfo
, ptvc
->tvb
, offset
, item_length
, encoding
);
3618 /* I believe it's ok if this is called with a NULL tree */
3619 value
= get_uint64_value(ptvc
->tree
, ptvc
->tvb
, offset
, length
, encoding
);
3623 if (hfinfo
->bitmask
) {
3624 /* Mask out irrelevant portions */
3625 bitval
&= hfinfo
->bitmask
;
3627 *retval
= (bitval
!= 0);
3630 ptvc
->offset
+= get_full_length(hfinfo
, ptvc
->tvb
, offset
, length
,
3631 item_length
, encoding
);
3633 CHECK_FOR_NULL_TREE(ptvc
->tree
);
3635 TRY_TO_FAKE_THIS_ITEM(ptvc
->tree
, hfinfo
->id
, hfinfo
);
3637 new_fi
= new_field_info(ptvc
->tree
, hfinfo
, ptvc
->tvb
, offset
, item_length
);
3639 return proto_tree_new_item(new_fi
, ptvc
->tree
, ptvc
->tvb
,
3640 offset
, length
, encoding
);
3644 proto_tree_add_item_ret_uint64(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3645 const int start
, int length
, const unsigned encoding
, uint64_t *retval
)
3647 header_field_info
*hfinfo
;
3651 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3653 switch (hfinfo
->type
) {
3660 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, or FT_UINT64",
3664 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length
,
3672 if (encoding
& ENC_STRING
) {
3673 REPORT_DISSECTOR_BUG("wrong encoding");
3675 /* I believe it's ok if this is called with a NULL tree */
3676 if (encoding
& ENC_VARINT_MASK
) {
3677 tvb_get_varint(tvb
, start
, length
, &value
, encoding
);
3679 value
= get_uint64_value(tree
, tvb
, start
, length
, encoding
);
3684 if (hfinfo
->bitmask
) {
3685 /* Mask out irrelevant portions */
3686 *retval
&= hfinfo
->bitmask
;
3688 *retval
>>= hfinfo_bitshift(hfinfo
);
3692 CHECK_FOR_NULL_TREE(tree
);
3694 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3696 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3698 proto_tree_set_uint64(new_fi
, value
);
3700 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
3701 if (encoding
& (ENC_VARINT_PROTOBUF
|ENC_VARINT_ZIGZAG
|ENC_VARINT_SDNV
)) {
3702 new_fi
->flags
|= FI_VARINT
;
3705 return proto_tree_add_node(tree
, new_fi
);
3709 proto_tree_add_item_ret_int64(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3710 const int start
, int length
, const unsigned encoding
, int64_t *retval
)
3712 header_field_info
*hfinfo
;
3716 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3718 switch (hfinfo
->type
) {
3725 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
3729 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length
,
3737 if (encoding
& ENC_STRING
) {
3738 REPORT_DISSECTOR_BUG("wrong encoding");
3740 /* I believe it's ok if this is called with a NULL tree */
3741 if (encoding
& ENC_VARINT_MASK
) {
3742 tvb_get_varint(tvb
, start
, length
, &value
, encoding
);
3745 value
= get_int64_value(tree
, tvb
, start
, length
, encoding
);
3752 CHECK_FOR_NULL_TREE(tree
);
3754 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3756 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3758 proto_tree_set_int64(new_fi
, value
);
3760 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
3761 if (encoding
& (ENC_VARINT_PROTOBUF
|ENC_VARINT_ZIGZAG
|ENC_VARINT_SDNV
)) {
3762 new_fi
->flags
|= FI_VARINT
;
3765 return proto_tree_add_node(tree
, new_fi
);
3769 proto_tree_add_item_ret_varint(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3770 const int start
, int length
, const unsigned encoding
, uint64_t *retval
, int *lenretval
)
3772 header_field_info
*hfinfo
;
3776 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3778 if ((!FT_IS_INT(hfinfo
->type
)) && (!FT_IS_UINT(hfinfo
->type
))) {
3779 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT or FT_INT",
3783 /* length validation for native number encoding caught by get_uint64_value() */
3784 /* length has to be -1 or > 0 regardless of encoding */
3786 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_varint",
3789 if (encoding
& ENC_STRING
) {
3790 REPORT_DISSECTOR_BUG("wrong encoding");
3793 length
= tvb_get_varint(tvb
, start
, (length
== -1) ? FT_VARINT_MAX_LEN
: length
, &value
, encoding
);
3797 if (hfinfo
->bitmask
) {
3798 /* Mask out irrelevant portions */
3799 *retval
&= hfinfo
->bitmask
;
3801 *retval
>>= hfinfo_bitshift(hfinfo
);
3806 *lenretval
= length
;
3809 CHECK_FOR_NULL_TREE(tree
);
3811 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3813 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3815 proto_tree_set_uint64(new_fi
, value
);
3817 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
3818 if (encoding
& (ENC_VARINT_PROTOBUF
|ENC_VARINT_ZIGZAG
|ENC_VARINT_SDNV
)) {
3819 new_fi
->flags
|= FI_VARINT
;
3822 return proto_tree_add_node(tree
, new_fi
);
3827 proto_tree_add_item_ret_boolean(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3828 const int start
, int length
,
3829 const unsigned encoding
, bool *retval
)
3831 header_field_info
*hfinfo
;
3833 uint64_t value
, bitval
;
3835 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3837 if (hfinfo
->type
!= FT_BOOLEAN
) {
3838 REPORT_DISSECTOR_BUG("field %s is not of type FT_BOOLEAN",
3842 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length
,
3850 if (encoding
& ENC_STRING
) {
3851 REPORT_DISSECTOR_BUG("wrong encoding");
3853 /* I believe it's ok if this is called with a NULL tree */
3854 value
= get_uint64_value(tree
, tvb
, start
, length
, encoding
);
3858 if (hfinfo
->bitmask
) {
3859 /* Mask out irrelevant portions */
3860 bitval
&= hfinfo
->bitmask
;
3862 *retval
= (bitval
!= 0);
3865 CHECK_FOR_NULL_TREE(tree
);
3867 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3869 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3871 proto_tree_set_boolean(new_fi
, value
);
3873 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
3875 return proto_tree_add_node(tree
, new_fi
);
3879 proto_tree_add_item_ret_float(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3880 const int start
, int length
,
3881 const unsigned encoding
, float *retval
)
3883 header_field_info
*hfinfo
= proto_registrar_get_nth(hfindex
);
3887 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
3889 if (hfinfo
->type
!= FT_FLOAT
) {
3890 REPORT_DISSECTOR_BUG("field %s is not of type FT_FLOAT", hfinfo
->abbrev
);
3894 report_type_length_mismatch(tree
, "a single-precision floating point number", length
, true);
3897 /* treat any nonzero encoding as little endian for backwards compatibility */
3898 value
= encoding
? tvb_get_letohieee_float(tvb
, start
) : tvb_get_ntohieee_float(tvb
, start
);
3903 CHECK_FOR_NULL_TREE(tree
);
3905 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3907 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3909 new_fi
->flags
|= FI_LITTLE_ENDIAN
;
3912 proto_tree_set_float(new_fi
, value
);
3914 return proto_tree_add_node(tree
, new_fi
);
3918 proto_tree_add_item_ret_double(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3919 const int start
, int length
,
3920 const unsigned encoding
, double *retval
)
3922 header_field_info
*hfinfo
= proto_registrar_get_nth(hfindex
);
3926 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
3928 if (hfinfo
->type
!= FT_DOUBLE
) {
3929 REPORT_DISSECTOR_BUG("field %s is not of type FT_DOUBLE", hfinfo
->abbrev
);
3933 report_type_length_mismatch(tree
, "a double-precision floating point number", length
, true);
3936 /* treat any nonzero encoding as little endian for backwards compatibility */
3937 value
= encoding
? tvb_get_letohieee_double(tvb
, start
) : tvb_get_ntohieee_double(tvb
, start
);
3942 CHECK_FOR_NULL_TREE(tree
);
3944 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3946 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3948 new_fi
->flags
|= FI_LITTLE_ENDIAN
;
3951 proto_tree_set_double(new_fi
, value
);
3953 return proto_tree_add_node(tree
, new_fi
);
3957 proto_tree_add_item_ret_ipv4(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3958 const int start
, int length
,
3959 const unsigned encoding
, ws_in4_addr
*retval
)
3961 header_field_info
*hfinfo
;
3965 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3967 switch (hfinfo
->type
) {
3971 REPORT_DISSECTOR_BUG("field %s is not of type FT_IPv4",
3975 if (length
!= FT_IPv4_LEN
)
3976 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_ipv4",
3979 if (encoding
& (ENC_STRING
| ENC_VARINT_MASK
)) {
3980 REPORT_DISSECTOR_BUG("wrong encoding");
3984 * NOTE: to support code written when proto_tree_add_item() took
3985 * a bool as its last argument, with false meaning "big-endian"
3986 * and true meaning "little-endian", we treat any non-zero value
3987 * of "encoding" as meaning "little-endian".
3989 value
= tvb_get_ipv4(tvb
, start
);
3991 value
= GUINT32_SWAP_LE_BE(value
);
3997 CHECK_FOR_NULL_TREE(tree
);
3999 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
4001 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
4003 proto_tree_set_ipv4(new_fi
, value
);
4005 new_fi
->flags
|= encoding
? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
4006 return proto_tree_add_node(tree
, new_fi
);
4010 proto_tree_add_item_ret_ipv6(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4011 const int start
, int length
,
4012 const unsigned encoding
, ws_in6_addr
*addr
)
4014 header_field_info
*hfinfo
= proto_registrar_get_nth(hfindex
);
4017 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
4019 switch (hfinfo
->type
) {
4023 REPORT_DISSECTOR_BUG("field %s is not of type FT_IPv6",
4027 if (length
!= FT_IPv6_LEN
)
4028 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_ipv6",
4032 REPORT_DISSECTOR_BUG("Encodings not yet implemented for proto_tree_add_item_ret_ipv6");
4035 tvb_get_ipv6(tvb
, start
, addr
);
4037 CHECK_FOR_NULL_TREE(tree
);
4039 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
4041 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
4043 proto_tree_set_ipv6(new_fi
, addr
);
4045 return proto_tree_add_node(tree
, new_fi
);
4049 proto_tree_add_item_ret_ether(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4050 const int start
, int length
, const unsigned encoding
, uint8_t *retval
) {
4052 header_field_info
*hfinfo
= proto_registrar_get_nth(hfindex
);
4055 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
4057 switch (hfinfo
->type
) {
4061 REPORT_DISSECTOR_BUG("field %s is not of type FT_ETHER",
4065 if (length
!= FT_ETHER_LEN
)
4066 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_ether",
4070 REPORT_DISSECTOR_BUG("Encodings not yet implemented for proto_tree_add_item_ret_ether");
4073 tvb_memcpy(tvb
, retval
, start
, length
);
4075 CHECK_FOR_NULL_TREE(tree
);
4077 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
4079 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
4081 proto_tree_set_ether(new_fi
, retval
);
4083 return proto_tree_add_node(tree
, new_fi
);
4088 proto_tree_add_item_ret_string_and_length(proto_tree
*tree
, int hfindex
,
4090 const int start
, int length
,
4091 const unsigned encoding
,
4092 wmem_allocator_t
*scope
,
4093 const uint8_t **retval
,
4097 header_field_info
*hfinfo
;
4099 const uint8_t *value
;
4101 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4103 switch (hfinfo
->type
) {
4105 value
= get_string_value(scope
, tvb
, start
, length
, lenretval
, encoding
);
4108 value
= get_stringz_value(scope
, tree
, tvb
, start
, length
, lenretval
, encoding
);
4110 case FT_UINT_STRING
:
4111 value
= get_uint_string_value(scope
, tree
, tvb
, start
, length
, lenretval
, encoding
);
4114 value
= get_stringzpad_value(scope
, tvb
, start
, length
, lenretval
, encoding
);
4116 case FT_STRINGZTRUNC
:
4117 value
= get_stringztrunc_value(scope
, tvb
, start
, length
, lenretval
, encoding
);
4120 REPORT_DISSECTOR_BUG("field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, FT_STRINGZPAD, or FT_STRINGZTRUNC",
4127 CHECK_FOR_NULL_TREE(tree
);
4129 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
4131 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, *lenretval
);
4133 proto_tree_set_string(new_fi
, value
);
4135 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
4137 pi
= proto_tree_add_node(tree
, new_fi
);
4139 switch (hfinfo
->type
) {
4143 case FT_STRINGZTRUNC
:
4144 case FT_UINT_STRING
:
4148 detect_trailing_stray_characters(encoding
, value
, length
, pi
);
4152 ws_assert_not_reached();
4159 proto_tree_add_item_ret_string(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4160 const int start
, int length
,
4161 const unsigned encoding
, wmem_allocator_t
*scope
,
4162 const uint8_t **retval
)
4164 return proto_tree_add_item_ret_string_and_length(tree
, hfindex
,
4165 tvb
, start
, length
, encoding
, scope
, retval
, &length
);
4169 proto_tree_add_item_ret_display_string_and_length(proto_tree
*tree
, int hfindex
,
4171 const int start
, int length
,
4172 const unsigned encoding
,
4173 wmem_allocator_t
*scope
,
4178 header_field_info
*hfinfo
;
4180 const uint8_t *value
;
4183 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4185 switch (hfinfo
->type
) {
4187 value
= get_string_value(scope
, tvb
, start
, length
, lenretval
, encoding
);
4188 *retval
= wmem_alloc(scope
, ITEM_LABEL_LENGTH
);
4189 ws_label_strcpy(*retval
, ITEM_LABEL_LENGTH
, 0, value
, label_strcat_flags(hfinfo
));
4192 value
= get_stringz_value(scope
, tree
, tvb
, start
, length
, lenretval
, encoding
);
4193 *retval
= wmem_alloc(scope
, ITEM_LABEL_LENGTH
);
4194 ws_label_strcpy(*retval
, ITEM_LABEL_LENGTH
, 0, value
, label_strcat_flags(hfinfo
));
4196 case FT_UINT_STRING
:
4197 value
= get_uint_string_value(scope
, tree
, tvb
, start
, length
, lenretval
, encoding
);
4198 *retval
= wmem_alloc(scope
, ITEM_LABEL_LENGTH
);
4199 ws_label_strcpy(*retval
, ITEM_LABEL_LENGTH
, 0, value
, label_strcat_flags(hfinfo
));
4202 value
= get_stringzpad_value(scope
, tvb
, start
, length
, lenretval
, encoding
);
4203 *retval
= wmem_alloc(scope
, ITEM_LABEL_LENGTH
);
4204 ws_label_strcpy(*retval
, ITEM_LABEL_LENGTH
, 0, value
, label_strcat_flags(hfinfo
));
4206 case FT_STRINGZTRUNC
:
4207 value
= get_stringztrunc_value(scope
, tvb
, start
, length
, lenretval
, encoding
);
4208 *retval
= wmem_alloc(scope
, ITEM_LABEL_LENGTH
);
4209 ws_label_strcpy(*retval
, ITEM_LABEL_LENGTH
, 0, value
, label_strcat_flags(hfinfo
));
4212 tvb_ensure_bytes_exist(tvb
, start
, length
);
4213 value
= tvb_get_ptr(tvb
, start
, length
);
4214 *retval
= format_bytes_hfinfo(scope
, hfinfo
, value
, length
);
4215 *lenretval
= length
;
4218 n
= get_uint_value(tree
, tvb
, start
, length
, encoding
);
4219 tvb_ensure_bytes_exist(tvb
, start
+ length
, n
);
4220 value
= tvb_get_ptr(tvb
, start
+ length
, n
);
4221 *retval
= format_bytes_hfinfo(scope
, hfinfo
, value
, n
);
4222 *lenretval
= length
+ n
;
4225 REPORT_DISSECTOR_BUG("field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, FT_STRINGZPAD, FT_STRINGZTRUNC, FT_BYTES, or FT_UINT_BYTES",
4229 CHECK_FOR_NULL_TREE(tree
);
4231 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
4233 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, *lenretval
);
4235 switch (hfinfo
->type
) {
4239 case FT_UINT_STRING
:
4241 case FT_STRINGZTRUNC
:
4242 proto_tree_set_string(new_fi
, value
);
4246 proto_tree_set_bytes(new_fi
, value
, length
);
4250 proto_tree_set_bytes(new_fi
, value
, n
);
4254 ws_assert_not_reached();
4257 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
4259 pi
= proto_tree_add_node(tree
, new_fi
);
4261 switch (hfinfo
->type
) {
4265 case FT_STRINGZTRUNC
:
4266 case FT_UINT_STRING
:
4270 detect_trailing_stray_characters(encoding
, value
, length
, pi
);
4278 ws_assert_not_reached();
4285 proto_tree_add_item_ret_display_string(proto_tree
*tree
, int hfindex
,
4287 const int start
, int length
,
4288 const unsigned encoding
,
4289 wmem_allocator_t
*scope
,
4292 return proto_tree_add_item_ret_display_string_and_length(tree
, hfindex
,
4293 tvb
, start
, length
, encoding
, scope
, retval
, &length
);
4297 proto_tree_add_item_ret_time_string(proto_tree
*tree
, int hfindex
,
4299 const int start
, int length
, const unsigned encoding
,
4300 wmem_allocator_t
*scope
, char **retval
)
4302 header_field_info
*hfinfo
;
4304 nstime_t time_stamp
;
4307 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4309 switch (hfinfo
->type
) {
4310 case FT_ABSOLUTE_TIME
:
4311 get_time_value(tree
, tvb
, start
, length
, encoding
, &time_stamp
, false);
4312 flags
= ABS_TIME_TO_STR_SHOW_ZONE
;
4313 if (prefs
.display_abs_time_ascii
< ABS_TIME_ASCII_TREE
) {
4314 flags
|= ABS_TIME_TO_STR_ISO8601
;
4316 *retval
= abs_time_to_str_ex(scope
, &time_stamp
, hfinfo
->display
, flags
);
4318 case FT_RELATIVE_TIME
:
4319 get_time_value(tree
, tvb
, start
, length
, encoding
, &time_stamp
, true);
4320 *retval
= rel_time_to_secs_str(scope
, &time_stamp
);
4323 REPORT_DISSECTOR_BUG("field %s is not of type FT_ABSOLUTE_TIME or FT_RELATIVE_TIME",
4327 CHECK_FOR_NULL_TREE(tree
);
4329 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
4331 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
4333 switch (hfinfo
->type
) {
4335 case FT_ABSOLUTE_TIME
:
4336 case FT_RELATIVE_TIME
:
4337 proto_tree_set_time(new_fi
, &time_stamp
);
4340 ws_assert_not_reached();
4343 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
4345 return proto_tree_add_node(tree
, new_fi
);
4348 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
4349 and returns proto_item* */
4351 ptvcursor_add(ptvcursor_t
*ptvc
, int hfindex
, int length
,
4352 const unsigned encoding
)
4355 header_field_info
*hfinfo
;
4359 offset
= ptvc
->offset
;
4360 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4361 get_hfi_length(hfinfo
, ptvc
->tvb
, offset
, &length
, &item_length
, encoding
);
4362 test_length(hfinfo
, ptvc
->tvb
, offset
, item_length
, encoding
);
4364 ptvc
->offset
+= get_full_length(hfinfo
, ptvc
->tvb
, offset
, length
,
4365 item_length
, encoding
);
4367 CHECK_FOR_NULL_TREE(ptvc
->tree
);
4369 /* Coast clear. Try and fake it */
4370 TRY_TO_FAKE_THIS_ITEM(ptvc
->tree
, hfindex
, hfinfo
);
4372 new_fi
= new_field_info(ptvc
->tree
, hfinfo
, ptvc
->tvb
, offset
, item_length
);
4374 return proto_tree_new_item(new_fi
, ptvc
->tree
, ptvc
->tvb
,
4375 offset
, length
, encoding
);
4378 /* Add an item to a proto_tree, using the text label registered to that item;
4379 the item is extracted from the tvbuff handed to it. */
4381 proto_tree_add_item_new(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
,
4382 const int start
, int length
, const unsigned encoding
)
4387 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
4389 get_hfi_length(hfinfo
, tvb
, start
, &length
, &item_length
, encoding
);
4390 test_length(hfinfo
, tvb
, start
, item_length
, encoding
);
4392 CHECK_FOR_NULL_TREE(tree
);
4394 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
4396 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, item_length
);
4398 return proto_tree_new_item(new_fi
, tree
, tvb
, start
, length
, encoding
);
4402 proto_tree_add_item(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4403 const int start
, int length
, const unsigned encoding
)
4405 register header_field_info
*hfinfo
;
4407 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4408 return proto_tree_add_item_new(tree
, hfinfo
, tvb
, start
, length
, encoding
);
4411 /* Add an item to a proto_tree, using the text label registered to that item;
4412 the item is extracted from the tvbuff handed to it.
4414 Return the length of the item through the pointer. */
4416 proto_tree_add_item_new_ret_length(proto_tree
*tree
, header_field_info
*hfinfo
,
4417 tvbuff_t
*tvb
, const int start
,
4418 int length
, const unsigned encoding
,
4425 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
4427 get_hfi_length(hfinfo
, tvb
, start
, &length
, &item_length
, encoding
);
4428 test_length(hfinfo
, tvb
, start
, item_length
, encoding
);
4432 * We need to get the correct item length here.
4433 * That's normally done by proto_tree_new_item(),
4434 * but we won't be calling it.
4436 *lenretval
= get_full_length(hfinfo
, tvb
, start
, length
,
4437 item_length
, encoding
);
4441 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree
, hfinfo
->id
, hfinfo
, {
4443 * Even if the tree item is not referenced (and thus faked),
4444 * the caller must still be informed of the actual length.
4446 *lenretval
= get_full_length(hfinfo
, tvb
, start
, length
,
4447 item_length
, encoding
);
4450 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, item_length
);
4452 item
= proto_tree_new_item(new_fi
, tree
, tvb
, start
, length
, encoding
);
4453 *lenretval
= new_fi
->length
;
4458 proto_tree_add_item_ret_length(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4459 const int start
, int length
,
4460 const unsigned encoding
, int *lenretval
)
4462 register header_field_info
*hfinfo
;
4464 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4465 return proto_tree_add_item_new_ret_length(tree
, hfinfo
, tvb
, start
, length
, encoding
, lenretval
);
4468 /* which FT_ types can use proto_tree_add_bytes_item() */
4470 validate_proto_tree_add_bytes_ftype(const enum ftenum type
)
4472 return (type
== FT_BYTES
||
4473 type
== FT_UINT_BYTES
||
4475 type
== FT_REL_OID
||
4476 type
== FT_SYSTEM_ID
);
4479 /* Note: this does no validation that the byte array of an FT_OID or
4480 FT_REL_OID is actually valid; and neither does proto_tree_add_item(),
4481 so I think it's ok to continue not validating it?
4484 proto_tree_add_bytes_item(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4485 const int start
, int length
, const unsigned encoding
,
4486 GByteArray
*retval
, int *endoff
, int *err
)
4489 GByteArray
*bytes
= retval
;
4490 GByteArray
*created_bytes
= NULL
;
4491 bool failed
= false;
4493 header_field_info
*hfinfo
;
4494 bool generate
= (bytes
|| tree
) ? true : false;
4496 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4498 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
4500 DISSECTOR_ASSERT_HINT(validate_proto_tree_add_bytes_ftype(hfinfo
->type
),
4501 "Called proto_tree_add_bytes_item but not a bytes-based FT_XXX type");
4503 CHECK_FOR_ZERO_OR_MINUS_LENGTH(length
);
4505 if (encoding
& ENC_STR_NUM
) {
4506 REPORT_DISSECTOR_BUG("Decoding number strings for byte arrays is not supported");
4509 if (generate
&& (encoding
& ENC_STR_HEX
)) {
4510 if (hfinfo
->type
== FT_UINT_BYTES
) {
4511 /* can't decode FT_UINT_BYTES from strings */
4512 REPORT_DISSECTOR_BUG("proto_tree_add_bytes_item called for "
4513 "FT_UINT_BYTES type, but as ENC_STR_HEX");
4517 /* caller doesn't care about return value, but we need it to
4518 call tvb_get_string_bytes() and set the tree later */
4519 bytes
= created_bytes
= g_byte_array_new();
4523 * bytes might be NULL after this, but can't add expert
4524 * error until later; if it's NULL, just note that
4527 bytes
= tvb_get_string_bytes(tvb
, start
, length
, encoding
, bytes
, endoff
);
4531 else if (generate
) {
4532 tvb_ensure_bytes_exist(tvb
, start
, length
);
4534 if (hfinfo
->type
== FT_UINT_BYTES
) {
4535 n
= length
; /* n is now the "header" length */
4536 length
= get_uint_value(tree
, tvb
, start
, n
, encoding
);
4537 /* length is now the value's length; only store the value in the array */
4538 tvb_ensure_bytes_exist(tvb
, start
+ n
, length
);
4540 /* caller doesn't care about return value, but
4541 * we may need it to set the tree later */
4542 bytes
= created_bytes
= g_byte_array_new();
4544 g_byte_array_append(bytes
, tvb_get_ptr(tvb
, start
+ n
, length
), length
);
4546 else if (length
> 0) {
4548 /* caller doesn't care about return value, but
4549 * we may need it to set the tree later */
4550 bytes
= created_bytes
= g_byte_array_new();
4552 g_byte_array_append(bytes
, tvb_get_ptr(tvb
, start
, length
), length
);
4556 *endoff
= start
+ n
+ length
;
4560 *err
= failed
? EINVAL
: 0;
4562 CHECK_FOR_NULL_TREE_AND_FREE(tree
,
4565 g_byte_array_free(created_bytes
, true);
4566 created_bytes
= NULL
;
4570 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree
, hfinfo
->id
, hfinfo
,
4573 g_byte_array_free(created_bytes
, true);
4574 created_bytes
= NULL
;
4578 /* n will be zero except when it's a FT_UINT_BYTES */
4579 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, n
+ length
);
4581 if (encoding
& ENC_STRING
) {
4583 expert_add_info(NULL
, tree
, &ei_byte_array_string_decoding_failed_error
);
4586 proto_tree_set_bytes_gbytearray(new_fi
, bytes
);
4588 proto_tree_set_bytes(new_fi
, NULL
, 0);
4591 g_byte_array_free(created_bytes
, true);
4594 /* n will be zero except when it's a FT_UINT_BYTES */
4595 proto_tree_set_bytes_tvb(new_fi
, tvb
, start
+ n
, length
);
4597 /* XXX: If we have a non-NULL tree but NULL retval, we don't
4598 * use the byte array created above in this case.
4601 g_byte_array_free(created_bytes
, true);
4604 (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
);
4607 return proto_tree_add_node(tree
, new_fi
);
4612 proto_tree_add_time_item(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4613 const int start
, int length
, const unsigned encoding
,
4614 nstime_t
*retval
, int *endoff
, int *err
)
4617 nstime_t time_stamp
;
4619 header_field_info
*hfinfo
;
4621 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4623 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
4625 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length
,
4629 nstime_set_zero(retval
);
4633 nstime_set_zero(&time_stamp
);
4635 if (encoding
& ENC_STR_TIME_MASK
) {
4636 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_ABSOLUTE_TIME
);
4637 /* The only string format that could be a relative time is
4638 * ENC_ISO_8601_TIME, and that is treated as an absolute time
4639 * relative to "now" currently.
4641 if (!tvb_get_string_time(tvb
, start
, length
, encoding
, &time_stamp
, endoff
))
4645 DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo
);
4646 const bool is_relative
= (hfinfo
->type
== FT_RELATIVE_TIME
) ? true : false;
4648 tvb_ensure_bytes_exist(tvb
, start
, length
);
4649 get_time_value(tree
, tvb
, start
, length
, encoding
, &time_stamp
, is_relative
);
4650 if (endoff
) *endoff
= start
+ length
;
4653 if (err
) *err
= saved_err
;
4656 retval
->secs
= time_stamp
.secs
;
4657 retval
->nsecs
= time_stamp
.nsecs
;
4660 CHECK_FOR_NULL_TREE(tree
);
4662 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
4664 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
4666 proto_tree_set_time(new_fi
, &time_stamp
);
4668 if (encoding
& ENC_STRING
) {
4670 expert_add_info(NULL
, tree
, &ei_date_time_string_decoding_failed_error
);
4674 (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
);
4677 return proto_tree_add_node(tree
, new_fi
);
4680 /* Add a FT_NONE to a proto_tree */
4682 proto_tree_add_none_format(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
4683 const int start
, int length
, const char *format
,
4688 header_field_info
*hfinfo
;
4690 CHECK_FOR_NULL_TREE(tree
);
4692 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
4694 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_NONE
);
4696 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
4698 TRY_TO_FAKE_THIS_REPR(pi
);
4700 va_start(ap
, format
);
4701 proto_tree_set_representation(pi
, format
, ap
);
4704 /* no value to set for FT_NONE */
4708 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
4709 * offset, and returns proto_item* */
4711 ptvcursor_add_no_advance(ptvcursor_t
* ptvc
, int hf
, int length
,
4712 const unsigned encoding
)
4716 item
= proto_tree_add_item(ptvc
->tree
, hf
, ptvc
->tvb
, ptvc
->offset
,
4722 /* Advance the ptvcursor's offset within its tvbuff without
4723 * adding anything to the proto_tree. */
4725 ptvcursor_advance(ptvcursor_t
* ptvc
, int length
)
4727 ptvc
->offset
+= length
;
4732 proto_tree_set_protocol_tvb(field_info
*fi
, tvbuff_t
*tvb
, const char* field_data
, int length
)
4734 fvalue_set_protocol(fi
->value
, tvb
, field_data
, length
);
4737 /* Add a FT_PROTOCOL to a proto_tree */
4739 proto_tree_add_protocol_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4740 int start
, int length
, const char *format
, ...)
4743 tvbuff_t
*protocol_tvb
;
4745 header_field_info
*hfinfo
;
4748 CHECK_FOR_NULL_TREE(tree
);
4750 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
4752 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_PROTOCOL
);
4755 * This can throw an exception, so do it before we allocate anything.
4757 protocol_tvb
= (start
== 0 ? tvb
: tvb_new_subset_length(tvb
, start
, length
));
4759 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
4761 va_start(ap
, format
);
4762 protocol_rep
= ws_strdup_vprintf(format
, ap
);
4763 proto_tree_set_protocol_tvb(PNODE_FINFO(pi
), protocol_tvb
, protocol_rep
, length
);
4764 g_free(protocol_rep
);
4767 TRY_TO_FAKE_THIS_REPR(pi
);
4769 va_start(ap
, format
);
4770 proto_tree_set_representation(pi
, format
, ap
);
4776 /* Add a FT_BYTES to a proto_tree */
4778 proto_tree_add_bytes(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
4779 int length
, const uint8_t *start_ptr
)
4782 header_field_info
*hfinfo
;
4785 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4786 get_hfi_length(hfinfo
, tvb
, start
, &length
, &item_length
, ENC_NA
);
4787 test_length(hfinfo
, tvb
, start
, item_length
, ENC_NA
);
4789 CHECK_FOR_NULL_TREE(tree
);
4791 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
4793 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_BYTES
);
4795 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
4796 proto_tree_set_bytes(PNODE_FINFO(pi
), start_ptr
, length
);
4801 /* Add a FT_BYTES to a proto_tree */
4803 proto_tree_add_bytes_with_length(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
4804 int tvbuff_length
, const uint8_t *start_ptr
, int ptr_length
)
4807 header_field_info
*hfinfo
;
4810 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4811 get_hfi_length(hfinfo
, tvb
, start
, &tvbuff_length
, &item_length
, ENC_NA
);
4812 test_length(hfinfo
, tvb
, start
, item_length
, ENC_NA
);
4814 CHECK_FOR_NULL_TREE(tree
);
4816 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
4818 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_BYTES
);
4820 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &tvbuff_length
);
4821 proto_tree_set_bytes(PNODE_FINFO(pi
), start_ptr
, ptr_length
);
4827 proto_tree_add_bytes_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4828 int start
, int length
,
4829 const uint8_t *start_ptr
,
4830 const char *format
, ...)
4835 if (start_ptr
== NULL
)
4836 start_ptr
= tvb_get_ptr(tvb
, start
, length
);
4838 pi
= proto_tree_add_bytes(tree
, hfindex
, tvb
, start
, length
, start_ptr
);
4840 TRY_TO_FAKE_THIS_REPR_NESTED(pi
);
4842 va_start(ap
, format
);
4843 proto_tree_set_representation_value(pi
, format
, ap
);
4850 proto_tree_add_bytes_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4851 int start
, int length
, const uint8_t *start_ptr
,
4852 const char *format
, ...)
4857 if (start_ptr
== NULL
)
4858 start_ptr
= tvb_get_ptr(tvb
, start
, length
);
4860 pi
= proto_tree_add_bytes(tree
, hfindex
, tvb
, start
, length
, start_ptr
);
4862 TRY_TO_FAKE_THIS_REPR_NESTED(pi
);
4864 va_start(ap
, format
);
4865 proto_tree_set_representation(pi
, format
, ap
);
4872 proto_tree_set_bytes(field_info
*fi
, const uint8_t* start_ptr
, int length
)
4874 DISSECTOR_ASSERT(length
>= 0);
4875 DISSECTOR_ASSERT(start_ptr
!= NULL
|| length
== 0);
4877 fvalue_set_bytes_data(fi
->value
, start_ptr
, length
);
4882 proto_tree_set_bytes_tvb(field_info
*fi
, tvbuff_t
*tvb
, int offset
, int length
)
4884 tvb_ensure_bytes_exist(tvb
, offset
, length
);
4885 proto_tree_set_bytes(fi
, tvb_get_ptr(tvb
, offset
, length
), length
);
4889 proto_tree_set_bytes_gbytearray(field_info
*fi
, const GByteArray
*value
)
4893 DISSECTOR_ASSERT(value
!= NULL
);
4895 bytes
= byte_array_dup(value
);
4897 fvalue_set_byte_array(fi
->value
, bytes
);
4900 /* Add a FT_*TIME to a proto_tree */
4902 proto_tree_add_time(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
4903 int length
, const nstime_t
*value_ptr
)
4906 header_field_info
*hfinfo
;
4908 CHECK_FOR_NULL_TREE(tree
);
4910 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
4912 DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo
);
4914 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
4915 proto_tree_set_time(PNODE_FINFO(pi
), value_ptr
);
4921 proto_tree_add_time_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4922 int start
, int length
, nstime_t
*value_ptr
,
4923 const char *format
, ...)
4928 pi
= proto_tree_add_time(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
4930 va_start(ap
, format
);
4931 proto_tree_set_representation_value(pi
, format
, ap
);
4939 proto_tree_add_time_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4940 int start
, int length
, nstime_t
*value_ptr
,
4941 const char *format
, ...)
4946 pi
= proto_tree_add_time(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
4948 TRY_TO_FAKE_THIS_REPR(pi
);
4950 va_start(ap
, format
);
4951 proto_tree_set_representation(pi
, format
, ap
);
4958 /* Set the FT_*TIME value */
4960 proto_tree_set_time(field_info
*fi
, const nstime_t
*value_ptr
)
4962 DISSECTOR_ASSERT(value_ptr
!= NULL
);
4964 fvalue_set_time(fi
->value
, value_ptr
);
4967 /* Add a FT_IPXNET to a proto_tree */
4969 proto_tree_add_ipxnet(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
4970 int length
, uint32_t value
)
4973 header_field_info
*hfinfo
;
4975 CHECK_FOR_NULL_TREE(tree
);
4977 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
4979 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_IPXNET
);
4981 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
4982 proto_tree_set_ipxnet(PNODE_FINFO(pi
), value
);
4988 proto_tree_add_ipxnet_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4989 int start
, int length
, uint32_t value
,
4990 const char *format
, ...)
4995 pi
= proto_tree_add_ipxnet(tree
, hfindex
, tvb
, start
, length
, value
);
4997 va_start(ap
, format
);
4998 proto_tree_set_representation_value(pi
, format
, ap
);
5006 proto_tree_add_ipxnet_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5007 int start
, int length
, uint32_t value
,
5008 const char *format
, ...)
5013 pi
= proto_tree_add_ipxnet(tree
, hfindex
, tvb
, start
, length
, value
);
5015 TRY_TO_FAKE_THIS_REPR(pi
);
5017 va_start(ap
, format
);
5018 proto_tree_set_representation(pi
, format
, ap
);
5025 /* Set the FT_IPXNET value */
5027 proto_tree_set_ipxnet(field_info
*fi
, uint32_t value
)
5029 fvalue_set_uinteger(fi
->value
, value
);
5032 /* Add a FT_IPv4 to a proto_tree */
5034 proto_tree_add_ipv4(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5035 int length
, ws_in4_addr value
)
5038 header_field_info
*hfinfo
;
5040 CHECK_FOR_NULL_TREE(tree
);
5042 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5044 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_IPv4
);
5046 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5047 proto_tree_set_ipv4(PNODE_FINFO(pi
), value
);
5053 proto_tree_add_ipv4_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5054 int start
, int length
, ws_in4_addr value
,
5055 const char *format
, ...)
5060 pi
= proto_tree_add_ipv4(tree
, hfindex
, tvb
, start
, length
, value
);
5062 va_start(ap
, format
);
5063 proto_tree_set_representation_value(pi
, format
, ap
);
5071 proto_tree_add_ipv4_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5072 int start
, int length
, ws_in4_addr value
,
5073 const char *format
, ...)
5078 pi
= proto_tree_add_ipv4(tree
, hfindex
, tvb
, start
, length
, value
);
5080 TRY_TO_FAKE_THIS_REPR(pi
);
5082 va_start(ap
, format
);
5083 proto_tree_set_representation(pi
, format
, ap
);
5090 /* Set the FT_IPv4 value */
5092 proto_tree_set_ipv4(field_info
*fi
, ws_in4_addr value
)
5094 ipv4_addr_and_mask ipv4
;
5095 ws_ipv4_addr_and_mask_init(&ipv4
, value
, 32);
5096 fvalue_set_ipv4(fi
->value
, &ipv4
);
5099 /* Add a FT_IPv6 to a proto_tree */
5101 proto_tree_add_ipv6(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5102 int length
, const ws_in6_addr
*value
)
5105 header_field_info
*hfinfo
;
5107 CHECK_FOR_NULL_TREE(tree
);
5109 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5111 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_IPv6
);
5113 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5114 proto_tree_set_ipv6(PNODE_FINFO(pi
), value
);
5120 proto_tree_add_ipv6_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5121 int start
, int length
,
5122 const ws_in6_addr
*value_ptr
,
5123 const char *format
, ...)
5128 pi
= proto_tree_add_ipv6(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
5130 va_start(ap
, format
);
5131 proto_tree_set_representation_value(pi
, format
, ap
);
5139 proto_tree_add_ipv6_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5140 int start
, int length
,
5141 const ws_in6_addr
*value_ptr
,
5142 const char *format
, ...)
5147 pi
= proto_tree_add_ipv6(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
5149 TRY_TO_FAKE_THIS_REPR(pi
);
5151 va_start(ap
, format
);
5152 proto_tree_set_representation(pi
, format
, ap
);
5159 /* Set the FT_IPv6 value */
5161 proto_tree_set_ipv6(field_info
*fi
, const ws_in6_addr
*value
)
5163 DISSECTOR_ASSERT(value
!= NULL
);
5164 ipv6_addr_and_prefix ipv6
;
5167 fvalue_set_ipv6(fi
->value
, &ipv6
);
5171 proto_tree_set_ipv6_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, int length
)
5173 proto_tree_set_ipv6(fi
, (const ws_in6_addr
*)tvb_get_ptr(tvb
, start
, length
));
5176 /* Set the FT_FCWWN value */
5178 proto_tree_set_fcwwn(field_info
*fi
, const uint8_t* value_ptr
)
5180 DISSECTOR_ASSERT(value_ptr
!= NULL
);
5181 fvalue_set_fcwwn(fi
->value
, value_ptr
);
5185 proto_tree_set_fcwwn_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, int length
)
5187 proto_tree_set_fcwwn(fi
, tvb_get_ptr(tvb
, start
, length
));
5190 /* Add a FT_GUID to a proto_tree */
5192 proto_tree_add_guid(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5193 int length
, const e_guid_t
*value_ptr
)
5196 header_field_info
*hfinfo
;
5198 CHECK_FOR_NULL_TREE(tree
);
5200 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5202 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_GUID
);
5204 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5205 proto_tree_set_guid(PNODE_FINFO(pi
), value_ptr
);
5211 proto_tree_add_guid_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5212 int start
, int length
,
5213 const e_guid_t
*value_ptr
,
5214 const char *format
, ...)
5219 pi
= proto_tree_add_guid(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
5221 va_start(ap
, format
);
5222 proto_tree_set_representation_value(pi
, format
, ap
);
5230 proto_tree_add_guid_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5231 int start
, int length
, const e_guid_t
*value_ptr
,
5232 const char *format
, ...)
5237 pi
= proto_tree_add_guid(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
5239 TRY_TO_FAKE_THIS_REPR(pi
);
5241 va_start(ap
, format
);
5242 proto_tree_set_representation(pi
, format
, ap
);
5249 /* Set the FT_GUID value */
5251 proto_tree_set_guid(field_info
*fi
, const e_guid_t
*value_ptr
)
5253 DISSECTOR_ASSERT(value_ptr
!= NULL
);
5254 fvalue_set_guid(fi
->value
, value_ptr
);
5258 proto_tree_set_guid_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
,
5259 const unsigned encoding
)
5263 tvb_get_guid(tvb
, start
, &guid
, encoding
);
5264 proto_tree_set_guid(fi
, &guid
);
5267 /* Add a FT_OID to a proto_tree */
5269 proto_tree_add_oid(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5270 int length
, const uint8_t* value_ptr
)
5273 header_field_info
*hfinfo
;
5275 CHECK_FOR_NULL_TREE(tree
);
5277 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5279 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_OID
);
5281 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5282 proto_tree_set_oid(PNODE_FINFO(pi
), value_ptr
, length
);
5288 proto_tree_add_oid_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5289 int start
, int length
,
5290 const uint8_t* value_ptr
,
5291 const char *format
, ...)
5296 pi
= proto_tree_add_oid(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
5298 va_start(ap
, format
);
5299 proto_tree_set_representation_value(pi
, format
, ap
);
5307 proto_tree_add_oid_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5308 int start
, int length
, const uint8_t* value_ptr
,
5309 const char *format
, ...)
5314 pi
= proto_tree_add_oid(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
5316 TRY_TO_FAKE_THIS_REPR(pi
);
5318 va_start(ap
, format
);
5319 proto_tree_set_representation(pi
, format
, ap
);
5326 /* Set the FT_OID value */
5328 proto_tree_set_oid(field_info
*fi
, const uint8_t* value_ptr
, int length
)
5332 DISSECTOR_ASSERT(value_ptr
!= NULL
|| length
== 0);
5334 bytes
= g_byte_array_new();
5336 g_byte_array_append(bytes
, value_ptr
, length
);
5338 fvalue_set_byte_array(fi
->value
, bytes
);
5342 proto_tree_set_oid_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, int length
)
5344 proto_tree_set_oid(fi
, tvb_get_ptr(tvb
, start
, length
), length
);
5347 /* Set the FT_SYSTEM_ID value */
5349 proto_tree_set_system_id(field_info
*fi
, const uint8_t* value_ptr
, int length
)
5353 DISSECTOR_ASSERT(value_ptr
!= NULL
|| length
== 0);
5355 bytes
= g_byte_array_new();
5357 g_byte_array_append(bytes
, value_ptr
, length
);
5359 fvalue_set_byte_array(fi
->value
, bytes
);
5363 proto_tree_set_system_id_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, int length
)
5365 proto_tree_set_system_id(fi
, tvb_get_ptr(tvb
, start
, length
), length
);
5368 /* Add a FT_STRING, FT_STRINGZ, FT_STRINGZPAD, or FT_STRINGZTRUNC to a
5369 * proto_tree. Creates own copy of string, and frees it when the proto_tree
5372 proto_tree_add_string(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5373 int length
, const char* value
)
5376 header_field_info
*hfinfo
;
5379 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
5380 get_hfi_length(hfinfo
, tvb
, start
, &length
, &item_length
, ENC_NA
);
5382 * Special case - if the length is 0, skip the test, so that
5383 * we can have an empty string right after the end of the
5384 * packet. (This handles URL-encoded forms where the last field
5385 * has no value so the form ends right after the =.)
5387 if (item_length
!= 0)
5388 test_length(hfinfo
, tvb
, start
, item_length
, ENC_NA
);
5390 CHECK_FOR_NULL_TREE(tree
);
5392 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5394 DISSECTOR_ASSERT_FIELD_TYPE_IS_STRING(hfinfo
);
5396 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5397 DISSECTOR_ASSERT(length
>= 0);
5399 WS_UTF_8_CHECK(value
, -1);
5400 proto_tree_set_string(PNODE_FINFO(pi
), value
);
5406 proto_tree_add_string_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5407 int start
, int length
, const char* value
,
5414 pi
= proto_tree_add_string(tree
, hfindex
, tvb
, start
, length
, value
);
5416 va_start(ap
, format
);
5417 proto_tree_set_representation_value(pi
, format
, ap
);
5425 proto_tree_add_string_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5426 int start
, int length
, const char* value
,
5427 const char *format
, ...)
5432 pi
= proto_tree_add_string(tree
, hfindex
, tvb
, start
, length
, value
);
5434 TRY_TO_FAKE_THIS_REPR(pi
);
5436 va_start(ap
, format
);
5437 proto_tree_set_representation(pi
, format
, ap
);
5444 /* Set the FT_STRING value */
5446 proto_tree_set_string(field_info
*fi
, const char* value
)
5449 fvalue_set_string(fi
->value
, value
);
5452 * XXX - why is a null value for a string field
5455 fvalue_set_string(fi
->value
, "[ Null ]");
5459 /* Set the FT_AX25 value */
5461 proto_tree_set_ax25(field_info
*fi
, const uint8_t* value
)
5463 fvalue_set_ax25(fi
->value
, value
);
5467 proto_tree_set_ax25_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
)
5469 proto_tree_set_ax25(fi
, tvb_get_ptr(tvb
, start
, 7));
5472 /* Set the FT_VINES value */
5474 proto_tree_set_vines(field_info
*fi
, const uint8_t* value
)
5476 fvalue_set_vines(fi
->value
, value
);
5480 proto_tree_set_vines_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
)
5482 proto_tree_set_vines(fi
, tvb_get_ptr(tvb
, start
, FT_VINES_ADDR_LEN
));
5485 /* Add a FT_ETHER to a proto_tree */
5487 proto_tree_add_ether(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5488 int length
, const uint8_t* value
)
5491 header_field_info
*hfinfo
;
5493 CHECK_FOR_NULL_TREE(tree
);
5495 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5497 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_ETHER
);
5499 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5500 proto_tree_set_ether(PNODE_FINFO(pi
), value
);
5506 proto_tree_add_ether_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5507 int start
, int length
, const uint8_t* value
,
5508 const char *format
, ...)
5513 pi
= proto_tree_add_ether(tree
, hfindex
, tvb
, start
, length
, value
);
5515 va_start(ap
, format
);
5516 proto_tree_set_representation_value(pi
, format
, ap
);
5524 proto_tree_add_ether_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5525 int start
, int length
, const uint8_t* value
,
5526 const char *format
, ...)
5531 pi
= proto_tree_add_ether(tree
, hfindex
, tvb
, start
, length
, value
);
5533 TRY_TO_FAKE_THIS_REPR(pi
);
5535 va_start(ap
, format
);
5536 proto_tree_set_representation(pi
, format
, ap
);
5543 /* Set the FT_ETHER value */
5545 proto_tree_set_ether(field_info
*fi
, const uint8_t* value
)
5547 fvalue_set_ether(fi
->value
, value
);
5551 proto_tree_set_ether_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
)
5553 proto_tree_set_ether(fi
, tvb_get_ptr(tvb
, start
, FT_ETHER_LEN
));
5556 /* Add a FT_BOOLEAN to a proto_tree */
5558 proto_tree_add_boolean(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5559 int length
, uint64_t value
)
5562 header_field_info
*hfinfo
;
5564 CHECK_FOR_NULL_TREE(tree
);
5566 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5568 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_BOOLEAN
);
5570 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5571 proto_tree_set_boolean(PNODE_FINFO(pi
), value
);
5577 proto_tree_add_boolean_format_value(proto_tree
*tree
, int hfindex
,
5578 tvbuff_t
*tvb
, int start
, int length
,
5579 uint64_t value
, const char *format
, ...)
5584 pi
= proto_tree_add_boolean(tree
, hfindex
, tvb
, start
, length
, value
);
5586 va_start(ap
, format
);
5587 proto_tree_set_representation_value(pi
, format
, ap
);
5595 proto_tree_add_boolean_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5596 int start
, int length
, uint64_t value
,
5597 const char *format
, ...)
5602 pi
= proto_tree_add_boolean(tree
, hfindex
, tvb
, start
, length
, value
);
5604 TRY_TO_FAKE_THIS_REPR(pi
);
5606 va_start(ap
, format
);
5607 proto_tree_set_representation(pi
, format
, ap
);
5614 /* Set the FT_BOOLEAN value */
5616 proto_tree_set_boolean(field_info
*fi
, uint64_t value
)
5618 proto_tree_set_uint64(fi
, value
);
5621 /* Generate, into "buf", a string showing the bits of a bitfield.
5622 Return a pointer to the character after that string. */
5624 other_decode_bitfield_value(char *buf
, const uint64_t val
, const uint64_t mask
, const int width
)
5632 /* This is a devel error. It is safer to stop here. */
5633 DISSECTOR_ASSERT(width
>= 1);
5635 bit
= UINT64_C(1) << (width
- 1);
5638 /* This bit is part of the field. Show its value. */
5644 /* This bit is not part of the field. */
5659 decode_bitfield_value(char *buf
, const uint64_t val
, const uint64_t mask
, const int width
)
5663 p
= other_decode_bitfield_value(buf
, val
, mask
, width
);
5664 p
= g_stpcpy(p
, " = ");
5670 other_decode_bitfield_varint_value(char *buf
, uint64_t val
, uint64_t mask
, const int width
)
5678 /* This is a devel error. It is safer to stop here. */
5679 DISSECTOR_ASSERT(width
>= 1);
5681 bit
= UINT64_C(1) << (width
- 1);
5683 if (((8-(i
% 8)) != 8) && /* MSB is never used for value. */
5685 /* This bit is part of the field. Show its value. */
5691 /* This bit is not part of the field. */
5707 decode_bitfield_varint_value(char *buf
, const uint64_t val
, const uint64_t mask
, const int width
)
5711 p
= other_decode_bitfield_varint_value(buf
, val
, mask
, width
);
5712 p
= g_stpcpy(p
, " = ");
5717 /* Add a FT_FLOAT to a proto_tree */
5719 proto_tree_add_float(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5720 int length
, float value
)
5723 header_field_info
*hfinfo
;
5725 CHECK_FOR_NULL_TREE(tree
);
5727 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5729 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_FLOAT
);
5731 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5732 proto_tree_set_float(PNODE_FINFO(pi
), value
);
5738 proto_tree_add_float_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5739 int start
, int length
, float value
,
5740 const char *format
, ...)
5745 pi
= proto_tree_add_float(tree
, hfindex
, tvb
, start
, length
, value
);
5747 va_start(ap
, format
);
5748 proto_tree_set_representation_value(pi
, format
, ap
);
5756 proto_tree_add_float_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5757 int start
, int length
, float value
,
5758 const char *format
, ...)
5763 pi
= proto_tree_add_float(tree
, hfindex
, tvb
, start
, length
, value
);
5765 TRY_TO_FAKE_THIS_REPR(pi
);
5767 va_start(ap
, format
);
5768 proto_tree_set_representation(pi
, format
, ap
);
5775 /* Set the FT_FLOAT value */
5777 proto_tree_set_float(field_info
*fi
, float value
)
5779 fvalue_set_floating(fi
->value
, value
);
5782 /* Add a FT_DOUBLE to a proto_tree */
5784 proto_tree_add_double(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5785 int length
, double value
)
5788 header_field_info
*hfinfo
;
5790 CHECK_FOR_NULL_TREE(tree
);
5792 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5794 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_DOUBLE
);
5796 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5797 proto_tree_set_double(PNODE_FINFO(pi
), value
);
5803 proto_tree_add_double_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5804 int start
, int length
, double value
,
5805 const char *format
, ...)
5810 pi
= proto_tree_add_double(tree
, hfindex
, tvb
, start
, length
, value
);
5812 va_start(ap
, format
);
5813 proto_tree_set_representation_value(pi
, format
, ap
);
5821 proto_tree_add_double_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5822 int start
, int length
, double value
,
5823 const char *format
, ...)
5828 pi
= proto_tree_add_double(tree
, hfindex
, tvb
, start
, length
, value
);
5830 TRY_TO_FAKE_THIS_REPR(pi
);
5832 va_start(ap
, format
);
5833 proto_tree_set_representation(pi
, format
, ap
);
5840 /* Set the FT_DOUBLE value */
5842 proto_tree_set_double(field_info
*fi
, double value
)
5844 fvalue_set_floating(fi
->value
, value
);
5847 /* Add FT_CHAR or FT_UINT{8,16,24,32} to a proto_tree */
5849 proto_tree_add_uint(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5850 int length
, uint32_t value
)
5852 proto_item
*pi
= NULL
;
5853 header_field_info
*hfinfo
;
5855 CHECK_FOR_NULL_TREE(tree
);
5857 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5859 switch (hfinfo
->type
) {
5866 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5867 proto_tree_set_uint(PNODE_FINFO(pi
), value
);
5871 REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, FT_UINT32, or FT_FRAMENUM",
5879 proto_tree_add_uint_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5880 int start
, int length
, uint32_t value
,
5881 const char *format
, ...)
5886 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, start
, length
, value
);
5888 va_start(ap
, format
);
5889 proto_tree_set_representation_value(pi
, format
, ap
);
5897 proto_tree_add_uint_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5898 int start
, int length
, uint32_t value
,
5899 const char *format
, ...)
5904 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, start
, length
, value
);
5906 TRY_TO_FAKE_THIS_REPR(pi
);
5908 va_start(ap
, format
);
5909 proto_tree_set_representation(pi
, format
, ap
);
5916 /* Set the FT_UINT{8,16,24,32} value */
5918 proto_tree_set_uint(field_info
*fi
, uint32_t value
)
5920 const header_field_info
*hfinfo
;
5923 hfinfo
= fi
->hfinfo
;
5926 if (hfinfo
->bitmask
) {
5927 /* Mask out irrelevant portions */
5928 integer
&= (uint32_t)(hfinfo
->bitmask
);
5931 integer
>>= hfinfo_bitshift(hfinfo
);
5933 FI_SET_FLAG(fi
, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo
)));
5934 FI_SET_FLAG(fi
, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo
)));
5937 fvalue_set_uinteger(fi
->value
, integer
);
5940 /* Add FT_UINT{40,48,56,64} to a proto_tree */
5942 proto_tree_add_uint64(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5943 int length
, uint64_t value
)
5945 proto_item
*pi
= NULL
;
5946 header_field_info
*hfinfo
;
5948 CHECK_FOR_NULL_TREE(tree
);
5950 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5952 switch (hfinfo
->type
) {
5958 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5959 proto_tree_set_uint64(PNODE_FINFO(pi
), value
);
5963 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, FT_UINT64, or FT_FRAMENUM",
5971 proto_tree_add_uint64_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5972 int start
, int length
, uint64_t value
,
5973 const char *format
, ...)
5978 pi
= proto_tree_add_uint64(tree
, hfindex
, tvb
, start
, length
, value
);
5980 va_start(ap
, format
);
5981 proto_tree_set_representation_value(pi
, format
, ap
);
5989 proto_tree_add_uint64_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5990 int start
, int length
, uint64_t value
,
5991 const char *format
, ...)
5996 pi
= proto_tree_add_uint64(tree
, hfindex
, tvb
, start
, length
, value
);
5998 TRY_TO_FAKE_THIS_REPR(pi
);
6000 va_start(ap
, format
);
6001 proto_tree_set_representation(pi
, format
, ap
);
6008 /* Set the FT_UINT{40,48,56,64} value */
6010 proto_tree_set_uint64(field_info
*fi
, uint64_t value
)
6012 const header_field_info
*hfinfo
;
6015 hfinfo
= fi
->hfinfo
;
6018 if (hfinfo
->bitmask
) {
6019 /* Mask out irrelevant portions */
6020 integer
&= hfinfo
->bitmask
;
6023 integer
>>= hfinfo_bitshift(hfinfo
);
6025 FI_SET_FLAG(fi
, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo
)));
6026 FI_SET_FLAG(fi
, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo
)));
6029 fvalue_set_uinteger64(fi
->value
, integer
);
6032 /* Add FT_INT{8,16,24,32} to a proto_tree */
6034 proto_tree_add_int(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
6035 int length
, int32_t value
)
6037 proto_item
*pi
= NULL
;
6038 header_field_info
*hfinfo
;
6040 CHECK_FOR_NULL_TREE(tree
);
6042 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
6044 switch (hfinfo
->type
) {
6049 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
6050 proto_tree_set_int(PNODE_FINFO(pi
), value
);
6054 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
6062 proto_tree_add_int_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
6063 int start
, int length
, int32_t value
,
6064 const char *format
, ...)
6069 pi
= proto_tree_add_int(tree
, hfindex
, tvb
, start
, length
, value
);
6071 va_start(ap
, format
);
6072 proto_tree_set_representation_value(pi
, format
, ap
);
6080 proto_tree_add_int_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
6081 int start
, int length
, int32_t value
,
6082 const char *format
, ...)
6087 pi
= proto_tree_add_int(tree
, hfindex
, tvb
, start
, length
, value
);
6089 TRY_TO_FAKE_THIS_REPR(pi
);
6091 va_start(ap
, format
);
6092 proto_tree_set_representation(pi
, format
, ap
);
6099 /* Set the FT_INT{8,16,24,32} value */
6101 proto_tree_set_int(field_info
*fi
, int32_t value
)
6103 const header_field_info
*hfinfo
;
6107 hfinfo
= fi
->hfinfo
;
6108 integer
= (uint32_t) value
;
6110 if (hfinfo
->bitmask
) {
6111 /* Mask out irrelevant portions */
6112 integer
&= (uint32_t)(hfinfo
->bitmask
);
6115 integer
>>= hfinfo_bitshift(hfinfo
);
6117 no_of_bits
= ws_count_ones(hfinfo
->bitmask
);
6118 integer
= ws_sign_ext32(integer
, no_of_bits
);
6120 FI_SET_FLAG(fi
, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo
)));
6121 FI_SET_FLAG(fi
, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo
)));
6124 fvalue_set_sinteger(fi
->value
, integer
);
6127 /* Add FT_INT{40,48,56,64} to a proto_tree */
6129 proto_tree_add_int64(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
6130 int length
, int64_t value
)
6132 proto_item
*pi
= NULL
;
6133 header_field_info
*hfinfo
;
6135 CHECK_FOR_NULL_TREE(tree
);
6137 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
6139 switch (hfinfo
->type
) {
6144 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
6145 proto_tree_set_int64(PNODE_FINFO(pi
), value
);
6149 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
6157 proto_tree_add_int64_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
6158 int start
, int length
, int64_t value
,
6159 const char *format
, ...)
6164 pi
= proto_tree_add_int64(tree
, hfindex
, tvb
, start
, length
, value
);
6166 va_start(ap
, format
);
6167 proto_tree_set_representation_value(pi
, format
, ap
);
6174 /* Set the FT_INT{40,48,56,64} value */
6176 proto_tree_set_int64(field_info
*fi
, int64_t value
)
6178 const header_field_info
*hfinfo
;
6182 hfinfo
= fi
->hfinfo
;
6185 if (hfinfo
->bitmask
) {
6186 /* Mask out irrelevant portions */
6187 integer
&= hfinfo
->bitmask
;
6190 integer
>>= hfinfo_bitshift(hfinfo
);
6192 no_of_bits
= ws_count_ones(hfinfo
->bitmask
);
6193 integer
= ws_sign_ext64(integer
, no_of_bits
);
6195 FI_SET_FLAG(fi
, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo
)));
6196 FI_SET_FLAG(fi
, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo
)));
6199 fvalue_set_sinteger64(fi
->value
, integer
);
6203 proto_tree_add_int64_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
6204 int start
, int length
, int64_t value
,
6205 const char *format
, ...)
6210 pi
= proto_tree_add_int64(tree
, hfindex
, tvb
, start
, length
, value
);
6212 TRY_TO_FAKE_THIS_REPR(pi
);
6214 va_start(ap
, format
);
6215 proto_tree_set_representation(pi
, format
, ap
);
6222 /* Add a FT_EUI64 to a proto_tree */
6224 proto_tree_add_eui64(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
6225 int length
, const uint64_t value
)
6228 header_field_info
*hfinfo
;
6230 CHECK_FOR_NULL_TREE(tree
);
6232 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
6234 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_EUI64
);
6236 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
6237 proto_tree_set_eui64(PNODE_FINFO(pi
), value
);
6243 proto_tree_add_eui64_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
6244 int start
, int length
, const uint64_t value
,
6245 const char *format
, ...)
6250 pi
= proto_tree_add_eui64(tree
, hfindex
, tvb
, start
, length
, value
);
6252 va_start(ap
, format
);
6253 proto_tree_set_representation_value(pi
, format
, ap
);
6261 proto_tree_add_eui64_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
6262 int start
, int length
, const uint64_t value
,
6263 const char *format
, ...)
6268 pi
= proto_tree_add_eui64(tree
, hfindex
, tvb
, start
, length
, value
);
6270 TRY_TO_FAKE_THIS_REPR(pi
);
6272 va_start(ap
, format
);
6273 proto_tree_set_representation(pi
, format
, ap
);
6280 /* Set the FT_EUI64 value */
6282 proto_tree_set_eui64(field_info
*fi
, const uint64_t value
)
6284 fvalue_set_uinteger64(fi
->value
, value
);
6287 proto_tree_set_eui64_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, const unsigned encoding
)
6291 proto_tree_set_eui64(fi
, tvb_get_letoh64(tvb
, start
));
6293 proto_tree_set_eui64(fi
, tvb_get_ntoh64(tvb
, start
));
6298 proto_tree_add_mac48_detail(const mac_hf_list_t
*list_specific
,
6299 const mac_hf_list_t
*list_generic
,
6300 int idx
, tvbuff_t
*tvb
,
6301 proto_tree
*tree
, int offset
)
6303 const uint8_t addr
[6];
6304 const char *addr_name
= NULL
;
6305 const char *oui_name
= NULL
;
6306 proto_item
*addr_item
= NULL
;
6307 proto_tree
*addr_tree
= NULL
;
6308 proto_item
*ret_val
= NULL
;
6310 if (tree
== NULL
|| list_specific
== NULL
) {
6314 /* Resolve what we can of the address */
6315 tvb_memcpy(tvb
, (void *)addr
, offset
, 6);
6316 if (list_specific
->hf_addr_resolved
|| (list_generic
&& list_generic
->hf_addr_resolved
)) {
6317 addr_name
= get_ether_name(addr
);
6319 if (list_specific
->hf_oui_resolved
|| (list_generic
&& list_generic
->hf_oui_resolved
)) {
6320 oui_name
= get_manuf_name_if_known(addr
, sizeof(addr
));
6323 /* Add the item for the specific address type */
6324 ret_val
= proto_tree_add_item(tree
, *list_specific
->hf_addr
, tvb
, offset
, 6, ENC_NA
);
6326 addr_tree
= proto_item_add_subtree(ret_val
, idx
);
6332 if (list_specific
->hf_addr_resolved
!= NULL
) {
6333 addr_item
= proto_tree_add_string(addr_tree
, *list_specific
->hf_addr_resolved
,
6334 tvb
, offset
, 6, addr_name
);
6335 proto_item_set_generated(addr_item
);
6336 proto_item_set_hidden(addr_item
);
6339 if (list_specific
->hf_oui
!= NULL
) {
6340 addr_item
= proto_tree_add_item(addr_tree
, *list_specific
->hf_oui
, tvb
, offset
, 3, ENC_NA
);
6341 proto_item_set_generated(addr_item
);
6342 proto_item_set_hidden(addr_item
);
6344 if (oui_name
!= NULL
&& list_specific
->hf_oui_resolved
!= NULL
) {
6345 addr_item
= proto_tree_add_string(addr_tree
, *list_specific
->hf_oui_resolved
, tvb
, offset
, 6, oui_name
);
6346 proto_item_set_generated(addr_item
);
6347 proto_item_set_hidden(addr_item
);
6351 if (list_specific
->hf_lg
!= NULL
) {
6352 proto_tree_add_item(addr_tree
, *list_specific
->hf_lg
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
6354 if (list_specific
->hf_ig
!= NULL
) {
6355 proto_tree_add_item(addr_tree
, *list_specific
->hf_ig
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
6358 /* Were we given a list for generic address fields? If not, stop here */
6359 if (list_generic
== NULL
) {
6363 addr_item
= proto_tree_add_item(addr_tree
, *list_generic
->hf_addr
, tvb
, offset
, 6, ENC_NA
);
6364 proto_item_set_hidden(addr_item
);
6366 if (list_generic
->hf_addr_resolved
!= NULL
) {
6367 addr_item
= proto_tree_add_string(addr_tree
, *list_generic
->hf_addr_resolved
,
6368 tvb
, offset
, 6, addr_name
);
6369 proto_item_set_generated(addr_item
);
6370 proto_item_set_hidden(addr_item
);
6373 if (list_generic
->hf_oui
!= NULL
) {
6374 addr_item
= proto_tree_add_item(addr_tree
, *list_generic
->hf_oui
, tvb
, offset
, 3, ENC_NA
);
6375 proto_item_set_generated(addr_item
);
6376 proto_item_set_hidden(addr_item
);
6378 if (oui_name
!= NULL
&& list_generic
->hf_oui_resolved
!= NULL
) {
6379 addr_item
= proto_tree_add_string(addr_tree
, *list_generic
->hf_oui_resolved
, tvb
, offset
, 6, oui_name
);
6380 proto_item_set_generated(addr_item
);
6381 proto_item_set_hidden(addr_item
);
6385 if (list_generic
->hf_lg
!= NULL
) {
6386 addr_item
= proto_tree_add_item(addr_tree
, *list_generic
->hf_lg
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
6387 proto_item_set_hidden(addr_item
);
6389 if (list_generic
->hf_ig
!= NULL
) {
6390 addr_item
= proto_tree_add_item(addr_tree
, *list_generic
->hf_ig
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
6391 proto_item_set_hidden(addr_item
);
6396 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
6398 proto_tree_add_node(proto_tree
*tree
, field_info
*fi
)
6400 proto_node
*pnode
, *tnode
, *sibling
;
6405 * Restrict our depth. proto_tree_traverse_pre_order and
6406 * proto_tree_traverse_post_order (and possibly others) are recursive
6407 * so we need to be mindful of our stack size.
6409 if (tree
->first_child
== NULL
) {
6410 for (tnode
= tree
; tnode
!= NULL
; tnode
= tnode
->parent
) {
6412 if (G_UNLIKELY(depth
> prefs
.gui_max_tree_depth
)) {
6413 fvalue_free(fi
->value
);
6415 THROW_MESSAGE(DissectorError
, wmem_strdup_printf(PNODE_POOL(tree
),
6416 "Maximum tree depth %d exceeded for \"%s\" - \"%s\" (%s:%u) (Maximum depth can be increased in advanced preferences)",
6417 prefs
.gui_max_tree_depth
,
6418 fi
->hfinfo
->name
, fi
->hfinfo
->abbrev
, G_STRFUNC
, __LINE__
));
6424 * Make sure "tree" is ready to have subtrees under it, by
6425 * checking whether it's been given an ett_ value.
6427 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
6428 * node of the protocol tree. That node is not displayed,
6429 * so it doesn't need an ett_ value to remember whether it
6433 tfi
= PNODE_FINFO(tnode
);
6434 if (tfi
!= NULL
&& (tfi
->tree_type
< 0 || tfi
->tree_type
>= num_tree_types
)) {
6435 /* Since we are not adding fi to a node, its fvalue won't get
6436 * freed by proto_tree_free_node(), so free it now.
6438 fvalue_free(fi
->value
);
6440 REPORT_DISSECTOR_BUG("\"%s\" - \"%s\" tfi->tree_type: %d invalid (%s:%u)",
6441 fi
->hfinfo
->name
, fi
->hfinfo
->abbrev
, tfi
->tree_type
, __FILE__
, __LINE__
);
6442 /* XXX - is it safe to continue here? */
6445 pnode
= wmem_new(PNODE_POOL(tree
), proto_node
);
6446 PROTO_NODE_INIT(pnode
);
6447 pnode
->parent
= tnode
;
6448 PNODE_FINFO(pnode
) = fi
;
6449 pnode
->tree_data
= PTREE_DATA(tree
);
6451 if (tnode
->last_child
!= NULL
) {
6452 sibling
= tnode
->last_child
;
6453 DISSECTOR_ASSERT(sibling
->next
== NULL
);
6454 sibling
->next
= pnode
;
6456 tnode
->first_child
= pnode
;
6457 tnode
->last_child
= pnode
;
6459 tree_data_add_maybe_interesting_field(pnode
->tree_data
, fi
);
6461 return (proto_item
*)pnode
;
6465 /* Generic way to allocate field_info and add to proto_tree.
6466 * Sets *pfi to address of newly-allocated field_info struct */
6468 proto_tree_add_pi(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
, int start
,
6475 get_hfi_length(hfinfo
, tvb
, start
, length
, &item_length
, ENC_NA
);
6476 fi
= new_field_info(tree
, hfinfo
, tvb
, start
, item_length
);
6477 pi
= proto_tree_add_node(tree
, fi
);
6484 get_hfi_length(header_field_info
*hfinfo
, tvbuff_t
*tvb
, const int start
, int *length
,
6485 int *item_length
, const unsigned encoding
)
6487 int length_remaining
;
6490 * We only allow a null tvbuff if the item has a zero length,
6491 * i.e. if there's no data backing it.
6493 DISSECTOR_ASSERT(tvb
!= NULL
|| *length
== 0);
6496 * XXX - in some protocols, there are 32-bit unsigned length
6497 * fields, so lengths in protocol tree and tvbuff routines
6498 * should really be unsigned. We should have, for those
6499 * field types for which "to the end of the tvbuff" makes sense,
6500 * additional routines that take no length argument and
6501 * add fields that run to the end of the tvbuff.
6503 if (*length
== -1) {
6505 * For FT_NONE, FT_PROTOCOL, FT_BYTES, FT_STRING,
6506 * FT_STRINGZPAD, and FT_STRINGZTRUNC fields, a length
6507 * of -1 means "set the length to what remains in the
6510 * The assumption is either that
6512 * 1) the length of the item can only be determined
6513 * by dissection (typically true of items with
6514 * subitems, which are probably FT_NONE or
6519 * 2) if the tvbuff is "short" (either due to a short
6520 * snapshot length or due to lack of reassembly of
6521 * fragments/segments/whatever), we want to display
6522 * what's available in the field (probably FT_BYTES
6523 * or FT_STRING) and then throw an exception later
6527 * 3) the field is defined to be "what's left in the
6530 * so we set the length to what remains in the tvbuff so
6531 * that, if we throw an exception while dissecting, it
6532 * has what is probably the right value.
6534 * For FT_STRINGZ, it means "the string is null-terminated,
6535 * not null-padded; set the length to the actual length
6536 * of the string", and if the tvbuff if short, we just
6537 * throw an exception.
6539 * For ENC_VARINT_PROTOBUF|ENC_VARINT_QUIC|ENC_VARIANT_ZIGZAG|ENC_VARINT_SDNV, it means "find the end of the string",
6540 * and if the tvbuff if short, we just throw an exception.
6542 * It's not valid for any other type of field. For those
6543 * fields, we treat -1 the same way we treat other
6544 * negative values - we assume the length is a Really
6545 * Big Positive Number, and throw a ReportedBoundsError
6546 * exception, under the assumption that the Really Big
6547 * Length would run past the end of the packet.
6549 if ((FT_IS_INT(hfinfo
->type
)) || (FT_IS_UINT(hfinfo
->type
))) {
6550 if (encoding
& (ENC_VARINT_PROTOBUF
|ENC_VARINT_ZIGZAG
|ENC_VARINT_SDNV
)) {
6552 * Leave the length as -1, so our caller knows
6555 *item_length
= *length
;
6557 } else if (encoding
& ENC_VARINT_QUIC
) {
6558 switch (tvb_get_uint8(tvb
, start
) >> 6)
6560 case 0: /* 0b00 => 1 byte length (6 bits Usable) */
6563 case 1: /* 0b01 => 2 bytes length (14 bits Usable) */
6566 case 2: /* 0b10 => 4 bytes length (30 bits Usable) */
6569 case 3: /* 0b11 => 8 bytes length (62 bits Usable) */
6576 switch (hfinfo
->type
) {
6583 case FT_STRINGZTRUNC
:
6585 * We allow FT_PROTOCOLs to be zero-length -
6586 * for example, an ONC RPC NULL procedure has
6587 * neither arguments nor reply, so the
6588 * payload for that protocol is empty.
6590 * We also allow the others to be zero-length -
6591 * because that's the way the code has been for a
6594 * However, we want to ensure that the start
6595 * offset is not *past* the byte past the end
6596 * of the tvbuff: we throw an exception in that
6599 *length
= tvb_captured_length(tvb
) ? tvb_ensure_captured_length_remaining(tvb
, start
) : 0;
6600 DISSECTOR_ASSERT(*length
>= 0);
6605 * Leave the length as -1, so our caller knows
6611 THROW(ReportedBoundsError
);
6612 DISSECTOR_ASSERT_NOT_REACHED();
6614 *item_length
= *length
;
6616 *item_length
= *length
;
6617 if (hfinfo
->type
== FT_PROTOCOL
|| hfinfo
->type
== FT_NONE
) {
6619 * These types are for interior nodes of the
6620 * tree, and don't have data associated with
6621 * them; if the length is negative (XXX - see
6622 * above) or goes past the end of the tvbuff,
6623 * cut it short at the end of the tvbuff.
6624 * That way, if this field is selected in
6625 * Wireshark, we don't highlight stuff past
6626 * the end of the data.
6628 /* XXX - what to do, if we don't have a tvb? */
6630 length_remaining
= tvb_captured_length_remaining(tvb
, start
);
6631 if (*item_length
< 0 ||
6632 (*item_length
> 0 &&
6633 (length_remaining
< *item_length
)))
6634 *item_length
= length_remaining
;
6637 if (*item_length
< 0) {
6638 THROW(ReportedBoundsError
);
6644 get_full_length(header_field_info
*hfinfo
, tvbuff_t
*tvb
, const int start
,
6645 int length
, unsigned item_length
, const int encoding
)
6650 * We need to get the correct item length here.
6651 * That's normally done by proto_tree_new_item(),
6652 * but we won't be calling it.
6654 switch (hfinfo
->type
) {
6660 * The length is the specified length.
6665 n
= get_uint_value(NULL
, tvb
, start
, length
, encoding
);
6667 if ((int)item_length
< length
) {
6668 THROW(ReportedBoundsError
);
6672 /* XXX - make these just FT_UINT? */
6681 /* XXX - make these just FT_INT? */
6690 if (encoding
& ENC_VARINT_MASK
) {
6692 report_type_length_mismatch(NULL
, "a FT_[U]INT", length
, true);
6696 /* This can throw an exception */
6697 /* XXX - do this without fetching the varint? */
6698 length
= tvb_get_varint(tvb
, start
, FT_VARINT_MAX_LEN
, &dummy
, encoding
);
6700 THROW(ReportedBoundsError
);
6703 item_length
= length
;
6708 * The length is the specified length.
6730 * The length is the specified length.
6736 report_type_length_mismatch(NULL
, "a string", length
, true);
6739 /* This can throw an exception */
6740 /* XXX - do this without fetching the string? */
6741 wmem_free(NULL
, tvb_get_stringz_enc(NULL
, tvb
, start
, &length
, encoding
));
6743 item_length
= length
;
6746 case FT_UINT_STRING
:
6747 n
= get_uint_value(NULL
, tvb
, start
, length
, encoding
& ~ENC_CHARENCODING_MASK
);
6749 if ((int)item_length
< length
) {
6750 THROW(ReportedBoundsError
);
6755 case FT_STRINGZTRUNC
:
6756 case FT_ABSOLUTE_TIME
:
6757 case FT_RELATIVE_TIME
:
6758 case FT_IEEE_11073_SFLOAT
:
6759 case FT_IEEE_11073_FLOAT
:
6761 * The length is the specified length.
6766 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in gset_full_length()",
6769 ftype_name(hfinfo
->type
));
6776 new_field_info(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
,
6777 const int start
, const int item_length
)
6781 FIELD_INFO_NEW(PNODE_POOL(tree
), fi
);
6783 fi
->hfinfo
= hfinfo
;
6785 fi
->start
+= (tvb
)?tvb_raw_offset(tvb
):0;
6786 fi
->length
= item_length
;
6789 if (!PTREE_DATA(tree
)->visible
) {
6790 /* If the tree is not visible, set the item hidden, unless we
6791 * need the representation or length and can't fake them.
6793 if (hfinfo
->ref_type
!= HF_REF_TYPE_PRINT
&& (hfinfo
->type
!= FT_PROTOCOL
|| PTREE_DATA(tree
)->fake_protocols
)) {
6794 FI_SET_FLAG(fi
, FI_HIDDEN
);
6797 fi
->value
= fvalue_new(fi
->hfinfo
->type
);
6800 /* add the data source tvbuff */
6801 fi
->ds_tvb
= tvb
? tvb_get_ds_tvb(tvb
) : NULL
;
6803 fi
->appendix_start
= 0;
6804 fi
->appendix_length
= 0;
6806 fi
->total_layer_num
= tree
->tree_data
->pinfo
->curr_layer_num
;
6807 fi
->proto_layer_num
= tree
->tree_data
->pinfo
->curr_proto_layer_num
;
6812 static size_t proto_find_value_pos(const header_field_info
*hfinfo
, const char *representation
)
6814 if (hfinfo
->display
& BASE_NO_DISPLAY_VALUE
) {
6818 /* Search for field name */
6819 char *ptr
= strstr(representation
, hfinfo
->name
);
6824 /* Check if field name ends with the ": " delimiter */
6825 ptr
+= strlen(hfinfo
->name
);
6826 if (strncmp(ptr
, ": ", 2) == 0) {
6830 /* Return offset to after field name */
6831 return ptr
- representation
;
6834 /* If the protocol tree is to be visible, set the representation of a
6835 proto_tree entry with the name of the field for the item and with
6836 the value formatted with the supplied printf-style format and
6839 proto_tree_set_representation_value(proto_item
*pi
, const char *format
, va_list ap
)
6843 /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
6844 * items string representation */
6845 if (PTREE_DATA(pi
)->visible
|| !proto_item_is_hidden(pi
)) {
6846 size_t name_pos
, ret
= 0;
6848 field_info
*fi
= PITEM_FINFO(pi
);
6849 const header_field_info
*hf
;
6851 DISSECTOR_ASSERT(fi
);
6855 ITEM_LABEL_NEW(PNODE_POOL(pi
), fi
->rep
);
6856 if (hf
->bitmask
&& (hf
->type
== FT_BOOLEAN
|| FT_IS_UINT(hf
->type
))) {
6860 if (FT_IS_UINT32(hf
->type
))
6861 val
= fvalue_get_uinteger(fi
->value
);
6863 val
= fvalue_get_uinteger64(fi
->value
);
6865 val
<<= hfinfo_bitshift(hf
);
6867 p
= decode_bitfield_value(fi
->rep
->representation
, val
, hf
->bitmask
, hfinfo_container_bitwidth(hf
));
6868 ret
= (p
- fi
->rep
->representation
);
6871 /* put in the hf name */
6872 name_pos
= ret
= label_concat(fi
->rep
->representation
, ret
, hf
->name
);
6874 ret
= label_concat(fi
->rep
->representation
, ret
, ": ");
6875 /* If possible, Put in the value of the string */
6876 str
= wmem_strdup_vprintf(PNODE_POOL(pi
), format
, ap
);
6877 WS_UTF_8_CHECK(str
, -1);
6878 fi
->rep
->value_pos
= ret
;
6879 ret
= ws_label_strcpy(fi
->rep
->representation
, ITEM_LABEL_LENGTH
, ret
, str
, 0);
6880 if (ret
>= ITEM_LABEL_LENGTH
) {
6881 /* Uh oh, we don't have enough room. Tell the user
6882 * that the field is truncated.
6884 label_mark_truncated(fi
->rep
->representation
, name_pos
, &fi
->rep
->value_pos
);
6886 fi
->rep
->value_len
= strlen(fi
->rep
->representation
) - fi
->rep
->value_pos
;
6890 /* If the protocol tree is to be visible, set the representation of a
6891 proto_tree entry with the representation formatted with the supplied
6892 printf-style format and argument list. */
6894 proto_tree_set_representation(proto_item
*pi
, const char *format
, va_list ap
)
6896 size_t ret
; /*tmp return value */
6898 field_info
*fi
= PITEM_FINFO(pi
);
6900 DISSECTOR_ASSERT(fi
);
6902 if (!proto_item_is_hidden(pi
)) {
6903 ITEM_LABEL_NEW(PNODE_POOL(pi
), fi
->rep
);
6905 str
= wmem_strdup_vprintf(PNODE_POOL(pi
), format
, ap
);
6906 WS_UTF_8_CHECK(str
, -1);
6907 fi
->rep
->value_pos
= proto_find_value_pos(fi
->hfinfo
, str
);
6908 ret
= ws_label_strcpy(fi
->rep
->representation
, ITEM_LABEL_LENGTH
, 0, str
, 0);
6909 if (ret
>= ITEM_LABEL_LENGTH
) {
6910 /* Uh oh, we don't have enough room. Tell the user
6911 * that the field is truncated.
6913 LABEL_MARK_TRUNCATED_START(fi
->rep
->representation
, &fi
->rep
->value_pos
);
6915 fi
->rep
->value_len
= strlen(fi
->rep
->representation
) - fi
->rep
->value_pos
;
6920 protoo_strlcpy(char *dest
, const char *src
, size_t dest_size
)
6922 if (dest_size
== 0) return 0;
6924 size_t res
= g_strlcpy(dest
, src
, dest_size
);
6926 /* At most dest_size - 1 characters will be copied
6927 * (unless dest_size is 0). */
6928 if (res
>= dest_size
)
6929 res
= dest_size
- 1;
6933 static header_field_info
*
6934 hfinfo_same_name_get_prev(const header_field_info
*hfinfo
)
6936 header_field_info
*dup_hfinfo
;
6938 if (hfinfo
->same_name_prev_id
== -1)
6940 PROTO_REGISTRAR_GET_NTH(hfinfo
->same_name_prev_id
, dup_hfinfo
);
6945 hfinfo_remove_from_gpa_name_map(const header_field_info
*hfinfo
)
6947 g_free(last_field_name
);
6948 last_field_name
= NULL
;
6950 if (!hfinfo
->same_name_next
&& hfinfo
->same_name_prev_id
== -1) {
6951 /* No hfinfo with the same name */
6952 g_hash_table_steal(gpa_name_map
, hfinfo
->abbrev
);
6956 if (hfinfo
->same_name_next
) {
6957 hfinfo
->same_name_next
->same_name_prev_id
= hfinfo
->same_name_prev_id
;
6960 if (hfinfo
->same_name_prev_id
!= -1) {
6961 header_field_info
*same_name_prev
= hfinfo_same_name_get_prev(hfinfo
);
6962 same_name_prev
->same_name_next
= hfinfo
->same_name_next
;
6963 if (!hfinfo
->same_name_next
) {
6964 /* It's always the latest added hfinfo which is stored in gpa_name_map */
6965 g_hash_table_insert(gpa_name_map
, (void *) (same_name_prev
->abbrev
), same_name_prev
);
6971 proto_item_fill_display_label(const field_info
*finfo
, char *display_label_str
, const int label_str_size
)
6973 const header_field_info
*hfinfo
= finfo
->hfinfo
;
6977 const uint8_t *bytes
;
6980 const char *hf_str_val
;
6981 char number_buf
[NUMBER_LABEL_LENGTH
];
6982 const char *number_out
;
6984 const ipv4_addr_and_mask
*ipv4
;
6985 const ipv6_addr_and_prefix
*ipv6
;
6987 switch (hfinfo
->type
) {
6991 return protoo_strlcpy(display_label_str
, UTF8_CHECK_MARK
, label_str_size
);
6995 tmp_str
= format_bytes_hfinfo_maxlen(NULL
,
6997 fvalue_get_bytes_data(finfo
->value
),
6998 (unsigned)fvalue_length2(finfo
->value
),
7000 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7001 wmem_free(NULL
, tmp_str
);
7004 case FT_ABSOLUTE_TIME
:
7006 int flags
= ABS_TIME_TO_STR_SHOW_ZONE
;
7007 if (prefs
.display_abs_time_ascii
< ABS_TIME_ASCII_COLUMN
) {
7008 flags
|= ABS_TIME_TO_STR_ISO8601
;
7010 tmp_str
= abs_time_to_str_ex(NULL
, fvalue_get_time(finfo
->value
), hfinfo
->display
, flags
);
7011 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7012 wmem_free(NULL
, tmp_str
);
7016 case FT_RELATIVE_TIME
:
7017 tmp_str
= rel_time_to_secs_str(NULL
, fvalue_get_time(finfo
->value
));
7018 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7019 wmem_free(NULL
, tmp_str
);
7023 number64
= fvalue_get_uinteger64(finfo
->value
);
7024 label_len
= protoo_strlcpy(display_label_str
,
7025 tfs_get_string(!!number64
, hfinfo
->strings
), label_str_size
);
7029 number
= fvalue_get_uinteger(finfo
->value
);
7031 if (FIELD_DISPLAY(hfinfo
->display
) == BASE_CUSTOM
) {
7032 char tmp
[ITEM_LABEL_LENGTH
];
7033 custom_fmt_func_t fmtfunc
= (custom_fmt_func_t
)hfinfo
->strings
;
7035 DISSECTOR_ASSERT(fmtfunc
);
7036 fmtfunc(tmp
, number
);
7038 label_len
= protoo_strlcpy(display_label_str
, tmp
, label_str_size
);
7040 } else if (hfinfo
->strings
) {
7041 number_out
= hf_try_val_to_str(number
, hfinfo
);
7044 number_out
= hfinfo_char_value_format_display(BASE_HEX
, number_buf
, number
);
7047 label_len
= protoo_strlcpy(display_label_str
, number_out
, label_str_size
);
7050 number_out
= hfinfo_char_value_format(hfinfo
, number_buf
, number
);
7052 label_len
= protoo_strlcpy(display_label_str
, number_out
, label_str_size
);
7057 /* XXX - make these just FT_NUMBER? */
7068 number
= FT_IS_INT(hfinfo
->type
) ?
7069 (uint32_t) fvalue_get_sinteger(finfo
->value
) :
7070 fvalue_get_uinteger(finfo
->value
);
7072 if (FIELD_DISPLAY(hfinfo
->display
) == BASE_CUSTOM
) {
7073 char tmp
[ITEM_LABEL_LENGTH
];
7074 custom_fmt_func_t fmtfunc
= (custom_fmt_func_t
)hfinfo
->strings
;
7076 DISSECTOR_ASSERT(fmtfunc
);
7077 fmtfunc(tmp
, number
);
7079 label_len
= protoo_strlcpy(display_label_str
, tmp
, label_str_size
);
7081 } else if (hfinfo
->strings
&& hfinfo
->type
!= FT_FRAMENUM
) {
7082 if (hfinfo
->display
& BASE_UNIT_STRING
) {
7083 number_out
= hfinfo_numeric_value_format(hfinfo
, number_buf
, number
);
7084 label_len
= protoo_strlcpy(display_label_str
, number_out
, label_str_size
);
7085 hf_str_val
= hf_try_val_to_str(number
, hfinfo
);
7086 label_len
+= protoo_strlcpy(display_label_str
+label_len
, hf_str_val
, label_str_size
-label_len
);
7088 number_out
= hf_try_val_to_str(number
, hfinfo
);
7091 number_out
= hfinfo_number_value_format_display(hfinfo
, hfinfo
->display
, number_buf
, number
);
7094 label_len
= protoo_strlcpy(display_label_str
, number_out
, label_str_size
);
7097 number_out
= hfinfo_number_value_format(hfinfo
, number_buf
, number
);
7099 label_len
= protoo_strlcpy(display_label_str
, number_out
, label_str_size
);
7113 number64
= FT_IS_INT(hfinfo
->type
) ?
7114 (uint64_t) fvalue_get_sinteger64(finfo
->value
) :
7115 fvalue_get_uinteger64(finfo
->value
);
7117 if (FIELD_DISPLAY(hfinfo
->display
) == BASE_CUSTOM
) {
7118 char tmp
[ITEM_LABEL_LENGTH
];
7119 custom_fmt_func_64_t fmtfunc64
= (custom_fmt_func_64_t
)hfinfo
->strings
;
7121 DISSECTOR_ASSERT(fmtfunc64
);
7122 fmtfunc64(tmp
, number64
);
7124 label_len
= protoo_strlcpy(display_label_str
, tmp
, label_str_size
);
7125 } else if (hfinfo
->strings
) {
7126 if (hfinfo
->display
& BASE_UNIT_STRING
) {
7127 number_out
= hfinfo_numeric_value_format64(hfinfo
, number_buf
, number64
);
7128 label_len
= protoo_strlcpy(display_label_str
, number_out
, label_str_size
);
7129 hf_str_val
= hf_try_val64_to_str(number64
, hfinfo
);
7130 label_len
+= protoo_strlcpy(display_label_str
+label_len
, hf_str_val
, label_str_size
-label_len
);
7132 number_out
= hf_try_val64_to_str(number64
, hfinfo
);
7135 number_out
= hfinfo_number_value_format_display64(hfinfo
, hfinfo
->display
, number_buf
, number64
);
7137 label_len
= protoo_strlcpy(display_label_str
, number_out
, label_str_size
);
7140 number_out
= hfinfo_number_value_format64(hfinfo
, number_buf
, number64
);
7142 label_len
= protoo_strlcpy(display_label_str
, number_out
, label_str_size
);
7148 tmp_str
= eui64_to_str(NULL
, fvalue_get_uinteger64(finfo
->value
));
7149 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7150 wmem_free(NULL
, tmp_str
);
7154 ipv4
= fvalue_get_ipv4(finfo
->value
);
7155 //XXX: Should we ignore the mask?
7156 set_address_ipv4(&addr
, ipv4
);
7157 tmp_str
= address_to_display(NULL
, &addr
);
7158 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7159 wmem_free(NULL
, tmp_str
);
7160 free_address(&addr
);
7164 ipv6
= fvalue_get_ipv6(finfo
->value
);
7165 set_address_ipv6(&addr
, ipv6
);
7166 tmp_str
= address_to_display(NULL
, &addr
);
7167 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7168 wmem_free(NULL
, tmp_str
);
7169 free_address(&addr
);
7173 set_address (&addr
, AT_FCWWN
, FCWWN_ADDR_LEN
, fvalue_get_bytes_data(finfo
->value
));
7174 tmp_str
= address_to_display(NULL
, &addr
);
7175 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7176 wmem_free(NULL
, tmp_str
);
7180 set_address (&addr
, AT_ETHER
, FT_ETHER_LEN
, fvalue_get_bytes_data(finfo
->value
));
7181 tmp_str
= address_to_display(NULL
, &addr
);
7182 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7183 wmem_free(NULL
, tmp_str
);
7187 tmp_str
= guid_to_str(NULL
, fvalue_get_guid(finfo
->value
));
7188 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7189 wmem_free(NULL
, tmp_str
);
7193 bytes
= fvalue_get_bytes_data(finfo
->value
);
7194 tmp_str
= rel_oid_resolved_from_encoded(NULL
, bytes
, (int)fvalue_length2(finfo
->value
));
7195 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7196 wmem_free(NULL
, tmp_str
);
7200 bytes
= fvalue_get_bytes_data(finfo
->value
);
7201 tmp_str
= oid_resolved_from_encoded(NULL
, bytes
, (int)fvalue_length2(finfo
->value
));
7202 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7203 wmem_free(NULL
, tmp_str
);
7207 bytes
= fvalue_get_bytes_data(finfo
->value
);
7208 tmp_str
= print_system_id(NULL
, bytes
, (int)fvalue_length2(finfo
->value
));
7209 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7210 wmem_free(NULL
, tmp_str
);
7215 label_len
= (int)fill_display_label_float(finfo
, display_label_str
);
7220 case FT_UINT_STRING
:
7222 case FT_STRINGZTRUNC
:
7223 str
= fvalue_get_string(finfo
->value
);
7224 label_len
= (int)ws_label_strcpy(display_label_str
, label_str_size
, 0, str
, label_strcat_flags(hfinfo
));
7225 if (label_len
>= label_str_size
) {
7226 /* Truncation occurred. Get the real length
7227 * copied (not including '\0') */
7228 label_len
= label_str_size
? label_str_size
- 1 : 0;
7233 /* First try ftype string representation */
7234 tmp_str
= fvalue_to_string_repr(NULL
, finfo
->value
, FTREPR_DISPLAY
, hfinfo
->display
);
7236 /* Default to show as bytes */
7237 bytes
= fvalue_get_bytes_data(finfo
->value
);
7238 tmp_str
= bytes_to_str(NULL
, bytes
, fvalue_length2(finfo
->value
));
7240 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7241 wmem_free(NULL
, tmp_str
);
7247 /* -------------------------- */
7248 /* Sets the text for a custom column from proto fields.
7250 * @param[out] result The "resolved" column text (human readable, uses strings)
7251 * @param[out] expr The "unresolved" column text (values, display repr)
7252 * @return The filter (abbrev) for the field (XXX: Only the first if multifield)
7255 proto_custom_set(proto_tree
* tree
, GSList
*field_ids
, int occurrence
, bool display_details
,
7256 char *result
, char *expr
, const int size
)
7258 int len
, prev_len
, last
, i
, offset_r
= 0, offset_e
= 0;
7260 field_info
*finfo
= NULL
;
7261 header_field_info
* hfinfo
;
7262 const char *abbrev
= NULL
;
7264 const char *hf_str_val
;
7266 col_custom_t
*field_idx
;
7270 ws_assert(field_ids
!= NULL
);
7271 while ((field_idx
= (col_custom_t
*) g_slist_nth_data(field_ids
, ii
++))) {
7272 field_id
= field_idx
->field_id
;
7273 if (field_id
== 0) {
7274 GPtrArray
*fvals
= NULL
;
7275 bool passed
= dfilter_apply_full(field_idx
->dfilter
, tree
, &fvals
);
7276 if (fvals
!= NULL
) {
7278 // XXX - Handling occurrences is unusual when more
7279 // than one field is involved, e.g. there's four
7280 // results for tcp.port + tcp.port. We may really
7281 // want to apply it to the operands, not the output.
7282 // Note that occurrences are not quite the same as
7283 // the layer operator (should the grammar support
7285 /* Calculate single index or set outer boundaries */
7286 len
= g_ptr_array_len(fvals
);
7287 if (occurrence
< 0) {
7288 i
= occurrence
+ len
;
7290 } else if (occurrence
> 0) {
7297 if (i
< 0 || i
>= len
) {
7298 g_ptr_array_unref(fvals
);
7301 for (; i
<= last
; i
++) {
7302 /* XXX - We could have a "resolved" result
7303 * for types where the value depends only
7304 * on the type, e.g. FT_IPv4, and not on
7305 * hfinfo->strings. Supporting the latter
7306 * requires knowing which hfinfo matched
7307 * if there are multiple with the same
7308 * abbreviation. In any case, we need to
7309 * know the expected return type of the
7312 str
= fvalue_to_string_repr(NULL
, fvals
->pdata
[i
], FTREPR_DISPLAY
, BASE_NONE
);
7313 if (offset_r
&& (offset_r
< (size
- 1)))
7314 result
[offset_r
++] = ',';
7315 if (offset_e
&& (offset_e
< (size
- 1)))
7316 expr
[offset_e
++] = ',';
7317 offset_r
+= protoo_strlcpy(result
+offset_r
, str
, size
-offset_r
);
7318 offset_e
+= protoo_strlcpy(expr
+offset_e
, str
, size
-offset_e
);
7321 g_ptr_array_unref(fvals
);
7322 } else if (passed
) {
7323 // XXX - Occurrence doesn't make sense for a test
7324 // output, it should be applied to the operands.
7325 if (offset_r
&& (offset_r
< (size
- 1)))
7326 result
[offset_r
++] = ',';
7327 if (offset_e
&& (offset_e
< (size
- 1)))
7328 expr
[offset_e
++] = ',';
7329 /* Prevent multiple check marks */
7330 if (strstr(result
, UTF8_CHECK_MARK
",") == NULL
) {
7331 offset_r
+= protoo_strlcpy(result
+offset_r
, UTF8_CHECK_MARK
, size
-offset_r
);
7333 result
[--offset_r
] = '\0'; /* Remove the added trailing ',' */
7335 if (strstr(expr
, UTF8_CHECK_MARK
",") == NULL
) {
7336 offset_e
+= protoo_strlcpy(expr
+offset_e
, UTF8_CHECK_MARK
, size
-offset_e
);
7338 expr
[--offset_e
] = '\0'; /* Remove the added trailing ',' */
7343 PROTO_REGISTRAR_GET_NTH((unsigned)field_id
, hfinfo
);
7345 /* do we need to rewind ? */
7349 if (occurrence
< 0) {
7350 /* Search other direction */
7351 while (hfinfo
->same_name_prev_id
!= -1) {
7352 PROTO_REGISTRAR_GET_NTH(hfinfo
->same_name_prev_id
, hfinfo
);
7356 prev_len
= 0; /* Reset handled occurrences */
7359 finfos
= proto_get_finfo_ptr_array(tree
, hfinfo
->id
);
7361 if (!finfos
|| !(len
= g_ptr_array_len(finfos
))) {
7362 if (occurrence
< 0) {
7363 hfinfo
= hfinfo
->same_name_next
;
7365 hfinfo
= hfinfo_same_name_get_prev(hfinfo
);
7370 /* Are there enough occurrences of the field? */
7371 if (((occurrence
- prev_len
) > len
) || ((occurrence
+ prev_len
) < -len
)) {
7372 if (occurrence
< 0) {
7373 hfinfo
= hfinfo
->same_name_next
;
7375 hfinfo
= hfinfo_same_name_get_prev(hfinfo
);
7381 /* Calculate single index or set outer boundaries */
7382 if (occurrence
< 0) {
7383 i
= occurrence
+ len
+ prev_len
;
7385 } else if (occurrence
> 0) {
7386 i
= occurrence
- 1 - prev_len
;
7393 prev_len
+= len
; /* Count handled occurrences */
7396 finfo
= (field_info
*)g_ptr_array_index(finfos
, i
);
7398 if (offset_r
&& (offset_r
< (size
- 1)))
7399 result
[offset_r
++] = ',';
7401 if (display_details
) {
7402 char representation
[ITEM_LABEL_LENGTH
];
7405 if (finfo
->rep
&& finfo
->rep
->value_len
) {
7406 g_strlcpy(representation
, &finfo
->rep
->representation
[finfo
->rep
->value_pos
],
7407 MIN(finfo
->rep
->value_len
+ 1, ITEM_LABEL_LENGTH
));
7409 proto_item_fill_label(finfo
, representation
, &offset
);
7411 offset_r
+= protoo_strlcpy(result
+offset_r
, &representation
[offset
], size
-offset_r
);
7413 switch (hfinfo
->type
) {
7417 /* Prevent multiple check marks */
7418 if (strstr(result
, UTF8_CHECK_MARK
",") == NULL
) {
7419 offset_r
+= proto_item_fill_display_label(finfo
, result
+offset_r
, size
-offset_r
);
7421 result
[--offset_r
] = '\0'; /* Remove the added trailing ',' again */
7426 offset_r
+= proto_item_fill_display_label(finfo
, result
+offset_r
, size
-offset_r
);
7431 if (offset_e
&& (offset_e
< (size
- 1)))
7432 expr
[offset_e
++] = ',';
7434 if (hfinfo
->strings
&& hfinfo
->type
!= FT_FRAMENUM
&& FIELD_DISPLAY(hfinfo
->display
) == BASE_NONE
&& (FT_IS_INT(hfinfo
->type
) || FT_IS_UINT(hfinfo
->type
))) {
7435 /* Integer types with BASE_NONE never get the numeric value. */
7436 if (FT_IS_INT32(hfinfo
->type
)) {
7437 hf_str_val
= hf_try_val_to_str_const(fvalue_get_sinteger(finfo
->value
), hfinfo
, "Unknown");
7438 } else if (FT_IS_UINT32(hfinfo
->type
)) {
7439 hf_str_val
= hf_try_val_to_str_const(fvalue_get_uinteger(finfo
->value
), hfinfo
, "Unknown");
7440 } else if (FT_IS_INT64(hfinfo
->type
)) {
7441 hf_str_val
= hf_try_val64_to_str_const(fvalue_get_sinteger64(finfo
->value
), hfinfo
, "Unknown");
7442 } else { // if (FT_IS_UINT64(hfinfo->type)) {
7443 hf_str_val
= hf_try_val64_to_str_const(fvalue_get_uinteger64(finfo
->value
), hfinfo
, "Unknown");
7445 snprintf(expr
+offset_e
, size
-offset_e
, "\"%s\"", hf_str_val
);
7446 offset_e
= (int)strlen(expr
);
7447 } else if (hfinfo
->type
== FT_NONE
|| hfinfo
->type
== FT_PROTOCOL
) {
7448 /* Prevent multiple check marks */
7449 if (strstr(expr
, UTF8_CHECK_MARK
",") == NULL
) {
7450 offset_e
+= proto_item_fill_display_label(finfo
, expr
+offset_e
, size
-offset_e
);
7452 expr
[--offset_e
] = '\0'; /* Remove the added trailing ',' again */
7455 str
= fvalue_to_string_repr(NULL
, finfo
->value
, FTREPR_RAW
, finfo
->hfinfo
->display
);
7456 offset_e
+= protoo_strlcpy(expr
+offset_e
, str
, size
-offset_e
);
7457 wmem_free(NULL
, str
);
7462 /* XXX: Why is only the first abbreviation returned for a multifield
7465 /* Store abbrev for return value */
7466 abbrev
= hfinfo
->abbrev
;
7469 if (occurrence
== 0) {
7470 /* Fetch next hfinfo with same name (abbrev) */
7471 hfinfo
= hfinfo_same_name_get_prev(hfinfo
);
7478 if (offset_r
>= (size
- 1)) {
7479 mark_truncated(result
, 0, size
, NULL
);
7481 if (offset_e
>= (size
- 1)) {
7482 mark_truncated(expr
, 0, size
, NULL
);
7484 return abbrev
? abbrev
: "";
7488 proto_custom_get_filter(epan_dissect_t
* edt
, GSList
*field_ids
, int occurrence
)
7490 int len
, prev_len
, last
, i
;
7492 field_info
*finfo
= NULL
;
7493 header_field_info
* hfinfo
;
7495 char *filter
= NULL
;
7496 GPtrArray
*filter_array
;
7498 col_custom_t
*col_custom
;
7501 ws_assert(field_ids
!= NULL
);
7502 filter_array
= g_ptr_array_new_full(g_slist_length(field_ids
), g_free
);
7503 for (GSList
*iter
= field_ids
; iter
; iter
= iter
->next
) {
7504 col_custom
= (col_custom_t
*)iter
->data
;
7505 field_id
= col_custom
->field_id
;
7506 if (field_id
== 0) {
7507 GPtrArray
*fvals
= NULL
;
7508 bool passed
= dfilter_apply_full(col_custom
->dfilter
, edt
->tree
, &fvals
);
7509 if (fvals
!= NULL
) {
7510 // XXX - Handling occurrences is unusual when more
7511 // than one field is involved, e.g. there's four
7512 // results for tcp.port + tcp.port. We really
7513 // want to apply it to the operands, not the output.
7514 /* Calculate single index or set outer boundaries */
7515 len
= g_ptr_array_len(fvals
);
7516 if (occurrence
< 0) {
7517 i
= occurrence
+ len
;
7519 } else if (occurrence
> 0) {
7526 if (i
< 0 || i
>= len
) {
7527 g_ptr_array_unref(fvals
);
7530 for (; i
<= last
; i
++) {
7531 /* XXX - Should multiple values for one
7532 * field use set membership to reduce
7533 * verbosity, here and below? */
7534 char *str
= fvalue_to_string_repr(NULL
, fvals
->pdata
[i
], FTREPR_DFILTER
, BASE_NONE
);
7535 filter
= wmem_strdup_printf(NULL
, "%s == %s", col_custom
->dftext
, str
);
7536 wmem_free(NULL
, str
);
7537 if (!g_ptr_array_find_with_equal_func(filter_array
, filter
, g_str_equal
, NULL
)) {
7538 g_ptr_array_add(filter_array
, filter
);
7541 g_ptr_array_unref(fvals
);
7542 } else if (passed
) {
7543 filter
= wmem_strdup(NULL
, col_custom
->dftext
);
7544 if (!g_ptr_array_find_with_equal_func(filter_array
, filter
, g_str_equal
, NULL
)) {
7545 g_ptr_array_add(filter_array
, filter
);
7548 filter
= wmem_strdup_printf(NULL
, "!(%s)", col_custom
->dftext
);
7549 if (!g_ptr_array_find_with_equal_func(filter_array
, filter
, g_str_equal
, NULL
)) {
7550 g_ptr_array_add(filter_array
, filter
);
7556 PROTO_REGISTRAR_GET_NTH((unsigned)field_id
, hfinfo
);
7558 /* do we need to rewind ? */
7562 if (occurrence
< 0) {
7563 /* Search other direction */
7564 while (hfinfo
->same_name_prev_id
!= -1) {
7565 PROTO_REGISTRAR_GET_NTH(hfinfo
->same_name_prev_id
, hfinfo
);
7569 prev_len
= 0; /* Reset handled occurrences */
7572 finfos
= proto_get_finfo_ptr_array(edt
->tree
, hfinfo
->id
);
7574 if (!finfos
|| !(len
= g_ptr_array_len(finfos
))) {
7575 if (occurrence
< 0) {
7576 hfinfo
= hfinfo
->same_name_next
;
7578 hfinfo
= hfinfo_same_name_get_prev(hfinfo
);
7583 /* Are there enough occurrences of the field? */
7584 if (((occurrence
- prev_len
) > len
) || ((occurrence
+ prev_len
) < -len
)) {
7585 if (occurrence
< 0) {
7586 hfinfo
= hfinfo
->same_name_next
;
7588 hfinfo
= hfinfo_same_name_get_prev(hfinfo
);
7594 /* Calculate single index or set outer boundaries */
7595 if (occurrence
< 0) {
7596 i
= occurrence
+ len
+ prev_len
;
7598 } else if (occurrence
> 0) {
7599 i
= occurrence
- 1 - prev_len
;
7606 prev_len
+= len
; /* Count handled occurrences */
7609 finfo
= (field_info
*)g_ptr_array_index(finfos
, i
);
7611 filter
= proto_construct_match_selected_string(finfo
, edt
);
7613 /* Only add the same expression once (especially for FT_PROTOCOL).
7614 * The ptr array doesn't have NULL entries so g_str_equal is fine.
7616 if (!g_ptr_array_find_with_equal_func(filter_array
, filter
, g_str_equal
, NULL
)) {
7617 g_ptr_array_add(filter_array
, filter
);
7623 if (occurrence
== 0) {
7624 /* Fetch next hfinfo with same name (abbrev) */
7625 hfinfo
= hfinfo_same_name_get_prev(hfinfo
);
7632 g_ptr_array_add(filter_array
, NULL
);
7634 /* XXX: Should this be || or && ? */
7635 char *output
= g_strjoinv(" || ", (char **)filter_array
->pdata
);
7637 g_ptr_array_free(filter_array
, true);
7642 /* Set text of proto_item after having already been created. */
7644 proto_item_set_text(proto_item
*pi
, const char *format
, ...)
7646 field_info
*fi
= NULL
;
7649 TRY_TO_FAKE_THIS_REPR_VOID(pi
);
7651 fi
= PITEM_FINFO(pi
);
7656 ITEM_LABEL_FREE(PNODE_POOL(pi
), fi
->rep
);
7660 va_start(ap
, format
);
7661 proto_tree_set_representation(pi
, format
, ap
);
7665 /* Append to text of proto_item after having already been created. */
7667 proto_item_append_text(proto_item
*pi
, const char *format
, ...)
7669 field_info
*fi
= NULL
;
7674 TRY_TO_FAKE_THIS_REPR_VOID(pi
);
7676 fi
= PITEM_FINFO(pi
);
7681 if (!proto_item_is_hidden(pi
)) {
7683 * If we don't already have a representation,
7684 * generate the default representation.
7686 if (fi
->rep
== NULL
) {
7687 ITEM_LABEL_NEW(PNODE_POOL(pi
), fi
->rep
);
7688 proto_item_fill_label(fi
, fi
->rep
->representation
, &fi
->rep
->value_pos
);
7689 /* Check for special case append value to FT_NONE or FT_PROTOCOL */
7690 if ((fi
->hfinfo
->type
== FT_NONE
|| fi
->hfinfo
->type
== FT_PROTOCOL
) &&
7691 (strncmp(format
, ": ", 2) == 0)) {
7692 fi
->rep
->value_pos
+= 2;
7696 curlen
= strlen(fi
->rep
->representation
);
7697 /* curlen doesn't include the \0 byte.
7698 * XXX: If curlen + 4 > ITEM_LABEL_LENGTH, we can't tell if
7699 * the representation has already been truncated (of an up
7700 * to 4 byte UTF-8 character) or is just at the maximum length
7701 * unless we search for " [truncated]" (which may not be
7703 * It's safer to do nothing.
7705 if (ITEM_LABEL_LENGTH
> (curlen
+ 4)) {
7706 va_start(ap
, format
);
7707 str
= wmem_strdup_vprintf(PNODE_POOL(pi
), format
, ap
);
7709 WS_UTF_8_CHECK(str
, -1);
7710 /* Keep fi->rep->value_pos */
7711 curlen
= ws_label_strcpy(fi
->rep
->representation
, ITEM_LABEL_LENGTH
, curlen
, str
, 0);
7712 if (curlen
>= ITEM_LABEL_LENGTH
) {
7713 /* Uh oh, we don't have enough room. Tell the user
7714 * that the field is truncated.
7716 LABEL_MARK_TRUNCATED_START(fi
->rep
->representation
, &fi
->rep
->value_pos
);
7718 fi
->rep
->value_len
= strlen(fi
->rep
->representation
) - fi
->rep
->value_pos
;
7724 /* Prepend to text of proto_item after having already been created. */
7726 proto_item_prepend_text(proto_item
*pi
, const char *format
, ...)
7728 field_info
*fi
= NULL
;
7730 char representation
[ITEM_LABEL_LENGTH
];
7734 TRY_TO_FAKE_THIS_REPR_VOID(pi
);
7736 fi
= PITEM_FINFO(pi
);
7741 if (!proto_item_is_hidden(pi
)) {
7743 * If we don't already have a representation,
7744 * generate the default representation.
7746 if (fi
->rep
== NULL
) {
7747 ITEM_LABEL_NEW(PNODE_POOL(pi
), fi
->rep
);
7748 proto_item_fill_label(fi
, representation
, &fi
->rep
->value_pos
);
7750 (void) g_strlcpy(representation
, fi
->rep
->representation
, ITEM_LABEL_LENGTH
);
7752 va_start(ap
, format
);
7753 str
= wmem_strdup_vprintf(PNODE_POOL(pi
), format
, ap
);
7755 WS_UTF_8_CHECK(str
, -1);
7756 fi
->rep
->value_pos
+= strlen(str
);
7757 pos
= ws_label_strcpy(fi
->rep
->representation
, ITEM_LABEL_LENGTH
, 0, str
, 0);
7758 pos
= ws_label_strcpy(fi
->rep
->representation
, ITEM_LABEL_LENGTH
, pos
, representation
, 0);
7759 /* XXX: As above, if the old representation is close to the label
7760 * length, it might already be marked as truncated. */
7761 if (pos
>= ITEM_LABEL_LENGTH
&& (strlen(representation
) + 4) <= ITEM_LABEL_LENGTH
) {
7762 /* Uh oh, we don't have enough room. Tell the user
7763 * that the field is truncated.
7765 LABEL_MARK_TRUNCATED_START(fi
->rep
->representation
, &fi
->rep
->value_pos
);
7767 fi
->rep
->value_len
= strlen(fi
->rep
->representation
) - fi
->rep
->value_pos
;
7772 finfo_set_len(field_info
*fi
, const int length
)
7774 int length_remaining
;
7776 DISSECTOR_ASSERT_HINT(length
>= 0, fi
->hfinfo
->abbrev
);
7777 length_remaining
= tvb_captured_length_remaining(fi
->ds_tvb
, fi
->start
);
7778 if (length
> length_remaining
)
7779 fi
->length
= length_remaining
;
7781 fi
->length
= length
;
7783 /* If we have an FT_PROTOCOL we need to set the length of the fvalue tvbuff as well. */
7784 if (fvalue_type_ftenum(fi
->value
) == FT_PROTOCOL
) {
7785 fvalue_set_protocol_length(fi
->value
, fi
->length
);
7789 * You cannot just make the "len" field of a GByteArray
7790 * larger, if there's no data to back that length;
7791 * you can only make it smaller.
7793 if (fvalue_type_ftenum(fi
->value
) == FT_BYTES
&& fi
->length
> 0) {
7794 GBytes
*bytes
= fvalue_get_bytes(fi
->value
);
7796 const void *data
= g_bytes_get_data(bytes
, &size
);
7797 if ((size_t)fi
->length
<= size
) {
7798 fvalue_set_bytes_data(fi
->value
, data
, fi
->length
);
7800 g_bytes_unref(bytes
);
7805 proto_item_set_len(proto_item
*pi
, const int length
)
7809 /* If the item is not visible, we can't set the length because
7810 * we can't distinguish which proto item this is being called
7811 * on, since faked items share proto items. (#17877)
7813 TRY_TO_FAKE_THIS_REPR_VOID(pi
);
7815 fi
= PITEM_FINFO(pi
);
7819 finfo_set_len(fi
, length
);
7823 * Sets the length of the item based on its start and on the specified
7824 * offset, which is the offset past the end of the item; as the start
7825 * in the item is relative to the beginning of the data source tvbuff,
7826 * we need to pass in a tvbuff - the end offset is relative to the beginning
7830 proto_item_set_end(proto_item
*pi
, tvbuff_t
*tvb
, int end
)
7835 /* As with proto_item_set_len() above */
7836 TRY_TO_FAKE_THIS_REPR_VOID(pi
);
7838 fi
= PITEM_FINFO(pi
);
7842 end
+= tvb_raw_offset(tvb
);
7843 DISSECTOR_ASSERT(end
>= fi
->start
);
7844 length
= end
- fi
->start
;
7846 finfo_set_len(fi
, length
);
7850 proto_item_get_len(const proto_item
*pi
)
7856 fi
= PITEM_FINFO(pi
);
7857 return fi
? fi
->length
: -1;
7861 proto_item_set_bits_offset_len(proto_item
*ti
, int bits_offset
, int bits_len
) {
7865 FI_SET_FLAG(PNODE_FINFO(ti
), FI_BITS_OFFSET(bits_offset
));
7866 FI_SET_FLAG(PNODE_FINFO(ti
), FI_BITS_SIZE(bits_len
));
7870 proto_item_get_display_repr(wmem_allocator_t
*scope
, proto_item
*pi
)
7876 fi
= PITEM_FINFO(pi
);
7877 DISSECTOR_ASSERT(fi
->hfinfo
!= NULL
);
7878 return fvalue_to_string_repr(scope
, fi
->value
, FTREPR_DISPLAY
, fi
->hfinfo
->display
);
7882 proto_tree_create_root(packet_info
*pinfo
)
7886 /* Initialize the proto_node */
7887 pnode
= g_slice_new(proto_tree
);
7888 PROTO_NODE_INIT(pnode
);
7889 pnode
->parent
= NULL
;
7890 PNODE_FINFO(pnode
) = NULL
;
7891 pnode
->tree_data
= g_slice_new(tree_data_t
);
7893 /* Make sure we can access pinfo everywhere */
7894 pnode
->tree_data
->pinfo
= pinfo
;
7896 /* Don't initialize the tree_data_t. Wait until we know we need it */
7897 pnode
->tree_data
->interesting_hfids
= NULL
;
7899 /* Set the default to false so it's easier to
7900 * find errors; if we expect to see the protocol tree
7901 * but for some reason the default 'visible' is not
7902 * changed, then we'll find out very quickly. */
7903 pnode
->tree_data
->visible
= false;
7905 /* Make sure that we fake protocols (if possible) */
7906 pnode
->tree_data
->fake_protocols
= true;
7908 /* Keep track of the number of children */
7909 pnode
->tree_data
->count
= 0;
7911 return (proto_tree
*)pnode
;
7915 /* "prime" a proto_tree with a single hfid that a dfilter
7916 * is interested in. */
7918 proto_tree_prime_with_hfid(proto_tree
*tree _U_
, const int hfid
)
7920 header_field_info
*hfinfo
;
7922 PROTO_REGISTRAR_GET_NTH(hfid
, hfinfo
);
7923 /* this field is referenced by a filter so increase the refcount.
7924 also increase the refcount for the parent, i.e the protocol.
7925 Don't increase the refcount if we're already printing the
7926 type, as that is a superset of direct reference.
7928 if (hfinfo
->ref_type
!= HF_REF_TYPE_PRINT
) {
7929 hfinfo
->ref_type
= HF_REF_TYPE_DIRECT
;
7931 /* only increase the refcount if there is a parent.
7932 if this is a protocol and not a field then parent will be -1
7933 and there is no parent to add any refcounting for.
7935 if (hfinfo
->parent
!= -1) {
7936 header_field_info
*parent_hfinfo
;
7937 PROTO_REGISTRAR_GET_NTH(hfinfo
->parent
, parent_hfinfo
);
7939 /* Mark parent as indirectly referenced unless it is already directly
7940 * referenced, i.e. the user has specified the parent in a filter.
7942 if (parent_hfinfo
->ref_type
== HF_REF_TYPE_NONE
)
7943 parent_hfinfo
->ref_type
= HF_REF_TYPE_INDIRECT
;
7947 /* "prime" a proto_tree with a single hfid that a dfilter
7948 * is interested in. */
7950 proto_tree_prime_with_hfid_print(proto_tree
*tree _U_
, const int hfid
)
7952 header_field_info
*hfinfo
;
7954 PROTO_REGISTRAR_GET_NTH(hfid
, hfinfo
);
7955 /* this field is referenced by an (output) filter so increase the refcount.
7956 also increase the refcount for the parent, i.e the protocol.
7958 hfinfo
->ref_type
= HF_REF_TYPE_PRINT
;
7959 /* only increase the refcount if there is a parent.
7960 if this is a protocol and not a field then parent will be -1
7961 and there is no parent to add any refcounting for.
7963 if (hfinfo
->parent
!= -1) {
7964 header_field_info
*parent_hfinfo
;
7965 PROTO_REGISTRAR_GET_NTH(hfinfo
->parent
, parent_hfinfo
);
7967 /* Mark parent as indirectly referenced unless it is already directly
7968 * referenced, i.e. the user has specified the parent in a filter.
7970 if (parent_hfinfo
->ref_type
== HF_REF_TYPE_NONE
)
7971 parent_hfinfo
->ref_type
= HF_REF_TYPE_INDIRECT
;
7976 proto_item_add_subtree(proto_item
*pi
, const int idx
) {
7982 DISSECTOR_ASSERT(idx
>= 0 && idx
< num_tree_types
);
7984 fi
= PITEM_FINFO(pi
);
7986 return (proto_tree
*)pi
;
7988 fi
->tree_type
= idx
;
7990 return (proto_tree
*)pi
;
7994 proto_item_get_subtree(proto_item
*pi
) {
7999 fi
= PITEM_FINFO(pi
);
8000 if ( (!fi
) || (fi
->tree_type
== -1) )
8002 return (proto_tree
*)pi
;
8006 proto_item_get_parent(const proto_item
*ti
) {
8007 /* XXX: If we're faking items, this will return the parent of the
8008 * faked item, which may not be the logical parent expected.
8009 * We have no way of knowing exactly which real item the fake
8010 * item refers to here (the original item or one of its children
8011 * using it as a fake), and thus whether the parent should be the
8012 * faked item itself or the faked item's parent.
8014 * In that case, there's a good chance we end up returning the
8015 * root node of the protocol tree, which has "PNODE_FINFO()" null.
8017 * If we later add items to _that_, they will not be faked even though
8018 * they _should_ be, hurting performance (#8069). Also protocol
8019 * hierarchy stats (which fakes everything but protocols) may
8020 * behave oddly if unexpected items are added under the root node.
8028 proto_item_get_parent_nth(proto_item
*ti
, int gen
) {
8029 /* XXX: Same issue as above, even more so. */
8042 proto_tree_get_parent(proto_tree
*tree
) {
8045 return (proto_item
*)tree
;
8049 proto_tree_get_parent_tree(proto_tree
*tree
) {
8050 /* XXX: Same issue as proto_item_get_parent */
8054 /* we're the root tree, there's no parent
8055 return ourselves so the caller has at least a tree to attach to */
8059 return (proto_tree
*)tree
->parent
;
8063 proto_tree_get_root(proto_tree
*tree
) {
8066 while (tree
->parent
) {
8067 tree
= tree
->parent
;
8073 proto_tree_move_item(proto_tree
*tree
, proto_item
*fixed_item
,
8074 proto_item
*item_to_move
)
8076 /* This function doesn't generate any values. It only reorganizes the prococol tree
8077 * so we can bail out immediately if it isn't visible. */
8078 if (!tree
|| !PTREE_DATA(tree
)->visible
)
8081 DISSECTOR_ASSERT(item_to_move
->parent
== tree
);
8082 DISSECTOR_ASSERT(fixed_item
->parent
== tree
);
8084 /*** cut item_to_move out ***/
8086 /* is item_to_move the first? */
8087 if (tree
->first_child
== item_to_move
) {
8088 /* simply change first child to next */
8089 tree
->first_child
= item_to_move
->next
;
8091 DISSECTOR_ASSERT(tree
->last_child
!= item_to_move
);
8093 proto_item
*curr_item
;
8094 /* find previous and change it's next */
8095 for (curr_item
= tree
->first_child
; curr_item
!= NULL
; curr_item
= curr_item
->next
) {
8096 if (curr_item
->next
== item_to_move
) {
8101 DISSECTOR_ASSERT(curr_item
);
8103 curr_item
->next
= item_to_move
->next
;
8105 /* fix last_child if required */
8106 if (tree
->last_child
== item_to_move
) {
8107 tree
->last_child
= curr_item
;
8111 /*** insert to_move after fixed ***/
8112 item_to_move
->next
= fixed_item
->next
;
8113 fixed_item
->next
= item_to_move
;
8114 if (tree
->last_child
== fixed_item
) {
8115 tree
->last_child
= item_to_move
;
8120 proto_tree_set_appendix(proto_tree
*tree
, tvbuff_t
*tvb
, int start
,
8128 fi
= PTREE_FINFO(tree
);
8132 start
+= tvb_raw_offset(tvb
);
8133 DISSECTOR_ASSERT(start
>= 0);
8134 DISSECTOR_ASSERT(length
>= 0);
8136 fi
->appendix_start
= start
;
8137 fi
->appendix_length
= length
;
8141 check_protocol_filter_name_or_fail(const char *filter_name
)
8143 /* Require at least two characters. */
8144 if (filter_name
[0] == '\0' || filter_name
[1] == '\0') {
8145 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" cannot have length less than two.", filter_name
);
8148 if (proto_check_field_name(filter_name
) != '\0') {
8149 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" has one or more invalid characters."
8150 " Allowed are letters, digits, '-', '_' and non-repeating '.'."
8151 " This might be caused by an inappropriate plugin or a development error.", filter_name
);
8154 /* Check that it doesn't match some very common numeric forms. */
8155 if (filter_name
[0] == '0' &&
8156 (filter_name
[1] == 'x' || filter_name
[1] == 'X' ||
8157 filter_name
[1] == 'b' || filter_name
[1] == 'B')) {
8158 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" cannot start with \"%c%c\".",
8159 filter_name
, filter_name
[0], filter_name
[1]);
8162 /* Names starting with a digit must not contain a minus sign (currently not checked at runtime). */
8164 /* Check that it contains at least one letter. */
8165 bool have_letter
= false;
8166 for (const char *s
= filter_name
; *s
!= '\0'; s
++) {
8167 if (g_ascii_isalpha(*s
)) {
8173 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" must contain at least one letter a-z.",
8177 /* Check for reserved keywords. */
8178 if (g_hash_table_contains(proto_reserved_filter_names
, filter_name
)) {
8179 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" is invalid because it is a reserved keyword."
8180 " This might be caused by an inappropriate plugin or a development error.", filter_name
);
8185 proto_register_protocol(const char *name
, const char *short_name
,
8186 const char *filter_name
)
8188 protocol_t
*protocol
;
8189 header_field_info
*hfinfo
;
8192 * Make sure there's not already a protocol with any of those
8193 * names. Crash if there is, as that's an error in the code
8194 * or an inappropriate plugin.
8195 * This situation has to be fixed to not register more than one
8196 * protocol with the same name.
8199 if (g_hash_table_lookup(proto_names
, name
)) {
8200 /* ws_error will terminate the program */
8201 REPORT_DISSECTOR_BUG("Duplicate protocol name \"%s\"!"
8202 " This might be caused by an inappropriate plugin or a development error.", name
);
8205 if (g_hash_table_lookup(proto_short_names
, short_name
)) {
8206 REPORT_DISSECTOR_BUG("Duplicate protocol short_name \"%s\"!"
8207 " This might be caused by an inappropriate plugin or a development error.", short_name
);
8210 check_protocol_filter_name_or_fail(filter_name
);
8212 if (g_hash_table_lookup(proto_filter_names
, filter_name
)) {
8213 REPORT_DISSECTOR_BUG("Duplicate protocol filter_name \"%s\"!"
8214 " This might be caused by an inappropriate plugin or a development error.", filter_name
);
8218 * Add this protocol to the list of known protocols;
8219 * the list is sorted by protocol short name.
8221 protocol
= g_new(protocol_t
, 1);
8222 protocol
->name
= name
;
8223 protocol
->short_name
= short_name
;
8224 protocol
->filter_name
= filter_name
;
8225 protocol
->fields
= NULL
; /* Delegate until actually needed */
8226 protocol
->is_enabled
= true; /* protocol is enabled by default */
8227 protocol
->enabled_by_default
= true; /* see previous comment */
8228 protocol
->can_toggle
= true;
8229 protocol
->parent_proto_id
= -1;
8230 protocol
->heur_list
= NULL
;
8232 /* List will be sorted later by name, when all protocols completed registering */
8233 protocols
= g_list_prepend(protocols
, protocol
);
8234 g_hash_table_insert(proto_names
, (void *)name
, protocol
);
8235 g_hash_table_insert(proto_filter_names
, (void *)filter_name
, protocol
);
8236 g_hash_table_insert(proto_short_names
, (void *)short_name
, protocol
);
8238 /* Here we allocate a new header_field_info struct */
8239 hfinfo
= g_slice_new(header_field_info
);
8240 hfinfo
->name
= name
;
8241 hfinfo
->abbrev
= filter_name
;
8242 hfinfo
->type
= FT_PROTOCOL
;
8243 hfinfo
->display
= BASE_NONE
;
8244 hfinfo
->strings
= protocol
;
8245 hfinfo
->bitmask
= 0;
8246 hfinfo
->ref_type
= HF_REF_TYPE_NONE
;
8247 hfinfo
->blurb
= NULL
;
8248 hfinfo
->parent
= -1; /* This field differentiates protos and fields */
8250 protocol
->proto_id
= proto_register_field_init(hfinfo
, hfinfo
->parent
);
8251 return protocol
->proto_id
;
8255 proto_register_protocol_in_name_only(const char *name
, const char *short_name
, const char *filter_name
, int parent_proto
, enum ftenum field_type
)
8257 protocol_t
*protocol
;
8258 header_field_info
*hfinfo
;
8261 * Helper protocols don't need the strict rules as a "regular" protocol
8262 * Just register it in a list and make a hf_ field from it
8264 if ((field_type
!= FT_PROTOCOL
) && (field_type
!= FT_BYTES
)) {
8265 REPORT_DISSECTOR_BUG("Pino \"%s\" must be of type FT_PROTOCOL or FT_BYTES.", name
);
8268 if (parent_proto
<= 0) {
8269 REPORT_DISSECTOR_BUG("Must have a valid parent protocol for helper protocol \"%s\"!"
8270 " This might be caused by an inappropriate plugin or a development error.", name
);
8273 check_protocol_filter_name_or_fail(filter_name
);
8275 /* Add this protocol to the list of helper protocols (just so it can be properly freed) */
8276 protocol
= g_new(protocol_t
, 1);
8277 protocol
->name
= name
;
8278 protocol
->short_name
= short_name
;
8279 protocol
->filter_name
= filter_name
;
8280 protocol
->fields
= NULL
; /* Delegate until actually needed */
8282 /* Enabling and toggling is really determined by parent protocol,
8283 but provide default values here */
8284 protocol
->is_enabled
= true;
8285 protocol
->enabled_by_default
= true;
8286 protocol
->can_toggle
= true;
8288 protocol
->parent_proto_id
= parent_proto
;
8289 protocol
->heur_list
= NULL
;
8291 /* List will be sorted later by name, when all protocols completed registering */
8292 protocols
= g_list_prepend(protocols
, protocol
);
8294 /* Here we allocate a new header_field_info struct */
8295 hfinfo
= g_slice_new(header_field_info
);
8296 hfinfo
->name
= name
;
8297 hfinfo
->abbrev
= filter_name
;
8298 hfinfo
->type
= field_type
;
8299 hfinfo
->display
= BASE_NONE
;
8300 if (field_type
== FT_BYTES
) {
8301 hfinfo
->display
|= (BASE_NO_DISPLAY_VALUE
|BASE_PROTOCOL_INFO
);
8303 hfinfo
->strings
= protocol
;
8304 hfinfo
->bitmask
= 0;
8305 hfinfo
->ref_type
= HF_REF_TYPE_NONE
;
8306 hfinfo
->blurb
= NULL
;
8307 hfinfo
->parent
= -1; /* This field differentiates protos and fields */
8309 protocol
->proto_id
= proto_register_field_init(hfinfo
, hfinfo
->parent
);
8310 return protocol
->proto_id
;
8314 proto_deregister_protocol(const char *short_name
)
8316 protocol_t
*protocol
;
8317 header_field_info
*hfinfo
;
8321 proto_id
= proto_get_id_by_short_name(short_name
);
8322 protocol
= find_protocol_by_id(proto_id
);
8323 if (protocol
== NULL
)
8326 g_hash_table_remove(proto_names
, protocol
->name
);
8327 g_hash_table_remove(proto_short_names
, (void *)short_name
);
8328 g_hash_table_remove(proto_filter_names
, (void *)protocol
->filter_name
);
8330 if (protocol
->fields
) {
8331 for (i
= 0; i
< protocol
->fields
->len
; i
++) {
8332 hfinfo
= (header_field_info
*)g_ptr_array_index(protocol
->fields
, i
);
8333 hfinfo_remove_from_gpa_name_map(hfinfo
);
8334 expert_deregister_expertinfo(hfinfo
->abbrev
);
8335 g_ptr_array_add(deregistered_fields
, gpa_hfinfo
.hfi
[hfinfo
->id
]);
8337 g_ptr_array_free(protocol
->fields
, true);
8338 protocol
->fields
= NULL
;
8341 g_list_free(protocol
->heur_list
);
8343 /* Remove this protocol from the list of known protocols */
8344 protocols
= g_list_remove(protocols
, protocol
);
8346 g_ptr_array_add(deregistered_fields
, gpa_hfinfo
.hfi
[proto_id
]);
8347 g_hash_table_steal(gpa_name_map
, protocol
->filter_name
);
8349 g_free(last_field_name
);
8350 last_field_name
= NULL
;
8356 proto_register_alias(const int proto_id
, const char *alias_name
)
8358 protocol_t
*protocol
;
8360 protocol
= find_protocol_by_id(proto_id
);
8361 if (alias_name
&& protocol
) {
8362 g_hash_table_insert(gpa_protocol_aliases
, (void *) alias_name
, (void *)protocol
->filter_name
);
8367 * Routines to use to iterate over the protocols.
8368 * The argument passed to the iterator routines is an opaque cookie to
8369 * their callers; it's the GList pointer for the current element in
8371 * The ID of the protocol is returned, or -1 if there is no protocol.
8374 proto_get_first_protocol(void **cookie
)
8376 protocol_t
*protocol
;
8378 if (protocols
== NULL
)
8380 *cookie
= protocols
;
8381 protocol
= (protocol_t
*)protocols
->data
;
8382 return protocol
->proto_id
;
8386 proto_get_data_protocol(void *cookie
)
8388 GList
*list_item
= (GList
*)cookie
;
8390 protocol_t
*protocol
= (protocol_t
*)list_item
->data
;
8391 return protocol
->proto_id
;
8395 proto_get_next_protocol(void **cookie
)
8397 GList
*list_item
= (GList
*)*cookie
;
8398 protocol_t
*protocol
;
8400 list_item
= g_list_next(list_item
);
8401 if (list_item
== NULL
)
8403 *cookie
= list_item
;
8404 protocol
= (protocol_t
*)list_item
->data
;
8405 return protocol
->proto_id
;
8409 proto_get_first_protocol_field(const int proto_id
, void **cookie
)
8411 protocol_t
*protocol
= find_protocol_by_id(proto_id
);
8413 if ((protocol
== NULL
) || (protocol
->fields
== NULL
) || (protocol
->fields
->len
== 0))
8416 *cookie
= GUINT_TO_POINTER(0);
8417 return (header_field_info
*)g_ptr_array_index(protocol
->fields
, 0);
8421 proto_get_next_protocol_field(const int proto_id
, void **cookie
)
8423 protocol_t
*protocol
= find_protocol_by_id(proto_id
);
8424 unsigned i
= GPOINTER_TO_UINT(*cookie
);
8428 if ((protocol
->fields
== NULL
) || (i
>= protocol
->fields
->len
))
8431 *cookie
= GUINT_TO_POINTER(i
);
8432 return (header_field_info
*)g_ptr_array_index(protocol
->fields
, i
);
8436 find_protocol_by_id(const int proto_id
)
8438 header_field_info
*hfinfo
;
8443 PROTO_REGISTRAR_GET_NTH(proto_id
, hfinfo
);
8444 if (hfinfo
->type
!= FT_PROTOCOL
) {
8445 DISSECTOR_ASSERT(hfinfo
->display
& BASE_PROTOCOL_INFO
);
8447 return (protocol_t
*)hfinfo
->strings
;
8451 proto_get_id(const protocol_t
*protocol
)
8453 return protocol
->proto_id
;
8457 proto_name_already_registered(const char *name
)
8459 DISSECTOR_ASSERT_HINT(name
, "No name present");
8461 if (g_hash_table_lookup(proto_names
, name
) != NULL
)
8467 proto_get_id_by_filter_name(const char *filter_name
)
8469 const protocol_t
*protocol
= NULL
;
8471 DISSECTOR_ASSERT_HINT(filter_name
, "No filter name present");
8473 protocol
= (const protocol_t
*)g_hash_table_lookup(proto_filter_names
, filter_name
);
8475 if (protocol
== NULL
)
8477 return protocol
->proto_id
;
8481 proto_get_id_by_short_name(const char *short_name
)
8483 const protocol_t
*protocol
= NULL
;
8485 DISSECTOR_ASSERT_HINT(short_name
, "No short name present");
8487 protocol
= (const protocol_t
*)g_hash_table_lookup(proto_short_names
, short_name
);
8489 if (protocol
== NULL
)
8491 return protocol
->proto_id
;
8495 proto_get_protocol_name(const int proto_id
)
8497 protocol_t
*protocol
;
8499 protocol
= find_protocol_by_id(proto_id
);
8501 if (protocol
== NULL
)
8503 return protocol
->name
;
8507 proto_get_protocol_short_name(const protocol_t
*protocol
)
8509 if (protocol
== NULL
)
8511 return protocol
->short_name
;
8515 proto_get_protocol_long_name(const protocol_t
*protocol
)
8517 if (protocol
== NULL
)
8519 return protocol
->name
;
8523 proto_get_protocol_filter_name(const int proto_id
)
8525 protocol_t
*protocol
;
8527 protocol
= find_protocol_by_id(proto_id
);
8528 if (protocol
== NULL
)
8530 return protocol
->filter_name
;
8533 void proto_add_heuristic_dissector(protocol_t
*protocol
, const char *short_name
)
8535 heur_dtbl_entry_t
* heuristic_dissector
;
8537 if (protocol
== NULL
)
8540 heuristic_dissector
= find_heur_dissector_by_unique_short_name(short_name
);
8541 if (heuristic_dissector
!= NULL
)
8543 protocol
->heur_list
= g_list_prepend (protocol
->heur_list
, heuristic_dissector
);
8547 void proto_heuristic_dissector_foreach(const protocol_t
*protocol
, GFunc func
, void *user_data
)
8549 if (protocol
== NULL
)
8552 g_list_foreach(protocol
->heur_list
, func
, user_data
);
8556 proto_get_frame_protocols(const wmem_list_t
*layers
, bool *is_ip
,
8557 bool *is_tcp
, bool *is_udp
,
8558 bool *is_sctp
, bool *is_tls
,
8562 wmem_list_frame_t
*protos
= wmem_list_head(layers
);
8564 const char *proto_name
;
8566 /* Walk the list of a available protocols in the packet and
8567 attempt to find "major" ones. */
8568 /* It might make more sense to assemble and return a bitfield. */
8569 while (protos
!= NULL
)
8571 proto_id
= GPOINTER_TO_INT(wmem_list_frame_data(protos
));
8572 proto_name
= proto_get_protocol_filter_name(proto_id
);
8574 if (is_ip
&& ((!strcmp(proto_name
, "ip")) ||
8575 (!strcmp(proto_name
, "ipv6")))) {
8577 } else if (is_tcp
&& !strcmp(proto_name
, "tcp")) {
8579 } else if (is_udp
&& !strcmp(proto_name
, "udp")) {
8581 } else if (is_sctp
&& !strcmp(proto_name
, "sctp")) {
8583 } else if (is_tls
&& !strcmp(proto_name
, "tls")) {
8585 } else if (is_rtp
&& !strcmp(proto_name
, "rtp")) {
8587 } else if (is_lte_rlc
&& (!strcmp(proto_name
, "rlc-lte") || !strcmp(proto_name
, "rlc-nr"))) {
8591 protos
= wmem_list_frame_next(protos
);
8596 proto_is_frame_protocol(const wmem_list_t
*layers
, const char* proto_name
)
8598 wmem_list_frame_t
*protos
= wmem_list_head(layers
);
8602 /* Walk the list of a available protocols in the packet and
8603 attempt to find the specified protocol. */
8604 while (protos
!= NULL
)
8606 proto_id
= GPOINTER_TO_INT(wmem_list_frame_data(protos
));
8607 name
= proto_get_protocol_filter_name(proto_id
);
8609 if (!strcmp(name
, proto_name
))
8614 protos
= wmem_list_frame_next(protos
);
8621 proto_list_layers(const packet_info
*pinfo
)
8624 wmem_list_frame_t
*layers
= wmem_list_head(pinfo
->layers
);
8626 buf
= wmem_strbuf_new_sized(pinfo
->pool
, 128);
8628 /* Walk the list of layers in the packet and
8629 return a string of all entries. */
8630 while (layers
!= NULL
)
8632 wmem_strbuf_append(buf
, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(layers
))));
8634 layers
= wmem_list_frame_next(layers
);
8635 if (layers
!= NULL
) {
8636 wmem_strbuf_append_c(buf
, ':');
8640 return wmem_strbuf_finalize(buf
);
8644 proto_is_pino(const protocol_t
*protocol
)
8646 return (protocol
->parent_proto_id
!= -1);
8650 // NOLINTNEXTLINE(misc-no-recursion)
8651 proto_is_protocol_enabled(const protocol_t
*protocol
)
8653 if (protocol
== NULL
)
8656 //parent protocol determines enable/disable for helper dissectors
8657 if (proto_is_pino(protocol
))
8658 return proto_is_protocol_enabled(find_protocol_by_id(protocol
->parent_proto_id
));
8660 return protocol
->is_enabled
;
8664 // NOLINTNEXTLINE(misc-no-recursion)
8665 proto_is_protocol_enabled_by_default(const protocol_t
*protocol
)
8667 //parent protocol determines enable/disable for helper dissectors
8668 if (proto_is_pino(protocol
))
8669 return proto_is_protocol_enabled_by_default(find_protocol_by_id(protocol
->parent_proto_id
));
8671 return protocol
->enabled_by_default
;
8675 // NOLINTNEXTLINE(misc-no-recursion)
8676 proto_can_toggle_protocol(const int proto_id
)
8678 protocol_t
*protocol
;
8680 protocol
= find_protocol_by_id(proto_id
);
8681 //parent protocol determines toggling for helper dissectors
8682 if (proto_is_pino(protocol
))
8683 return proto_can_toggle_protocol(protocol
->parent_proto_id
);
8685 return protocol
->can_toggle
;
8689 proto_disable_by_default(const int proto_id
)
8691 protocol_t
*protocol
;
8693 protocol
= find_protocol_by_id(proto_id
);
8694 DISSECTOR_ASSERT(protocol
->can_toggle
);
8695 DISSECTOR_ASSERT(proto_is_pino(protocol
) == false);
8696 protocol
->is_enabled
= false;
8697 protocol
->enabled_by_default
= false;
8701 proto_set_decoding(const int proto_id
, const bool enabled
)
8703 protocol_t
*protocol
;
8705 protocol
= find_protocol_by_id(proto_id
);
8706 DISSECTOR_ASSERT(protocol
->can_toggle
);
8707 DISSECTOR_ASSERT(proto_is_pino(protocol
) == false);
8708 protocol
->is_enabled
= enabled
;
8712 proto_disable_all(void)
8714 /* This doesn't explicitly disable heuristic protocols,
8715 * but the heuristic doesn't get called if the parent
8716 * protocol isn't enabled.
8718 protocol_t
*protocol
;
8719 GList
*list_item
= protocols
;
8721 if (protocols
== NULL
)
8725 protocol
= (protocol_t
*)list_item
->data
;
8726 if (protocol
->can_toggle
) {
8727 protocol
->is_enabled
= false;
8729 list_item
= g_list_next(list_item
);
8734 heur_reenable_cb(void *data
, void *user_data _U_
)
8736 heur_dtbl_entry_t
*heur
= (heur_dtbl_entry_t
*)data
;
8738 heur
->enabled
= heur
->enabled_by_default
;
8742 proto_reenable_all(void)
8744 protocol_t
*protocol
;
8745 GList
*list_item
= protocols
;
8747 if (protocols
== NULL
)
8751 protocol
= (protocol_t
*)list_item
->data
;
8752 if (protocol
->can_toggle
)
8753 protocol
->is_enabled
= protocol
->enabled_by_default
;
8754 proto_heuristic_dissector_foreach(protocol
, heur_reenable_cb
, NULL
);
8755 list_item
= g_list_next(list_item
);
8760 proto_set_cant_toggle(const int proto_id
)
8762 protocol_t
*protocol
;
8764 protocol
= find_protocol_by_id(proto_id
);
8765 protocol
->can_toggle
= false;
8769 proto_register_field_common(protocol_t
*proto
, header_field_info
*hfi
, const int parent
)
8771 if (proto
!= NULL
) {
8772 g_ptr_array_add(proto
->fields
, hfi
);
8775 return proto_register_field_init(hfi
, parent
);
8778 /* for use with static arrays only, since we don't allocate our own copies
8779 of the header_field_info struct contained within the hf_register_info struct */
8781 proto_register_field_array(const int parent
, hf_register_info
*hf
, const int num_records
)
8783 hf_register_info
*ptr
= hf
;
8787 proto
= find_protocol_by_id(parent
);
8789 if (proto
->fields
== NULL
) {
8790 proto
->fields
= g_ptr_array_sized_new(num_records
);
8793 for (i
= 0; i
< num_records
; i
++, ptr
++) {
8795 * Make sure we haven't registered this yet.
8796 * Most fields have variables associated with them
8797 * that are initialized to -1; some have array elements,
8798 * or possibly uninitialized variables, so we also allow
8799 * 0 (which is unlikely to be the field ID we get back
8800 * from "proto_register_field_init()").
8802 if (*ptr
->p_id
!= -1 && *ptr
->p_id
!= 0) {
8803 REPORT_DISSECTOR_BUG(
8804 "Duplicate field detected in call to proto_register_field_array: %s is already registered",
8805 ptr
->hfinfo
.abbrev
);
8809 *ptr
->p_id
= proto_register_field_common(proto
, &ptr
->hfinfo
, parent
);
8813 /* deregister already registered fields */
8815 proto_deregister_field (const int parent
, int hf_id
)
8817 header_field_info
*hfi
;
8821 g_free(last_field_name
);
8822 last_field_name
= NULL
;
8824 if (hf_id
== -1 || hf_id
== 0)
8827 proto
= find_protocol_by_id (parent
);
8828 if (!proto
|| proto
->fields
== NULL
) {
8832 for (i
= 0; i
< proto
->fields
->len
; i
++) {
8833 hfi
= (header_field_info
*)g_ptr_array_index(proto
->fields
, i
);
8834 if (hfi
->id
== hf_id
) {
8835 /* Found the hf_id in this protocol */
8836 g_hash_table_steal(gpa_name_map
, hfi
->abbrev
);
8837 g_ptr_array_remove_index_fast(proto
->fields
, i
);
8838 g_ptr_array_add(deregistered_fields
, gpa_hfinfo
.hfi
[hf_id
]);
8845 proto_add_deregistered_data (void *data
)
8847 g_ptr_array_add(deregistered_data
, data
);
8851 proto_add_deregistered_slice (size_t block_size
, void *mem_block
)
8853 struct g_slice_data
*slice_data
= g_slice_new(struct g_slice_data
);
8855 slice_data
->block_size
= block_size
;
8856 slice_data
->mem_block
= mem_block
;
8858 g_ptr_array_add(deregistered_slice
, slice_data
);
8861 void proto_free_field_strings (ftenum_t field_type
, unsigned int field_display
, const void *field_strings
)
8863 if (field_strings
== NULL
) {
8867 switch (field_type
) {
8869 /* This is just an integer represented as a pointer */
8872 protocol_t
*protocol
= (protocol_t
*)field_strings
;
8873 g_free((char *)protocol
->short_name
);
8877 true_false_string
*tf
= (true_false_string
*)field_strings
;
8878 g_free((char *)tf
->true_string
);
8879 g_free((char *)tf
->false_string
);
8890 if (field_display
& BASE_UNIT_STRING
) {
8891 unit_name_string
*unit
= (unit_name_string
*)field_strings
;
8892 g_free((char *)unit
->singular
);
8893 g_free((char *)unit
->plural
);
8894 } else if (field_display
& BASE_RANGE_STRING
) {
8895 range_string
*rs
= (range_string
*)field_strings
;
8896 while (rs
->strptr
) {
8897 g_free((char *)rs
->strptr
);
8900 } else if (field_display
& BASE_EXT_STRING
) {
8901 val64_string_ext
*vse
= (val64_string_ext
*)field_strings
;
8902 val64_string
*vs
= (val64_string
*)vse
->_vs_p
;
8903 while (vs
->strptr
) {
8904 g_free((char *)vs
->strptr
);
8907 val64_string_ext_free(vse
);
8908 field_strings
= NULL
;
8909 } else if (field_display
== BASE_CUSTOM
) {
8910 /* this will be a pointer to a function, don't free that */
8911 field_strings
= NULL
;
8913 val64_string
*vs64
= (val64_string
*)field_strings
;
8914 while (vs64
->strptr
) {
8915 g_free((char *)vs64
->strptr
);
8932 if (field_display
& BASE_UNIT_STRING
) {
8933 unit_name_string
*unit
= (unit_name_string
*)field_strings
;
8934 g_free((char *)unit
->singular
);
8935 g_free((char *)unit
->plural
);
8936 } else if (field_display
& BASE_RANGE_STRING
) {
8937 range_string
*rs
= (range_string
*)field_strings
;
8938 while (rs
->strptr
) {
8939 g_free((char *)rs
->strptr
);
8942 } else if (field_display
& BASE_EXT_STRING
) {
8943 value_string_ext
*vse
= (value_string_ext
*)field_strings
;
8944 value_string
*vs
= (value_string
*)vse
->_vs_p
;
8945 while (vs
->strptr
) {
8946 g_free((char *)vs
->strptr
);
8949 value_string_ext_free(vse
);
8950 field_strings
= NULL
;
8951 } else if (field_display
== BASE_CUSTOM
) {
8952 /* this will be a pointer to a function, don't free that */
8953 field_strings
= NULL
;
8955 value_string
*vs
= (value_string
*)field_strings
;
8956 while (vs
->strptr
) {
8957 g_free((char *)vs
->strptr
);
8967 if (field_type
!= FT_FRAMENUM
) {
8968 g_free((void *)field_strings
);
8973 free_deregistered_field (void *data
, void *user_data _U_
)
8975 header_field_info
*hfi
= (header_field_info
*) data
;
8976 int hf_id
= hfi
->id
;
8978 g_free((char *)hfi
->name
);
8979 g_free((char *)hfi
->abbrev
);
8980 g_free((char *)hfi
->blurb
);
8982 proto_free_field_strings(hfi
->type
, hfi
->display
, hfi
->strings
);
8984 if (hfi
->parent
== -1)
8985 g_slice_free(header_field_info
, hfi
);
8987 gpa_hfinfo
.hfi
[hf_id
] = NULL
; /* Invalidate this hf_id / proto_id */
8991 free_deregistered_data (void *data
, void *user_data _U_
)
8997 free_deregistered_slice (void *data
, void *user_data _U_
)
8999 struct g_slice_data
*slice_data
= (struct g_slice_data
*)data
;
9001 g_slice_free1(slice_data
->block_size
, slice_data
->mem_block
);
9002 g_slice_free(struct g_slice_data
, slice_data
);
9005 /* free deregistered fields and data */
9007 proto_free_deregistered_fields (void)
9009 expert_free_deregistered_expertinfos();
9011 g_ptr_array_foreach(deregistered_fields
, free_deregistered_field
, NULL
);
9012 g_ptr_array_free(deregistered_fields
, true);
9013 deregistered_fields
= g_ptr_array_new();
9015 g_ptr_array_foreach(deregistered_data
, free_deregistered_data
, NULL
);
9016 g_ptr_array_free(deregistered_data
, true);
9017 deregistered_data
= g_ptr_array_new();
9019 g_ptr_array_foreach(deregistered_slice
, free_deregistered_slice
, NULL
);
9020 g_ptr_array_free(deregistered_slice
, true);
9021 deregistered_slice
= g_ptr_array_new();
9024 static const value_string hf_display
[] = {
9025 { BASE_NONE
, "BASE_NONE" },
9026 { BASE_DEC
, "BASE_DEC" },
9027 { BASE_HEX
, "BASE_HEX" },
9028 { BASE_OCT
, "BASE_OCT" },
9029 { BASE_DEC_HEX
, "BASE_DEC_HEX" },
9030 { BASE_HEX_DEC
, "BASE_HEX_DEC" },
9031 { BASE_CUSTOM
, "BASE_CUSTOM" },
9032 { BASE_NONE
|BASE_RANGE_STRING
, "BASE_NONE|BASE_RANGE_STRING" },
9033 { BASE_DEC
|BASE_RANGE_STRING
, "BASE_DEC|BASE_RANGE_STRING" },
9034 { BASE_HEX
|BASE_RANGE_STRING
, "BASE_HEX|BASE_RANGE_STRING" },
9035 { BASE_OCT
|BASE_RANGE_STRING
, "BASE_OCT|BASE_RANGE_STRING" },
9036 { BASE_DEC_HEX
|BASE_RANGE_STRING
, "BASE_DEC_HEX|BASE_RANGE_STRING" },
9037 { BASE_HEX_DEC
|BASE_RANGE_STRING
, "BASE_HEX_DEC|BASE_RANGE_STRING" },
9038 { BASE_CUSTOM
|BASE_RANGE_STRING
, "BASE_CUSTOM|BASE_RANGE_STRING" },
9039 { BASE_NONE
|BASE_VAL64_STRING
, "BASE_NONE|BASE_VAL64_STRING" },
9040 { BASE_DEC
|BASE_VAL64_STRING
, "BASE_DEC|BASE_VAL64_STRING" },
9041 { BASE_HEX
|BASE_VAL64_STRING
, "BASE_HEX|BASE_VAL64_STRING" },
9042 { BASE_OCT
|BASE_VAL64_STRING
, "BASE_OCT|BASE_VAL64_STRING" },
9043 { BASE_DEC_HEX
|BASE_VAL64_STRING
, "BASE_DEC_HEX|BASE_VAL64_STRING" },
9044 { BASE_HEX_DEC
|BASE_VAL64_STRING
, "BASE_HEX_DEC|BASE_VAL64_STRING" },
9045 { BASE_CUSTOM
|BASE_VAL64_STRING
, "BASE_CUSTOM|BASE_VAL64_STRING" },
9046 { ABSOLUTE_TIME_LOCAL
, "ABSOLUTE_TIME_LOCAL" },
9047 { ABSOLUTE_TIME_UTC
, "ABSOLUTE_TIME_UTC" },
9048 { ABSOLUTE_TIME_DOY_UTC
, "ABSOLUTE_TIME_DOY_UTC" },
9049 { BASE_PT_UDP
, "BASE_PT_UDP" },
9050 { BASE_PT_TCP
, "BASE_PT_TCP" },
9051 { BASE_PT_DCCP
, "BASE_PT_DCCP" },
9052 { BASE_PT_SCTP
, "BASE_PT_SCTP" },
9053 { BASE_OUI
, "BASE_OUI" },
9056 const char* proto_field_display_to_string(int field_display
)
9058 return val_to_str_const(field_display
, hf_display
, "Unknown");
9061 static inline port_type
9062 display_to_port_type(field_display_e e
)
9079 /* temporary function containing assert part for easier profiling */
9081 tmp_fld_check_assert(header_field_info
*hfinfo
)
9085 /* The field must have a name (with length > 0) */
9086 if (!hfinfo
->name
|| !hfinfo
->name
[0]) {
9088 /* Try to identify the field */
9089 REPORT_DISSECTOR_BUG("Field (abbrev='%s') does not have a name",
9093 REPORT_DISSECTOR_BUG("Field does not have a name (nor an abbreviation)");
9096 /* fields with an empty string for an abbreviation aren't filterable */
9097 if (!hfinfo
->abbrev
|| !hfinfo
->abbrev
[0])
9098 REPORT_DISSECTOR_BUG("Field '%s' does not have an abbreviation", hfinfo
->name
);
9100 /* These types of fields are allowed to have value_strings,
9101 * true_false_strings or a protocol_t struct
9103 if (hfinfo
->strings
!= NULL
&& FIELD_DISPLAY(hfinfo
->display
) != BASE_CUSTOM
) {
9104 switch (hfinfo
->type
) {
9107 * These types are allowed to support display value_strings,
9108 * value64_strings, the extended versions of the previous
9109 * two, range strings, or unit strings.
9133 * This is allowed to have a value of type
9134 * enum ft_framenum_type to indicate what relationship
9135 * the frame in question has to the frame in which
9142 * These types are allowed to support only unit strings.
9146 if (!(hfinfo
->display
& BASE_UNIT_STRING
)) {
9147 REPORT_DISSECTOR_BUG("Field '%s' (%s) has a non-unit-strings 'strings' value but is of type %s"
9148 " (which is only allowed to have unit strings)",
9149 hfinfo
->name
, hfinfo
->abbrev
, ftype_name(hfinfo
->type
));
9154 * This type is only allowed to support a string if it's
9155 * a protocol (for pinos).
9158 if (!(hfinfo
->display
& BASE_PROTOCOL_INFO
)) {
9159 REPORT_DISSECTOR_BUG("Field '%s' (%s) has a non-protocol-info 'strings' value but is of type %s"
9160 " (which is only allowed to have protocol-info strings)",
9161 hfinfo
->name
, hfinfo
->abbrev
, ftype_name(hfinfo
->type
));
9166 REPORT_DISSECTOR_BUG("Field '%s' (%s) has a 'strings' value but is of type %s"
9167 " (which is not allowed to have strings)",
9168 hfinfo
->name
, hfinfo
->abbrev
, ftype_name(hfinfo
->type
));
9172 /* TODO: This check may slow down startup, and output quite a few warnings.
9173 It would be good to be able to enable this (and possibly other checks?)
9174 in non-release builds. */
9175 #ifdef ENABLE_CHECK_FILTER
9176 /* Check for duplicate value_string values.
9177 There are lots that have the same value *and* string, so for now only
9178 report those that have same value but different string. */
9179 if ((hfinfo
->strings
!= NULL
) &&
9180 !(hfinfo
->display
& BASE_RANGE_STRING
) &&
9181 !(hfinfo
->display
& BASE_UNIT_STRING
) &&
9182 !((hfinfo
->display
& FIELD_DISPLAY_E_MASK
) == BASE_CUSTOM
) &&
9184 (hfinfo
->type
== FT_CHAR
) ||
9185 (hfinfo
->type
== FT_UINT8
) ||
9186 (hfinfo
->type
== FT_UINT16
) ||
9187 (hfinfo
->type
== FT_UINT24
) ||
9188 (hfinfo
->type
== FT_UINT32
) ||
9189 (hfinfo
->type
== FT_INT8
) ||
9190 (hfinfo
->type
== FT_INT16
) ||
9191 (hfinfo
->type
== FT_INT24
) ||
9192 (hfinfo
->type
== FT_INT32
) )) {
9194 if (hfinfo
->display
& BASE_EXT_STRING
) {
9195 if (hfinfo
->display
& BASE_VAL64_STRING
) {
9196 const val64_string
*start_values
= VAL64_STRING_EXT_VS_P((const val64_string_ext
*)hfinfo
->strings
);
9197 CHECK_HF_VALUE(val64_string
, PRIu64
, start_values
);
9199 const value_string
*start_values
= VALUE_STRING_EXT_VS_P((const value_string_ext
*)hfinfo
->strings
);
9200 CHECK_HF_VALUE(value_string
, "u", start_values
);
9203 const value_string
*start_values
= (const value_string
*)hfinfo
->strings
;
9204 CHECK_HF_VALUE(value_string
, "u", start_values
);
9208 if (hfinfo
->type
== FT_BOOLEAN
) {
9209 const true_false_string
*tfs
= (const true_false_string
*)hfinfo
->strings
;
9211 if (strcmp(tfs
->false_string
, tfs
->true_string
) == 0) {
9212 ws_warning("Field '%s' (%s) has identical true and false strings (\"%s\", \"%s\")",
9213 hfinfo
->name
, hfinfo
->abbrev
,
9214 tfs
->false_string
, tfs
->true_string
);
9219 if (hfinfo
->display
& BASE_RANGE_STRING
) {
9220 const range_string
*rs
= (const range_string
*)(hfinfo
->strings
);
9222 const range_string
*this_it
= rs
;
9225 if (this_it
->value_max
< this_it
->value_min
) {
9226 ws_warning("value_range_string error: %s (%s) entry for \"%s\" - max(%"PRIu64
" 0x%"PRIx64
") is less than min(%"PRIu64
" 0x%"PRIx64
")",
9227 hfinfo
->name
, hfinfo
->abbrev
,
9229 this_it
->value_max
, this_it
->value_max
,
9230 this_it
->value_min
, this_it
->value_min
);
9235 for (const range_string
*prev_it
=rs
; prev_it
< this_it
; ++prev_it
) {
9236 /* Not OK if this one is completely hidden by an earlier one! */
9237 if ((prev_it
->value_min
<= this_it
->value_min
) && (prev_it
->value_max
>= this_it
->value_max
)) {
9238 ws_warning("value_range_string error: %s (%s) hidden by earlier entry "
9239 "(prev=\"%s\": %"PRIu64
" 0x%"PRIx64
" -> %"PRIu64
" 0x%"PRIx64
") (this=\"%s\": %"PRIu64
" 0x%"PRIx64
" -> %"PRIu64
" 0x%"PRIx64
")",
9240 hfinfo
->name
, hfinfo
->abbrev
,
9241 prev_it
->strptr
, prev_it
->value_min
, prev_it
->value_min
,
9242 prev_it
->value_max
, prev_it
->value_max
,
9243 this_it
->strptr
, this_it
->value_min
, this_it
->value_min
,
9244 this_it
->value_max
, this_it
->value_max
);
9248 } while (this_it
->strptr
);
9253 switch (hfinfo
->type
) {
9256 /* Require the char type to have BASE_HEX, BASE_OCT,
9257 * BASE_CUSTOM, or BASE_NONE as its base.
9259 * If the display value is BASE_NONE and there is a
9260 * strings conversion then the dissector writer is
9261 * telling us that the field's numerical value is
9262 * meaningless; we'll avoid showing the value to the
9265 switch (FIELD_DISPLAY(hfinfo
->display
)) {
9268 case BASE_CUSTOM
: /* hfinfo_numeric_value_format() treats this as decimal */
9271 if (hfinfo
->strings
== NULL
)
9272 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an integral value (%s)"
9273 " but is being displayed as BASE_NONE but"
9274 " without a strings conversion",
9275 hfinfo
->name
, hfinfo
->abbrev
,
9276 ftype_name(hfinfo
->type
));
9279 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Unknown: 0x%x)");
9280 REPORT_DISSECTOR_BUG("Field '%s' (%s) is a character value (%s)"
9281 " but is being displayed as %s",
9282 hfinfo
->name
, hfinfo
->abbrev
,
9283 ftype_name(hfinfo
->type
), tmp_str
);
9284 //wmem_free(NULL, tmp_str);
9286 if (hfinfo
->display
& BASE_UNIT_STRING
) {
9287 REPORT_DISSECTOR_BUG("Field '%s' (%s) is a character value (%s) but has a unit string",
9288 hfinfo
->name
, hfinfo
->abbrev
,
9289 ftype_name(hfinfo
->type
));
9300 /* Hexadecimal and octal are, in printf() and everywhere
9301 * else, unsigned so don't allow dissectors to register a
9302 * signed field to be displayed unsigned. (Else how would
9303 * we display negative values?)
9305 switch (FIELD_DISPLAY(hfinfo
->display
)) {
9310 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Bit count: %d)");
9311 REPORT_DISSECTOR_BUG("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)",
9312 hfinfo
->name
, hfinfo
->abbrev
,
9313 ftype_name(hfinfo
->type
), tmp_str
);
9314 //wmem_free(NULL, tmp_str);
9325 if (IS_BASE_PORT(hfinfo
->display
)) {
9326 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Unknown: 0x%x)");
9327 if (hfinfo
->type
!= FT_UINT16
) {
9328 REPORT_DISSECTOR_BUG("Field '%s' (%s) has 'display' value %s but it can only be used with FT_UINT16, not %s",
9329 hfinfo
->name
, hfinfo
->abbrev
,
9330 tmp_str
, ftype_name(hfinfo
->type
));
9332 if (hfinfo
->strings
!= NULL
) {
9333 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s (%s) but has a strings value",
9334 hfinfo
->name
, hfinfo
->abbrev
,
9335 ftype_name(hfinfo
->type
), tmp_str
);
9337 if (hfinfo
->bitmask
!= 0) {
9338 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s (%s) but has a bitmask",
9339 hfinfo
->name
, hfinfo
->abbrev
,
9340 ftype_name(hfinfo
->type
), tmp_str
);
9342 wmem_free(NULL
, tmp_str
);
9346 if (hfinfo
->display
== BASE_OUI
) {
9347 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Unknown: 0x%x)");
9348 if (hfinfo
->type
!= FT_UINT24
) {
9349 REPORT_DISSECTOR_BUG("Field '%s' (%s) has 'display' value %s but it can only be used with FT_UINT24, not %s",
9350 hfinfo
->name
, hfinfo
->abbrev
,
9351 tmp_str
, ftype_name(hfinfo
->type
));
9353 if (hfinfo
->strings
!= NULL
) {
9354 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s (%s) but has a strings value",
9355 hfinfo
->name
, hfinfo
->abbrev
,
9356 ftype_name(hfinfo
->type
), tmp_str
);
9358 if (hfinfo
->bitmask
!= 0) {
9359 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s (%s) but has a bitmask",
9360 hfinfo
->name
, hfinfo
->abbrev
,
9361 ftype_name(hfinfo
->type
), tmp_str
);
9363 wmem_free(NULL
, tmp_str
);
9367 /* Require integral types (other than frame number,
9368 * which is always displayed in decimal) to have a
9371 * If the display value is BASE_NONE and there is a
9372 * strings conversion then the dissector writer is
9373 * telling us that the field's numerical value is
9374 * meaningless; we'll avoid showing the value to the
9377 switch (FIELD_DISPLAY(hfinfo
->display
)) {
9383 case BASE_CUSTOM
: /* hfinfo_numeric_value_format() treats this as decimal */
9386 if (hfinfo
->strings
== NULL
) {
9387 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an integral value (%s)"
9388 " but is being displayed as BASE_NONE but"
9389 " without a strings conversion",
9390 hfinfo
->name
, hfinfo
->abbrev
,
9391 ftype_name(hfinfo
->type
));
9393 if (hfinfo
->display
& BASE_SPECIAL_VALS
) {
9394 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an integral value (%s)"
9395 " that is being displayed as BASE_NONE but"
9396 " with BASE_SPECIAL_VALS",
9397 hfinfo
->name
, hfinfo
->abbrev
,
9398 ftype_name(hfinfo
->type
));
9403 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Unknown: 0x%x)");
9404 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an integral value (%s)"
9405 " but is being displayed as %s",
9406 hfinfo
->name
, hfinfo
->abbrev
,
9407 ftype_name(hfinfo
->type
), tmp_str
);
9408 //wmem_free(NULL, tmp_str);
9413 /* Require bytes to have a "display type" that could
9414 * add a character between displayed bytes.
9416 switch (FIELD_DISPLAY(hfinfo
->display
)) {
9424 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Bit count: %d)");
9425 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an byte array but is being displayed as %s instead of BASE_NONE, SEP_DOT, SEP_DASH, SEP_COLON, or SEP_SPACE",
9426 hfinfo
->name
, hfinfo
->abbrev
, tmp_str
);
9427 //wmem_free(NULL, tmp_str);
9429 if (hfinfo
->bitmask
!= 0)
9430 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9431 hfinfo
->name
, hfinfo
->abbrev
,
9432 ftype_name(hfinfo
->type
));
9433 //allowed to support string if its a protocol (for pinos)
9434 if ((hfinfo
->strings
!= NULL
) && (!(hfinfo
->display
& BASE_PROTOCOL_INFO
)))
9435 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a strings value",
9436 hfinfo
->name
, hfinfo
->abbrev
,
9437 ftype_name(hfinfo
->type
));
9442 if (hfinfo
->display
!= BASE_NONE
) {
9443 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Bit count: %d)");
9444 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE",
9445 hfinfo
->name
, hfinfo
->abbrev
,
9446 ftype_name(hfinfo
->type
), tmp_str
);
9447 //wmem_free(NULL, tmp_str);
9449 if (hfinfo
->bitmask
!= 0)
9450 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9451 hfinfo
->name
, hfinfo
->abbrev
,
9452 ftype_name(hfinfo
->type
));
9458 case FT_ABSOLUTE_TIME
:
9459 if (!FIELD_DISPLAY_IS_ABSOLUTE_TIME(hfinfo
->display
)) {
9460 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Bit count: %d)");
9461 REPORT_DISSECTOR_BUG("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time",
9462 hfinfo
->name
, hfinfo
->abbrev
, ftype_name(hfinfo
->type
), tmp_str
);
9463 //wmem_free(NULL, tmp_str);
9465 if (hfinfo
->bitmask
!= 0)
9466 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9467 hfinfo
->name
, hfinfo
->abbrev
,
9468 ftype_name(hfinfo
->type
));
9473 case FT_UINT_STRING
:
9475 case FT_STRINGZTRUNC
:
9476 switch (FIELD_DISPLAY(hfinfo
->display
)) {
9482 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Unknown: 0x%x)");
9483 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an string value (%s)"
9484 " but is being displayed as %s",
9485 hfinfo
->name
, hfinfo
->abbrev
,
9486 ftype_name(hfinfo
->type
), tmp_str
);
9487 //wmem_free(NULL, tmp_str);
9490 if (hfinfo
->bitmask
!= 0)
9491 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9492 hfinfo
->name
, hfinfo
->abbrev
,
9493 ftype_name(hfinfo
->type
));
9494 if (hfinfo
->strings
!= NULL
)
9495 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a strings value",
9496 hfinfo
->name
, hfinfo
->abbrev
,
9497 ftype_name(hfinfo
->type
));
9501 switch (hfinfo
->display
) {
9507 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Unknown: 0x%x)");
9508 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an IPv4 value (%s)"
9509 " but is being displayed as %s",
9510 hfinfo
->name
, hfinfo
->abbrev
,
9511 ftype_name(hfinfo
->type
), tmp_str
);
9512 //wmem_free(NULL, tmp_str);
9518 switch (FIELD_DISPLAY(hfinfo
->display
)) {
9526 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Unknown: 0x%x)");
9527 REPORT_DISSECTOR_BUG("Field '%s' (%s) is a float value (%s)"
9528 " but is being displayed as %s",
9529 hfinfo
->name
, hfinfo
->abbrev
,
9530 ftype_name(hfinfo
->type
), tmp_str
);
9531 //wmem_free(NULL, tmp_str);
9533 if (hfinfo
->bitmask
!= 0)
9534 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9535 hfinfo
->name
, hfinfo
->abbrev
,
9536 ftype_name(hfinfo
->type
));
9537 if (FIELD_DISPLAY(hfinfo
->display
) != BASE_CUSTOM
&& (hfinfo
->strings
!= NULL
) && !(hfinfo
->display
& BASE_UNIT_STRING
))
9538 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a strings value",
9539 hfinfo
->name
, hfinfo
->abbrev
,
9540 ftype_name(hfinfo
->type
));
9543 if (hfinfo
->display
!= BASE_NONE
) {
9544 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Bit count: %d)");
9545 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE",
9546 hfinfo
->name
, hfinfo
->abbrev
,
9547 ftype_name(hfinfo
->type
),
9549 //wmem_free(NULL, tmp_str);
9551 if (hfinfo
->bitmask
!= 0)
9552 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9553 hfinfo
->name
, hfinfo
->abbrev
,
9554 ftype_name(hfinfo
->type
));
9555 if (hfinfo
->strings
!= NULL
)
9556 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a strings value",
9557 hfinfo
->name
, hfinfo
->abbrev
,
9558 ftype_name(hfinfo
->type
));
9563 #ifdef ENABLE_CHECK_FILTER
9565 _ftype_common(enum ftenum type
)
9589 case FT_UINT_STRING
:
9602 case FT_ABSOLUTE_TIME
:
9603 case FT_RELATIVE_TIME
:
9604 return FT_ABSOLUTE_TIME
;
9613 register_type_length_mismatch(void)
9615 static ei_register_info ei
[] = {
9616 { &ei_type_length_mismatch_error
, { "_ws.type_length.mismatch", PI_MALFORMED
, PI_ERROR
, "Trying to fetch X with length Y", EXPFILL
}},
9617 { &ei_type_length_mismatch_warn
, { "_ws.type_length.mismatch", PI_MALFORMED
, PI_WARN
, "Trying to fetch X with length Y", EXPFILL
}},
9620 expert_module_t
* expert_type_length_mismatch
;
9622 proto_type_length_mismatch
= proto_register_protocol("Type Length Mismatch", "Type length mismatch", "_ws.type_length");
9624 expert_type_length_mismatch
= expert_register_protocol(proto_type_length_mismatch
);
9625 expert_register_field_array(expert_type_length_mismatch
, ei
, array_length(ei
));
9627 /* "Type Length Mismatch" isn't really a protocol, it's an error indication;
9628 disabling them makes no sense. */
9629 proto_set_cant_toggle(proto_type_length_mismatch
);
9633 register_byte_array_string_decodinws_error(void)
9635 static ei_register_info ei
[] = {
9636 { &ei_byte_array_string_decoding_failed_error
,
9637 { "_ws.byte_array_string.decoding_error.failed", PI_MALFORMED
, PI_ERROR
,
9638 "Failed to decode byte array from string", EXPFILL
9643 expert_module_t
* expert_byte_array_string_decoding_error
;
9645 proto_byte_array_string_decoding_error
=
9646 proto_register_protocol("Byte Array-String Decoding Error",
9647 "Byte Array-string decoding error",
9648 "_ws.byte_array_string.decoding_error");
9650 expert_byte_array_string_decoding_error
=
9651 expert_register_protocol(proto_byte_array_string_decoding_error
);
9652 expert_register_field_array(expert_byte_array_string_decoding_error
, ei
, array_length(ei
));
9654 /* "Byte Array-String Decoding Error" isn't really a protocol, it's an error indication;
9655 disabling them makes no sense. */
9656 proto_set_cant_toggle(proto_byte_array_string_decoding_error
);
9660 register_date_time_string_decodinws_error(void)
9662 static ei_register_info ei
[] = {
9663 { &ei_date_time_string_decoding_failed_error
,
9664 { "_ws.date_time_string.decoding_error.failed", PI_MALFORMED
, PI_ERROR
,
9665 "Failed to decode date and time from string", EXPFILL
9670 expert_module_t
* expert_date_time_string_decoding_error
;
9672 proto_date_time_string_decoding_error
=
9673 proto_register_protocol("Date and Time-String Decoding Error",
9674 "Date and Time-string decoding error",
9675 "_ws.date_time_string.decoding_error");
9677 expert_date_time_string_decoding_error
=
9678 expert_register_protocol(proto_date_time_string_decoding_error
);
9679 expert_register_field_array(expert_date_time_string_decoding_error
, ei
, array_length(ei
));
9681 /* "Date and Time-String Decoding Error" isn't really a protocol, it's an error indication;
9682 disabling them makes no sense. */
9683 proto_set_cant_toggle(proto_date_time_string_decoding_error
);
9687 register_string_errors(void)
9689 static ei_register_info ei
[] = {
9690 { &ei_string_trailing_characters
,
9691 { "_ws.string.trailing_stray_characters", PI_UNDECODED
, PI_WARN
, "Trailing stray characters", EXPFILL
}
9695 expert_module_t
* expert_string_errors
;
9697 proto_string_errors
= proto_register_protocol("String Errors", "String errors", "_ws.string");
9699 expert_string_errors
= expert_register_protocol(proto_string_errors
);
9700 expert_register_field_array(expert_string_errors
, ei
, array_length(ei
));
9702 /* "String Errors" isn't really a protocol, it's an error indication;
9703 disabling them makes no sense. */
9704 proto_set_cant_toggle(proto_string_errors
);
9707 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM (300000+PRE_ALLOC_EXPERT_FIELDS_MEM)
9709 proto_register_field_init(header_field_info
*hfinfo
, const int parent
)
9712 tmp_fld_check_assert(hfinfo
);
9714 hfinfo
->parent
= parent
;
9715 hfinfo
->same_name_next
= NULL
;
9716 hfinfo
->same_name_prev_id
= -1;
9718 /* if we always add and never delete, then id == len - 1 is correct */
9719 if (gpa_hfinfo
.len
>= gpa_hfinfo
.allocated_len
) {
9720 if (!gpa_hfinfo
.hfi
) {
9721 gpa_hfinfo
.allocated_len
= PROTO_PRE_ALLOC_HF_FIELDS_MEM
;
9722 gpa_hfinfo
.hfi
= (header_field_info
**)g_malloc(sizeof(header_field_info
*)*PROTO_PRE_ALLOC_HF_FIELDS_MEM
);
9723 /* The entry with index 0 is not used. */
9724 gpa_hfinfo
.hfi
[0] = NULL
;
9727 gpa_hfinfo
.allocated_len
+= 1000;
9728 gpa_hfinfo
.hfi
= (header_field_info
**)g_realloc(gpa_hfinfo
.hfi
,
9729 sizeof(header_field_info
*)*gpa_hfinfo
.allocated_len
);
9730 /*ws_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
9733 gpa_hfinfo
.hfi
[gpa_hfinfo
.len
] = hfinfo
;
9735 hfinfo
->id
= gpa_hfinfo
.len
- 1;
9737 /* if we have real names, enter this field in the name tree */
9738 if ((hfinfo
->name
[0] != 0) && (hfinfo
->abbrev
[0] != 0 )) {
9740 header_field_info
*same_name_next_hfinfo
;
9743 /* Check that the filter name (abbreviation) is legal;
9744 * it must contain only alphanumerics, '-', "_", and ".". */
9745 c
= proto_check_field_name(hfinfo
->abbrev
);
9748 REPORT_DISSECTOR_BUG("Invalid leading, duplicated or trailing '.' found in filter name '%s'", hfinfo
->abbrev
);
9749 } else if (g_ascii_isprint(c
)) {
9750 REPORT_DISSECTOR_BUG("Invalid character '%c' in filter name '%s'", c
, hfinfo
->abbrev
);
9752 REPORT_DISSECTOR_BUG("Invalid byte \\%03o in filter name '%s'", c
, hfinfo
->abbrev
);
9756 /* We allow multiple hfinfo's to be registered under the same
9757 * abbreviation. This was done for X.25, as, depending
9758 * on whether it's modulo-8 or modulo-128 operation,
9759 * some bitfield fields may be in different bits of
9760 * a byte, and we want to be able to refer to that field
9761 * with one name regardless of whether the packets
9762 * are modulo-8 or modulo-128 packets. */
9764 same_name_hfinfo
= NULL
;
9766 g_hash_table_insert(gpa_name_map
, (void *) (hfinfo
->abbrev
), hfinfo
);
9767 /* GLIB 2.x - if it is already present
9768 * the previous hfinfo with the same name is saved
9769 * to same_name_hfinfo by value destroy callback */
9770 if (same_name_hfinfo
) {
9771 /* There's already a field with this name.
9772 * Put the current field *before* that field
9773 * in the list of fields with this name, Thus,
9774 * we end up with an effectively
9775 * doubly-linked-list of same-named hfinfo's,
9776 * with the head of the list (stored in the
9777 * hash) being the last seen hfinfo.
9779 same_name_next_hfinfo
=
9780 same_name_hfinfo
->same_name_next
;
9782 hfinfo
->same_name_next
= same_name_next_hfinfo
;
9783 if (same_name_next_hfinfo
)
9784 same_name_next_hfinfo
->same_name_prev_id
= hfinfo
->id
;
9786 same_name_hfinfo
->same_name_next
= hfinfo
;
9787 hfinfo
->same_name_prev_id
= same_name_hfinfo
->id
;
9788 #ifdef ENABLE_CHECK_FILTER
9789 while (same_name_hfinfo
) {
9790 if (_ftype_common(hfinfo
->type
) != _ftype_common(same_name_hfinfo
->type
))
9791 ws_warning("'%s' exists multiple times with incompatible types: %s and %s", hfinfo
->abbrev
, ftype_name(hfinfo
->type
), ftype_name(same_name_hfinfo
->type
));
9792 same_name_hfinfo
= same_name_hfinfo
->same_name_next
;
9802 proto_register_subtree_array(int * const *indices
, const int num_indices
)
9805 int *const *ptr
= indices
;
9808 * If we've already allocated the array of tree types, expand
9809 * it; this lets plugins such as mate add tree types after
9810 * the initial startup. (If we haven't already allocated it,
9811 * we don't allocate it; on the first pass, we just assign
9812 * ett values and keep track of how many we've assigned, and
9813 * when we're finished registering all dissectors we allocate
9814 * the array, so that we do only one allocation rather than
9815 * wasting CPU time and memory by growing the array for each
9816 * dissector that registers ett values.)
9818 if (tree_is_expanded
!= NULL
) {
9819 tree_is_expanded
= (uint32_t *)g_realloc(tree_is_expanded
, (1+((num_tree_types
+ num_indices
)/32)) * sizeof(uint32_t));
9821 /* set new items to 0 */
9822 /* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of uint32_t to 0) */
9823 for (i
= num_tree_types
; i
< num_tree_types
+ num_indices
; i
++)
9824 tree_is_expanded
[i
>> 5] &= ~(1U << (i
& 31));
9828 * Assign "num_indices" subtree numbers starting at "num_tree_types",
9829 * returning the indices through the pointers in the array whose
9830 * first element is pointed to by "indices", and update
9831 * "num_tree_types" appropriately.
9833 for (i
= 0; i
< num_indices
; i
++, ptr
++, num_tree_types
++) {
9834 if (**ptr
!= -1 && **ptr
!= 0) {
9835 REPORT_DISSECTOR_BUG("register_subtree_array: subtree item type (ett_...) not -1 or 0 !"
9836 " This is a development error:"
9837 " Either the subtree item type has already been assigned or"
9838 " was not initialized to -1 or 0.");
9840 **ptr
= num_tree_types
;
9845 mark_truncated(char *label_str
, size_t name_pos
, const size_t size
, size_t *value_pos
)
9847 static const char trunc_str
[] = " [" UTF8_HORIZONTAL_ELLIPSIS
"]";
9848 const size_t trunc_len
= sizeof(trunc_str
)-1;
9851 /* ..... field_name: dataaaaaaaaaaaaa
9855 * ..... field_name […]: dataaaaaaaaaaaaa
9857 * name_pos==0 means that we have only data or only a field_name
9860 if (name_pos
< size
- trunc_len
) {
9861 memmove(label_str
+ name_pos
+ trunc_len
, label_str
+ name_pos
, size
- name_pos
- trunc_len
);
9862 memcpy(label_str
+ name_pos
, trunc_str
, trunc_len
);
9864 /* in general, label_str is UTF-8
9865 we can truncate it only at the beginning of a new character
9866 we go backwards from the byte right after our buffer and
9867 find the next starting byte of a UTF-8 character, this is
9869 there's no need to use g_utf8_find_prev_char(), the search
9870 will always succeed since we copied trunc_str into the
9872 /* g_utf8_prev_char does not deference the memory address
9873 * passed in (until after decrementing it, so it is perfectly
9874 * legal to pass in a pointer one past the last element.
9876 last_char
= g_utf8_prev_char(label_str
+ size
);
9879 if (value_pos
&& *value_pos
> 0) {
9880 if (name_pos
== 0) {
9881 *value_pos
+= trunc_len
;
9883 /* Move one back to include trunc_str in the value. */
9887 } else if (name_pos
< size
)
9888 (void) g_strlcpy(label_str
+ name_pos
, trunc_str
, size
- name_pos
);
9892 label_mark_truncated(char *label_str
, size_t name_pos
, size_t *value_pos
)
9894 mark_truncated(label_str
, name_pos
, ITEM_LABEL_LENGTH
, value_pos
);
9898 label_fill(char *label_str
, size_t pos
, const header_field_info
*hfinfo
, const char *text
, size_t *value_pos
)
9902 /* "%s: %s", hfinfo->name, text */
9903 name_pos
= pos
= label_concat(label_str
, pos
, hfinfo
->name
);
9904 if (!(hfinfo
->display
& BASE_NO_DISPLAY_VALUE
)) {
9905 pos
= label_concat(label_str
, pos
, ": ");
9909 pos
= ws_label_strcpy(label_str
, ITEM_LABEL_LENGTH
, pos
, text
? text
: "(null)", label_strcat_flags(hfinfo
));
9912 if (pos
>= ITEM_LABEL_LENGTH
) {
9913 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
9914 label_mark_truncated(label_str
, name_pos
, value_pos
);
9921 label_fill_descr(char *label_str
, size_t pos
, const header_field_info
*hfinfo
, const char *text
, const char *descr
, size_t *value_pos
)
9925 /* "%s: %s (%s)", hfinfo->name, text, descr */
9926 name_pos
= pos
= label_concat(label_str
, pos
, hfinfo
->name
);
9927 if (!(hfinfo
->display
& BASE_NO_DISPLAY_VALUE
)) {
9928 pos
= label_concat(label_str
, pos
, ": ");
9932 if (hfinfo
->display
& BASE_UNIT_STRING
) {
9933 pos
= label_concat(label_str
, pos
, descr
? descr
: "(null)");
9934 pos
= label_concat(label_str
, pos
, text
? text
: "(null)");
9936 pos
= label_concat(label_str
, pos
, text
? text
: "(null)");
9937 pos
= label_concat(label_str
, pos
, " (");
9938 pos
= label_concat(label_str
, pos
, descr
? descr
: "(null)");
9939 pos
= label_concat(label_str
, pos
, ")");
9943 if (pos
>= ITEM_LABEL_LENGTH
) {
9944 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
9945 label_mark_truncated(label_str
, name_pos
, value_pos
);
9952 proto_item_fill_label(const field_info
*fi
, char *label_str
, size_t *value_pos
)
9954 const header_field_info
*hfinfo
;
9956 const uint8_t *bytes
;
9959 const ipv4_addr_and_mask
*ipv4
;
9960 const ipv6_addr_and_prefix
*ipv6
;
9961 const e_guid_t
*guid
;
9968 ws_warning("NULL label_str passed to proto_item_fill_label.");
9978 hfinfo
= fi
->hfinfo
;
9980 switch (hfinfo
->type
) {
9983 (void) g_strlcpy(label_str
, hfinfo
->name
, ITEM_LABEL_LENGTH
);
9985 *value_pos
= strlen(hfinfo
->name
);
9990 fill_label_boolean(fi
, label_str
, value_pos
);
9995 tmp
= format_bytes_hfinfo(NULL
, hfinfo
,
9996 fvalue_get_bytes_data(fi
->value
),
9997 (unsigned)fvalue_length2(fi
->value
));
9998 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
9999 wmem_free(NULL
, tmp
);
10003 if (hfinfo
->bitmask
) {
10004 fill_label_bitfield_char(fi
, label_str
, value_pos
);
10006 fill_label_char(fi
, label_str
, value_pos
);
10010 /* Four types of integers to take care of:
10011 * Bitfield, with val_string
10012 * Bitfield, w/o val_string
10013 * Non-bitfield, with val_string
10014 * Non-bitfield, w/o val_string
10020 if (hfinfo
->bitmask
) {
10021 fill_label_bitfield(fi
, label_str
, value_pos
, false);
10023 fill_label_number(fi
, label_str
, value_pos
, false);
10028 fill_label_number(fi
, label_str
, value_pos
, false);
10035 if (hfinfo
->bitmask
) {
10036 fill_label_bitfield64(fi
, label_str
, value_pos
, false);
10038 fill_label_number64(fi
, label_str
, value_pos
, false);
10046 if (hfinfo
->bitmask
) {
10047 fill_label_bitfield(fi
, label_str
, value_pos
, true);
10049 fill_label_number(fi
, label_str
, value_pos
, true);
10057 if (hfinfo
->bitmask
) {
10058 fill_label_bitfield64(fi
, label_str
, value_pos
, true);
10060 fill_label_number64(fi
, label_str
, value_pos
, true);
10066 fill_label_float(fi
, label_str
, value_pos
);
10069 case FT_ABSOLUTE_TIME
:
10071 int flags
= ABS_TIME_TO_STR_SHOW_ZONE
;
10072 if (prefs
.display_abs_time_ascii
< ABS_TIME_ASCII_TREE
) {
10073 flags
|= ABS_TIME_TO_STR_ISO8601
;
10075 tmp
= abs_time_to_str_ex(NULL
, fvalue_get_time(fi
->value
), hfinfo
->display
, flags
);
10076 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10077 wmem_free(NULL
, tmp
);
10080 case FT_RELATIVE_TIME
:
10081 tmp
= rel_time_to_str(NULL
, fvalue_get_time(fi
->value
));
10082 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10083 wmem_free(NULL
, tmp
);
10087 integer
= fvalue_get_uinteger(fi
->value
);
10088 tmp
= get_ipxnet_name(NULL
, integer
);
10089 addr_str
= wmem_strdup_printf(NULL
, "0x%08X", integer
);
10090 label_fill_descr(label_str
, 0, hfinfo
, tmp
, addr_str
, value_pos
);
10091 wmem_free(NULL
, tmp
);
10092 wmem_free(NULL
, addr_str
);
10096 addr
.type
= AT_VINES
;
10097 addr
.len
= VINES_ADDR_LEN
;
10098 addr
.data
= fvalue_get_bytes_data(fi
->value
);
10100 addr_str
= (char*)address_to_str(NULL
, &addr
);
10101 label_fill(label_str
, 0, hfinfo
, addr_str
, value_pos
);
10102 wmem_free(NULL
, addr_str
);
10106 bytes
= fvalue_get_bytes_data(fi
->value
);
10108 addr
.type
= AT_ETHER
;
10112 addr_str
= (char*)address_with_resolution_to_str(NULL
, &addr
);
10113 label_fill(label_str
, 0, hfinfo
, addr_str
, value_pos
);
10114 wmem_free(NULL
, addr_str
);
10118 ipv4
= fvalue_get_ipv4(fi
->value
);
10119 set_address_ipv4(&addr
, ipv4
);
10121 if (hfinfo
->display
== BASE_NETMASK
) {
10122 addr_str
= (char*)address_to_str(NULL
, &addr
);
10124 addr_str
= (char*)address_with_resolution_to_str(NULL
, &addr
);
10126 label_fill(label_str
, 0, hfinfo
, addr_str
, value_pos
);
10127 wmem_free(NULL
, addr_str
);
10128 free_address(&addr
);
10132 ipv6
= fvalue_get_ipv6(fi
->value
);
10133 set_address_ipv6(&addr
, ipv6
);
10135 addr_str
= (char*)address_with_resolution_to_str(NULL
, &addr
);
10136 label_fill(label_str
, 0, hfinfo
, addr_str
, value_pos
);
10137 wmem_free(NULL
, addr_str
);
10138 free_address(&addr
);
10142 bytes
= fvalue_get_bytes_data(fi
->value
);
10143 addr
.type
= AT_FCWWN
;
10144 addr
.len
= FCWWN_ADDR_LEN
;
10147 addr_str
= (char*)address_with_resolution_to_str(NULL
, &addr
);
10148 label_fill(label_str
, 0, hfinfo
, addr_str
, value_pos
);
10149 wmem_free(NULL
, addr_str
);
10153 guid
= fvalue_get_guid(fi
->value
);
10154 tmp
= guid_to_str(NULL
, guid
);
10155 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10156 wmem_free(NULL
, tmp
);
10160 bytes
= fvalue_get_bytes_data(fi
->value
);
10161 name
= oid_resolved_from_encoded(NULL
, bytes
, (int)fvalue_length2(fi
->value
));
10162 tmp
= oid_encoded2string(NULL
, bytes
, (unsigned)fvalue_length2(fi
->value
));
10164 label_fill_descr(label_str
, 0, hfinfo
, tmp
, name
, value_pos
);
10165 wmem_free(NULL
, name
);
10167 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10169 wmem_free(NULL
, tmp
);
10173 bytes
= fvalue_get_bytes_data(fi
->value
);
10174 name
= rel_oid_resolved_from_encoded(NULL
, bytes
, (int)fvalue_length2(fi
->value
));
10175 tmp
= rel_oid_encoded2string(NULL
, bytes
, (unsigned)fvalue_length2(fi
->value
));
10177 label_fill_descr(label_str
, 0, hfinfo
, tmp
, name
, value_pos
);
10178 wmem_free(NULL
, name
);
10180 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10182 wmem_free(NULL
, tmp
);
10186 bytes
= fvalue_get_bytes_data(fi
->value
);
10187 tmp
= print_system_id(NULL
, bytes
, (int)fvalue_length2(fi
->value
));
10188 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10189 wmem_free(NULL
, tmp
);
10193 integer64
= fvalue_get_uinteger64(fi
->value
);
10194 addr_str
= eui64_to_str(NULL
, integer64
);
10195 tmp
= (char*)eui64_to_display(NULL
, integer64
);
10196 label_fill_descr(label_str
, 0, hfinfo
, tmp
, addr_str
, value_pos
);
10197 wmem_free(NULL
, tmp
);
10198 wmem_free(NULL
, addr_str
);
10202 case FT_UINT_STRING
:
10203 case FT_STRINGZPAD
:
10204 case FT_STRINGZTRUNC
:
10206 str
= fvalue_get_string(fi
->value
);
10207 label_fill(label_str
, 0, hfinfo
, str
, value_pos
);
10210 case FT_IEEE_11073_SFLOAT
:
10211 case FT_IEEE_11073_FLOAT
:
10212 tmp
= fvalue_to_string_repr(NULL
, fi
->value
, FTREPR_DISPLAY
, hfinfo
->display
);
10213 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10214 wmem_free(NULL
, tmp
);
10218 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_item_fill_label()",
10221 ftype_name(hfinfo
->type
));
10227 fill_label_boolean(const field_info
*fi
, char *label_str
, size_t *value_pos
)
10230 int bitfield_byte_length
= 0, bitwidth
;
10231 uint64_t unshifted_value
;
10234 const header_field_info
*hfinfo
= fi
->hfinfo
;
10236 value
= fvalue_get_uinteger64(fi
->value
);
10237 if (hfinfo
->bitmask
) {
10238 /* Figure out the bit width */
10239 bitwidth
= hfinfo_container_bitwidth(hfinfo
);
10241 /* Un-shift bits */
10242 unshifted_value
= value
;
10243 unshifted_value
<<= hfinfo_bitshift(hfinfo
);
10245 /* Create the bitfield first */
10246 p
= decode_bitfield_value(label_str
, unshifted_value
, hfinfo
->bitmask
, bitwidth
);
10247 bitfield_byte_length
= (int) (p
- label_str
);
10250 /* Fill in the textual info */
10251 label_fill(label_str
, bitfield_byte_length
, hfinfo
, tfs_get_string(!!value
, hfinfo
->strings
), value_pos
);
10254 static const char *
10255 hf_try_val_to_str(uint32_t value
, const header_field_info
*hfinfo
)
10257 if (hfinfo
->display
& BASE_RANGE_STRING
)
10258 return try_rval_to_str(value
, (const range_string
*) hfinfo
->strings
);
10260 if (hfinfo
->display
& BASE_EXT_STRING
) {
10261 if (hfinfo
->display
& BASE_VAL64_STRING
)
10262 return try_val64_to_str_ext(value
, (val64_string_ext
*) hfinfo
->strings
);
10264 return try_val_to_str_ext(value
, (value_string_ext
*) hfinfo
->strings
);
10267 if (hfinfo
->display
& BASE_VAL64_STRING
)
10268 return try_val64_to_str(value
, (const val64_string
*) hfinfo
->strings
);
10270 if (hfinfo
->display
& BASE_UNIT_STRING
)
10271 return unit_name_string_get_value(value
, (const struct unit_name_string
*) hfinfo
->strings
);
10273 return try_val_to_str(value
, (const value_string
*) hfinfo
->strings
);
10276 static const char *
10277 hf_try_val64_to_str(uint64_t value
, const header_field_info
*hfinfo
)
10279 if (hfinfo
->display
& BASE_VAL64_STRING
) {
10280 if (hfinfo
->display
& BASE_EXT_STRING
)
10281 return try_val64_to_str_ext(value
, (val64_string_ext
*) hfinfo
->strings
);
10283 return try_val64_to_str(value
, (const val64_string
*) hfinfo
->strings
);
10286 if (hfinfo
->display
& BASE_RANGE_STRING
)
10287 return try_rval64_to_str(value
, (const range_string
*) hfinfo
->strings
);
10289 if (hfinfo
->display
& BASE_UNIT_STRING
)
10290 return unit_name_string_get_value64(value
, (const struct unit_name_string
*) hfinfo
->strings
);
10292 /* If this is reached somebody registered a 64-bit field with a 32-bit
10293 * value-string, which isn't right. */
10294 REPORT_DISSECTOR_BUG("field %s is a 64-bit field with a 32-bit value_string",
10297 /* This is necessary to squelch MSVC errors; is there
10298 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
10303 static const char *
10304 hf_try_double_val_to_str(double value
, const header_field_info
*hfinfo
)
10306 if (hfinfo
->display
& BASE_UNIT_STRING
)
10307 return unit_name_string_get_double(value
, (const struct unit_name_string
*)hfinfo
->strings
);
10309 REPORT_DISSECTOR_BUG("field %s (FT_DOUBLE) has no base_unit_string", hfinfo
->abbrev
);
10311 /* This is necessary to squelch MSVC errors; is there
10312 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
10317 static const char *
10318 hf_try_val_to_str_const(uint32_t value
, const header_field_info
*hfinfo
, const char *unknown_str
)
10320 const char *str
= hf_try_val_to_str(value
, hfinfo
);
10322 return (str
) ? str
: unknown_str
;
10325 static const char *
10326 hf_try_val64_to_str_const(uint64_t value
, const header_field_info
*hfinfo
, const char *unknown_str
)
10328 const char *str
= hf_try_val64_to_str(value
, hfinfo
);
10330 return (str
) ? str
: unknown_str
;
10333 /* Fills data for bitfield chars with val_strings */
10335 fill_label_bitfield_char(const field_info
*fi
, char *label_str
, size_t *value_pos
)
10338 int bitfield_byte_length
, bitwidth
;
10339 uint32_t unshifted_value
;
10345 const header_field_info
*hfinfo
= fi
->hfinfo
;
10347 /* Figure out the bit width */
10348 bitwidth
= hfinfo_container_bitwidth(hfinfo
);
10350 /* Un-shift bits */
10351 value
= fvalue_get_uinteger(fi
->value
);
10353 unshifted_value
= value
;
10354 if (hfinfo
->bitmask
) {
10355 unshifted_value
<<= hfinfo_bitshift(hfinfo
);
10358 /* Create the bitfield first */
10359 p
= decode_bitfield_value(label_str
, unshifted_value
, hfinfo
->bitmask
, bitwidth
);
10360 bitfield_byte_length
= (int) (p
- label_str
);
10362 /* Fill in the textual info using stored (shifted) value */
10363 if (hfinfo
->display
== BASE_CUSTOM
) {
10364 char tmp
[ITEM_LABEL_LENGTH
];
10365 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hfinfo
->strings
;
10367 DISSECTOR_ASSERT(fmtfunc
);
10368 fmtfunc(tmp
, value
);
10369 label_fill(label_str
, bitfield_byte_length
, hfinfo
, tmp
, value_pos
);
10371 else if (hfinfo
->strings
) {
10372 const char *val_str
= hf_try_val_to_str_const(value
, hfinfo
, "Unknown");
10374 out
= hfinfo_char_vals_format(hfinfo
, buf
, value
);
10375 if (out
== NULL
) /* BASE_NONE so don't put integer in descr */
10376 label_fill(label_str
, bitfield_byte_length
, hfinfo
, val_str
, value_pos
);
10378 label_fill_descr(label_str
, bitfield_byte_length
, hfinfo
, val_str
, out
, value_pos
);
10381 out
= hfinfo_char_value_format(hfinfo
, buf
, value
);
10383 label_fill(label_str
, bitfield_byte_length
, hfinfo
, out
, value_pos
);
10387 /* Fills data for bitfield ints with val_strings */
10389 fill_label_bitfield(const field_info
*fi
, char *label_str
, size_t *value_pos
, bool is_signed
)
10392 int bitfield_byte_length
, bitwidth
;
10393 uint32_t value
, unshifted_value
;
10394 char buf
[NUMBER_LABEL_LENGTH
];
10397 const header_field_info
*hfinfo
= fi
->hfinfo
;
10399 /* Figure out the bit width */
10400 if (fi
->flags
& FI_VARINT
)
10401 bitwidth
= fi
->length
*8;
10403 bitwidth
= hfinfo_container_bitwidth(hfinfo
);
10405 /* Un-shift bits */
10407 value
= fvalue_get_sinteger(fi
->value
);
10409 value
= fvalue_get_uinteger(fi
->value
);
10411 unshifted_value
= value
;
10412 if (hfinfo
->bitmask
) {
10413 unshifted_value
<<= hfinfo_bitshift(hfinfo
);
10416 /* Create the bitfield first */
10417 if (fi
->flags
& FI_VARINT
)
10418 p
= decode_bitfield_varint_value(label_str
, unshifted_value
, hfinfo
->bitmask
, bitwidth
);
10420 p
= decode_bitfield_value(label_str
, unshifted_value
, hfinfo
->bitmask
, bitwidth
);
10421 bitfield_byte_length
= (int) (p
- label_str
);
10423 /* Fill in the textual info using stored (shifted) value */
10424 if (hfinfo
->display
== BASE_CUSTOM
) {
10425 char tmp
[ITEM_LABEL_LENGTH
];
10426 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hfinfo
->strings
;
10428 DISSECTOR_ASSERT(fmtfunc
);
10429 fmtfunc(tmp
, value
);
10430 label_fill(label_str
, bitfield_byte_length
, hfinfo
, tmp
, value_pos
);
10432 else if (hfinfo
->strings
) {
10433 const char *val_str
= hf_try_val_to_str(value
, hfinfo
);
10435 out
= hfinfo_number_vals_format(hfinfo
, buf
, value
);
10436 if (hfinfo
->display
& BASE_SPECIAL_VALS
) {
10438 * Unique values only display value_string string
10439 * if there is a match. Otherwise it's just a number
10442 label_fill_descr(label_str
, bitfield_byte_length
, hfinfo
, val_str
, out
, value_pos
);
10444 label_fill(label_str
, bitfield_byte_length
, hfinfo
, out
, value_pos
);
10447 if (val_str
== NULL
)
10448 val_str
= "Unknown";
10450 if (out
== NULL
) /* BASE_NONE so don't put integer in descr */
10451 label_fill(label_str
, bitfield_byte_length
, hfinfo
, val_str
, value_pos
);
10453 label_fill_descr(label_str
, bitfield_byte_length
, hfinfo
, val_str
, out
, value_pos
);
10457 out
= hfinfo_number_value_format(hfinfo
, buf
, value
);
10459 label_fill(label_str
, bitfield_byte_length
, hfinfo
, out
, value_pos
);
10464 fill_label_bitfield64(const field_info
*fi
, char *label_str
, size_t *value_pos
, bool is_signed
)
10467 int bitfield_byte_length
, bitwidth
;
10468 uint64_t value
, unshifted_value
;
10469 char buf
[NUMBER_LABEL_LENGTH
];
10472 const header_field_info
*hfinfo
= fi
->hfinfo
;
10474 /* Figure out the bit width */
10475 if (fi
->flags
& FI_VARINT
)
10476 bitwidth
= fi
->length
*8;
10478 bitwidth
= hfinfo_container_bitwidth(hfinfo
);
10480 /* Un-shift bits */
10482 value
= fvalue_get_sinteger64(fi
->value
);
10484 value
= fvalue_get_uinteger64(fi
->value
);
10486 unshifted_value
= value
;
10487 if (hfinfo
->bitmask
) {
10488 unshifted_value
<<= hfinfo_bitshift(hfinfo
);
10491 /* Create the bitfield first */
10492 if (fi
->flags
& FI_VARINT
)
10493 p
= decode_bitfield_varint_value(label_str
, unshifted_value
, hfinfo
->bitmask
, bitwidth
);
10495 p
= decode_bitfield_value(label_str
, unshifted_value
, hfinfo
->bitmask
, bitwidth
);
10496 bitfield_byte_length
= (int) (p
- label_str
);
10498 /* Fill in the textual info using stored (shifted) value */
10499 if (hfinfo
->display
== BASE_CUSTOM
) {
10500 char tmp
[ITEM_LABEL_LENGTH
];
10501 const custom_fmt_func_64_t fmtfunc64
= (const custom_fmt_func_64_t
)hfinfo
->strings
;
10503 DISSECTOR_ASSERT(fmtfunc64
);
10504 fmtfunc64(tmp
, value
);
10505 label_fill(label_str
, bitfield_byte_length
, hfinfo
, tmp
, value_pos
);
10507 else if (hfinfo
->strings
) {
10508 const char *val_str
= hf_try_val64_to_str(value
, hfinfo
);
10510 out
= hfinfo_number_vals_format64(hfinfo
, buf
, value
);
10511 if (hfinfo
->display
& BASE_SPECIAL_VALS
) {
10513 * Unique values only display value_string string
10514 * if there is a match. Otherwise it's just a number
10517 label_fill_descr(label_str
, bitfield_byte_length
, hfinfo
, val_str
, out
, value_pos
);
10519 label_fill(label_str
, bitfield_byte_length
, hfinfo
, out
, value_pos
);
10522 if (val_str
== NULL
)
10523 val_str
= "Unknown";
10525 if (out
== NULL
) /* BASE_NONE so don't put integer in descr */
10526 label_fill(label_str
, bitfield_byte_length
, hfinfo
, val_str
, value_pos
);
10528 label_fill_descr(label_str
, bitfield_byte_length
, hfinfo
, val_str
, out
, value_pos
);
10532 out
= hfinfo_number_value_format64(hfinfo
, buf
, value
);
10534 label_fill(label_str
, bitfield_byte_length
, hfinfo
, out
, value_pos
);
10539 fill_label_char(const field_info
*fi
, char *label_str
, size_t *value_pos
)
10541 const header_field_info
*hfinfo
= fi
->hfinfo
;
10547 value
= fvalue_get_uinteger(fi
->value
);
10549 /* Fill in the textual info */
10550 if (hfinfo
->display
== BASE_CUSTOM
) {
10551 char tmp
[ITEM_LABEL_LENGTH
];
10552 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hfinfo
->strings
;
10554 DISSECTOR_ASSERT(fmtfunc
);
10555 fmtfunc(tmp
, value
);
10556 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10558 else if (hfinfo
->strings
) {
10559 const char *val_str
= hf_try_val_to_str_const(value
, hfinfo
, "Unknown");
10561 out
= hfinfo_char_vals_format(hfinfo
, buf
, value
);
10562 label_fill_descr(label_str
, 0, hfinfo
, val_str
, out
, value_pos
);
10565 out
= hfinfo_char_value_format(hfinfo
, buf
, value
);
10567 label_fill(label_str
, 0, hfinfo
, out
, value_pos
);
10572 fill_label_number(const field_info
*fi
, char *label_str
, size_t *value_pos
, bool is_signed
)
10574 const header_field_info
*hfinfo
= fi
->hfinfo
;
10577 char buf
[NUMBER_LABEL_LENGTH
];
10581 value
= fvalue_get_sinteger(fi
->value
);
10583 value
= fvalue_get_uinteger(fi
->value
);
10585 /* Fill in the textual info */
10586 if (hfinfo
->display
== BASE_CUSTOM
) {
10587 char tmp
[ITEM_LABEL_LENGTH
];
10588 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hfinfo
->strings
;
10590 DISSECTOR_ASSERT(fmtfunc
);
10591 fmtfunc(tmp
, value
);
10592 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10594 else if (hfinfo
->strings
&& hfinfo
->type
!= FT_FRAMENUM
) {
10596 * It makes no sense to have a value-string table for a
10597 * frame-number field - they're just integers giving
10598 * the ordinal frame number.
10600 const char *val_str
= hf_try_val_to_str(value
, hfinfo
);
10602 out
= hfinfo_number_vals_format(hfinfo
, buf
, value
);
10603 if (hfinfo
->display
& BASE_SPECIAL_VALS
) {
10605 * Unique values only display value_string string
10606 * if there is a match. Otherwise it's just a number
10609 label_fill_descr(label_str
, 0, hfinfo
, val_str
, out
, value_pos
);
10611 label_fill(label_str
, 0, hfinfo
, out
, value_pos
);
10614 if (val_str
== NULL
)
10615 val_str
= "Unknown";
10617 if (out
== NULL
) /* BASE_NONE so don't put integer in descr */
10618 label_fill(label_str
, 0, hfinfo
, val_str
, value_pos
);
10620 label_fill_descr(label_str
, 0, hfinfo
, val_str
, out
, value_pos
);
10623 else if (IS_BASE_PORT(hfinfo
->display
)) {
10624 char tmp
[ITEM_LABEL_LENGTH
];
10626 port_with_resolution_to_str_buf(tmp
, sizeof(tmp
),
10627 display_to_port_type((field_display_e
)hfinfo
->display
), value
);
10628 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10631 out
= hfinfo_number_value_format(hfinfo
, buf
, value
);
10633 label_fill(label_str
, 0, hfinfo
, out
, value_pos
);
10638 fill_label_number64(const field_info
*fi
, char *label_str
, size_t *value_pos
, bool is_signed
)
10640 const header_field_info
*hfinfo
= fi
->hfinfo
;
10643 char buf
[NUMBER_LABEL_LENGTH
];
10647 value
= fvalue_get_sinteger64(fi
->value
);
10649 value
= fvalue_get_uinteger64(fi
->value
);
10651 /* Fill in the textual info */
10652 if (hfinfo
->display
== BASE_CUSTOM
) {
10653 char tmp
[ITEM_LABEL_LENGTH
];
10654 const custom_fmt_func_64_t fmtfunc64
= (const custom_fmt_func_64_t
)hfinfo
->strings
;
10656 DISSECTOR_ASSERT(fmtfunc64
);
10657 fmtfunc64(tmp
, value
);
10658 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10660 else if (hfinfo
->strings
) {
10661 const char *val_str
= hf_try_val64_to_str(value
, hfinfo
);
10663 out
= hfinfo_number_vals_format64(hfinfo
, buf
, value
);
10664 if (hfinfo
->display
& BASE_SPECIAL_VALS
) {
10666 * Unique values only display value_string string
10667 * if there is a match. Otherwise it's just a number
10670 label_fill_descr(label_str
, 0, hfinfo
, val_str
, out
, value_pos
);
10672 label_fill(label_str
, 0, hfinfo
, out
, value_pos
);
10675 if (val_str
== NULL
)
10676 val_str
= "Unknown";
10678 if (out
== NULL
) /* BASE_NONE so don't put integer in descr */
10679 label_fill(label_str
, 0, hfinfo
, val_str
, value_pos
);
10681 label_fill_descr(label_str
, 0, hfinfo
, val_str
, out
, value_pos
);
10685 out
= hfinfo_number_value_format64(hfinfo
, buf
, value
);
10687 label_fill(label_str
, 0, hfinfo
, out
, value_pos
);
10692 fill_display_label_float(const field_info
*fi
, char *label_str
)
10699 display
= FIELD_DISPLAY(fi
->hfinfo
->display
);
10700 value
= fvalue_get_floating(fi
->value
);
10702 if (display
== BASE_CUSTOM
) {
10703 const custom_fmt_func_double_t fmtfunc
= (const custom_fmt_func_double_t
)fi
->hfinfo
->strings
;
10704 DISSECTOR_ASSERT(fmtfunc
);
10705 fmtfunc(label_str
, value
);
10706 return strlen(label_str
);
10711 if (fi
->hfinfo
->type
== FT_FLOAT
)
10716 n
= snprintf(label_str
, ITEM_LABEL_LENGTH
, "%.*g", digits
, value
);
10719 n
= snprintf(label_str
, ITEM_LABEL_LENGTH
, "%f", value
);
10722 n
= snprintf(label_str
, ITEM_LABEL_LENGTH
, "%a", value
);
10725 n
= snprintf(label_str
, ITEM_LABEL_LENGTH
, "%e", value
);
10728 ws_assert_not_reached();
10731 return 0; /* error */
10733 if ((fi
->hfinfo
->strings
) && (fi
->hfinfo
->display
& BASE_UNIT_STRING
)) {
10734 const char *hf_str_val
;
10735 hf_str_val
= hf_try_double_val_to_str(value
, fi
->hfinfo
);
10736 n
+= protoo_strlcpy(label_str
+ n
, hf_str_val
, ITEM_LABEL_LENGTH
- n
);
10738 if (n
> ITEM_LABEL_LENGTH
) {
10739 ws_warning("label length too small");
10740 return strlen(label_str
);
10747 fill_label_float(const field_info
*fi
, char *label_str
, size_t *value_pos
)
10749 char tmp
[ITEM_LABEL_LENGTH
];
10751 fill_display_label_float(fi
, tmp
);
10752 label_fill(label_str
, 0, fi
->hfinfo
, tmp
, value_pos
);
10756 hfinfo_bitshift(const header_field_info
*hfinfo
)
10758 return ws_ctz(hfinfo
->bitmask
);
10763 hfinfo_bitoffset(const header_field_info
*hfinfo
)
10765 if (!hfinfo
->bitmask
) {
10769 /* ilog2 = first set bit, counting 0 as the last bit; we want 0
10770 * as the first bit */
10771 return hfinfo_container_bitwidth(hfinfo
) - 1 - ws_ilog2(hfinfo
->bitmask
);
10775 hfinfo_mask_bitwidth(const header_field_info
*hfinfo
)
10777 if (!hfinfo
->bitmask
) {
10781 /* ilog2 = first set bit, ctz = last set bit */
10782 return ws_ilog2(hfinfo
->bitmask
) - ws_ctz(hfinfo
->bitmask
) + 1;
10786 hfinfo_type_bitwidth(enum ftenum type
)
10825 DISSECTOR_ASSERT_NOT_REACHED();
10833 hfinfo_container_bitwidth(const header_field_info
*hfinfo
)
10835 if (!hfinfo
->bitmask
) {
10839 if (hfinfo
->type
== FT_BOOLEAN
) {
10840 return hfinfo
->display
; /* hacky? :) */
10843 return hfinfo_type_bitwidth(hfinfo
->type
);
10847 hfinfo_hex_digits(const header_field_info
*hfinfo
)
10851 /* If we have a bitmask, hfinfo->type is the width of the container, so not
10852 * appropriate to determine the number of hex digits for the field.
10853 * So instead, we compute it from the bitmask.
10855 if (hfinfo
->bitmask
!= 0) {
10856 bitwidth
= hfinfo_mask_bitwidth(hfinfo
);
10858 bitwidth
= hfinfo_type_bitwidth(hfinfo
->type
);
10861 /* Divide by 4, rounding up, to get number of hex digits. */
10862 return (bitwidth
+ 3) / 4;
10866 hfinfo_char_value_format_display(int display
, char buf
[7], uint32_t value
)
10868 char *ptr
= &buf
[6];
10869 static const char hex_digits
[16] =
10870 { '0', '1', '2', '3', '4', '5', '6', '7',
10871 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
10875 /* Properly format value */
10876 if (g_ascii_isprint(value
)) {
10878 * Printable, so just show the character, and, if it needs
10879 * to be escaped, escape it.
10882 if (value
== '\\' || value
== '\'')
10886 * Non-printable; show it as an escape sequence.
10892 * Show a NUL with only one digit.
10926 switch (FIELD_DISPLAY(display
)) {
10929 *(--ptr
) = (value
& 0x7) + '0';
10931 *(--ptr
) = (value
& 0x7) + '0';
10933 *(--ptr
) = (value
& 0x7) + '0';
10937 *(--ptr
) = hex_digits
[value
& 0x0F];
10939 *(--ptr
) = hex_digits
[value
& 0x0F];
10944 REPORT_DISSECTOR_BUG("Invalid base: %d", FIELD_DISPLAY(display
));
10953 static const char *
10954 hfinfo_number_value_format_display(const header_field_info
*hfinfo
, int display
, char buf
[NUMBER_LABEL_LENGTH
], uint32_t value
)
10956 char *ptr
= &buf
[NUMBER_LABEL_LENGTH
-1];
10957 bool isint
= FT_IS_INT(hfinfo
->type
);
10960 /* Properly format value */
10961 switch (FIELD_DISPLAY(display
)) {
10963 return isint
? int_to_str_back(ptr
, (int32_t) value
) : uint_to_str_back(ptr
, value
);
10967 ptr
= hex_to_str_back_len(ptr
, value
, hfinfo_hex_digits(hfinfo
));
10970 ptr
= isint
? int_to_str_back(ptr
, (int32_t) value
) : uint_to_str_back(ptr
, value
);
10974 return oct_to_str_back(ptr
, value
);
10977 return hex_to_str_back_len(ptr
, value
, hfinfo_hex_digits(hfinfo
));
10981 ptr
= isint
? int_to_str_back(ptr
, (int32_t) value
) : uint_to_str_back(ptr
, value
);
10984 ptr
= hex_to_str_back_len(ptr
, value
, hfinfo_hex_digits(hfinfo
));
10991 port_with_resolution_to_str_buf(buf
, NUMBER_LABEL_LENGTH
,
10992 display_to_port_type((field_display_e
)display
), value
);
10997 const char *manuf_name
;
10999 p_oui
[0] = value
>> 16 & 0xFF;
11000 p_oui
[1] = value
>> 8 & 0xFF;
11001 p_oui
[2] = value
& 0xFF;
11003 /* Attempt an OUI lookup. */
11004 manuf_name
= uint_get_manuf_name_if_known(value
);
11005 if (manuf_name
== NULL
) {
11006 /* Could not find an OUI. */
11007 snprintf(buf
, NUMBER_LABEL_LENGTH
, "%02x:%02x:%02x", p_oui
[0], p_oui
[1], p_oui
[2]);
11010 /* Found an address string. */
11011 snprintf(buf
, NUMBER_LABEL_LENGTH
, "%02x:%02x:%02x (%s)", p_oui
[0], p_oui
[1], p_oui
[2], manuf_name
);
11017 REPORT_DISSECTOR_BUG("Invalid base: %d", FIELD_DISPLAY(display
));
11022 static const char *
11023 hfinfo_number_value_format_display64(const header_field_info
*hfinfo
, int display
, char buf
[NUMBER_LABEL_LENGTH
], uint64_t value
)
11025 char *ptr
= &buf
[NUMBER_LABEL_LENGTH
-1];
11026 bool isint
= FT_IS_INT(hfinfo
->type
);
11029 /* Properly format value */
11030 switch (FIELD_DISPLAY(display
)) {
11032 return isint
? int64_to_str_back(ptr
, (int64_t) value
) : uint64_to_str_back(ptr
, value
);
11036 ptr
= hex64_to_str_back_len(ptr
, value
, hfinfo_hex_digits(hfinfo
));
11039 ptr
= isint
? int64_to_str_back(ptr
, (int64_t) value
) : uint64_to_str_back(ptr
, value
);
11043 return oct64_to_str_back(ptr
, value
);
11046 return hex64_to_str_back_len(ptr
, value
, hfinfo_hex_digits(hfinfo
));
11050 ptr
= isint
? int64_to_str_back(ptr
, (int64_t) value
) : uint64_to_str_back(ptr
, value
);
11053 ptr
= hex64_to_str_back_len(ptr
, value
, hfinfo_hex_digits(hfinfo
));
11057 REPORT_DISSECTOR_BUG("Invalid base: %d", FIELD_DISPLAY(display
));
11063 static const char *
11064 hfinfo_number_value_format(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint32_t value
)
11066 int display
= hfinfo
->display
;
11068 if (hfinfo
->type
== FT_FRAMENUM
) {
11070 * Frame numbers are always displayed in decimal.
11072 display
= BASE_DEC
;
11075 return hfinfo_number_value_format_display(hfinfo
, display
, buf
, value
);
11078 static const char *
11079 hfinfo_number_value_format64(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint64_t value
)
11081 int display
= hfinfo
->display
;
11083 if (hfinfo
->type
== FT_FRAMENUM
) {
11085 * Frame numbers are always displayed in decimal.
11087 display
= BASE_DEC
;
11090 return hfinfo_number_value_format_display64(hfinfo
, display
, buf
, value
);
11093 static const char *
11094 hfinfo_char_value_format(const header_field_info
*hfinfo
, char buf
[32], uint32_t value
)
11096 /* Get the underlying BASE_ value */
11097 int display
= FIELD_DISPLAY(hfinfo
->display
);
11099 return hfinfo_char_value_format_display(display
, buf
, value
);
11102 static const char *
11103 hfinfo_numeric_value_format(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint32_t value
)
11105 /* Get the underlying BASE_ value */
11106 int display
= FIELD_DISPLAY(hfinfo
->display
);
11108 if (hfinfo
->type
== FT_FRAMENUM
) {
11110 * Frame numbers are always displayed in decimal.
11112 display
= BASE_DEC
;
11115 if (IS_BASE_PORT(display
)) {
11116 display
= BASE_DEC
;
11117 } else if (display
== BASE_OUI
) {
11118 display
= BASE_HEX
;
11123 /* case BASE_DEC: */
11125 case BASE_OCT
: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
11127 display
= BASE_DEC
;
11130 /* case BASE_HEX: */
11132 display
= BASE_HEX
;
11136 return hfinfo_number_value_format_display(hfinfo
, display
, buf
, value
);
11139 static const char *
11140 hfinfo_numeric_value_format64(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint64_t value
)
11142 /* Get the underlying BASE_ value */
11143 int display
= FIELD_DISPLAY(hfinfo
->display
);
11145 if (hfinfo
->type
== FT_FRAMENUM
) {
11147 * Frame numbers are always displayed in decimal.
11149 display
= BASE_DEC
;
11154 /* case BASE_DEC: */
11156 case BASE_OCT
: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
11158 display
= BASE_DEC
;
11161 /* case BASE_HEX: */
11163 display
= BASE_HEX
;
11167 return hfinfo_number_value_format_display64(hfinfo
, display
, buf
, value
);
11170 static const char *
11171 hfinfo_char_vals_format(const header_field_info
*hfinfo
, char buf
[32], uint32_t value
)
11173 /* Get the underlying BASE_ value */
11174 int display
= FIELD_DISPLAY(hfinfo
->display
);
11176 return hfinfo_char_value_format_display(display
, buf
, value
);
11179 static const char *
11180 hfinfo_number_vals_format(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint32_t value
)
11182 /* Get the underlying BASE_ value */
11183 int display
= FIELD_DISPLAY(hfinfo
->display
);
11185 if (display
== BASE_NONE
)
11188 if (display
== BASE_DEC_HEX
)
11189 display
= BASE_DEC
;
11190 if (display
== BASE_HEX_DEC
)
11191 display
= BASE_HEX
;
11193 return hfinfo_number_value_format_display(hfinfo
, display
, buf
, value
);
11196 static const char *
11197 hfinfo_number_vals_format64(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint64_t value
)
11199 /* Get the underlying BASE_ value */
11200 int display
= FIELD_DISPLAY(hfinfo
->display
);
11202 if (display
== BASE_NONE
)
11205 if (display
== BASE_DEC_HEX
)
11206 display
= BASE_DEC
;
11207 if (display
== BASE_HEX_DEC
)
11208 display
= BASE_HEX
;
11210 return hfinfo_number_value_format_display64(hfinfo
, display
, buf
, value
);
11214 proto_registrar_get_name(const int n
)
11216 header_field_info
*hfinfo
;
11218 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
11219 return hfinfo
->name
;
11223 proto_registrar_get_abbrev(const int n
)
11225 header_field_info
*hfinfo
;
11227 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
11228 return hfinfo
->abbrev
;
11232 proto_registrar_get_ftype(const int n
)
11234 header_field_info
*hfinfo
;
11236 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
11237 return hfinfo
->type
;
11241 proto_registrar_get_parent(const int n
)
11243 header_field_info
*hfinfo
;
11245 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
11246 return hfinfo
->parent
;
11250 proto_registrar_is_protocol(const int n
)
11252 header_field_info
*hfinfo
;
11254 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
11255 return (((hfinfo
->id
!= hf_text_only
) && (hfinfo
->parent
== -1)) ? true : false);
11258 /* Returns length of field in packet (not necessarily the length
11259 * in our internal representation, as in the case of IPv4).
11260 * 0 means undeterminable at time of registration
11261 * -1 means the field is not registered. */
11263 proto_registrar_get_length(const int n
)
11265 header_field_info
*hfinfo
;
11267 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
11268 return ftype_wire_size(hfinfo
->type
);
11271 /* Looks for a protocol or a field in a proto_tree. Returns true if
11272 * it exists anywhere, or false if it exists nowhere. */
11274 proto_check_for_protocol_or_field(const proto_tree
* tree
, const int id
)
11276 GPtrArray
*ptrs
= proto_get_finfo_ptr_array(tree
, id
);
11278 if (g_ptr_array_len(ptrs
) > 0) {
11286 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
11287 * This only works if the hfindex was "primed" before the dissection
11288 * took place, as we just pass back the already-created GPtrArray*.
11289 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
11292 proto_get_finfo_ptr_array(const proto_tree
*tree
, const int id
)
11297 if (PTREE_DATA(tree
)->interesting_hfids
!= NULL
)
11298 return (GPtrArray
*)g_hash_table_lookup(PTREE_DATA(tree
)->interesting_hfids
,
11299 GINT_TO_POINTER(id
));
11305 proto_tracking_interesting_fields(const proto_tree
*tree
)
11307 GHashTable
*interesting_hfids
;
11312 interesting_hfids
= PTREE_DATA(tree
)->interesting_hfids
;
11314 return (interesting_hfids
!= NULL
) && g_hash_table_size(interesting_hfids
);
11317 /* Helper struct for proto_find_info() and proto_all_finfos() */
11323 /* Helper function for proto_find_info() */
11325 find_finfo(proto_node
*node
, void * data
)
11327 field_info
*fi
= PNODE_FINFO(node
);
11328 if (fi
&& fi
->hfinfo
) {
11329 if (fi
->hfinfo
->id
== ((ffdata_t
*)data
)->id
) {
11330 g_ptr_array_add(((ffdata_t
*)data
)->array
, fi
);
11334 /* Don't stop traversing. */
11338 /* Helper function for proto_find_first_info() */
11340 find_first_finfo(proto_node
*node
, void *data
)
11342 field_info
*fi
= PNODE_FINFO(node
);
11343 if (fi
&& fi
->hfinfo
) {
11344 if (fi
->hfinfo
->id
== ((ffdata_t
*)data
)->id
) {
11345 g_ptr_array_add(((ffdata_t
*)data
)->array
, fi
);
11347 /* Stop traversing. */
11352 /* Continue traversing. */
11356 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
11357 * This works on any proto_tree, primed or unprimed, but actually searches
11358 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
11359 * The caller does need to free the returned GPtrArray with
11360 * g_ptr_array_free(<array>, true).
11363 proto_find_finfo(proto_tree
*tree
, const int id
)
11367 ffdata
.array
= g_ptr_array_new();
11370 proto_tree_traverse_pre_order(tree
, find_finfo
, &ffdata
);
11372 return ffdata
.array
;
11375 /* Return GPtrArray* of first field_info pointers for the searched hfindex that appear in a tree.
11376 * This works on any proto_tree, primed or unprimed, but actually searches
11377 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
11378 * The caller does need to free the returned GPtrArray with
11379 * g_ptr_array_free(<array>, true).
11382 proto_find_first_finfo(proto_tree
*tree
, const int id
)
11386 ffdata
.array
= g_ptr_array_new();
11389 proto_tree_traverse_pre_order(tree
, find_first_finfo
, &ffdata
);
11391 return ffdata
.array
;
11394 /* Helper function for proto_all_finfos() */
11396 every_finfo(proto_node
*node
, void * data
)
11398 field_info
*fi
= PNODE_FINFO(node
);
11399 if (fi
&& fi
->hfinfo
) {
11400 g_ptr_array_add(((ffdata_t
*)data
)->array
, fi
);
11403 /* Don't stop traversing. */
11407 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree.
11408 * The caller does need to free the returned GPtrArray with
11409 * g_ptr_array_free(<array>, true).
11412 proto_all_finfos(proto_tree
*tree
)
11416 /* Pre allocate enough space to hold all fields in most cases */
11417 ffdata
.array
= g_ptr_array_sized_new(512);
11420 proto_tree_traverse_pre_order(tree
, every_finfo
, &ffdata
);
11422 return ffdata
.array
;
11433 check_for_offset(proto_node
*node
, void * data
)
11435 field_info
*fi
= PNODE_FINFO(node
);
11436 offset_search_t
*offsearch
= (offset_search_t
*)data
;
11438 /* !fi == the top most container node which holds nothing */
11439 if (fi
&& !proto_item_is_hidden(node
) && !proto_item_is_generated(node
) && fi
->ds_tvb
&& offsearch
->tvb
== fi
->ds_tvb
) {
11440 if (offsearch
->offset
>= (unsigned) fi
->start
&&
11441 offsearch
->offset
< (unsigned) (fi
->start
+ fi
->length
)) {
11443 offsearch
->finfo
= fi
;
11444 return false; /* keep traversing */
11447 return false; /* keep traversing */
11450 /* Search a proto_tree backwards (from leaves to root) looking for the field
11451 * whose start/length occupies 'offset' */
11452 /* XXX - I couldn't find an easy way to search backwards, so I search
11453 * forwards, w/o stopping. Therefore, the last finfo I find will the be
11454 * the one I want to return to the user. This algorithm is inefficient
11455 * and could be re-done, but I'd have to handle all the children and
11456 * siblings of each node myself. When I have more time I'll do that.
11459 proto_find_field_from_offset(proto_tree
*tree
, unsigned offset
, tvbuff_t
*tvb
)
11461 offset_search_t offsearch
;
11463 offsearch
.offset
= offset
;
11464 offsearch
.finfo
= NULL
;
11465 offsearch
.tvb
= tvb
;
11467 proto_tree_traverse_pre_order(tree
, check_for_offset
, &offsearch
);
11469 return offsearch
.finfo
;
11478 check_for_undecoded(proto_node
*node
, void * data
)
11480 field_info
*fi
= PNODE_FINFO(node
);
11481 decoded_data_t
* decoded
= (decoded_data_t
*)data
;
11486 if (fi
&& fi
->hfinfo
->type
!= FT_PROTOCOL
) {
11487 for (i
= fi
->start
; i
< fi
->start
+ fi
->length
&& i
< decoded
->length
; i
++) {
11490 decoded
->buf
[byte
] |= (1 << bit
);
11498 proto_find_undecoded_data(proto_tree
*tree
, unsigned length
)
11500 decoded_data_t decoded
;
11501 decoded
.length
= length
;
11502 decoded
.buf
= (char*)wmem_alloc0(PNODE_POOL(tree
), length
/ 8 + 1);
11504 proto_tree_traverse_pre_order(tree
, check_for_undecoded
, &decoded
);
11505 return decoded
.buf
;
11508 /* Dumps the protocols in the registration database to stdout. An independent
11509 * program can take this output and format it into nice tables or HTML or
11512 * There is one record per line. The fields are tab-delimited.
11514 * Field 1 = protocol name
11515 * Field 2 = protocol short name
11516 * Field 3 = protocol filter name
11517 * Field 4 = protocol enabled
11518 * Field 5 = protocol enabled by default
11519 * Field 6 = protocol can toggle
11522 proto_registrar_dump_protocols(void)
11524 protocol_t
*protocol
;
11526 void *cookie
= NULL
;
11529 i
= proto_get_first_protocol(&cookie
);
11531 protocol
= find_protocol_by_id(i
);
11532 printf("%s\t%s\t%s\t%c\t%c\t%c\n",
11534 protocol
->short_name
,
11535 protocol
->filter_name
,
11536 (proto_is_protocol_enabled_by_default(protocol
) ? 'T' : 'F'),
11537 (proto_is_protocol_enabled(protocol
) ? 'T' : 'F'),
11538 (proto_can_toggle_protocol(protocol
->proto_id
) ? 'T' : 'F'));
11539 i
= proto_get_next_protocol(&cookie
);
11543 /* Dumps the value_strings, extended value string headers, range_strings
11544 * or true/false strings for fields that have them.
11545 * There is one record per line. Fields are tab-delimited.
11546 * There are four types of records: Value String, Extended Value String Header,
11547 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
11548 * the type of record.
11550 * Note that a record will be generated only if the value_string,... is referenced
11551 * in a registered hfinfo entry.
11557 * Field 2 = Field abbreviation to which this value string corresponds
11558 * Field 3 = Integer value
11561 * Extended Value String Headers
11562 * -----------------------------
11564 * Field 2 = Field abbreviation to which this extended value string header corresponds
11565 * Field 3 = Extended Value String "Name"
11566 * Field 4 = Number of entries in the associated value_string array
11567 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
11572 * Field 2 = Field abbreviation to which this range string corresponds
11573 * Field 3 = Integer value: lower bound
11574 * Field 4 = Integer value: upper bound
11577 * True/False Strings
11578 * ------------------
11580 * Field 2 = Field abbreviation to which this true/false string corresponds
11581 * Field 3 = True String
11582 * Field 4 = False String
11585 proto_registrar_dump_values(void)
11587 header_field_info
*hfinfo
;
11589 const value_string
*vals
;
11590 const val64_string
*vals64
;
11591 const range_string
*range
;
11592 const true_false_string
*tfs
;
11593 const unit_name_string
*units
;
11595 len
= gpa_hfinfo
.len
;
11596 for (i
= 0; i
< len
; i
++) {
11597 if (gpa_hfinfo
.hfi
[i
] == NULL
)
11598 continue; /* This is a deregistered protocol or field */
11600 PROTO_REGISTRAR_GET_NTH(i
, hfinfo
);
11602 if (hfinfo
->id
== hf_text_only
) {
11606 /* ignore protocols */
11607 if (proto_registrar_is_protocol(i
)) {
11610 /* process header fields */
11611 #if 0 /* XXX: We apparently allow fields with the same name but with differing "strings" content */
11613 * If this field isn't at the head of the list of
11614 * fields with this name, skip this field - all
11615 * fields with the same name are really just versions
11616 * of the same field stored in different bits, and
11617 * should have the same type/radix/value list, and
11618 * just differ in their bit masks. (If a field isn't
11619 * a bitfield, but can be, say, 1 or 2 bytes long,
11620 * it can just be made FT_UINT16, meaning the
11621 * *maximum* length is 2 bytes, and be used
11622 * for all lengths.)
11624 if (hfinfo
->same_name_prev_id
!= -1)
11633 if (hfinfo
->strings
!= NULL
) {
11634 if (FIELD_DISPLAY(hfinfo
->display
) != BASE_CUSTOM
&&
11635 (hfinfo
->type
== FT_CHAR
||
11636 hfinfo
->type
== FT_UINT8
||
11637 hfinfo
->type
== FT_UINT16
||
11638 hfinfo
->type
== FT_UINT24
||
11639 hfinfo
->type
== FT_UINT32
||
11640 hfinfo
->type
== FT_UINT40
||
11641 hfinfo
->type
== FT_UINT48
||
11642 hfinfo
->type
== FT_UINT56
||
11643 hfinfo
->type
== FT_UINT64
||
11644 hfinfo
->type
== FT_INT8
||
11645 hfinfo
->type
== FT_INT16
||
11646 hfinfo
->type
== FT_INT24
||
11647 hfinfo
->type
== FT_INT32
||
11648 hfinfo
->type
== FT_INT40
||
11649 hfinfo
->type
== FT_INT48
||
11650 hfinfo
->type
== FT_INT56
||
11651 hfinfo
->type
== FT_INT64
||
11652 hfinfo
->type
== FT_FLOAT
||
11653 hfinfo
->type
== FT_DOUBLE
)) {
11655 if (hfinfo
->display
& BASE_RANGE_STRING
) {
11656 range
= (const range_string
*)hfinfo
->strings
;
11657 } else if (hfinfo
->display
& BASE_EXT_STRING
) {
11658 if (hfinfo
->display
& BASE_VAL64_STRING
) {
11659 vals64
= VAL64_STRING_EXT_VS_P((const val64_string_ext
*)hfinfo
->strings
);
11661 vals
= VALUE_STRING_EXT_VS_P((const value_string_ext
*)hfinfo
->strings
);
11663 } else if (hfinfo
->display
& BASE_VAL64_STRING
) {
11664 vals64
= (const val64_string
*)hfinfo
->strings
;
11665 } else if (hfinfo
->display
& BASE_UNIT_STRING
) {
11666 units
= (const unit_name_string
*)hfinfo
->strings
;
11668 vals
= (const value_string
*)hfinfo
->strings
;
11671 else if (hfinfo
->type
== FT_BOOLEAN
) {
11672 tfs
= (const struct true_false_string
*)hfinfo
->strings
;
11676 /* Print value strings? */
11678 if (hfinfo
->display
& BASE_EXT_STRING
) {
11679 if (hfinfo
->display
& BASE_VAL64_STRING
) {
11680 val64_string_ext
*vse_p
= (val64_string_ext
*)hfinfo
->strings
;
11681 if (!val64_string_ext_validate(vse_p
)) {
11682 ws_warning("Invalid val64_string_ext ptr for: %s", hfinfo
->abbrev
);
11685 try_val64_to_str_ext(0, vse_p
); /* "prime" the extended val64_string */
11686 printf("E\t%s\t%u\t%s\t%s\n",
11688 VAL64_STRING_EXT_VS_NUM_ENTRIES(vse_p
),
11689 VAL64_STRING_EXT_VS_NAME(vse_p
),
11690 val64_string_ext_match_type_str(vse_p
));
11692 value_string_ext
*vse_p
= (value_string_ext
*)hfinfo
->strings
;
11693 if (!value_string_ext_validate(vse_p
)) {
11694 ws_warning("Invalid value_string_ext ptr for: %s", hfinfo
->abbrev
);
11697 try_val_to_str_ext(0, vse_p
); /* "prime" the extended value_string */
11698 printf("E\t%s\t%u\t%s\t%s\n",
11700 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p
),
11701 VALUE_STRING_EXT_VS_NAME(vse_p
),
11702 value_string_ext_match_type_str(vse_p
));
11706 while (vals
[vi
].strptr
) {
11707 /* Print in the proper base */
11708 if (hfinfo
->type
== FT_CHAR
) {
11709 if (g_ascii_isprint(vals
[vi
].value
)) {
11710 printf("V\t%s\t'%c'\t%s\n",
11715 if (hfinfo
->display
== BASE_HEX
) {
11716 printf("V\t%s\t'\\x%02x'\t%s\n",
11722 printf("V\t%s\t'\\%03o'\t%s\n",
11729 if (hfinfo
->display
== BASE_HEX
) {
11730 printf("V\t%s\t0x%x\t%s\n",
11736 printf("V\t%s\t%u\t%s\n",
11747 while (vals64
[vi
].strptr
) {
11748 printf("V64\t%s\t%" PRIu64
"\t%s\n",
11751 vals64
[vi
].strptr
);
11756 /* print range strings? */
11759 while (range
[vi
].strptr
) {
11760 /* Print in the proper base */
11761 if (FIELD_DISPLAY(hfinfo
->display
) == BASE_HEX
) {
11762 printf("R\t%s\t0x%"PRIx64
"\t0x%"PRIx64
"\t%s\n",
11764 range
[vi
].value_min
,
11765 range
[vi
].value_max
,
11769 printf("R\t%s\t%"PRIu64
"\t%"PRIu64
"\t%s\n",
11771 range
[vi
].value_min
,
11772 range
[vi
].value_max
,
11779 /* Print true/false strings? */
11781 printf("T\t%s\t%s\t%s\n", hfinfo
->abbrev
,
11782 tfs
->true_string
, tfs
->false_string
);
11784 /* Print unit strings? */
11786 printf("U\t%s\t%s\t%s\n", hfinfo
->abbrev
,
11787 units
->singular
, units
->plural
? units
->plural
: "(no plural)");
11792 /* Prints the number of registered fields.
11793 * Useful for determining an appropriate value for
11794 * PROTO_PRE_ALLOC_HF_FIELDS_MEM.
11796 * Returns false if PROTO_PRE_ALLOC_HF_FIELDS_MEM is larger than or equal to
11797 * the number of fields, true otherwise.
11800 proto_registrar_dump_fieldcount(void)
11803 header_field_info
*hfinfo
;
11804 uint32_t deregistered_count
= 0;
11805 uint32_t same_name_count
= 0;
11806 uint32_t protocol_count
= 0;
11808 for (i
= 0; i
< gpa_hfinfo
.len
; i
++) {
11809 if (gpa_hfinfo
.hfi
[i
] == NULL
) {
11810 deregistered_count
++;
11811 continue; /* This is a deregistered protocol or header field */
11814 PROTO_REGISTRAR_GET_NTH(i
, hfinfo
);
11816 if (proto_registrar_is_protocol(i
))
11819 if (hfinfo
->same_name_prev_id
!= -1)
11823 printf("There are %u header fields registered, of which:\n"
11824 "\t%u are deregistered\n"
11825 "\t%u are protocols\n"
11826 "\t%u have the same name as another field\n\n",
11827 gpa_hfinfo
.len
, deregistered_count
, protocol_count
,
11830 printf("%d fields were pre-allocated.\n%s", PROTO_PRE_ALLOC_HF_FIELDS_MEM
,
11831 (gpa_hfinfo
.allocated_len
> PROTO_PRE_ALLOC_HF_FIELDS_MEM
) ?
11832 "* * Please increase PROTO_PRE_ALLOC_HF_FIELDS_MEM (in epan/proto.c)! * *\n\n" :
11835 printf("The header field table consumes %u KiB of memory.\n",
11836 (unsigned int)(gpa_hfinfo
.allocated_len
* sizeof(header_field_info
*) / 1024));
11837 printf("The fields themselves consume %u KiB of memory.\n",
11838 (unsigned int)(gpa_hfinfo
.len
* sizeof(header_field_info
) / 1024));
11840 return (gpa_hfinfo
.allocated_len
> PROTO_PRE_ALLOC_HF_FIELDS_MEM
);
11844 elastic_add_base_mapping(json_dumper
*dumper
)
11846 json_dumper_set_member_name(dumper
, "settings");
11847 json_dumper_begin_object(dumper
);
11848 json_dumper_set_member_name(dumper
, "index.mapping.total_fields.limit");
11849 json_dumper_value_anyf(dumper
, "%d", 1000000);
11850 json_dumper_end_object(dumper
);
11854 ws_type_to_elastic(unsigned type _U_
)
11871 case FT_UINT64
: // Actually it's not handled by 'long' elastic type.
11881 case FT_ABSOLUTE_TIME
:
11882 case FT_RELATIVE_TIME
:
11885 case FT_UINT_BYTES
:
11895 dot_to_underscore(char* str
)
11898 for (i
= 0; i
< strlen(str
); i
++) {
11905 /* Dumps a mapping file for ElasticSearch
11908 proto_registrar_dump_elastic(const char* filter
)
11910 header_field_info
*hfinfo
;
11911 header_field_info
*parent_hfinfo
;
11913 bool open_object
= true;
11914 const char* prev_proto
= NULL
;
11916 char** protos
= NULL
;
11921 char* prev_item
= NULL
;
11923 /* We have filtering protocols. Extract them. */
11925 protos
= g_strsplit(filter
, ",", -1);
11929 * To help tracking down the json tree, objects have been appended with a comment:
11930 * n.label -> where n is the indentation level and label the name of the object
11933 json_dumper dumper
= {
11934 .output_file
= stdout
,
11935 .flags
= JSON_DUMPER_FLAGS_PRETTY_PRINT
,
11937 json_dumper_begin_object(&dumper
); // 1.root
11938 elastic_add_base_mapping(&dumper
);
11940 json_dumper_set_member_name(&dumper
, "mappings");
11941 json_dumper_begin_object(&dumper
); // 2.mappings
11942 json_dumper_set_member_name(&dumper
, "dynamic");
11943 json_dumper_value_anyf(&dumper
, "false");
11945 json_dumper_set_member_name(&dumper
, "properties");
11946 json_dumper_begin_object(&dumper
); // 3.properties
11947 json_dumper_set_member_name(&dumper
, "timestamp");
11948 json_dumper_begin_object(&dumper
); // 4.timestamp
11949 json_dumper_set_member_name(&dumper
, "type");
11950 json_dumper_value_string(&dumper
, "date");
11951 json_dumper_end_object(&dumper
); // 4.timestamp
11953 json_dumper_set_member_name(&dumper
, "layers");
11954 json_dumper_begin_object(&dumper
); // 4.layers
11955 json_dumper_set_member_name(&dumper
, "properties");
11956 json_dumper_begin_object(&dumper
); // 5.properties
11958 for (i
= 0; i
< gpa_hfinfo
.len
; i
++) {
11959 if (gpa_hfinfo
.hfi
[i
] == NULL
)
11960 continue; /* This is a deregistered protocol or header field */
11962 PROTO_REGISTRAR_GET_NTH(i
, hfinfo
);
11965 * Skip the pseudo-field for "proto_tree_add_text()" since
11966 * we don't want it in the list of filterable protocols.
11968 if (hfinfo
->id
== hf_text_only
)
11971 if (!proto_registrar_is_protocol(i
)) {
11972 PROTO_REGISTRAR_GET_NTH(hfinfo
->parent
, parent_hfinfo
);
11975 * Skip the field if filter protocols have been set and this one's
11976 * parent is not listed.
11983 if (!g_strcmp0(proto
, parent_hfinfo
->abbrev
)) {
11994 if (prev_proto
&& g_strcmp0(parent_hfinfo
->abbrev
, prev_proto
)) {
11995 json_dumper_end_object(&dumper
); // 7.properties
11996 json_dumper_end_object(&dumper
); // 8.parent_hfinfo->abbrev
11997 open_object
= true;
12000 prev_proto
= parent_hfinfo
->abbrev
;
12003 json_dumper_set_member_name(&dumper
, parent_hfinfo
->abbrev
);
12004 json_dumper_begin_object(&dumper
); // 6.parent_hfinfo->abbrev
12005 json_dumper_set_member_name(&dumper
, "properties");
12006 json_dumper_begin_object(&dumper
); // 7.properties
12007 open_object
= false;
12009 /* Skip the fields that would map into string. This is the default in elasticsearch. */
12010 type
= ws_type_to_elastic(hfinfo
->type
);
12011 /* when type is NULL, we have the default mapping: string */
12013 str
= ws_strdup_printf("%s_%s", prev_proto
, hfinfo
->abbrev
);
12014 dot_to_underscore(str
);
12015 if (g_strcmp0(prev_item
, str
)) {
12016 json_dumper_set_member_name(&dumper
, str
);
12017 json_dumper_begin_object(&dumper
); // 8.hfinfo->abbrev
12018 json_dumper_set_member_name(&dumper
, "type");
12019 json_dumper_value_string(&dumper
, type
);
12020 json_dumper_end_object(&dumper
); // 8.hfinfo->abbrev
12030 json_dumper_end_object(&dumper
); // 7.properties
12031 json_dumper_end_object(&dumper
); // 6.parent_hfinfo->abbrev
12034 json_dumper_end_object(&dumper
); // 5.properties
12035 json_dumper_end_object(&dumper
); // 4.layers
12036 json_dumper_end_object(&dumper
); // 3.properties
12037 json_dumper_end_object(&dumper
); // 2.mappings
12038 json_dumper_end_object(&dumper
); // 1.root
12039 bool ret
= json_dumper_finish(&dumper
);
12040 DISSECTOR_ASSERT(ret
);
12042 g_strfreev(protos
);
12045 /* Dumps the contents of the registration database to stdout. An independent
12046 * program can take this output and format it into nice tables or HTML or
12049 * There is one record per line. Each record is either a protocol or a header
12050 * field, differentiated by the first field. The fields are tab-delimited.
12055 * Field 2 = descriptive protocol name
12056 * Field 3 = protocol abbreviation
12061 * Field 2 = descriptive field name
12062 * Field 3 = field abbreviation
12063 * Field 4 = type ( textual representation of the ftenum type )
12064 * Field 5 = parent protocol abbreviation
12065 * Field 6 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
12066 * Field 7 = bitmask: format: hex: 0x....
12067 * Field 8 = blurb describing field
12070 proto_registrar_dump_fields(void)
12072 header_field_info
*hfinfo
, *parent_hfinfo
;
12074 const char *enum_name
;
12075 const char *base_name
;
12079 len
= gpa_hfinfo
.len
;
12080 for (i
= 0; i
< len
; i
++) {
12081 if (gpa_hfinfo
.hfi
[i
] == NULL
)
12082 continue; /* This is a deregistered protocol or header field */
12084 PROTO_REGISTRAR_GET_NTH(i
, hfinfo
);
12087 * Skip the pseudo-field for "proto_tree_add_text()" since
12088 * we don't want it in the list of filterable fields.
12090 if (hfinfo
->id
== hf_text_only
)
12093 /* format for protocols */
12094 if (proto_registrar_is_protocol(i
)) {
12095 printf("P\t%s\t%s\n", hfinfo
->name
, hfinfo
->abbrev
);
12097 /* format for header fields */
12100 * If this field isn't at the head of the list of
12101 * fields with this name, skip this field - all
12102 * fields with the same name are really just versions
12103 * of the same field stored in different bits, and
12104 * should have the same type/radix/value list, and
12105 * just differ in their bit masks. (If a field isn't
12106 * a bitfield, but can be, say, 1 or 2 bytes long,
12107 * it can just be made FT_UINT16, meaning the
12108 * *maximum* length is 2 bytes, and be used
12109 * for all lengths.)
12111 if (hfinfo
->same_name_prev_id
!= -1)
12114 PROTO_REGISTRAR_GET_NTH(hfinfo
->parent
, parent_hfinfo
);
12116 enum_name
= ftype_name(hfinfo
->type
);
12119 if (hfinfo
->type
== FT_CHAR
||
12120 hfinfo
->type
== FT_UINT8
||
12121 hfinfo
->type
== FT_UINT16
||
12122 hfinfo
->type
== FT_UINT24
||
12123 hfinfo
->type
== FT_UINT32
||
12124 hfinfo
->type
== FT_UINT40
||
12125 hfinfo
->type
== FT_UINT48
||
12126 hfinfo
->type
== FT_UINT56
||
12127 hfinfo
->type
== FT_UINT64
||
12128 hfinfo
->type
== FT_INT8
||
12129 hfinfo
->type
== FT_INT16
||
12130 hfinfo
->type
== FT_INT24
||
12131 hfinfo
->type
== FT_INT32
||
12132 hfinfo
->type
== FT_INT40
||
12133 hfinfo
->type
== FT_INT48
||
12134 hfinfo
->type
== FT_INT56
||
12135 hfinfo
->type
== FT_INT64
) {
12137 switch (FIELD_DISPLAY(hfinfo
->display
)) {
12150 base_name
= val_to_str_const(FIELD_DISPLAY(hfinfo
->display
), hf_display
, "????");
12153 base_name
= "????";
12156 } else if (hfinfo
->type
== FT_BOOLEAN
) {
12157 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
12158 snprintf(width
, sizeof(width
), "%d", hfinfo
->display
);
12162 blurb
= hfinfo
->blurb
;
12165 else if (strlen(blurb
) == 0)
12168 printf("F\t%s\t%s\t%s\t%s\t%s\t0x%" PRIx64
"\t%s\n",
12169 hfinfo
->name
, hfinfo
->abbrev
, enum_name
,
12170 parent_hfinfo
->abbrev
, base_name
,
12171 hfinfo
->bitmask
, blurb
);
12176 /* Dumps all abbreviated field and protocol completions of the given string to
12177 * stdout. An independent program may use this for command-line tab completion
12181 proto_registrar_dump_field_completions(const char *prefix
)
12183 header_field_info
*hfinfo
;
12186 bool matched
= false;
12188 prefix_len
= strlen(prefix
);
12189 len
= gpa_hfinfo
.len
;
12190 for (i
= 0; i
< len
; i
++) {
12191 if (gpa_hfinfo
.hfi
[i
] == NULL
)
12192 continue; /* This is a deregistered protocol or header field */
12194 PROTO_REGISTRAR_GET_NTH(i
, hfinfo
);
12197 * Skip the pseudo-field for "proto_tree_add_text()" since
12198 * we don't want it in the list of filterable fields.
12200 if (hfinfo
->id
== hf_text_only
)
12203 /* format for protocols */
12204 if (proto_registrar_is_protocol(i
)) {
12205 if(0 == strncmp(hfinfo
->abbrev
, prefix
, prefix_len
)) {
12207 printf("%s\t%s\n", hfinfo
->abbrev
, hfinfo
->name
);
12210 /* format for header fields */
12213 * If this field isn't at the head of the list of
12214 * fields with this name, skip this field - all
12215 * fields with the same name are really just versions
12216 * of the same field stored in different bits, and
12217 * should have the same type/radix/value list, and
12218 * just differ in their bit masks. (If a field isn't
12219 * a bitfield, but can be, say, 1 or 2 bytes long,
12220 * it can just be made FT_UINT16, meaning the
12221 * *maximum* length is 2 bytes, and be used
12222 * for all lengths.)
12224 if (hfinfo
->same_name_prev_id
!= -1)
12227 if(0 == strncmp(hfinfo
->abbrev
, prefix
, prefix_len
)) {
12229 printf("%s\t%s\n", hfinfo
->abbrev
, hfinfo
->name
);
12236 /* Dumps field types and descriptive names to stdout. An independent
12237 * program can take this output and format it into nice tables or HTML or
12240 * There is one record per line. The fields are tab-delimited.
12242 * Field 1 = field type name, e.g. FT_UINT8
12243 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
12246 proto_registrar_dump_ftypes(void)
12250 for (fte
= 0; fte
< FT_NUM_TYPES
; fte
++) {
12251 printf("%s\t%s\n", ftype_name((ftenum_t
)fte
), ftype_pretty_name((ftenum_t
)fte
));
12255 /* This function indicates whether it's possible to construct a
12256 * "match selected" display filter string for the specified field,
12257 * returns an indication of whether it's possible, and, if it's
12258 * possible and "filter" is non-null, constructs the filter and
12259 * sets "*filter" to point to it.
12260 * You do not need to [g_]free() this string since it will be automatically
12261 * freed once the next packet is dissected.
12264 construct_match_selected_string(const field_info
*finfo
, epan_dissect_t
*edt
,
12267 const header_field_info
*hfinfo
;
12271 int start
, length
, length_remaining
;
12277 hfinfo
= finfo
->hfinfo
;
12278 DISSECTOR_ASSERT(hfinfo
);
12280 /* If we have BASE_NONE and strings (a non-NULL FIELDCONVERT),
12281 * then "the numeric value ... is not used when preparing
12282 * filters for the field in question." If it's any other
12283 * base, we'll generate the filter normally (which will
12284 * be numeric, even though the human-readable string does
12285 * work for filtering.)
12287 * XXX - It might be nice to use fvalue_to_string_repr() in
12288 * "proto_item_fill_label()" as well, although, there, you'd
12289 * have to deal with the base *and* with resolved values for
12292 * Perhaps in addition to taking the repr type (DISPLAY
12293 * or DFILTER) and the display (base), fvalue_to_string_repr()
12294 * should have the the "strings" values in the header_field_info
12295 * structure for the field as a parameter, so it can have
12296 * if the field is Boolean or an enumerated integer type,
12297 * the tables used to generate human-readable values.
12299 if (hfinfo
->strings
&& FIELD_DISPLAY(hfinfo
->display
) == BASE_NONE
) {
12300 const char *str
= NULL
;
12302 switch (hfinfo
->type
) {
12308 str
= hf_try_val_to_str(fvalue_get_sinteger(finfo
->value
), hfinfo
);
12316 str
= hf_try_val_to_str(fvalue_get_uinteger(finfo
->value
), hfinfo
);
12323 if (str
!= NULL
&& filter
!= NULL
) {
12324 *filter
= wmem_strdup_printf(NULL
, "%s == \"%s\"", hfinfo
->abbrev
, str
);
12329 switch (hfinfo
->type
) {
12332 if (filter
!= NULL
)
12333 *filter
= wmem_strdup(NULL
, finfo
->hfinfo
->abbrev
);
12338 * If the length is 0, just match the name of the
12341 * (Also check for negative values, just in case,
12342 * as we'll cast it to an unsigned value later.)
12344 length
= finfo
->length
;
12346 if (filter
!= NULL
)
12347 *filter
= wmem_strdup(NULL
, finfo
->hfinfo
->abbrev
);
12354 * This doesn't have a value, so we'd match
12355 * on the raw bytes at this address.
12357 * Should we be allowed to access to the raw bytes?
12358 * If "edt" is NULL, the answer is "no".
12364 * Is this field part of the raw frame tvbuff?
12365 * If not, we can't use "frame[N:M]" to match
12368 * XXX - should this be frame-relative, or
12369 * protocol-relative?
12371 * XXX - does this fallback for non-registered
12372 * fields even make sense?
12374 if (finfo
->ds_tvb
!= edt
->tvb
)
12375 return false; /* you lose */
12378 * Don't go past the end of that tvbuff.
12380 length_remaining
= tvb_captured_length_remaining(finfo
->ds_tvb
, finfo
->start
);
12381 if (length
> length_remaining
)
12382 length
= length_remaining
;
12386 if (filter
!= NULL
) {
12387 start
= finfo
->start
;
12388 buf_len
= 32 + length
* 3;
12389 *filter
= (char *)wmem_alloc0(NULL
, buf_len
);
12392 ptr
+= snprintf(ptr
, buf_len
-(ptr
-*filter
),
12393 "frame[%d:%d] == ", finfo
->start
, length
);
12394 for (i
=0; i
<length
; i
++) {
12395 c
= tvb_get_uint8(finfo
->ds_tvb
, start
);
12398 ptr
+= snprintf(ptr
, buf_len
-(ptr
-*filter
), "%02x", c
);
12401 ptr
+= snprintf(ptr
, buf_len
-(ptr
-*filter
), ":%02x", c
);
12407 /* By default, use the fvalue's "to_string_repr" method. */
12409 if (filter
!= NULL
) {
12410 char *str
= fvalue_to_string_repr(NULL
, finfo
->value
, FTREPR_DFILTER
, finfo
->hfinfo
->display
);
12411 *filter
= wmem_strdup_printf(NULL
, "%s == %s", hfinfo
->abbrev
, str
);
12412 wmem_free(NULL
, str
);
12421 * Returns true if we can do a "match selected" on the field, false
12425 proto_can_match_selected(const field_info
*finfo
, epan_dissect_t
*edt
)
12427 return construct_match_selected_string(finfo
, edt
, NULL
);
12430 /* This function attempts to construct a "match selected" display filter
12431 * string for the specified field; if it can do so, it returns a pointer
12432 * to the string, otherwise it returns NULL.
12434 * The string is wmem allocated and must be freed with "wmem_free(NULL, ...)".
12437 proto_construct_match_selected_string(const field_info
*finfo
, epan_dissect_t
*edt
)
12439 char *filter
= NULL
;
12441 if (!construct_match_selected_string(finfo
, edt
, &filter
))
12443 wmem_free(NULL
, filter
);
12449 /* This function is common code for all proto_tree_add_bitmask... functions.
12453 proto_item_add_bitmask_tree(proto_item
*item
, tvbuff_t
*tvb
, const int offset
,
12454 const int len
, const int ett
, int * const *fields
,
12455 const int flags
, bool first
,
12456 bool use_parent_tree
,
12457 proto_tree
* tree
, uint64_t value
)
12459 uint64_t available_bits
= UINT64_MAX
;
12460 uint64_t bitmask
= 0;
12462 header_field_info
*hf
;
12463 uint32_t integer32
;
12468 REPORT_DISSECTOR_BUG("Illegal call of proto_item_add_bitmask_tree without fields");
12470 if (len
< 0 || len
> 8)
12471 REPORT_DISSECTOR_BUG("Invalid len: %d", len
);
12473 * packet-frame.c uses len=0 since the value is taken from the packet
12474 * metadata, not the packet bytes. In that case, assume that all bits
12475 * in the provided value are valid.
12478 available_bits
>>= (8 - (unsigned)len
)*8;
12481 if (use_parent_tree
== false)
12482 tree
= proto_item_add_subtree(item
, ett
);
12485 uint64_t present_bits
;
12486 PROTO_REGISTRAR_GET_NTH(**fields
,hf
);
12487 DISSECTOR_ASSERT_HINT(hf
->bitmask
!= 0, hf
->abbrev
);
12489 bitmask
|= hf
->bitmask
;
12491 /* Skip fields that aren't fully present */
12492 present_bits
= available_bits
& hf
->bitmask
;
12493 if (present_bits
!= hf
->bitmask
) {
12498 switch (hf
->type
) {
12504 proto_tree_add_uint(tree
, **fields
, tvb
, offset
, len
, (uint32_t)value
);
12511 proto_tree_add_int(tree
, **fields
, tvb
, offset
, len
, (int32_t)value
);
12518 proto_tree_add_uint64(tree
, **fields
, tvb
, offset
, len
, value
);
12525 proto_tree_add_int64(tree
, **fields
, tvb
, offset
, len
, (int64_t)value
);
12529 proto_tree_add_boolean(tree
, **fields
, tvb
, offset
, len
, value
);
12533 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_item_add_bitmask_tree()",
12536 ftype_name(hf
->type
));
12539 if (flags
& BMT_NO_APPEND
) {
12543 tmpval
= (value
& hf
->bitmask
) >> hfinfo_bitshift(hf
);
12545 /* XXX: README.developer and the comments have always defined
12546 * BMT_NO_INT as "only boolean flags are added to the title /
12547 * don't add non-boolean (integral) fields", but the
12548 * implementation has always added BASE_CUSTOM and fields with
12549 * value_strings, though not fields with unit_strings.
12550 * Possibly this is because some dissectors use a FT_UINT8
12551 * with a value_string for fields that should be a FT_BOOLEAN.
12553 switch (hf
->type
) {
12555 if (hf
->display
== BASE_CUSTOM
) {
12556 char lbl
[ITEM_LABEL_LENGTH
];
12557 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hf
->strings
;
12559 DISSECTOR_ASSERT(fmtfunc
);
12560 fmtfunc(lbl
, (uint32_t) tmpval
);
12561 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12565 else if (hf
->strings
) {
12566 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12567 hf
->name
, hf_try_val_to_str_const((uint32_t) tmpval
, hf
, "Unknown"));
12570 else if (!(flags
& BMT_NO_INT
)) {
12575 proto_item_append_text(item
, ", ");
12578 out
= hfinfo_char_value_format(hf
, buf
, (uint32_t) tmpval
);
12579 proto_item_append_text(item
, "%s: %s", hf
->name
, out
);
12589 if (hf
->display
== BASE_CUSTOM
) {
12590 char lbl
[ITEM_LABEL_LENGTH
];
12591 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hf
->strings
;
12593 DISSECTOR_ASSERT(fmtfunc
);
12594 fmtfunc(lbl
, (uint32_t) tmpval
);
12595 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12599 else if ((hf
->strings
) &&(!(hf
->display
& (BASE_UNIT_STRING
|BASE_SPECIAL_VALS
)))) {
12600 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12601 hf
->name
, hf_try_val_to_str_const((uint32_t) tmpval
, hf
, "Unknown"));
12604 else if (!(flags
& BMT_NO_INT
)) {
12605 char buf
[NUMBER_LABEL_LENGTH
];
12606 const char *out
= NULL
;
12609 proto_item_append_text(item
, ", ");
12612 if (hf
->strings
&& hf
->display
& BASE_SPECIAL_VALS
) {
12613 out
= hf_try_val_to_str((uint32_t) tmpval
, hf
);
12616 out
= hfinfo_number_value_format(hf
, buf
, (uint32_t) tmpval
);
12618 proto_item_append_text(item
, "%s: %s", hf
->name
, out
);
12619 if (hf
->strings
&& hf
->display
& BASE_UNIT_STRING
) {
12620 proto_item_append_text(item
, "%s", unit_name_string_get_value((uint32_t) tmpval
, (const unit_name_string
*)hf
->strings
));
12631 integer32
= (uint32_t) tmpval
;
12633 no_of_bits
= ws_count_ones(hf
->bitmask
);
12634 integer32
= ws_sign_ext32(integer32
, no_of_bits
);
12636 if (hf
->display
== BASE_CUSTOM
) {
12637 char lbl
[ITEM_LABEL_LENGTH
];
12638 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hf
->strings
;
12640 DISSECTOR_ASSERT(fmtfunc
);
12641 fmtfunc(lbl
, (int32_t) integer32
);
12642 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12646 else if ((hf
->strings
) &&(!(hf
->display
& (BASE_UNIT_STRING
|BASE_SPECIAL_VALS
)))) {
12647 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12648 hf
->name
, hf_try_val_to_str_const((int32_t) integer32
, hf
, "Unknown"));
12651 else if (!(flags
& BMT_NO_INT
)) {
12652 char buf
[NUMBER_LABEL_LENGTH
];
12653 const char *out
= NULL
;
12656 proto_item_append_text(item
, ", ");
12659 if (hf
->strings
&& hf
->display
& BASE_SPECIAL_VALS
) {
12660 out
= hf_try_val_to_str((int32_t) integer32
, hf
);
12663 out
= hfinfo_number_value_format(hf
, buf
, (int32_t) integer32
);
12665 proto_item_append_text(item
, "%s: %s", hf
->name
, out
);
12666 if (hf
->display
& BASE_UNIT_STRING
) {
12667 proto_item_append_text(item
, "%s", unit_name_string_get_value((uint32_t) tmpval
, (const unit_name_string
*)hf
->strings
));
12678 if (hf
->display
== BASE_CUSTOM
) {
12679 char lbl
[ITEM_LABEL_LENGTH
];
12680 const custom_fmt_func_64_t fmtfunc
= (const custom_fmt_func_64_t
)hf
->strings
;
12682 DISSECTOR_ASSERT(fmtfunc
);
12683 fmtfunc(lbl
, tmpval
);
12684 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12688 else if ((hf
->strings
) &&(!(hf
->display
& (BASE_UNIT_STRING
|BASE_SPECIAL_VALS
)))) {
12689 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12690 hf
->name
, hf_try_val64_to_str_const(tmpval
, hf
, "Unknown"));
12693 else if (!(flags
& BMT_NO_INT
)) {
12694 char buf
[NUMBER_LABEL_LENGTH
];
12695 const char *out
= NULL
;
12698 proto_item_append_text(item
, ", ");
12701 if (hf
->strings
&& hf
->display
& BASE_SPECIAL_VALS
) {
12702 out
= hf_try_val64_to_str(tmpval
, hf
);
12705 out
= hfinfo_number_value_format64(hf
, buf
, tmpval
);
12707 proto_item_append_text(item
, "%s: %s", hf
->name
, out
);
12708 if (hf
->strings
&& hf
->display
& BASE_UNIT_STRING
) {
12709 proto_item_append_text(item
, "%s", unit_name_string_get_value64(tmpval
, (const unit_name_string
*)hf
->strings
));
12721 no_of_bits
= ws_count_ones(hf
->bitmask
);
12722 tmpval
= ws_sign_ext64(tmpval
, no_of_bits
);
12724 if (hf
->display
== BASE_CUSTOM
) {
12725 char lbl
[ITEM_LABEL_LENGTH
];
12726 const custom_fmt_func_64_t fmtfunc
= (const custom_fmt_func_64_t
)hf
->strings
;
12728 DISSECTOR_ASSERT(fmtfunc
);
12729 fmtfunc(lbl
, (int64_t) tmpval
);
12730 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12734 else if ((hf
->strings
) &&(!(hf
->display
& (BASE_UNIT_STRING
|BASE_SPECIAL_VALS
)))) {
12735 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12736 hf
->name
, hf_try_val64_to_str_const((int64_t) tmpval
, hf
, "Unknown"));
12739 else if (!(flags
& BMT_NO_INT
)) {
12740 char buf
[NUMBER_LABEL_LENGTH
];
12741 const char *out
= NULL
;
12744 proto_item_append_text(item
, ", ");
12747 if (hf
->strings
&& hf
->display
& BASE_SPECIAL_VALS
) {
12748 out
= hf_try_val64_to_str((int64_t) tmpval
, hf
);
12751 out
= hfinfo_number_value_format64(hf
, buf
, (int64_t) tmpval
);
12753 proto_item_append_text(item
, "%s: %s", hf
->name
, out
);
12754 if (hf
->strings
&& hf
->display
& BASE_UNIT_STRING
) {
12755 proto_item_append_text(item
, "%s", unit_name_string_get_value64(tmpval
, (const unit_name_string
*)hf
->strings
));
12763 if (hf
->strings
&& !(flags
& BMT_NO_TFS
)) {
12764 /* If we have true/false strings, emit full - otherwise messages
12765 might look weird */
12766 const struct true_false_string
*tfs
=
12767 (const struct true_false_string
*)hf
->strings
;
12770 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12771 hf
->name
, tfs
->true_string
);
12773 } else if (!(flags
& BMT_NO_FALSE
)) {
12774 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12775 hf
->name
, tfs
->false_string
);
12778 } else if (hf
->bitmask
& value
) {
12779 /* If the flag is set, show the name */
12780 proto_item_append_text(item
, "%s%s", first
? "" : ", ", hf
->name
);
12785 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_item_add_bitmask_tree()",
12788 ftype_name(hf
->type
));
12795 /* XXX: We don't pass the hfi into this function. Perhaps we should,
12796 * but then again most dissectors don't set the bitmask field for
12797 * the higher level bitmask hfi, so calculate the bitmask from the
12798 * fields present. */
12800 bit_offset
= len
*8 - 1 - ws_ilog2(bitmask
);
12801 no_of_bits
= ws_ilog2(bitmask
) - ws_ctz(bitmask
) + 1;
12802 FI_SET_FLAG(PNODE_FINFO(item
), FI_BITS_OFFSET(bit_offset
));
12803 FI_SET_FLAG(PNODE_FINFO(item
), FI_BITS_SIZE(no_of_bits
));
12808 /* This function will dissect a sequence of bytes that describe a
12809 * bitmask and supply the value of that sequence through a pointer.
12810 * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
12812 * This field will form an expansion under which the individual fields of the
12813 * bitmask is dissected and displayed.
12814 * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
12816 * fields is an array of pointers to int that lists all the fields of the
12817 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
12818 * or another integer of the same type/size as hf_hdr with a mask specified.
12819 * This array is terminated by a NULL entry.
12821 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
12822 * FT_integer fields that have a value_string attached will have the
12823 * matched string displayed on the expansion line.
12826 proto_tree_add_bitmask_ret_uint64(proto_tree
*parent_tree
, tvbuff_t
*tvb
,
12827 const unsigned offset
, const int hf_hdr
,
12828 const int ett
, int * const *fields
,
12829 const unsigned encoding
, uint64_t *retval
)
12831 return proto_tree_add_bitmask_with_flags_ret_uint64(parent_tree
, tvb
, offset
, hf_hdr
, ett
, fields
, encoding
, BMT_NO_INT
|BMT_NO_TFS
, retval
);
12834 /* This function will dissect a sequence of bytes that describe a
12836 * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
12838 * This field will form an expansion under which the individual fields of the
12839 * bitmask is dissected and displayed.
12840 * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
12842 * fields is an array of pointers to int that lists all the fields of the
12843 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
12844 * or another integer of the same type/size as hf_hdr with a mask specified.
12845 * This array is terminated by a NULL entry.
12847 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
12848 * FT_integer fields that have a value_string attached will have the
12849 * matched string displayed on the expansion line.
12852 proto_tree_add_bitmask(proto_tree
*parent_tree
, tvbuff_t
*tvb
,
12853 const unsigned offset
, const int hf_hdr
,
12854 const int ett
, int * const *fields
,
12855 const unsigned encoding
)
12857 return proto_tree_add_bitmask_with_flags(parent_tree
, tvb
, offset
, hf_hdr
, ett
, fields
, encoding
, BMT_NO_INT
|BMT_NO_TFS
);
12860 /* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
12861 * what data is appended to the header.
12864 proto_tree_add_bitmask_with_flags_ret_uint64(proto_tree
*parent_tree
, tvbuff_t
*tvb
, const unsigned offset
,
12865 const int hf_hdr
, const int ett
, int * const *fields
, const unsigned encoding
, const int flags
,
12868 proto_item
*item
= NULL
;
12869 header_field_info
*hf
;
12873 PROTO_REGISTRAR_GET_NTH(hf_hdr
,hf
);
12874 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf
);
12875 len
= ftype_wire_size(hf
->type
);
12876 value
= get_uint64_value(parent_tree
, tvb
, offset
, len
, encoding
);
12879 item
= proto_tree_add_item(parent_tree
, hf_hdr
, tvb
, offset
, len
, encoding
);
12880 proto_item_add_bitmask_tree(item
, tvb
, offset
, len
, ett
, fields
,
12881 flags
, false, false, NULL
, value
);
12886 /* Mask out irrelevant portions */
12887 *retval
&= hf
->bitmask
;
12889 *retval
>>= hfinfo_bitshift(hf
);
12895 /* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
12896 * what data is appended to the header.
12899 proto_tree_add_bitmask_with_flags(proto_tree
*parent_tree
, tvbuff_t
*tvb
, const unsigned offset
,
12900 const int hf_hdr
, const int ett
, int * const *fields
, const unsigned encoding
, const int flags
)
12902 proto_item
*item
= NULL
;
12903 header_field_info
*hf
;
12907 PROTO_REGISTRAR_GET_NTH(hf_hdr
,hf
);
12908 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf
);
12911 len
= ftype_wire_size(hf
->type
);
12912 item
= proto_tree_add_item(parent_tree
, hf_hdr
, tvb
, offset
, len
, encoding
);
12913 value
= get_uint64_value(parent_tree
, tvb
, offset
, len
, encoding
);
12914 proto_item_add_bitmask_tree(item
, tvb
, offset
, len
, ett
, fields
,
12915 flags
, false, false, NULL
, value
);
12921 /* Similar to proto_tree_add_bitmask(), but with a passed in value (presumably because it
12922 can't be retrieved directly from tvb) */
12924 proto_tree_add_bitmask_value(proto_tree
*parent_tree
, tvbuff_t
*tvb
, const unsigned offset
,
12925 const int hf_hdr
, const int ett
, int * const *fields
, const uint64_t value
)
12927 return proto_tree_add_bitmask_value_with_flags(parent_tree
, tvb
, offset
,
12928 hf_hdr
, ett
, fields
, value
, BMT_NO_INT
|BMT_NO_TFS
);
12931 /* Similar to proto_tree_add_bitmask_value(), but with control of flag values */
12932 WS_DLL_PUBLIC proto_item
*
12933 proto_tree_add_bitmask_value_with_flags(proto_tree
*parent_tree
, tvbuff_t
*tvb
, const unsigned offset
,
12934 const int hf_hdr
, const int ett
, int * const *fields
, const uint64_t value
, const int flags
)
12936 proto_item
*item
= NULL
;
12937 header_field_info
*hf
;
12940 PROTO_REGISTRAR_GET_NTH(hf_hdr
,hf
);
12941 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf
);
12942 /* the proto_tree_add_uint/_uint64() calls below
12943 will fail if tvb==NULL and len!=0 */
12944 len
= tvb
? ftype_wire_size(hf
->type
) : 0;
12948 item
= proto_tree_add_uint(parent_tree
, hf_hdr
, tvb
, offset
, len
, (uint32_t)value
);
12950 item
= proto_tree_add_uint64(parent_tree
, hf_hdr
, tvb
, offset
, len
, value
);
12952 proto_item_add_bitmask_tree(item
, tvb
, offset
, len
, ett
, fields
,
12953 flags
, false, false, NULL
, value
);
12959 /* Similar to proto_tree_add_bitmask(), but with no "header" item to group all of the fields */
12961 proto_tree_add_bitmask_list(proto_tree
*tree
, tvbuff_t
*tvb
, const unsigned offset
,
12962 const int len
, int * const *fields
, const unsigned encoding
)
12967 value
= get_uint64_value(tree
, tvb
, offset
, len
, encoding
);
12968 proto_item_add_bitmask_tree(NULL
, tvb
, offset
, len
, -1, fields
,
12969 BMT_NO_APPEND
, false, true, tree
, value
);
12974 proto_tree_add_bitmask_list_ret_uint64(proto_tree
*tree
, tvbuff_t
*tvb
, const unsigned offset
,
12975 const int len
, int * const *fields
, const unsigned encoding
, uint64_t *retval
)
12979 value
= get_uint64_value(tree
, tvb
, offset
, len
, encoding
);
12981 proto_item_add_bitmask_tree(NULL
, tvb
, offset
, len
, -1, fields
,
12982 BMT_NO_APPEND
, false, true, tree
, value
);
12990 proto_tree_add_bitmask_list_value(proto_tree
*tree
, tvbuff_t
*tvb
, const unsigned offset
,
12991 const int len
, int * const *fields
, const uint64_t value
)
12994 proto_item_add_bitmask_tree(NULL
, tvb
, offset
, len
, -1, fields
,
12995 BMT_NO_APPEND
, false, true, tree
, value
);
13000 /* The same as proto_tree_add_bitmask(), but using a caller-supplied length.
13001 * This is intended to support bitmask fields whose lengths can vary, perhaps
13002 * as the underlying standard evolves over time.
13003 * With this API there is the possibility of being called to display more or
13004 * less data than the dissector was coded to support.
13005 * In such cases, it is assumed that bitmasks are extended on the MSb end.
13006 * Thus when presented with "too much" or "too little" data, MSbits will be
13007 * ignored or MSfields sacrificed.
13009 * Only fields for which all defined bits are available are displayed.
13012 proto_tree_add_bitmask_len(proto_tree
*parent_tree
, tvbuff_t
*tvb
,
13013 const unsigned offset
, const unsigned len
, const int hf_hdr
,
13014 const int ett
, int * const *fields
, struct expert_field
* exp
,
13015 const unsigned encoding
)
13017 proto_item
*item
= NULL
;
13018 header_field_info
*hf
;
13019 unsigned decodable_len
;
13020 unsigned decodable_offset
;
13021 uint32_t decodable_value
;
13024 PROTO_REGISTRAR_GET_NTH(hf_hdr
, hf
);
13025 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf
);
13027 decodable_offset
= offset
;
13028 decodable_len
= MIN(len
, (unsigned) ftype_wire_size(hf
->type
));
13030 /* If we are ftype_wire_size-limited,
13031 * make sure we decode as many LSBs as possible.
13033 if (encoding
== ENC_BIG_ENDIAN
) {
13034 decodable_offset
+= (len
- decodable_len
);
13038 decodable_value
= get_uint_value(parent_tree
, tvb
, decodable_offset
,
13039 decodable_len
, encoding
);
13041 /* The root item covers all the bytes even if we can't decode them all */
13042 item
= proto_tree_add_uint(parent_tree
, hf_hdr
, tvb
, offset
, len
,
13046 if (decodable_len
< len
) {
13047 /* Dissector likely requires updating for new protocol revision */
13048 expert_add_info_format(NULL
, item
, exp
,
13049 "Only least-significant %d of %d bytes decoded",
13050 decodable_len
, len
);
13054 value
= get_uint64_value(parent_tree
, tvb
, decodable_offset
, decodable_len
, encoding
);
13055 proto_item_add_bitmask_tree(item
, tvb
, decodable_offset
, decodable_len
,
13056 ett
, fields
, BMT_NO_INT
|BMT_NO_TFS
, false, false, NULL
, value
);
13062 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
13064 proto_tree_add_bitmask_text(proto_tree
*parent_tree
, tvbuff_t
*tvb
,
13065 const unsigned offset
, const unsigned len
,
13066 const char *name
, const char *fallback
,
13067 const int ett
, int * const *fields
,
13068 const unsigned encoding
, const int flags
)
13070 proto_item
*item
= NULL
;
13074 item
= proto_tree_add_text_internal(parent_tree
, tvb
, offset
, len
, "%s", name
? name
: "");
13075 value
= get_uint64_value(parent_tree
, tvb
, offset
, len
, encoding
);
13076 if (proto_item_add_bitmask_tree(item
, tvb
, offset
, len
, ett
, fields
,
13077 flags
, true, false, NULL
, value
) && fallback
) {
13078 /* Still at first item - append 'fallback' text if any */
13079 proto_item_append_text(item
, "%s", fallback
);
13087 proto_tree_add_bits_item(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
13088 const unsigned bit_offset
, const int no_of_bits
,
13089 const unsigned encoding
)
13091 header_field_info
*hfinfo
;
13095 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
13097 if (no_of_bits
< 0) {
13098 THROW(ReportedBoundsError
);
13100 octet_length
= (no_of_bits
+ 7) >> 3;
13101 octet_offset
= bit_offset
>> 3;
13102 test_length(hfinfo
, tvb
, octet_offset
, octet_length
, encoding
);
13104 /* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
13105 * but only after doing a bunch more work (which we can, in the common
13106 * case, shortcut here).
13108 CHECK_FOR_NULL_TREE(tree
);
13109 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
13111 return proto_tree_add_bits_ret_val(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, NULL
, encoding
);
13115 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
13116 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
13117 * Offset should be given in bits from the start of the tvb.
13120 static proto_item
*
13121 _proto_tree_add_bits_ret_val(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
13122 const unsigned bit_offset
, const int no_of_bits
,
13123 uint64_t *return_value
, const unsigned encoding
)
13127 uint8_t tot_no_bits
;
13129 char lbl_str
[ITEM_LABEL_LENGTH
];
13130 uint64_t value
= 0;
13131 uint8_t *bytes
= NULL
;
13132 size_t bytes_length
= 0;
13135 header_field_info
*hf_field
;
13137 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
13138 PROTO_REGISTRAR_GET_NTH(hfindex
, hf_field
);
13140 if (hf_field
->bitmask
!= 0) {
13141 REPORT_DISSECTOR_BUG("Incompatible use of proto_tree_add_bits_ret_val"
13142 " with field '%s' (%s) with bitmask != 0",
13143 hf_field
->abbrev
, hf_field
->name
);
13146 if (no_of_bits
< 0) {
13147 THROW(ReportedBoundsError
);
13148 } else if (no_of_bits
== 0) {
13149 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_ret_val() has a bit width of 0",
13153 /* Byte align offset */
13154 offset
= bit_offset
>>3;
13157 * Calculate the number of octets used to hold the bits
13159 tot_no_bits
= ((bit_offset
&0x7) + no_of_bits
);
13160 length
= (tot_no_bits
+ 7) >> 3;
13162 if (no_of_bits
< 65) {
13163 value
= tvb_get_bits64(tvb
, bit_offset
, no_of_bits
, encoding
);
13164 } else if (hf_field
->type
!= FT_BYTES
) {
13165 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_ret_val() has a bit width of %u > 65",
13166 hf_field
->abbrev
, no_of_bits
);
13170 /* Sign extend for signed types */
13171 switch (hf_field
->type
) {
13180 value
= ws_sign_ext64(value
, no_of_bits
);
13187 if (return_value
) {
13188 *return_value
= value
;
13191 /* Coast clear. Try and fake it */
13192 CHECK_FOR_NULL_TREE(tree
);
13193 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13195 bf_str
= decode_bits_in_field(PNODE_POOL(tree
), bit_offset
, no_of_bits
, value
, encoding
);
13197 switch (hf_field
->type
) {
13199 /* Boolean field */
13200 return proto_tree_add_boolean_format(tree
, hfindex
, tvb
, offset
, length
, value
,
13202 bf_str
, hf_field
->name
, tfs_get_string(!!value
, hf_field
->strings
));
13206 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, offset
, length
, (uint32_t)value
);
13207 fill_label_char(PITEM_FINFO(pi
), lbl_str
, NULL
);
13214 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, offset
, length
, (uint32_t)value
);
13215 fill_label_number(PITEM_FINFO(pi
), lbl_str
, NULL
, false);
13222 pi
= proto_tree_add_int(tree
, hfindex
, tvb
, offset
, length
, (int32_t)value
);
13223 fill_label_number(PITEM_FINFO(pi
), lbl_str
, NULL
, true);
13230 pi
= proto_tree_add_uint64(tree
, hfindex
, tvb
, offset
, length
, value
);
13231 fill_label_number64(PITEM_FINFO(pi
), lbl_str
, NULL
, false);
13238 pi
= proto_tree_add_int64(tree
, hfindex
, tvb
, offset
, length
, (int64_t)value
);
13239 fill_label_number64(PITEM_FINFO(pi
), lbl_str
, NULL
, true);
13243 bytes
= tvb_get_bits_array(PNODE_POOL(tree
), tvb
, bit_offset
, no_of_bits
, &bytes_length
, encoding
);
13244 pi
= proto_tree_add_bytes_with_length(tree
, hfindex
, tvb
, offset
, length
, bytes
, (int) bytes_length
);
13245 proto_item_fill_label(PITEM_FINFO(pi
), lbl_str
, NULL
);
13246 proto_item_set_text(pi
, "%s", lbl_str
);
13249 /* TODO: should handle FT_UINT_BYTES ? */
13252 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_tree_add_bits_ret_val()",
13255 ftype_name(hf_field
->type
));
13259 proto_item_set_text(pi
, "%s = %s", bf_str
, lbl_str
);
13264 proto_tree_add_split_bits_item_ret_val(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
13265 const unsigned bit_offset
, const crumb_spec_t
*crumb_spec
,
13266 uint64_t *return_value
)
13271 unsigned mask_initial_bit_offset
;
13272 unsigned mask_greatest_bit_offset
;
13273 unsigned octet_length
;
13276 char lbl_str
[ITEM_LABEL_LENGTH
];
13278 uint64_t composite_bitmask
;
13279 uint64_t composite_bitmap
;
13281 header_field_info
*hf_field
;
13283 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
13284 PROTO_REGISTRAR_GET_NTH(hfindex
, hf_field
);
13286 if (hf_field
->bitmask
!= 0) {
13287 REPORT_DISSECTOR_BUG("Incompatible use of proto_tree_add_split_bits_item_ret_val"
13288 " with field '%s' (%s) with bitmask != 0",
13289 hf_field
->abbrev
, hf_field
->name
);
13292 mask_initial_bit_offset
= bit_offset
% 8;
13297 mask_greatest_bit_offset
= 0;
13298 composite_bitmask
= 0;
13299 composite_bitmap
= 0;
13301 while (crumb_spec
[i
].crumb_bit_length
!= 0) {
13302 uint64_t crumb_mask
, crumb_value
;
13303 uint8_t crumb_end_bit_offset
;
13305 crumb_value
= tvb_get_bits64(tvb
,
13306 bit_offset
+ crumb_spec
[i
].crumb_bit_offset
,
13307 crumb_spec
[i
].crumb_bit_length
,
13309 value
+= crumb_value
;
13310 no_of_bits
+= crumb_spec
[i
].crumb_bit_length
;
13311 DISSECTOR_ASSERT_HINT(no_of_bits
<= 64, "a value larger than 64 bits cannot be represented");
13313 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
13314 octet containing the initial offset.
13315 If the mask is beyond 32 bits, then give up on bit map display.
13316 This could be improved in future, probably showing a table
13317 of 32 or 64 bits per row */
13318 if (mask_greatest_bit_offset
< 32) {
13319 crumb_end_bit_offset
= mask_initial_bit_offset
13320 + crumb_spec
[i
].crumb_bit_offset
13321 + crumb_spec
[i
].crumb_bit_length
;
13322 crumb_mask
= (UINT64_C(1) << crumb_spec
[i
].crumb_bit_length
) - 1;
13324 if (crumb_end_bit_offset
> mask_greatest_bit_offset
) {
13325 mask_greatest_bit_offset
= crumb_end_bit_offset
;
13327 /* Currently the bitmap of the crumbs are only shown if
13328 * smaller than 32 bits. Do not bother calculating the
13329 * mask if it is larger than that. */
13330 if (crumb_end_bit_offset
<= 32) {
13331 composite_bitmask
|= (crumb_mask
<< (64 - crumb_end_bit_offset
));
13332 composite_bitmap
|= (crumb_value
<< (64 - crumb_end_bit_offset
));
13335 /* Shift left for the next segment */
13336 value
<<= crumb_spec
[++i
].crumb_bit_length
;
13339 /* Sign extend for signed types */
13340 switch (hf_field
->type
) {
13349 value
= ws_sign_ext64(value
, no_of_bits
);
13355 if (return_value
) {
13356 *return_value
= value
;
13359 /* Coast clear. Try and fake it */
13360 CHECK_FOR_NULL_TREE(tree
);
13361 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13363 /* initialise the format string */
13366 octet_offset
= bit_offset
>> 3;
13368 /* Round up mask length to nearest octet */
13369 octet_length
= ((mask_greatest_bit_offset
+ 7) >> 3);
13370 mask_greatest_bit_offset
= octet_length
<< 3;
13372 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
13373 It would be a useful enhancement to eliminate this restriction. */
13374 if (mask_greatest_bit_offset
> 0 && mask_greatest_bit_offset
<= 32) {
13375 other_decode_bitfield_value(bf_str
,
13376 (uint32_t)(composite_bitmap
>> (64 - mask_greatest_bit_offset
)),
13377 (uint32_t)(composite_bitmask
>> (64 - mask_greatest_bit_offset
)),
13378 mask_greatest_bit_offset
);
13380 /* If the bitmask is too large, try to describe its contents. */
13381 snprintf(bf_str
, sizeof(bf_str
), "%d bits", no_of_bits
);
13384 switch (hf_field
->type
) {
13385 case FT_BOOLEAN
: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
13386 /* Boolean field */
13387 return proto_tree_add_boolean_format(tree
, hfindex
,
13388 tvb
, octet_offset
, octet_length
, value
,
13390 bf_str
, hf_field
->name
, tfs_get_string(!!value
, hf_field
->strings
));
13394 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, octet_offset
, octet_length
, (uint32_t)value
);
13395 fill_label_char(PITEM_FINFO(pi
), lbl_str
, NULL
);
13402 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, octet_offset
, octet_length
, (uint32_t)value
);
13403 fill_label_number(PITEM_FINFO(pi
), lbl_str
, NULL
, false);
13410 pi
= proto_tree_add_int(tree
, hfindex
, tvb
, octet_offset
, octet_length
, (int32_t)value
);
13411 fill_label_number(PITEM_FINFO(pi
), lbl_str
, NULL
, true);
13418 pi
= proto_tree_add_uint64(tree
, hfindex
, tvb
, octet_offset
, octet_length
, value
);
13419 fill_label_number64(PITEM_FINFO(pi
), lbl_str
, NULL
, false);
13426 pi
= proto_tree_add_int64(tree
, hfindex
, tvb
, octet_offset
, octet_length
, (int64_t)value
);
13427 fill_label_number64(PITEM_FINFO(pi
), lbl_str
, NULL
, true);
13431 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_tree_add_split_bits_item_ret_val()",
13434 ftype_name(hf_field
->type
));
13437 proto_item_set_text(pi
, "%s = %s", bf_str
, lbl_str
);
13442 proto_tree_add_split_bits_crumb(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
, const unsigned bit_offset
,
13443 const crumb_spec_t
*crumb_spec
, uint16_t crumb_index
)
13445 header_field_info
*hfinfo
;
13446 int start
= bit_offset
>> 3;
13447 int length
= ((bit_offset
+ crumb_spec
[crumb_index
].crumb_bit_length
- 1) >> 3) - (bit_offset
>> 3) + 1;
13449 /* We have to duplicate this length check from proto_tree_add_text_internal in order to check for a null tree
13450 * so that we can use the tree's memory scope in calculating the string */
13451 if (length
== -1) {
13452 tvb_captured_length(tvb
) ? tvb_ensure_captured_length_remaining(tvb
, start
) : 0;
13454 tvb_ensure_bytes_exist(tvb
, start
, length
);
13458 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
13459 proto_tree_add_text_internal(tree
, tvb
, start
, length
,
13460 "%s crumb %d of %s (decoded above)",
13461 decode_bits_in_field(PNODE_POOL(tree
), bit_offset
, crumb_spec
[crumb_index
].crumb_bit_length
,
13464 crumb_spec
[crumb_index
].crumb_bit_length
,
13472 proto_tree_add_bits_ret_val(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
13473 const unsigned bit_offset
, const int no_of_bits
,
13474 uint64_t *return_value
, const unsigned encoding
)
13478 if ((item
= _proto_tree_add_bits_ret_val(tree
, hfindex
, tvb
,
13479 bit_offset
, no_of_bits
,
13480 return_value
, encoding
))) {
13481 FI_SET_FLAG(PNODE_FINFO(item
), FI_BITS_OFFSET(bit_offset
));
13482 FI_SET_FLAG(PNODE_FINFO(item
), FI_BITS_SIZE(no_of_bits
));
13487 static proto_item
*
13488 _proto_tree_add_bits_format_value(proto_tree
*tree
, const int hfindex
,
13489 tvbuff_t
*tvb
, const unsigned bit_offset
,
13490 const int no_of_bits
, void *value_ptr
,
13491 const unsigned encoding
, char *value_str
)
13495 uint8_t tot_no_bits
;
13497 uint64_t value
= 0;
13498 header_field_info
*hf_field
;
13500 /* We do not have to return a value, try to fake it as soon as possible */
13501 CHECK_FOR_NULL_TREE(tree
);
13502 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13504 if (hf_field
->bitmask
!= 0) {
13505 REPORT_DISSECTOR_BUG("Incompatible use of proto_tree_add_bits_format_value"
13506 " with field '%s' (%s) with bitmask != 0",
13507 hf_field
->abbrev
, hf_field
->name
);
13510 if (no_of_bits
< 0) {
13511 THROW(ReportedBoundsError
);
13512 } else if (no_of_bits
== 0) {
13513 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_format_value() has a bit width of 0",
13517 /* Byte align offset */
13518 offset
= bit_offset
>>3;
13521 * Calculate the number of octets used to hold the bits
13523 tot_no_bits
= ((bit_offset
&0x7) + no_of_bits
);
13524 length
= tot_no_bits
>>3;
13525 /* If we are using part of the next octet, increase length by 1 */
13526 if (tot_no_bits
& 0x07)
13529 if (no_of_bits
< 65) {
13530 value
= tvb_get_bits64(tvb
, bit_offset
, no_of_bits
, encoding
);
13532 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_format_value() has a bit width of %u > 65",
13533 hf_field
->abbrev
, no_of_bits
);
13537 str
= decode_bits_in_field(PNODE_POOL(tree
), bit_offset
, no_of_bits
, value
, encoding
);
13539 (void) g_strlcat(str
, " = ", 256+64);
13540 (void) g_strlcat(str
, hf_field
->name
, 256+64);
13543 * This function does not receive an actual value but a dimensionless pointer to that value.
13544 * For this reason, the type of the header field is examined in order to determine
13545 * what kind of value we should read from this address.
13546 * The caller of this function must make sure that for the specific header field type the address of
13547 * a compatible value is provided.
13549 switch (hf_field
->type
) {
13551 return proto_tree_add_boolean_format(tree
, hfindex
, tvb
, offset
, length
, *(uint64_t *)value_ptr
,
13552 "%s: %s", str
, value_str
);
13560 return proto_tree_add_uint_format(tree
, hfindex
, tvb
, offset
, length
, *(uint32_t *)value_ptr
,
13561 "%s: %s", str
, value_str
);
13568 return proto_tree_add_uint64_format(tree
, hfindex
, tvb
, offset
, length
, *(uint64_t *)value_ptr
,
13569 "%s: %s", str
, value_str
);
13576 return proto_tree_add_int_format(tree
, hfindex
, tvb
, offset
, length
, *(int32_t *)value_ptr
,
13577 "%s: %s", str
, value_str
);
13584 return proto_tree_add_int64_format(tree
, hfindex
, tvb
, offset
, length
, *(int64_t *)value_ptr
,
13585 "%s: %s", str
, value_str
);
13589 return proto_tree_add_float_format(tree
, hfindex
, tvb
, offset
, length
, *(float *)value_ptr
,
13590 "%s: %s", str
, value_str
);
13594 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_tree_add_bits_format_value()",
13597 ftype_name(hf_field
->type
));
13602 static proto_item
*
13603 proto_tree_add_bits_format_value(proto_tree
*tree
, const int hfindex
,
13604 tvbuff_t
*tvb
, const unsigned bit_offset
,
13605 const int no_of_bits
, void *value_ptr
,
13606 const unsigned encoding
, char *value_str
)
13610 if ((item
= _proto_tree_add_bits_format_value(tree
, hfindex
,
13611 tvb
, bit_offset
, no_of_bits
,
13612 value_ptr
, encoding
, value_str
))) {
13613 FI_SET_FLAG(PNODE_FINFO(item
), FI_BITS_OFFSET(bit_offset
));
13614 FI_SET_FLAG(PNODE_FINFO(item
), FI_BITS_SIZE(no_of_bits
));
13619 #define CREATE_VALUE_STRING(tree,dst,format,ap) \
13620 va_start(ap, format); \
13621 dst = wmem_strdup_vprintf(PNODE_POOL(tree), format, ap); \
13625 proto_tree_add_uint_bits_format_value(proto_tree
*tree
, const int hfindex
,
13626 tvbuff_t
*tvb
, const unsigned bit_offset
,
13627 const int no_of_bits
, uint32_t value
,
13628 const unsigned encoding
,
13629 const char *format
, ...)
13633 header_field_info
*hf_field
;
13635 CHECK_FOR_NULL_TREE(tree
);
13637 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13639 switch (hf_field
->type
) {
13647 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
13652 CREATE_VALUE_STRING(tree
, dst
, format
, ap
);
13654 return proto_tree_add_bits_format_value(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, &value
, encoding
, dst
);
13658 proto_tree_add_uint64_bits_format_value(proto_tree
*tree
, const int hfindex
,
13659 tvbuff_t
*tvb
, const unsigned bit_offset
,
13660 const int no_of_bits
, uint64_t value
,
13661 const unsigned encoding
,
13662 const char *format
, ...)
13666 header_field_info
*hf_field
;
13668 CHECK_FOR_NULL_TREE(tree
);
13670 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13672 switch (hf_field
->type
) {
13680 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, or FT_UINT64",
13685 CREATE_VALUE_STRING(tree
, dst
, format
, ap
);
13687 return proto_tree_add_bits_format_value(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, &value
, encoding
, dst
);
13691 proto_tree_add_float_bits_format_value(proto_tree
*tree
, const int hfindex
,
13692 tvbuff_t
*tvb
, const unsigned bit_offset
,
13693 const int no_of_bits
, float value
,
13694 const unsigned encoding
,
13695 const char *format
, ...)
13699 header_field_info
*hf_field
;
13701 CHECK_FOR_NULL_TREE(tree
);
13703 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13705 DISSECTOR_ASSERT_FIELD_TYPE(hf_field
, FT_FLOAT
);
13707 CREATE_VALUE_STRING(tree
, dst
, format
, ap
);
13709 return proto_tree_add_bits_format_value(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, &value
, encoding
, dst
);
13713 proto_tree_add_int_bits_format_value(proto_tree
*tree
, const int hfindex
,
13714 tvbuff_t
*tvb
, const unsigned bit_offset
,
13715 const int no_of_bits
, int32_t value
,
13716 const unsigned encoding
,
13717 const char *format
, ...)
13721 header_field_info
*hf_field
;
13723 CHECK_FOR_NULL_TREE(tree
);
13725 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13727 switch (hf_field
->type
) {
13735 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
13740 CREATE_VALUE_STRING(tree
, dst
, format
, ap
);
13742 return proto_tree_add_bits_format_value(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, &value
, encoding
, dst
);
13746 proto_tree_add_int64_bits_format_value(proto_tree
*tree
, const int hfindex
,
13747 tvbuff_t
*tvb
, const unsigned bit_offset
,
13748 const int no_of_bits
, int64_t value
,
13749 const unsigned encoding
,
13750 const char *format
, ...)
13754 header_field_info
*hf_field
;
13756 CHECK_FOR_NULL_TREE(tree
);
13758 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13760 switch (hf_field
->type
) {
13768 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
13773 CREATE_VALUE_STRING(tree
, dst
, format
, ap
);
13775 return proto_tree_add_bits_format_value(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, &value
, encoding
, dst
);
13779 proto_tree_add_boolean_bits_format_value(proto_tree
*tree
, const int hfindex
,
13780 tvbuff_t
*tvb
, const unsigned bit_offset
,
13781 const int no_of_bits
, uint64_t value
,
13782 const unsigned encoding
,
13783 const char *format
, ...)
13787 header_field_info
*hf_field
;
13789 CHECK_FOR_NULL_TREE(tree
);
13791 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13793 DISSECTOR_ASSERT_FIELD_TYPE(hf_field
, FT_BOOLEAN
);
13795 CREATE_VALUE_STRING(tree
, dst
, format
, ap
);
13797 return proto_tree_add_bits_format_value(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, &value
, encoding
, dst
);
13801 proto_tree_add_ts_23_038_7bits_packed_item(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
13802 const unsigned bit_offset
, const int no_of_chars
)
13805 header_field_info
*hfinfo
;
13810 CHECK_FOR_NULL_TREE(tree
);
13812 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
13814 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_STRING
);
13816 byte_length
= (((no_of_chars
+ 1) * 7) + (bit_offset
& 0x07)) >> 3;
13817 byte_offset
= bit_offset
>> 3;
13819 string
= tvb_get_ts_23_038_7bits_string_packed(PNODE_POOL(tree
), tvb
, bit_offset
, no_of_chars
);
13821 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, byte_offset
, &byte_length
);
13822 DISSECTOR_ASSERT(byte_length
>= 0);
13823 proto_tree_set_string(PNODE_FINFO(pi
), string
);
13829 proto_tree_add_ascii_7bits_item(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
13830 const unsigned bit_offset
, const int no_of_chars
)
13833 header_field_info
*hfinfo
;
13838 CHECK_FOR_NULL_TREE(tree
);
13840 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
13842 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_STRING
);
13844 byte_length
= (((no_of_chars
+ 1) * 7) + (bit_offset
& 0x07)) >> 3;
13845 byte_offset
= bit_offset
>> 3;
13847 string
= tvb_get_ascii_7bits_string(PNODE_POOL(tree
), tvb
, bit_offset
, no_of_chars
);
13849 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, byte_offset
, &byte_length
);
13850 DISSECTOR_ASSERT(byte_length
>= 0);
13851 proto_tree_set_string(PNODE_FINFO(pi
), string
);
13856 const value_string proto_checksum_vals
[] = {
13857 { PROTO_CHECKSUM_E_BAD
, "Bad" },
13858 { PROTO_CHECKSUM_E_GOOD
, "Good" },
13859 { PROTO_CHECKSUM_E_UNVERIFIED
, "Unverified" },
13860 { PROTO_CHECKSUM_E_NOT_PRESENT
, "Not present" },
13861 { PROTO_CHECKSUM_E_ILLEGAL
, "Illegal" },
13867 proto_tree_add_checksum(proto_tree
*tree
, tvbuff_t
*tvb
, const unsigned offset
,
13868 const int hf_checksum
, const int hf_checksum_status
, struct expert_field
* bad_checksum_expert
,
13869 packet_info
*pinfo
, uint32_t computed_checksum
, const unsigned encoding
, const unsigned flags
)
13871 header_field_info
*hfinfo
;
13874 proto_item
* ti
= NULL
;
13876 bool incorrect_checksum
= true;
13878 PROTO_REGISTRAR_GET_NTH(hf_checksum
, hfinfo
);
13880 switch (hfinfo
->type
) {
13894 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
13898 if (flags
& PROTO_CHECKSUM_NOT_PRESENT
) {
13899 ti
= proto_tree_add_uint_format_value(tree
, hf_checksum
, tvb
, offset
, len
, 0, "[missing]");
13900 proto_item_set_generated(ti
);
13901 if (hf_checksum_status
!= -1) {
13902 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, len
, PROTO_CHECKSUM_E_NOT_PRESENT
);
13903 proto_item_set_generated(ti2
);
13908 if (flags
& PROTO_CHECKSUM_GENERATED
) {
13909 ti
= proto_tree_add_uint(tree
, hf_checksum
, tvb
, offset
, len
, computed_checksum
);
13910 proto_item_set_generated(ti
);
13912 ti
= proto_tree_add_item_ret_uint(tree
, hf_checksum
, tvb
, offset
, len
, encoding
, &checksum
);
13913 if (flags
& PROTO_CHECKSUM_VERIFY
) {
13914 if (flags
& (PROTO_CHECKSUM_IN_CKSUM
|PROTO_CHECKSUM_ZERO
)) {
13915 if (computed_checksum
== 0) {
13916 proto_item_append_text(ti
, " [correct]");
13917 if (hf_checksum_status
!= -1) {
13918 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, 0, PROTO_CHECKSUM_E_GOOD
);
13919 proto_item_set_generated(ti2
);
13921 incorrect_checksum
= false;
13922 } else if (flags
& PROTO_CHECKSUM_IN_CKSUM
) {
13923 computed_checksum
= in_cksum_shouldbe(checksum
, computed_checksum
);
13926 if (checksum
== computed_checksum
) {
13927 proto_item_append_text(ti
, " [correct]");
13928 if (hf_checksum_status
!= -1) {
13929 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, 0, PROTO_CHECKSUM_E_GOOD
);
13930 proto_item_set_generated(ti2
);
13932 incorrect_checksum
= false;
13936 if (incorrect_checksum
) {
13937 if (hf_checksum_status
!= -1) {
13938 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, 0, PROTO_CHECKSUM_E_BAD
);
13939 proto_item_set_generated(ti2
);
13941 if (flags
& PROTO_CHECKSUM_ZERO
) {
13942 proto_item_append_text(ti
, " [incorrect]");
13943 if (bad_checksum_expert
!= NULL
)
13944 expert_add_info_format(pinfo
, ti
, bad_checksum_expert
, "%s", expert_get_summary(bad_checksum_expert
));
13946 proto_item_append_text(ti
, " incorrect, should be 0x%0*x", len
*2, computed_checksum
);
13947 if (bad_checksum_expert
!= NULL
)
13948 expert_add_info_format(pinfo
, ti
, bad_checksum_expert
, "%s [should be 0x%0*x]", expert_get_summary(bad_checksum_expert
), len
* 2, computed_checksum
);
13952 if (hf_checksum_status
!= -1) {
13953 proto_item_append_text(ti
, " [unverified]");
13954 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, 0, PROTO_CHECKSUM_E_UNVERIFIED
);
13955 proto_item_set_generated(ti2
);
13964 proto_tree_add_checksum_bytes(proto_tree
*tree
, tvbuff_t
*tvb
, const unsigned offset
,
13965 const int hf_checksum
, const int hf_checksum_status
, struct expert_field
* bad_checksum_expert
,
13966 packet_info
*pinfo
, const uint8_t *computed_checksum
, size_t checksum_len
, const unsigned flags
)
13968 header_field_info
*hfinfo
;
13969 uint8_t *checksum
= NULL
;
13970 proto_item
* ti
= NULL
;
13972 bool incorrect_checksum
= true;
13974 PROTO_REGISTRAR_GET_NTH(hf_checksum
, hfinfo
);
13976 if (hfinfo
->type
!= FT_BYTES
) {
13977 REPORT_DISSECTOR_BUG("field %s is not of type FT_BYTES",
13981 if (flags
& PROTO_CHECKSUM_NOT_PRESENT
) {
13982 ti
= proto_tree_add_bytes_format_value(tree
, hf_checksum
, tvb
, offset
, (int)checksum_len
, 0, "[missing]");
13983 proto_item_set_generated(ti
);
13984 if (hf_checksum_status
!= -1) {
13985 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, (int)checksum_len
, PROTO_CHECKSUM_E_NOT_PRESENT
);
13986 proto_item_set_generated(ti2
);
13991 if (flags
& PROTO_CHECKSUM_GENERATED
) {
13992 ti
= proto_tree_add_bytes(tree
, hf_checksum
, tvb
, offset
, (int)checksum_len
, computed_checksum
);
13993 proto_item_set_generated(ti
);
13995 checksum
= (uint8_t*)wmem_alloc0_array(wmem_packet_scope(), uint8_t, checksum_len
);
13996 tvb_memcpy(tvb
, checksum
, offset
, checksum_len
);
13997 ti
= proto_tree_add_bytes(tree
, hf_checksum
, tvb
, offset
, (int)checksum_len
, checksum
);
13998 if (flags
& PROTO_CHECKSUM_VERIFY
) {
13999 if (flags
& (PROTO_CHECKSUM_IN_CKSUM
|PROTO_CHECKSUM_ZERO
)) {
14000 if (computed_checksum
== 0) {
14001 proto_item_append_text(ti
, " [correct]");
14002 if (hf_checksum_status
!= -1) {
14003 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, 0, PROTO_CHECKSUM_E_GOOD
);
14004 proto_item_set_generated(ti2
);
14006 incorrect_checksum
= false;
14009 if (memcmp(computed_checksum
, checksum
, checksum_len
) == 0) {
14010 proto_item_append_text(ti
, " [correct]");
14011 if (hf_checksum_status
!= -1) {
14012 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, 0, PROTO_CHECKSUM_E_GOOD
);
14013 proto_item_set_generated(ti2
);
14015 incorrect_checksum
= false;
14019 if (incorrect_checksum
) {
14020 if (hf_checksum_status
!= -1) {
14021 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, 0, PROTO_CHECKSUM_E_BAD
);
14022 proto_item_set_generated(ti2
);
14024 if (flags
& PROTO_CHECKSUM_ZERO
) {
14025 proto_item_append_text(ti
, " [incorrect]");
14026 if (bad_checksum_expert
!= NULL
)
14027 expert_add_info_format(pinfo
, ti
, bad_checksum_expert
, "%s", expert_get_summary(bad_checksum_expert
));
14029 size_t computed_checksum_str_len
= (2 * checksum_len
* sizeof(char)) + 1;
14030 char *computed_checksum_str
= (char*)wmem_alloc0_array(wmem_packet_scope(), char, computed_checksum_str_len
);
14031 for (size_t counter
= 0; counter
< checksum_len
; ++counter
) {
14033 /* On ecah iteration inserts two characters */
14034 (char*)&computed_checksum_str
[counter
<< 1],
14035 computed_checksum_str_len
- (counter
<< 1),
14037 computed_checksum
[counter
]);
14039 proto_item_append_text(ti
, " incorrect, should be 0x%s", computed_checksum_str
);
14040 if (bad_checksum_expert
!= NULL
)
14041 expert_add_info_format(pinfo
, ti
, bad_checksum_expert
, "%s [should be 0x%s]", expert_get_summary(bad_checksum_expert
), computed_checksum_str
);
14045 if (hf_checksum_status
!= -1) {
14046 proto_item_append_text(ti
, " [unverified]");
14047 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, 0, PROTO_CHECKSUM_E_UNVERIFIED
);
14048 proto_item_set_generated(ti2
);
14057 proto_check_field_name(const char *field_name
)
14059 return module_check_valid_name(field_name
, false);
14063 proto_check_field_name_lower(const char *field_name
)
14065 return module_check_valid_name(field_name
, true);
14069 tree_expanded(int tree_type
)
14071 if (tree_type
<= 0) {
14074 ws_assert(tree_type
>= 0 && tree_type
< num_tree_types
);
14075 return tree_is_expanded
[tree_type
>> 5] & (1U << (tree_type
& 31));
14079 tree_expanded_set(int tree_type
, bool value
)
14081 ws_assert(tree_type
>= 0 && tree_type
< num_tree_types
);
14084 tree_is_expanded
[tree_type
>> 5] |= (1U << (tree_type
& 31));
14086 tree_is_expanded
[tree_type
>> 5] &= ~(1U << (tree_type
& 31));
14090 * Editor modelines - https://www.wireshark.org/tools/modelines.html
14093 * c-basic-offset: 8
14095 * indent-tabs-mode: t
14098 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
14099 * :indentSize=8:tabSize=8:noTabs=false: