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 visible \
129 because that means we can change its length or repr, and we \
130 don't want to do so with calls intended for this faked new \
131 item, so this item needs a new (hidden) child node. \
132 We fake FT_PROTOCOL unless some clients have requested us \
135 PTREE_DATA(tree)->count++; \
136 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
137 if (PTREE_DATA(tree)->count > prefs.gui_max_tree_items) { \
139 if (wireshark_abort_on_too_many_items) \
140 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)", \
141 hfinfo->abbrev, prefs.gui_max_tree_items); \
142 /* Let the exception handler add items to the tree */ \
143 PTREE_DATA(tree)->count = 0; \
144 THROW_MESSAGE(DissectorError, \
145 wmem_strdup_printf(PNODE_POOL(tree), \
146 "Adding %s would put more than %d items in the tree -- possible infinite loop (max number of items can be increased in advanced preferences)", \
147 hfinfo->abbrev, prefs.gui_max_tree_items)); \
149 if (!(PTREE_DATA(tree)->visible)) { \
150 if (PROTO_ITEM_IS_HIDDEN(tree)) { \
151 if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
152 && (hfinfo->ref_type != HF_REF_TYPE_PRINT) \
153 && (hfinfo->type != FT_PROTOCOL || \
154 PTREE_DATA(tree)->fake_protocols)) { \
156 /* return fake node with no field info */\
157 return proto_tree_add_fake_node(tree, hfinfo); \
162 /** See inlined comments.
163 @param tree the tree to append this item to
164 @param hfindex field index
165 @param hfinfo header_field
166 @return the header field matching 'hfinfo' */
167 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
168 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, ((void)0))
171 /** See inlined comments.
172 @param pi the created protocol item we're about to return */
173 #define TRY_TO_FAKE_THIS_REPR(pi) \
175 if (!PITEM_FINFO(pi)) \
177 if (!(PTREE_DATA(pi)->visible) && \
178 PROTO_ITEM_IS_HIDDEN(pi)) { \
179 /* If the tree (GUI) or item isn't visible it's pointless for \
180 * us to generate the protocol item's string representation */ \
183 /* Same as above but returning void */
184 #define TRY_TO_FAKE_THIS_REPR_VOID(pi) \
185 if (!pi || !PITEM_FINFO(pi)) \
187 if (!(PTREE_DATA(pi)->visible) && \
188 PROTO_ITEM_IS_HIDDEN(pi)) { \
189 /* If the tree (GUI) or item isn't visible it's pointless for \
190 * us to generate the protocol item's string representation */ \
193 /* Similar to above, but allows a NULL tree */
194 #define TRY_TO_FAKE_THIS_REPR_NESTED(pi) \
195 if ((pi == NULL) || (PITEM_FINFO(pi) == NULL) || (!(PTREE_DATA(pi)->visible) && \
196 PROTO_ITEM_IS_HIDDEN(pi))) { \
197 /* If the tree (GUI) or item isn't visible it's pointless for \
198 * us to generate the protocol item's string representation */ \
202 #ifdef ENABLE_CHECK_FILTER
203 #define CHECK_HF_VALUE(type, spec, start_values) \
205 const type *current; \
207 current = start_values; \
208 for (n=0; current; n++, current++) { \
209 /* Drop out if we reached the end. */ \
210 if ((current->value == 0) && (current->strptr == NULL)) { \
213 /* Check value against all previous */ \
214 for (m=0; m < n; m++) { \
215 /* There are lots of duplicates with the same string, \
216 so only report if different... */ \
217 if ((start_values[m].value == current->value) && \
218 (strcmp(start_values[m].strptr, current->strptr) != 0)) { \
219 ws_warning("Field '%s' (%s) has a conflicting entry in its" \
220 " value_string: %" spec " is at indices %u (%s) and %u (%s)", \
221 hfinfo->name, hfinfo->abbrev, \
222 current->value, m, start_values[m].strptr, n, current->strptr); \
229 /* The longest NUMBER-like field label we have is for BASE_OUI, which
230 * can have up to 64 bytes for the manufacturer name if resolved plus
231 * 11 bytes for the "XX:XX:XX ()" part = 75 octets.
233 #define NUMBER_LABEL_LENGTH 80
235 static const char *hf_try_val_to_str(uint32_t value
, const header_field_info
*hfinfo
);
236 static const char *hf_try_val64_to_str(uint64_t value
, const header_field_info
*hfinfo
);
237 static const char *hf_try_val_to_str_const(uint32_t value
, const header_field_info
*hfinfo
, const char *unknown_str
);
238 static const char *hf_try_val64_to_str_const(uint64_t value
, const header_field_info
*hfinfo
, const char *unknown_str
);
239 static int hfinfo_bitoffset(const header_field_info
*hfinfo
);
240 static int hfinfo_mask_bitwidth(const header_field_info
*hfinfo
);
241 static int hfinfo_container_bitwidth(const header_field_info
*hfinfo
);
243 #define label_concat(dst, pos, src) \
244 ws_label_strcpy(dst, ITEM_LABEL_LENGTH, pos, src, 0)
246 static void mark_truncated(char *label_str
, size_t name_pos
, const size_t size
, size_t *value_pos
);
247 static void label_mark_truncated(char *label_str
, size_t name_pos
, size_t *value_pos
);
248 #define LABEL_MARK_TRUNCATED_START(label_str, value_pos) label_mark_truncated(label_str, 0, value_pos)
250 static void fill_label_boolean(const field_info
*fi
, char *label_str
, size_t *value_pos
);
251 static void fill_label_bitfield_char(const field_info
*fi
, char *label_str
, size_t *value_pos
);
252 static void fill_label_bitfield(const field_info
*fi
, char *label_str
, size_t *value_pos
, bool is_signed
);
253 static void fill_label_bitfield64(const field_info
*fi
, char *label_str
, size_t *value_pos
, bool is_signed
);
254 static void fill_label_char(const field_info
*fi
, char *label_str
, size_t *value_pos
);
255 static void fill_label_number(const field_info
*fi
, char *label_str
, size_t *value_pos
, bool is_signed
);
256 static void fill_label_number64(const field_info
*fi
, char *label_str
, size_t *value_pos
, bool is_signed
);
258 static size_t fill_display_label_float(const field_info
*fi
, char *label_str
);
259 static void fill_label_float(const field_info
*fi
, char *label_str
, size_t *value_pos
);
261 static const char *hfinfo_number_value_format_display(const header_field_info
*hfinfo
, int display
, char buf
[NUMBER_LABEL_LENGTH
], uint32_t value
);
262 static const char *hfinfo_number_value_format_display64(const header_field_info
*hfinfo
, int display
, char buf
[NUMBER_LABEL_LENGTH
], uint64_t value
);
263 static const char *hfinfo_char_vals_format(const header_field_info
*hfinfo
, char buf
[32], uint32_t value
);
264 static const char *hfinfo_number_vals_format(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint32_t value
);
265 static const char *hfinfo_number_vals_format64(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint64_t value
);
266 static const char *hfinfo_number_value_format(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint32_t value
);
267 static const char *hfinfo_number_value_format64(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint64_t value
);
268 static const char *hfinfo_char_value_format(const header_field_info
*hfinfo
, char buf
[32], uint32_t value
);
269 static const char *hfinfo_numeric_value_format(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint32_t value
);
270 static const char *hfinfo_numeric_value_format64(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint64_t value
);
272 static void proto_cleanup_base(void);
275 proto_tree_add_node(proto_tree
*tree
, field_info
*fi
);
278 proto_tree_add_fake_node(proto_tree
*tree
, const header_field_info
*hfinfo
);
281 get_hfi_length(header_field_info
*hfinfo
, tvbuff_t
*tvb
, const int start
, int *length
,
282 int *item_length
, const unsigned encoding
);
285 get_full_length(header_field_info
*hfinfo
, tvbuff_t
*tvb
, const int start
,
286 int length
, unsigned item_length
, const int encoding
);
289 new_field_info(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
,
290 const int start
, const int item_length
);
293 proto_tree_add_pi(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
,
294 int start
, int *length
);
297 proto_tree_set_representation_value(proto_item
*pi
, const char *format
, va_list ap
);
299 proto_tree_set_representation(proto_item
*pi
, const char *format
, va_list ap
);
302 proto_tree_set_protocol_tvb(field_info
*fi
, tvbuff_t
*tvb
, const char* field_data
, int length
);
304 proto_tree_set_bytes(field_info
*fi
, const uint8_t* start_ptr
, int length
);
306 proto_tree_set_bytes_tvb(field_info
*fi
, tvbuff_t
*tvb
, int offset
, int length
);
308 proto_tree_set_bytes_gbytearray(field_info
*fi
, const GByteArray
*value
);
310 proto_tree_set_time(field_info
*fi
, const nstime_t
*value_ptr
);
312 proto_tree_set_string(field_info
*fi
, const char* value
);
314 proto_tree_set_ax25(field_info
*fi
, const uint8_t* value
);
316 proto_tree_set_ax25_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
);
318 proto_tree_set_vines(field_info
*fi
, const uint8_t* value
);
320 proto_tree_set_vines_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
);
322 proto_tree_set_ether(field_info
*fi
, const uint8_t* value
);
324 proto_tree_set_ether_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
);
326 proto_tree_set_ipxnet(field_info
*fi
, uint32_t value
);
328 proto_tree_set_ipv4(field_info
*fi
, ws_in4_addr value
);
330 proto_tree_set_ipv6(field_info
*fi
, const ws_in6_addr
* value
);
332 proto_tree_set_ipv6_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, int length
);
334 proto_tree_set_fcwwn_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, int length
);
336 proto_tree_set_guid(field_info
*fi
, const e_guid_t
*value_ptr
);
338 proto_tree_set_guid_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, const unsigned encoding
);
340 proto_tree_set_oid(field_info
*fi
, const uint8_t* value_ptr
, int length
);
342 proto_tree_set_oid_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, int length
);
344 proto_tree_set_system_id(field_info
*fi
, const uint8_t* value_ptr
, int length
);
346 proto_tree_set_system_id_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, int length
);
348 proto_tree_set_boolean(field_info
*fi
, uint64_t value
);
350 proto_tree_set_float(field_info
*fi
, float value
);
352 proto_tree_set_double(field_info
*fi
, double value
);
354 proto_tree_set_uint(field_info
*fi
, uint32_t value
);
356 proto_tree_set_int(field_info
*fi
, int32_t value
);
358 proto_tree_set_uint64(field_info
*fi
, uint64_t value
);
360 proto_tree_set_int64(field_info
*fi
, int64_t value
);
362 proto_tree_set_eui64(field_info
*fi
, const uint64_t value
);
364 proto_tree_set_eui64_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, const unsigned encoding
);
366 /* Handle type length mismatch (now filterable) expert info */
367 static int proto_type_length_mismatch
;
368 static expert_field ei_type_length_mismatch_error
;
369 static expert_field ei_type_length_mismatch_warn
;
370 static void register_type_length_mismatch(void);
372 /* Handle byte array string decoding errors with expert info */
373 static int proto_byte_array_string_decoding_error
;
374 static expert_field ei_byte_array_string_decoding_failed_error
;
375 static void register_byte_array_string_decodinws_error(void);
377 /* Handle date and time string decoding errors with expert info */
378 static int proto_date_time_string_decoding_error
;
379 static expert_field ei_date_time_string_decoding_failed_error
;
380 static void register_date_time_string_decodinws_error(void);
382 /* Handle string errors expert info */
383 static int proto_string_errors
;
384 static expert_field ei_string_trailing_characters
;
385 static void register_string_errors(void);
387 static int proto_register_field_init(header_field_info
*hfinfo
, const int parent
);
389 /* special-case header field used within proto.c */
390 static header_field_info hfi_text_only
=
391 { "Text item", "text", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
};
394 /* Structure for information about a protocol */
396 const char *name
; /* long description */
397 const char *short_name
; /* short description */
398 const char *filter_name
; /* name of this protocol in filters */
399 GPtrArray
*fields
; /* fields for this protocol */
400 int proto_id
; /* field ID for this protocol */
401 bool is_enabled
; /* true if protocol is enabled */
402 bool enabled_by_default
; /* true if protocol is enabled by default */
403 bool can_toggle
; /* true if is_enabled can be changed */
404 int parent_proto_id
; /* Used to identify "pino"s (Protocol In Name Only).
405 For dissectors that need a protocol name so they
406 can be added to a dissector table, but use the
407 parent_proto_id for things like enable/disable */
408 GList
*heur_list
; /* Heuristic dissectors associated with this protocol */
411 /* List of all protocols */
412 static GList
*protocols
;
414 /* Structure stored for deregistered g_slice */
415 struct g_slice_data
{
420 /* Deregistered fields */
421 static GPtrArray
*deregistered_fields
;
422 static GPtrArray
*deregistered_data
;
423 static GPtrArray
*deregistered_slice
;
425 /* indexed by prefix, contains initializers */
426 static GHashTable
* prefixes
;
428 /* Contains information about a field when a dissector calls
429 * proto_tree_add_item. */
430 #define FIELD_INFO_NEW(pool, fi) fi = wmem_new(pool, field_info)
431 #define FIELD_INFO_FREE(pool, fi) wmem_free(pool, fi)
433 /* Contains the space for proto_nodes. */
434 #define PROTO_NODE_INIT(node) \
435 node->first_child = NULL; \
436 node->last_child = NULL; \
439 #define PROTO_NODE_FREE(pool, node) \
440 wmem_free(pool, node)
442 /* String space for protocol and field items for the GUI */
443 #define ITEM_LABEL_NEW(pool, il) \
444 il = wmem_new(pool, item_label_t); \
447 #define ITEM_LABEL_FREE(pool, il) \
450 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
451 if((hfindex == 0 || (unsigned)hfindex > gpa_hfinfo.len) && wireshark_abort_on_dissector_bug) \
452 ws_error("Unregistered hf! index=%d", hfindex); \
453 DISSECTOR_ASSERT_HINT(hfindex > 0 && (unsigned)hfindex < gpa_hfinfo.len, "Unregistered hf!"); \
454 DISSECTOR_ASSERT_HINT(gpa_hfinfo.hfi[hfindex] != NULL, "Unregistered hf!"); \
455 hfinfo = gpa_hfinfo.hfi[hfindex];
457 /* List which stores protocols and fields that have been registered */
458 typedef struct _gpa_hfinfo_t
{
460 uint32_t allocated_len
;
461 header_field_info
**hfi
;
464 static gpa_hfinfo_t gpa_hfinfo
;
466 /* Hash table of abbreviations and IDs */
467 static GHashTable
*gpa_name_map
;
468 static header_field_info
*same_name_hfinfo
;
470 /* Hash table protocol aliases. const char * -> const char * */
471 static GHashTable
*gpa_protocol_aliases
;
474 * We're called repeatedly with the same field name when sorting a column.
475 * Cache our last gpa_name_map hit for faster lookups.
477 static char *last_field_name
;
478 static header_field_info
*last_hfinfo
;
480 static void save_same_name_hfinfo(void *data
)
482 same_name_hfinfo
= (header_field_info
*)data
;
485 /* Points to the first element of an array of bits, indexed by
486 a subtree item type; that array element is true if subtrees of
487 an item of that type are to be expanded. */
488 static uint32_t *tree_is_expanded
;
490 /* Number of elements in that array. The entry with index 0 is not used. */
491 int num_tree_types
= 1;
493 /* Name hashtables for fast detection of duplicate names */
494 static GHashTable
* proto_names
;
495 static GHashTable
* proto_short_names
;
496 static GHashTable
* proto_filter_names
;
498 static const char *reserved_filter_names
[] = {
499 /* Display filter keywords. */
529 static GHashTable
*proto_reserved_filter_names
;
532 proto_compare_name(const void *p1_arg
, const void *p2_arg
)
534 const protocol_t
*p1
= (const protocol_t
*)p1_arg
;
535 const protocol_t
*p2
= (const protocol_t
*)p2_arg
;
537 return g_ascii_strcasecmp(p1
->short_name
, p2
->short_name
);
540 static GSList
*dissector_plugins
;
544 proto_register_plugin(const proto_plugin
*plug
)
546 dissector_plugins
= g_slist_prepend(dissector_plugins
, (proto_plugin
*)plug
);
548 #else /* HAVE_PLUGINS */
550 proto_register_plugin(const proto_plugin
*plug _U_
)
552 ws_warning("proto_register_plugin: built without support for binary plugins");
554 #endif /* HAVE_PLUGINS */
557 call_plugin_register_protoinfo(void *data
, void *user_data _U_
)
559 proto_plugin
*plug
= (proto_plugin
*)data
;
561 if (plug
->register_protoinfo
) {
562 plug
->register_protoinfo();
567 call_plugin_register_handoff(void *data
, void *user_data _U_
)
569 proto_plugin
*plug
= (proto_plugin
*)data
;
571 if (plug
->register_handoff
) {
572 plug
->register_handoff();
576 /* initialize data structures and register protocols and fields */
578 proto_init(GSList
*register_all_plugin_protocols_list
,
579 GSList
*register_all_plugin_handoffs_list
,
583 proto_cleanup_base();
585 proto_names
= g_hash_table_new(g_str_hash
, g_str_equal
);
586 proto_short_names
= g_hash_table_new(g_str_hash
, g_str_equal
);
587 proto_filter_names
= g_hash_table_new(g_str_hash
, g_str_equal
);
589 proto_reserved_filter_names
= g_hash_table_new(g_str_hash
, g_str_equal
);
590 for (const char **ptr
= reserved_filter_names
; *ptr
!= NULL
; ptr
++) {
591 /* GHashTable has no key destructor so the cast is safe. */
592 g_hash_table_add(proto_reserved_filter_names
, *(char **)ptr
);
596 gpa_hfinfo
.allocated_len
= 0;
597 gpa_hfinfo
.hfi
= NULL
;
598 gpa_name_map
= g_hash_table_new_full(g_str_hash
, g_str_equal
, NULL
, save_same_name_hfinfo
);
599 gpa_protocol_aliases
= g_hash_table_new(g_str_hash
, g_str_equal
);
600 deregistered_fields
= g_ptr_array_new();
601 deregistered_data
= g_ptr_array_new();
602 deregistered_slice
= g_ptr_array_new();
604 /* Initialize the ftype subsystem */
607 /* Initialize the address type subsystem */
608 address_types_initialize();
610 /* Register one special-case FT_TEXT_ONLY field for use when
611 converting wireshark to new-style proto_tree. These fields
612 are merely strings on the GUI tree; they are not filterable */
613 hf_text_only
= proto_register_field_init(&hfi_text_only
, -1);
615 /* Register the pseudo-protocols used for exceptions. */
616 register_show_exception();
617 register_type_length_mismatch();
618 register_byte_array_string_decodinws_error();
619 register_date_time_string_decodinws_error();
620 register_string_errors();
621 ftypes_register_pseudofields();
622 col_register_protocol();
624 /* Have each built-in dissector register its protocols, fields,
625 dissector tables, and dissectors to be called through a
626 handle, and do whatever one-time initialization it needs to
628 register_all_protocols(cb
, client_data
);
630 /* Now call the registration routines for all epan plugins. */
631 for (GSList
*l
= register_all_plugin_protocols_list
; l
!= NULL
; l
= l
->next
) {
632 ((void (*)(register_cb
, void *))l
->data
)(cb
, client_data
);
635 /* Now call the registration routines for all dissector plugins. */
637 (*cb
)(RA_PLUGIN_REGISTER
, NULL
, client_data
);
638 g_slist_foreach(dissector_plugins
, call_plugin_register_protoinfo
, NULL
);
640 /* Now call the "handoff registration" routines of all built-in
641 dissectors; those routines register the dissector in other
642 dissectors' handoff tables, and fetch any dissector handles
644 register_all_protocol_handoffs(cb
, client_data
);
646 /* Now do the same with epan plugins. */
647 for (GSList
*l
= register_all_plugin_handoffs_list
; l
!= NULL
; l
= l
->next
) {
648 ((void (*)(register_cb
, void *))l
->data
)(cb
, client_data
);
651 /* Now do the same with dissector plugins. */
653 (*cb
)(RA_PLUGIN_HANDOFF
, NULL
, client_data
);
654 g_slist_foreach(dissector_plugins
, call_plugin_register_handoff
, NULL
);
656 /* sort the protocols by protocol name */
657 protocols
= g_list_sort(protocols
, proto_compare_name
);
659 /* sort the dissector handles in dissector tables (for -G reports
660 * and -d error messages. The GUI sorts the handles itself.) */
661 packet_all_tables_sort_handles();
663 /* We've assigned all the subtree type values; allocate the array
664 for them, and zero it out. */
665 tree_is_expanded
= g_new0(uint32_t, (num_tree_types
/32)+1);
669 proto_cleanup_base(void)
671 protocol_t
*protocol
;
672 header_field_info
*hfinfo
;
674 /* Free the abbrev/ID hash table */
676 g_hash_table_destroy(gpa_name_map
);
679 if (gpa_protocol_aliases
) {
680 g_hash_table_destroy(gpa_protocol_aliases
);
681 gpa_protocol_aliases
= NULL
;
683 g_free(last_field_name
);
684 last_field_name
= NULL
;
687 protocol
= (protocol_t
*)protocols
->data
;
688 PROTO_REGISTRAR_GET_NTH(protocol
->proto_id
, hfinfo
);
689 DISSECTOR_ASSERT(protocol
->proto_id
== hfinfo
->id
);
691 g_slice_free(header_field_info
, hfinfo
);
692 if (protocol
->parent_proto_id
!= -1) {
694 DISSECTOR_ASSERT(protocol
->fields
== NULL
); //helpers should not have any registered fields
695 DISSECTOR_ASSERT(protocol
->heur_list
== NULL
); //helpers should not have a heuristic list
697 if (protocol
->fields
) {
698 g_ptr_array_free(protocol
->fields
, true);
700 g_list_free(protocol
->heur_list
);
702 protocols
= g_list_remove(protocols
, protocol
);
707 g_hash_table_destroy(proto_names
);
711 if (proto_short_names
) {
712 g_hash_table_destroy(proto_short_names
);
713 proto_short_names
= NULL
;
716 if (proto_filter_names
) {
717 g_hash_table_destroy(proto_filter_names
);
718 proto_filter_names
= NULL
;
721 if (proto_reserved_filter_names
) {
722 g_hash_table_destroy(proto_reserved_filter_names
);
723 proto_reserved_filter_names
= NULL
;
726 if (gpa_hfinfo
.allocated_len
) {
728 gpa_hfinfo
.allocated_len
= 0;
729 g_free(gpa_hfinfo
.hfi
);
730 gpa_hfinfo
.hfi
= NULL
;
733 if (deregistered_fields
) {
734 g_ptr_array_free(deregistered_fields
, true);
735 deregistered_fields
= NULL
;
738 if (deregistered_data
) {
739 g_ptr_array_free(deregistered_data
, true);
740 deregistered_data
= NULL
;
743 if (deregistered_slice
) {
744 g_ptr_array_free(deregistered_slice
, true);
745 deregistered_slice
= NULL
;
748 g_free(tree_is_expanded
);
749 tree_is_expanded
= NULL
;
752 g_hash_table_destroy(prefixes
);
758 proto_free_deregistered_fields();
759 proto_cleanup_base();
761 g_slist_free(dissector_plugins
);
762 dissector_plugins
= NULL
;
766 // NOLINTNEXTLINE(misc-no-recursion)
767 proto_tree_traverse_pre_order(proto_tree
*tree
, proto_tree_traverse_func func
,
770 proto_node
*pnode
= tree
;
774 if (func(pnode
, data
))
777 child
= pnode
->first_child
;
778 while (child
!= NULL
) {
780 * The routine we call might modify the child, e.g. by
781 * freeing it, so we get the child's successor before
782 * calling that routine.
785 child
= current
->next
;
786 // We recurse here, but we're limited by prefs.gui_max_tree_depth
787 if (proto_tree_traverse_pre_order((proto_tree
*)current
, func
, data
))
795 proto_tree_children_foreach(proto_tree
*tree
, proto_tree_foreach_func func
,
798 proto_node
*node
= tree
;
804 node
= node
->first_child
;
805 while (node
!= NULL
) {
807 node
= current
->next
;
808 func((proto_tree
*)current
, data
);
813 free_GPtrArray_value(void *key
, void *value
, void *user_data _U_
)
815 GPtrArray
*ptrs
= (GPtrArray
*)value
;
816 int hfid
= GPOINTER_TO_UINT(key
);
817 header_field_info
*hfinfo
;
819 PROTO_REGISTRAR_GET_NTH(hfid
, hfinfo
);
820 if (hfinfo
->ref_type
!= HF_REF_TYPE_NONE
) {
821 /* when a field is referenced by a filter this also
822 affects the refcount for the parent protocol so we need
823 to adjust the refcount for the parent as well
825 if (hfinfo
->parent
!= -1) {
826 header_field_info
*parent_hfinfo
;
827 PROTO_REGISTRAR_GET_NTH(hfinfo
->parent
, parent_hfinfo
);
828 parent_hfinfo
->ref_type
= HF_REF_TYPE_NONE
;
830 hfinfo
->ref_type
= HF_REF_TYPE_NONE
;
833 g_ptr_array_free(ptrs
, true);
837 proto_tree_free_node(proto_node
*node
, void *data _U_
)
839 field_info
*finfo
= PNODE_FINFO(node
);
841 proto_tree_children_foreach(node
, proto_tree_free_node
, NULL
);
844 fvalue_free(finfo
->value
);
850 proto_tree_reset(proto_tree
*tree
)
852 tree_data_t
*tree_data
= PTREE_DATA(tree
);
854 proto_tree_children_foreach(tree
, proto_tree_free_node
, NULL
);
857 if (tree_data
->interesting_hfids
) {
858 /* Free all the GPtrArray's in the interesting_hfids hash. */
859 g_hash_table_foreach(tree_data
->interesting_hfids
,
860 free_GPtrArray_value
, NULL
);
862 /* And then remove all values. */
863 g_hash_table_remove_all(tree_data
->interesting_hfids
);
866 /* Reset track of the number of children */
867 tree_data
->count
= 0;
869 /* Reset our loop checks */
870 tree_data
->max_start
= 0;
871 tree_data
->start_idle_count
= 0;
873 PROTO_NODE_INIT(tree
);
876 /* frees the resources that the dissection a proto_tree uses */
878 proto_tree_free(proto_tree
*tree
)
880 tree_data_t
*tree_data
= PTREE_DATA(tree
);
882 proto_tree_children_foreach(tree
, proto_tree_free_node
, NULL
);
885 if (tree_data
->interesting_hfids
) {
886 /* Free all the GPtrArray's in the interesting_hfids hash. */
887 g_hash_table_foreach(tree_data
->interesting_hfids
,
888 free_GPtrArray_value
, NULL
);
890 /* And then destroy the hash. */
891 g_hash_table_destroy(tree_data
->interesting_hfids
);
894 g_slice_free(tree_data_t
, tree_data
);
896 g_slice_free(proto_tree
, tree
);
899 /* Is the parsing being done for a visible proto_tree or an invisible one?
900 * By setting this correctly, the proto_tree creation is sped up by not
901 * having to call vsnprintf and copy strings around.
904 proto_tree_set_visible(proto_tree
*tree
, bool visible
)
906 bool old_visible
= PTREE_DATA(tree
)->visible
;
908 PTREE_DATA(tree
)->visible
= visible
;
914 proto_tree_set_fake_protocols(proto_tree
*tree
, bool fake_protocols
)
917 PTREE_DATA(tree
)->fake_protocols
= fake_protocols
;
920 /* Assume dissector set only its protocol fields.
921 This function is called by dissectors and allows the speeding up of filtering
922 in wireshark; if this function returns false it is safe to reset tree to NULL
923 and thus skip calling most of the expensive proto_tree_add_...()
925 If the tree is visible we implicitly assume the field is referenced.
928 proto_field_is_referenced(proto_tree
*tree
, int proto_id
)
930 register header_field_info
*hfinfo
;
936 if (PTREE_DATA(tree
)->visible
)
939 PROTO_REGISTRAR_GET_NTH(proto_id
, hfinfo
);
940 if (hfinfo
->ref_type
!= HF_REF_TYPE_NONE
)
943 if (hfinfo
->type
== FT_PROTOCOL
&& !PTREE_DATA(tree
)->fake_protocols
)
950 /* Finds a record in the hfinfo array by id. */
952 proto_registrar_get_nth(unsigned hfindex
)
954 register header_field_info
*hfinfo
;
956 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
961 /* Prefix initialization
962 * this allows for a dissector to register a display filter name prefix
963 * so that it can delay the initialization of the hf array as long as
967 /* compute a hash for the part before the dot of a display filter */
969 prefix_hash (const void *key
) {
970 /* end the string at the dot and compute its hash */
971 char* copy
= g_strdup((const char *)key
);
982 tmp
= g_str_hash(copy
);
987 /* are both strings equal up to the end or the dot? */
989 prefix_equal (const void *ap
, const void *bp
) {
990 const char* a
= (const char *)ap
;
991 const char* b
= (const char *)bp
;
997 if ( (ac
== '.' || ac
== '\0') && (bc
== '.' || bc
== '\0') ) return TRUE
;
999 if ( (ac
== '.' || ac
== '\0') && ! (bc
== '.' || bc
== '\0') ) return FALSE
;
1000 if ( (bc
== '.' || bc
== '\0') && ! (ac
== '.' || ac
== '\0') ) return FALSE
;
1002 if (ac
!= bc
) return FALSE
;
1008 /* Register a new prefix for "delayed" initialization of field arrays */
1010 proto_register_prefix(const char *prefix
, prefix_initializer_t pi
) {
1012 prefixes
= g_hash_table_new(prefix_hash
, prefix_equal
);
1015 g_hash_table_insert(prefixes
, (void *)prefix
, (void *)pi
);
1018 /* helper to call all prefix initializers */
1020 initialize_prefix(void *k
, void *v
, void *u _U_
) {
1021 ((prefix_initializer_t
)v
)((const char *)k
);
1025 /** Initialize every remaining uninitialized prefix. */
1027 proto_initialize_all_prefixes(void) {
1028 g_hash_table_foreach_remove(prefixes
, initialize_prefix
, NULL
);
1031 /* Finds a record in the hfinfo array by name.
1032 * If it fails to find it in the already registered fields,
1033 * it tries to find and call an initializer in the prefixes
1034 * table and if so it looks again.
1038 proto_registrar_get_byname(const char *field_name
)
1040 header_field_info
*hfinfo
;
1041 prefix_initializer_t pi
;
1046 if (g_strcmp0(field_name
, last_field_name
) == 0) {
1050 hfinfo
= (header_field_info
*)g_hash_table_lookup(gpa_name_map
, field_name
);
1053 g_free(last_field_name
);
1054 last_field_name
= g_strdup(field_name
);
1055 last_hfinfo
= hfinfo
;
1062 if ((pi
= (prefix_initializer_t
)g_hash_table_lookup(prefixes
, field_name
) ) != NULL
) {
1064 g_hash_table_remove(prefixes
, field_name
);
1069 hfinfo
= (header_field_info
*)g_hash_table_lookup(gpa_name_map
, field_name
);
1072 g_free(last_field_name
);
1073 last_field_name
= g_strdup(field_name
);
1074 last_hfinfo
= hfinfo
;
1080 proto_registrar_get_byalias(const char *alias_name
)
1086 /* Find our aliased protocol. */
1087 char *an_copy
= g_strdup(alias_name
);
1088 char *dot
= strchr(an_copy
, '.');
1092 const char *proto_pfx
= (const char *) g_hash_table_lookup(gpa_protocol_aliases
, an_copy
);
1098 /* Construct our aliased field and look it up. */
1099 GString
*filter_name
= g_string_new(proto_pfx
);
1101 g_string_append_printf(filter_name
, ".%s", dot
+1);
1103 header_field_info
*hfinfo
= proto_registrar_get_byname(filter_name
->str
);
1105 g_string_free(filter_name
, TRUE
);
1111 proto_registrar_get_id_byname(const char *field_name
)
1113 header_field_info
*hfinfo
;
1115 hfinfo
= proto_registrar_get_byname(field_name
);
1124 label_strcat_flags(const header_field_info
*hfinfo
)
1126 if (FIELD_DISPLAY(hfinfo
->display
) & BASE_STR_WSP
)
1127 return FORMAT_LABEL_REPLACE_SPACE
;
1133 format_bytes_hfinfo_maxlen(wmem_allocator_t
*scope
, const header_field_info
*hfinfo
,
1134 const uint8_t *bytes
, unsigned length
, size_t max_str_len
)
1141 if (hfinfo
->display
& BASE_SHOW_UTF_8_PRINTABLE
) {
1143 * If all bytes are valid and printable UTF-8, show the
1144 * bytes as a string - in quotes to indicate that it's
1147 if (isprint_utf8_string(bytes
, length
)) {
1148 str
= wmem_strdup_printf(scope
, "\"%.*s\"",
1149 (int)length
, bytes
);
1152 } else if (hfinfo
->display
& BASE_SHOW_ASCII_PRINTABLE
) {
1154 * Check whether all bytes are printable.
1156 is_printable
= true;
1157 for (p
= bytes
; p
< bytes
+length
; p
++) {
1158 if (!g_ascii_isprint(*p
)) {
1159 /* Not printable. */
1160 is_printable
= false;
1166 * If all bytes are printable ASCII, show the bytes
1167 * as a string - in quotes to indicate that it's
1171 str
= wmem_strdup_printf(scope
, "\"%.*s\"",
1172 (int)length
, bytes
);
1178 * Either it's not printable ASCII, or we don't care whether
1179 * it's printable ASCII; show it as hex bytes.
1181 switch (FIELD_DISPLAY(hfinfo
->display
)) {
1183 str
= bytes_to_str_punct_maxlen(scope
, bytes
, length
, '.', max_str_len
/3);
1186 str
= bytes_to_str_punct_maxlen(scope
, bytes
, length
, '-', max_str_len
/3);
1189 str
= bytes_to_str_punct_maxlen(scope
, bytes
, length
, ':', max_str_len
/3);
1192 str
= bytes_to_str_punct_maxlen(scope
, bytes
, length
, ' ', max_str_len
/3);
1196 if (prefs
.display_byte_fields_with_spaces
) {
1197 str
= bytes_to_str_punct_maxlen(scope
, bytes
, length
, ' ', max_str_len
/3);
1199 str
= bytes_to_str_maxlen(scope
, bytes
, length
, max_str_len
/2);
1205 if (hfinfo
->display
& BASE_ALLOW_ZERO
) {
1206 str
= wmem_strdup(scope
, "<none>");
1208 str
= wmem_strdup(scope
, "<MISSING>");
1215 format_bytes_hfinfo(wmem_allocator_t
*scope
, const header_field_info
*hfinfo
,
1216 const uint8_t *bytes
, unsigned length
)
1218 return format_bytes_hfinfo_maxlen(scope
, hfinfo
, bytes
, length
, ITEM_LABEL_LENGTH
);
1222 ptvcursor_new_subtree_levels(ptvcursor_t
*ptvc
)
1224 subtree_lvl
*pushed_tree
;
1226 DISSECTOR_ASSERT(ptvc
->pushed_tree_max
<= SUBTREE_MAX_LEVELS
-SUBTREE_ONCE_ALLOCATION_NUMBER
);
1227 ptvc
->pushed_tree_max
+= SUBTREE_ONCE_ALLOCATION_NUMBER
;
1229 pushed_tree
= (subtree_lvl
*)wmem_realloc(ptvc
->scope
, (void *)ptvc
->pushed_tree
, sizeof(subtree_lvl
) * ptvc
->pushed_tree_max
);
1230 DISSECTOR_ASSERT(pushed_tree
!= NULL
);
1231 ptvc
->pushed_tree
= pushed_tree
;
1235 ptvcursor_free_subtree_levels(ptvcursor_t
*ptvc
)
1237 ptvc
->pushed_tree
= NULL
;
1238 ptvc
->pushed_tree_max
= 0;
1239 DISSECTOR_ASSERT(ptvc
->pushed_tree_index
== 0);
1240 ptvc
->pushed_tree_index
= 0;
1243 /* Allocates an initializes a ptvcursor_t with 3 variables:
1244 * proto_tree, tvbuff, and offset. */
1246 ptvcursor_new(wmem_allocator_t
*scope
, proto_tree
*tree
, tvbuff_t
*tvb
, int offset
)
1250 ptvc
= wmem_new(scope
, ptvcursor_t
);
1251 ptvc
->scope
= scope
;
1254 ptvc
->offset
= offset
;
1255 ptvc
->pushed_tree
= NULL
;
1256 ptvc
->pushed_tree_max
= 0;
1257 ptvc
->pushed_tree_index
= 0;
1262 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
1264 ptvcursor_free(ptvcursor_t
*ptvc
)
1266 ptvcursor_free_subtree_levels(ptvc
);
1270 /* Returns tvbuff. */
1272 ptvcursor_tvbuff(ptvcursor_t
*ptvc
)
1277 /* Returns current offset. */
1279 ptvcursor_current_offset(ptvcursor_t
*ptvc
)
1281 return ptvc
->offset
;
1285 ptvcursor_tree(ptvcursor_t
*ptvc
)
1294 ptvcursor_set_tree(ptvcursor_t
*ptvc
, proto_tree
*tree
)
1299 /* creates a subtree, sets it as the working tree and pushes the old working tree */
1301 ptvcursor_push_subtree(ptvcursor_t
*ptvc
, proto_item
*it
, int ett_subtree
)
1303 subtree_lvl
*subtree
;
1304 if (ptvc
->pushed_tree_index
>= ptvc
->pushed_tree_max
)
1305 ptvcursor_new_subtree_levels(ptvc
);
1307 subtree
= ptvc
->pushed_tree
+ ptvc
->pushed_tree_index
;
1308 subtree
->tree
= ptvc
->tree
;
1310 ptvc
->pushed_tree_index
++;
1311 return ptvcursor_set_subtree(ptvc
, it
, ett_subtree
);
1314 /* pops a subtree */
1316 ptvcursor_pop_subtree(ptvcursor_t
*ptvc
)
1318 subtree_lvl
*subtree
;
1320 if (ptvc
->pushed_tree_index
<= 0)
1323 ptvc
->pushed_tree_index
--;
1324 subtree
= ptvc
->pushed_tree
+ ptvc
->pushed_tree_index
;
1325 if (subtree
->it
!= NULL
)
1326 proto_item_set_len(subtree
->it
, ptvcursor_current_offset(ptvc
) - subtree
->cursor_offset
);
1328 ptvc
->tree
= subtree
->tree
;
1331 /* saves the current tvb offset and the item in the current subtree level */
1333 ptvcursor_subtree_set_item(ptvcursor_t
*ptvc
, proto_item
*it
)
1335 subtree_lvl
*subtree
;
1337 DISSECTOR_ASSERT(ptvc
->pushed_tree_index
> 0);
1339 subtree
= ptvc
->pushed_tree
+ ptvc
->pushed_tree_index
- 1;
1341 subtree
->cursor_offset
= ptvcursor_current_offset(ptvc
);
1344 /* Creates a subtree and adds it to the cursor as the working tree but does not
1345 * save the old working tree */
1347 ptvcursor_set_subtree(ptvcursor_t
*ptvc
, proto_item
*it
, int ett_subtree
)
1349 ptvc
->tree
= proto_item_add_subtree(it
, ett_subtree
);
1354 ptvcursor_add_subtree_item(ptvcursor_t
*ptvc
, proto_item
*it
, int ett_subtree
, int length
)
1356 ptvcursor_push_subtree(ptvc
, it
, ett_subtree
);
1357 if (length
== SUBTREE_UNDEFINED_LENGTH
)
1358 ptvcursor_subtree_set_item(ptvc
, it
);
1359 return ptvcursor_tree(ptvc
);
1362 /* Add an item to the tree and create a subtree
1363 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1364 * In this case, when the subtree will be closed, the parent item length will
1365 * be equal to the advancement of the cursor since the creation of the subtree.
1368 ptvcursor_add_with_subtree(ptvcursor_t
*ptvc
, int hfindex
, int length
,
1369 const unsigned encoding
, int ett_subtree
)
1373 it
= ptvcursor_add_no_advance(ptvc
, hfindex
, length
, encoding
);
1374 return ptvcursor_add_subtree_item(ptvc
, it
, ett_subtree
, length
);
1378 proto_tree_add_text_node(proto_tree
*tree
, tvbuff_t
*tvb
, int start
, int length
);
1380 /* Add a text node to the tree and create a subtree
1381 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1382 * In this case, when the subtree will be closed, the item length will be equal
1383 * to the advancement of the cursor since the creation of the subtree.
1386 ptvcursor_add_text_with_subtree(ptvcursor_t
*ptvc
, int length
,
1387 int ett_subtree
, const char *format
, ...)
1391 header_field_info
*hfinfo
;
1394 tree
= ptvcursor_tree(ptvc
);
1396 CHECK_FOR_NULL_TREE(tree
);
1398 TRY_TO_FAKE_THIS_ITEM(tree
, hf_text_only
, hfinfo
);
1400 pi
= proto_tree_add_text_node(tree
, ptvcursor_tvbuff(ptvc
),
1401 ptvcursor_current_offset(ptvc
), length
);
1403 TRY_TO_FAKE_THIS_REPR(pi
);
1405 va_start(ap
, format
);
1406 proto_tree_set_representation(pi
, format
, ap
);
1409 return ptvcursor_add_subtree_item(ptvc
, pi
, ett_subtree
, length
);
1412 /* Add a text-only node, leaving it to our caller to fill the text in */
1414 proto_tree_add_text_node(proto_tree
*tree
, tvbuff_t
*tvb
, int start
, int length
)
1421 pi
= proto_tree_add_pi(tree
, &hfi_text_only
, tvb
, start
, &length
);
1426 /* (INTERNAL USE ONLY) Add a text-only node to the proto_tree */
1428 proto_tree_add_text_internal(proto_tree
*tree
, tvbuff_t
*tvb
, int start
, int length
,
1429 const char *format
, ...)
1433 header_field_info
*hfinfo
;
1436 length
= tvb_captured_length(tvb
) ? tvb_ensure_captured_length_remaining(tvb
, start
) : 0;
1438 tvb_ensure_bytes_exist(tvb
, start
, length
);
1441 CHECK_FOR_NULL_TREE(tree
);
1443 TRY_TO_FAKE_THIS_ITEM(tree
, hf_text_only
, hfinfo
);
1445 pi
= proto_tree_add_text_node(tree
, tvb
, start
, length
);
1447 TRY_TO_FAKE_THIS_REPR(pi
);
1449 va_start(ap
, format
);
1450 proto_tree_set_representation(pi
, format
, ap
);
1456 /* (INTERNAL USE ONLY) Add a text-only node to the proto_tree (va_list version) */
1458 proto_tree_add_text_valist_internal(proto_tree
*tree
, tvbuff_t
*tvb
, int start
,
1459 int length
, const char *format
, va_list ap
)
1462 header_field_info
*hfinfo
;
1464 /* proto_tree_add_text_node calls proto_tree_add_pi() with the
1465 * FT_NONE hf_text_only, which calls get_hfi_length, which adjusts
1466 * the length to be what's in the tvbuff if length is -1, and the
1467 * minimum of length and what's in the tvbuff if not.
1470 CHECK_FOR_NULL_TREE(tree
);
1472 TRY_TO_FAKE_THIS_ITEM(tree
, hf_text_only
, hfinfo
);
1474 pi
= proto_tree_add_text_node(tree
, tvb
, start
, length
);
1476 TRY_TO_FAKE_THIS_REPR(pi
);
1478 proto_tree_set_representation(pi
, format
, ap
);
1483 /* Add a text-only node that creates a subtree underneath.
1486 proto_tree_add_subtree(proto_tree
*tree
, tvbuff_t
*tvb
, int start
, int length
, int idx
, proto_item
**tree_item
, const char *text
)
1488 return proto_tree_add_subtree_format(tree
, tvb
, start
, length
, idx
, tree_item
, "%s", text
);
1491 /* Add a text-only node that creates a subtree underneath.
1494 proto_tree_add_subtree_format(proto_tree
*tree
, tvbuff_t
*tvb
, int start
, int length
, int idx
, proto_item
**tree_item
, const char *format
, ...)
1500 va_start(ap
, format
);
1501 pi
= proto_tree_add_text_valist_internal(tree
, tvb
, start
, length
, format
, ap
);
1504 if (tree_item
!= NULL
)
1507 pt
= proto_item_add_subtree(pi
, idx
);
1512 /* Add a text-only node for debugging purposes. The caller doesn't need
1513 * to worry about tvbuff, start, or length. Debug message gets sent to
1516 proto_tree_add_debug_text(proto_tree
*tree
, const char *format
, ...)
1521 pi
= proto_tree_add_text_node(tree
, NULL
, 0, 0);
1524 va_start(ap
, format
);
1525 proto_tree_set_representation(pi
, format
, ap
);
1528 va_start(ap
, format
);
1529 vprintf(format
, ap
);
1537 proto_tree_add_format_text(proto_tree
*tree
, tvbuff_t
*tvb
, int start
, int length
)
1540 header_field_info
*hfinfo
;
1542 CHECK_FOR_NULL_TREE(tree
);
1544 TRY_TO_FAKE_THIS_ITEM(tree
, hf_text_only
, hfinfo
);
1546 pi
= proto_tree_add_text_node(tree
, tvb
, start
, length
);
1548 TRY_TO_FAKE_THIS_REPR(pi
);
1550 proto_item_set_text(pi
, "%s", tvb_format_text(tree
->tree_data
->pinfo
->pool
, tvb
, start
, length
));
1556 proto_tree_add_format_wsp_text(proto_tree
*tree
, tvbuff_t
*tvb
, int start
, int length
)
1559 header_field_info
*hfinfo
;
1562 CHECK_FOR_NULL_TREE(tree
);
1564 TRY_TO_FAKE_THIS_ITEM(tree
, hf_text_only
, hfinfo
);
1566 pi
= proto_tree_add_text_node(tree
, tvb
, start
, length
);
1568 TRY_TO_FAKE_THIS_REPR(pi
);
1570 str
= tvb_format_text_wsp(NULL
, tvb
, start
, length
);
1571 proto_item_set_text(pi
, "%s", str
);
1572 wmem_free(NULL
, str
);
1577 void proto_report_dissector_bug(const char *format
, ...)
1581 if (wireshark_abort_on_dissector_bug
) {
1583 * Try to have the error message show up in the crash
1586 va_start(args
, format
);
1587 ws_vadd_crash_info(format
, args
);
1591 * Print the error message.
1593 va_start(args
, format
);
1594 vfprintf(stderr
, format
, args
);
1603 va_start(args
, format
);
1604 VTHROW_FORMATTED(DissectorError
, format
, args
);
1609 /* We could probably get away with changing is_error to a minimum length value. */
1611 report_type_length_mismatch(proto_tree
*tree
, const char *descr
, int length
, bool is_error
)
1614 expert_add_info_format(NULL
, tree
, &ei_type_length_mismatch_error
, "Trying to fetch %s with length %d", descr
, length
);
1616 expert_add_info_format(NULL
, tree
, &ei_type_length_mismatch_warn
, "Trying to fetch %s with length %d", descr
, length
);
1620 THROW(ReportedBoundsError
);
1625 get_uint_value(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int length
, const unsigned encoding
)
1633 value
= tvb_get_uint8(tvb
, offset
);
1634 if (encoding
& ENC_ZIGBEE
) {
1635 if (value
== 0xFF) { /* Invalid Zigbee length, set to 0 */
1642 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letohs(tvb
, offset
)
1643 : tvb_get_ntohs(tvb
, offset
);
1644 if (encoding
& ENC_ZIGBEE
) {
1645 if (value
== 0xFFFF) { /* Invalid Zigbee length, set to 0 */
1652 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letoh24(tvb
, offset
)
1653 : tvb_get_ntoh24(tvb
, offset
);
1657 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letohl(tvb
, offset
)
1658 : tvb_get_ntohl(tvb
, offset
);
1663 length_error
= true;
1666 length_error
= false;
1667 value
= (encoding
& ENC_LITTLE_ENDIAN
) ? tvb_get_letohl(tvb
, offset
)
1668 : tvb_get_ntohl(tvb
, offset
);
1670 report_type_length_mismatch(tree
, "an unsigned integer", length
, length_error
);
1676 static inline uint64_t
1677 get_uint64_value(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, unsigned length
, const unsigned encoding
)
1681 value
= tvb_get_uint64_with_length(tvb
, offset
, length
, encoding
);
1683 if (length
< 1 || length
> 8) {
1684 report_type_length_mismatch(tree
, "an unsigned integer", length
, (length
< 1));
1691 get_int_value(proto_tree
*tree
, tvbuff_t
*tvb
, int offset
, int length
, const unsigned encoding
)
1699 value
= tvb_get_int8(tvb
, offset
);
1703 value
= encoding
? tvb_get_letohis(tvb
, offset
)
1704 : tvb_get_ntohis(tvb
, offset
);
1708 value
= encoding
? tvb_get_letohi24(tvb
, offset
)
1709 : tvb_get_ntohi24(tvb
, offset
);
1713 value
= encoding
? tvb_get_letohil(tvb
, offset
)
1714 : tvb_get_ntohil(tvb
, offset
);
1719 length_error
= true;
1722 length_error
= false;
1723 value
= encoding
? tvb_get_letohil(tvb
, offset
)
1724 : tvb_get_ntohil(tvb
, offset
);
1726 report_type_length_mismatch(tree
, "a signed integer", length
, length_error
);
1732 /* Note: this returns an unsigned int64, but with the appropriate bit(s) set to
1733 * be cast-able as a int64_t. This is weird, but what the code has always done.
1735 static inline uint64_t
1736 get_int64_value(proto_tree
*tree
, tvbuff_t
*tvb
, int start
, unsigned length
, const unsigned encoding
)
1738 uint64_t value
= get_uint64_value(tree
, tvb
, start
, length
, encoding
);
1742 value
= ws_sign_ext64(value
, 56);
1745 value
= ws_sign_ext64(value
, 48);
1748 value
= ws_sign_ext64(value
, 40);
1751 value
= ws_sign_ext64(value
, 32);
1754 value
= ws_sign_ext64(value
, 24);
1757 value
= ws_sign_ext64(value
, 16);
1760 value
= ws_sign_ext64(value
, 8);
1768 static inline const uint8_t *
1769 get_string_value(wmem_allocator_t
*scope
, tvbuff_t
*tvb
, int start
,
1770 int length
, int *ret_length
, const unsigned encoding
)
1773 length
= tvb_ensure_captured_length_remaining(tvb
, start
);
1775 *ret_length
= length
;
1776 return tvb_get_string_enc(scope
, tvb
, start
, length
, encoding
);
1779 /* For FT_STRINGZ */
1780 static inline const uint8_t *
1781 get_stringz_value(wmem_allocator_t
*scope
, proto_tree
*tree
, tvbuff_t
*tvb
,
1782 int start
, int length
, int *ret_length
, const unsigned encoding
)
1784 const uint8_t *value
;
1787 report_type_length_mismatch(tree
, "a string", length
, true);
1790 /* This can throw an exception */
1791 value
= tvb_get_stringz_enc(scope
, tvb
, start
, &length
, encoding
);
1793 /* In this case, length signifies the length of the string.
1795 * This could either be a null-padded string, which doesn't
1796 * necessarily have a '\0' at the end, or a null-terminated
1797 * string, with a trailing '\0'. (Yes, there are cases
1798 * where you have a string that's both counted and null-
1801 * In the first case, we must allocate a buffer of length
1802 * "length+1", to make room for a trailing '\0'.
1804 * In the second case, we don't assume that there is a
1805 * trailing '\0' there, as the packet might be malformed.
1806 * (XXX - should we throw an exception if there's no
1807 * trailing '\0'?) Therefore, we allocate a buffer of
1808 * length "length+1", and put in a trailing '\0', just to
1811 * (XXX - this would change if we made string values counted
1812 * rather than null-terminated.)
1814 value
= tvb_get_string_enc(scope
, tvb
, start
, length
, encoding
);
1816 *ret_length
= length
;
1820 /* For FT_UINT_STRING */
1821 static inline const uint8_t *
1822 get_uint_string_value(wmem_allocator_t
*scope
, proto_tree
*tree
,
1823 tvbuff_t
*tvb
, int start
, int length
, int *ret_length
,
1824 const unsigned encoding
)
1827 const uint8_t *value
;
1829 /* I believe it's ok if this is called with a NULL tree */
1830 n
= get_uint_value(tree
, tvb
, start
, length
, encoding
& ~ENC_CHARENCODING_MASK
);
1831 value
= tvb_get_string_enc(scope
, tvb
, start
+ length
, n
, encoding
);
1833 *ret_length
= length
;
1837 /* For FT_STRINGZPAD */
1838 static inline const uint8_t *
1839 get_stringzpad_value(wmem_allocator_t
*scope
, tvbuff_t
*tvb
, int start
,
1840 int length
, int *ret_length
, const unsigned encoding
)
1843 * XXX - currently, string values are null-
1844 * terminated, so a "zero-padded" string
1845 * isn't special. If we represent string
1846 * values as something that includes a counted
1847 * array of bytes, we'll need to strip the
1851 length
= tvb_ensure_captured_length_remaining(tvb
, start
);
1853 *ret_length
= length
;
1854 return tvb_get_string_enc(scope
, tvb
, start
, length
, encoding
);
1857 /* For FT_STRINGZTRUNC */
1858 static inline const uint8_t *
1859 get_stringztrunc_value(wmem_allocator_t
*scope
, tvbuff_t
*tvb
, int start
,
1860 int length
, int *ret_length
, const unsigned encoding
)
1863 * XXX - currently, string values are null-
1864 * terminated, so a "zero-truncated" string
1865 * isn't special. If we represent string
1866 * values as something that includes a counted
1867 * array of bytes, we'll need to strip everything
1868 * starting with the terminating NUL.
1871 length
= tvb_ensure_captured_length_remaining(tvb
, start
);
1873 *ret_length
= length
;
1874 return tvb_get_string_enc(scope
, tvb
, start
, length
, encoding
);
1878 * Deltas between the epochs for various non-UN*X time stamp formats and
1879 * the January 1, 1970, 00:00:00 (proleptic?) UTC epoch for the UN*X time
1884 * NTP Era 0: the epoch is January 1, 1900, 00:00:00 (proleptic?) UTC.
1885 * XXX - if it's OK if this is unsigned, can we just use
1886 * EPOCH_DELTA_1900_01_01_00_00_00_UTC?
1888 #define NTP_TIMEDIFF1900TO1970SEC INT64_C(2208988800)
1891 * NTP Era 1: the epoch is February 7, 2036, 06:28:16 UTC.
1893 #define NTP_TIMEDIFF1970TO2036SEC INT64_C(2085978496)
1895 /* this can be called when there is no tree, so tree may be null */
1897 get_time_value(proto_tree
*tree
, tvbuff_t
*tvb
, const int start
,
1898 const int length
, const unsigned encoding
, nstime_t
*time_stamp
,
1899 const bool is_relative
)
1907 case ENC_TIME_SECS_NSECS
|ENC_BIG_ENDIAN
:
1909 * If the length is 16, 8-byte seconds, followed
1910 * by 8-byte fractional time in nanoseconds,
1913 * If the length is 12, 8-byte seconds, followed
1914 * by 4-byte fractional time in nanoseconds,
1917 * If the length is 8, 4-byte seconds, followed
1918 * by 4-byte fractional time in nanoseconds,
1921 * For absolute times, the seconds are seconds
1922 * since the UN*X epoch.
1925 time_stamp
->secs
= (time_t)tvb_get_ntoh64(tvb
, start
);
1926 time_stamp
->nsecs
= (uint32_t)tvb_get_ntoh64(tvb
, start
+8);
1927 } else if (length
== 12) {
1928 time_stamp
->secs
= (time_t)tvb_get_ntoh64(tvb
, start
);
1929 time_stamp
->nsecs
= tvb_get_ntohl(tvb
, start
+8);
1930 } else if (length
== 8) {
1931 time_stamp
->secs
= (time_t)tvb_get_ntohl(tvb
, start
);
1932 time_stamp
->nsecs
= tvb_get_ntohl(tvb
, start
+4);
1933 } else if (length
== 4) {
1935 * Backwards compatibility.
1936 * ENC_TIME_SECS_NSECS is 0; using
1937 * ENC_BIG_ENDIAN by itself with a 4-byte
1938 * time-in-seconds value was done in the
1941 time_stamp
->secs
= (time_t)tvb_get_ntohl(tvb
, start
);
1942 time_stamp
->nsecs
= 0;
1944 time_stamp
->secs
= 0;
1945 time_stamp
->nsecs
= 0;
1946 report_type_length_mismatch(tree
, "a timespec", length
, (length
< 4));
1950 case ENC_TIME_SECS_NSECS
|ENC_LITTLE_ENDIAN
:
1952 * If the length is 16, 8-byte seconds, followed
1953 * by 8-byte fractional time in nanoseconds,
1954 * both little-endian.
1956 * If the length is 12, 8-byte seconds, followed
1957 * by 4-byte fractional time in nanoseconds,
1958 * both little-endian.
1960 * If the length is 8, 4-byte seconds, followed
1961 * by 4-byte fractional time in nanoseconds,
1962 * both little-endian.
1964 * For absolute times, the seconds are seconds
1965 * since the UN*X epoch.
1968 time_stamp
->secs
= (time_t)tvb_get_letoh64(tvb
, start
);
1969 time_stamp
->nsecs
= (uint32_t)tvb_get_letoh64(tvb
, start
+8);
1970 } else if (length
== 12) {
1971 time_stamp
->secs
= (time_t)tvb_get_letoh64(tvb
, start
);
1972 time_stamp
->nsecs
= tvb_get_letohl(tvb
, start
+8);
1973 } else if (length
== 8) {
1974 time_stamp
->secs
= (time_t)tvb_get_letohl(tvb
, start
);
1975 time_stamp
->nsecs
= tvb_get_letohl(tvb
, start
+4);
1976 } else if (length
== 4) {
1978 * Backwards compatibility.
1979 * ENC_TIME_SECS_NSECS is 0; using
1980 * ENC_LITTLE_ENDIAN by itself with a 4-byte
1981 * time-in-seconds value was done in the
1984 time_stamp
->secs
= (time_t)tvb_get_letohl(tvb
, start
);
1985 time_stamp
->nsecs
= 0;
1987 time_stamp
->secs
= 0;
1988 time_stamp
->nsecs
= 0;
1989 report_type_length_mismatch(tree
, "a timespec", length
, (length
< 4));
1993 case ENC_TIME_NTP
|ENC_BIG_ENDIAN
:
1995 * NTP time stamp, big-endian.
1996 * Only supported for absolute times.
1998 DISSECTOR_ASSERT(!is_relative
);
2000 /* We need a temporary variable here so the unsigned math
2001 * works correctly (for years > 2036 according to RFC 2030
2004 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2005 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2006 * If bit 0 is not set, the time is in the range 2036-2104 and
2007 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2009 tmpsecs
= tvb_get_ntohl(tvb
, start
);
2010 if ((tmpsecs
& 0x80000000) != 0)
2011 time_stamp
->secs
= (time_t)((int64_t)tmpsecs
- NTP_TIMEDIFF1900TO1970SEC
);
2013 time_stamp
->secs
= (time_t)((int64_t)tmpsecs
+ NTP_TIMEDIFF1970TO2036SEC
);
2016 tmp64secs
= tvb_get_ntoh64(tvb
, start
);
2017 if (tmp64secs
== 0) {
2018 //This is "NULL" time
2019 time_stamp
->secs
= 0;
2020 time_stamp
->nsecs
= 0;
2023 * Convert 1/2^32s of a second to
2026 time_stamp
->nsecs
= (int)(1000000000*(tvb_get_ntohl(tvb
, start
+4)/4294967296.0));
2028 } else if (length
== 4) {
2030 * Backwards compatibility.
2033 //This is "NULL" time
2034 time_stamp
->secs
= 0;
2036 time_stamp
->nsecs
= 0;
2038 time_stamp
->secs
= 0;
2039 time_stamp
->nsecs
= 0;
2040 report_type_length_mismatch(tree
, "an NTP time stamp", length
, (length
< 4));
2044 case ENC_TIME_NTP
|ENC_LITTLE_ENDIAN
:
2046 * NTP time stamp, little-endian.
2047 * Only supported for absolute times.
2049 * NTP doesn't use this, because it's an Internet format
2050 * and hence big-endian. Any implementation must decide
2051 * whether the NTP timestamp is a 64-bit unsigned fixed
2052 * point number (RFC 1305, RFC 4330) or a 64-bit struct
2053 * with a 32-bit unsigned seconds field followed by a
2054 * 32-bit fraction field (cf. RFC 5905, which obsoletes
2055 * the previous two).
2057 * XXX: We do the latter, but no dissector uses this format.
2058 * OTOH, ERF timestamps do the former, so perhaps we
2059 * should switch the interpretation so that packet-erf.c
2060 * could use this directly?
2062 DISSECTOR_ASSERT(!is_relative
);
2064 /* We need a temporary variable here so the unsigned math
2065 * works correctly (for years > 2036 according to RFC 2030
2068 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2069 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2070 * If bit 0 is not set, the time is in the range 2036-2104 and
2071 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2073 tmpsecs
= tvb_get_letohl(tvb
, start
);
2074 if ((tmpsecs
& 0x80000000) != 0)
2075 time_stamp
->secs
= (time_t)((int64_t)tmpsecs
- NTP_TIMEDIFF1900TO1970SEC
);
2077 time_stamp
->secs
= (time_t)((int64_t)tmpsecs
+ NTP_TIMEDIFF1970TO2036SEC
);
2080 tmp64secs
= tvb_get_letoh64(tvb
, start
);
2081 if (tmp64secs
== 0) {
2082 //This is "NULL" time
2083 time_stamp
->secs
= 0;
2084 time_stamp
->nsecs
= 0;
2087 * Convert 1/2^32s of a second to
2090 time_stamp
->nsecs
= (int)(1000000000*(tvb_get_letohl(tvb
, start
+4)/4294967296.0));
2092 } else if (length
== 4) {
2094 * Backwards compatibility.
2097 //This is "NULL" time
2098 time_stamp
->secs
= 0;
2100 time_stamp
->nsecs
= 0;
2102 time_stamp
->secs
= 0;
2103 time_stamp
->nsecs
= 0;
2104 report_type_length_mismatch(tree
, "an NTP time stamp", length
, (length
< 4));
2108 case ENC_TIME_TOD
|ENC_BIG_ENDIAN
:
2110 * S/3x0 and z/Architecture TOD clock time stamp,
2111 * big-endian. The epoch is January 1, 1900,
2112 * 00:00:00 (proleptic?) UTC.
2114 * Only supported for absolute times.
2116 DISSECTOR_ASSERT(!is_relative
);
2117 DISSECTOR_ASSERT(length
== 8);
2120 todusecs
= tvb_get_ntoh64(tvb
, start
) >> 12;
2121 time_stamp
->secs
= (time_t)((todusecs
/ 1000000) - EPOCH_DELTA_1900_01_01_00_00_00_UTC
);
2122 time_stamp
->nsecs
= (int)((todusecs
% 1000000) * 1000);
2124 time_stamp
->secs
= 0;
2125 time_stamp
->nsecs
= 0;
2126 report_type_length_mismatch(tree
, "a TOD clock time stamp", length
, (length
< 4));
2130 case ENC_TIME_TOD
|ENC_LITTLE_ENDIAN
:
2132 * S/3x0 and z/Architecture TOD clock time stamp,
2133 * little-endian. The epoch is January 1, 1900,
2134 * 00:00:00 (proleptic?) UTC.
2136 * Only supported for absolute times.
2138 DISSECTOR_ASSERT(!is_relative
);
2141 todusecs
= tvb_get_letoh64(tvb
, start
) >> 12 ;
2142 time_stamp
->secs
= (time_t)((todusecs
/ 1000000) - EPOCH_DELTA_1900_01_01_00_00_00_UTC
);
2143 time_stamp
->nsecs
= (int)((todusecs
% 1000000) * 1000);
2145 time_stamp
->secs
= 0;
2146 time_stamp
->nsecs
= 0;
2147 report_type_length_mismatch(tree
, "a TOD clock time stamp", length
, (length
< 4));
2151 case ENC_TIME_RTPS
|ENC_BIG_ENDIAN
:
2153 * Time stamp using the same seconds/fraction format
2154 * as NTP, but with the origin of the time stamp being
2155 * the UNIX epoch rather than the NTP epoch; big-
2158 * Only supported for absolute times.
2160 DISSECTOR_ASSERT(!is_relative
);
2163 time_stamp
->secs
= (time_t)tvb_get_ntohl(tvb
, start
);
2165 * Convert 1/2^32s of a second to nanoseconds.
2167 time_stamp
->nsecs
= (int)(1000000000*(tvb_get_ntohl(tvb
, start
+4)/4294967296.0));
2169 time_stamp
->secs
= 0;
2170 time_stamp
->nsecs
= 0;
2171 report_type_length_mismatch(tree
, "an RTPS time stamp", length
, (length
< 4));
2175 case ENC_TIME_RTPS
|ENC_LITTLE_ENDIAN
:
2177 * Time stamp using the same seconds/fraction format
2178 * as NTP, but with the origin of the time stamp being
2179 * the UNIX epoch rather than the NTP epoch; little-
2182 * Only supported for absolute times.
2184 * The RTPS specification explicitly supports Little
2185 * Endian encoding. In one place, it states that its
2186 * Time_t representation "is the one defined by ...
2187 * RFC 1305", but in another explicitly defines it as
2188 * a struct consisting of an 32 bit unsigned seconds
2189 * field and a 32 bit unsigned fraction field, not a 64
2190 * bit fixed point, so we do that here.
2191 * https://www.omg.org/spec/DDSI-RTPS/2.5/PDF
2193 DISSECTOR_ASSERT(!is_relative
);
2196 time_stamp
->secs
= (time_t)tvb_get_letohl(tvb
, start
);
2198 * Convert 1/2^32s of a second to nanoseconds.
2200 time_stamp
->nsecs
= (int)(1000000000*(tvb_get_letohl(tvb
, start
+4)/4294967296.0));
2202 time_stamp
->secs
= 0;
2203 time_stamp
->nsecs
= 0;
2204 report_type_length_mismatch(tree
, "an RTPS time stamp", length
, (length
< 4));
2208 case ENC_TIME_MIP6
| ENC_BIG_ENDIAN
:
2210 * MIP6 time stamp, big-endian.
2211 * A 64-bit unsigned integer field containing a timestamp. The
2212 * value indicates the number of seconds since January 1, 1970,
2213 * 00:00 UTC, by using a fixed point format. In this format, the
2214 * integer number of seconds is contained in the first 48 bits of
2215 * the field, and the remaining 16 bits indicate the number of
2216 * 1/65536 fractions of a second.
2218 * Only supported for absolute times.
2220 DISSECTOR_ASSERT(!is_relative
);
2223 /* We need a temporary variable here so the casting and fractions
2224 * of a second work correctly.
2226 tmp64secs
= tvb_get_ntoh48(tvb
, start
);
2227 tmpsecs
= tvb_get_ntohs(tvb
, start
+ 6);
2230 if ((tmp64secs
== 0) && (tmpsecs
== 0)) {
2231 //This is "NULL" time
2232 time_stamp
->secs
= 0;
2233 time_stamp
->nsecs
= 0;
2235 time_stamp
->secs
= (time_t)tmp64secs
;
2236 time_stamp
->nsecs
= (int)((tmpsecs
/ 4294967296.0) * 1000000000);
2239 time_stamp
->secs
= 0;
2240 time_stamp
->nsecs
= 0;
2241 report_type_length_mismatch(tree
, "an NTP time stamp", length
, (length
!= 8));
2245 case ENC_TIME_SECS_USECS
|ENC_BIG_ENDIAN
:
2247 * If the length is 16, 8-byte seconds, followed
2248 * by 8-byte fractional time in microseconds,
2251 * If the length is 12, 8-byte seconds, followed
2252 * by 4-byte fractional time in microseconds,
2255 * If the length is 8, 4-byte seconds, followed
2256 * by 4-byte fractional time in microseconds,
2259 * For absolute times, the seconds are seconds
2260 * since the UN*X epoch.
2263 time_stamp
->secs
= (time_t)tvb_get_ntoh64(tvb
, start
);
2264 time_stamp
->nsecs
= (uint32_t)tvb_get_ntoh64(tvb
, start
+8)*1000;
2265 } else if (length
== 12) {
2266 time_stamp
->secs
= (time_t)tvb_get_ntoh64(tvb
, start
);
2267 time_stamp
->nsecs
= tvb_get_ntohl(tvb
, start
+8)*1000;
2268 } else if (length
== 8) {
2269 time_stamp
->secs
= (time_t)tvb_get_ntohl(tvb
, start
);
2270 time_stamp
->nsecs
= tvb_get_ntohl(tvb
, start
+4)*1000;
2272 time_stamp
->secs
= 0;
2273 time_stamp
->nsecs
= 0;
2274 report_type_length_mismatch(tree
, "a timeval", length
, (length
< 4));
2278 case ENC_TIME_SECS_USECS
|ENC_LITTLE_ENDIAN
:
2280 * If the length is 16, 8-byte seconds, followed
2281 * by 8-byte fractional time in microseconds,
2282 * both little-endian.
2284 * If the length is 12, 8-byte seconds, followed
2285 * by 4-byte fractional time in microseconds,
2286 * both little-endian.
2288 * If the length is 8, 4-byte seconds, followed
2289 * by 4-byte fractional time in microseconds,
2290 * both little-endian.
2292 * For absolute times, the seconds are seconds
2293 * since the UN*X epoch.
2296 time_stamp
->secs
= (time_t)tvb_get_letoh64(tvb
, start
);
2297 time_stamp
->nsecs
= (uint32_t)tvb_get_letoh64(tvb
, start
+8)*1000;
2298 } else if (length
== 12) {
2299 time_stamp
->secs
= (time_t)tvb_get_letoh64(tvb
, start
);
2300 time_stamp
->nsecs
= tvb_get_letohl(tvb
, start
+8)*1000;
2301 } else if (length
== 8) {
2302 time_stamp
->secs
= (time_t)tvb_get_letohl(tvb
, start
);
2303 time_stamp
->nsecs
= tvb_get_letohl(tvb
, start
+4)*1000;
2305 time_stamp
->secs
= 0;
2306 time_stamp
->nsecs
= 0;
2307 report_type_length_mismatch(tree
, "a timeval", length
, (length
< 4));
2311 case ENC_TIME_SECS
|ENC_BIG_ENDIAN
:
2312 case ENC_TIME_SECS
|ENC_LITTLE_ENDIAN
:
2314 * Seconds, 1 to 8 bytes.
2315 * For absolute times, it's seconds since the
2318 if (length
>= 1 && length
<= 8) {
2319 time_stamp
->secs
= (time_t)get_uint64_value(tree
, tvb
, start
, length
, encoding
);
2320 time_stamp
->nsecs
= 0;
2322 time_stamp
->secs
= 0;
2323 time_stamp
->nsecs
= 0;
2324 report_type_length_mismatch(tree
, "a time-in-seconds time stamp", length
, (length
< 4));
2328 case ENC_TIME_MSECS
|ENC_BIG_ENDIAN
:
2329 case ENC_TIME_MSECS
|ENC_LITTLE_ENDIAN
:
2331 * Milliseconds, 1 to 8 bytes.
2332 * For absolute times, it's milliseconds since the
2335 if (length
>= 1 && length
<= 8) {
2338 msecs
= get_uint64_value(tree
, tvb
, start
, length
, encoding
);
2339 time_stamp
->secs
= (time_t)(msecs
/ 1000);
2340 time_stamp
->nsecs
= (int)(msecs
% 1000)*1000000;
2342 time_stamp
->secs
= 0;
2343 time_stamp
->nsecs
= 0;
2344 report_type_length_mismatch(tree
, "a time-in-milliseconds time stamp", length
, (length
< 4));
2348 case ENC_TIME_USECS
|ENC_BIG_ENDIAN
:
2349 case ENC_TIME_USECS
|ENC_LITTLE_ENDIAN
:
2351 * Microseconds, 1 to 8 bytes.
2352 * For absolute times, it's microseconds since the
2355 if (length
>= 1 && length
<= 8) {
2358 usecs
= get_uint64_value(tree
, tvb
, start
, length
, encoding
);
2359 time_stamp
->secs
= (time_t)(usecs
/ 1000000);
2360 time_stamp
->nsecs
= (int)(usecs
% 1000000)*1000;
2362 time_stamp
->secs
= 0;
2363 time_stamp
->nsecs
= 0;
2364 report_type_length_mismatch(tree
, "a time-in-microseconds time stamp", length
, (length
< 4));
2368 case ENC_TIME_NSECS
|ENC_BIG_ENDIAN
:
2369 case ENC_TIME_NSECS
|ENC_LITTLE_ENDIAN
:
2371 * nanoseconds, 1 to 8 bytes.
2372 * For absolute times, it's nanoseconds since the
2376 if (length
>= 1 && length
<= 8) {
2379 nsecs
= get_uint64_value(tree
, tvb
, start
, length
, encoding
);
2380 time_stamp
->secs
= (time_t)(nsecs
/ 1000000000);
2381 time_stamp
->nsecs
= (int)(nsecs
% 1000000000);
2383 time_stamp
->secs
= 0;
2384 time_stamp
->nsecs
= 0;
2385 report_type_length_mismatch(tree
, "a time-in-nanoseconds time stamp", length
, (length
< 4));
2389 case ENC_TIME_RFC_3971
|ENC_BIG_ENDIAN
:
2391 * 1/64ths of a second since the UN*X epoch,
2394 * Only supported for absolute times.
2396 DISSECTOR_ASSERT(!is_relative
);
2400 * The upper 48 bits are seconds since the
2403 time_stamp
->secs
= (time_t)tvb_get_ntoh48(tvb
, start
);
2405 * The lower 16 bits are 1/2^16s of a second;
2406 * convert them to nanoseconds.
2408 * XXX - this may give the impression of higher
2409 * precision than you actually get.
2411 time_stamp
->nsecs
= (int)(1000000000*(tvb_get_ntohs(tvb
, start
+6)/65536.0));
2413 time_stamp
->secs
= 0;
2414 time_stamp
->nsecs
= 0;
2415 report_type_length_mismatch(tree
, "an RFC 3971-style time stamp", length
, (length
< 4));
2419 case ENC_TIME_RFC_3971
|ENC_LITTLE_ENDIAN
:
2421 * 1/64ths of a second since the UN*X epoch,
2424 * Only supported for absolute times.
2426 DISSECTOR_ASSERT(!is_relative
);
2430 * XXX - this is assuming that, if anybody
2431 * were ever to use this format - RFC 3971
2432 * doesn't, because that's an Internet
2433 * protocol, and those use network byte
2434 * order, i.e. big-endian - they'd treat it
2435 * as a 64-bit count of 1/2^16s of a second,
2436 * putting the upper 48 bits at the end.
2438 * The lower 48 bits are seconds since the
2441 time_stamp
->secs
= (time_t)tvb_get_letoh48(tvb
, start
+2);
2443 * The upper 16 bits are 1/2^16s of a second;
2444 * convert them to nanoseconds.
2446 * XXX - this may give the impression of higher
2447 * precision than you actually get.
2449 time_stamp
->nsecs
= (int)(1000000000*(tvb_get_letohs(tvb
, start
)/65536.0));
2451 time_stamp
->secs
= 0;
2452 time_stamp
->nsecs
= 0;
2453 report_type_length_mismatch(tree
, "an RFC 3971-style time stamp", length
, (length
< 4));
2457 case ENC_TIME_SECS_NTP
|ENC_BIG_ENDIAN
:
2459 * NTP time stamp, with 1-second resolution (i.e.,
2460 * seconds since the NTP epoch), big-endian.
2461 * Only supported for absolute times.
2463 DISSECTOR_ASSERT(!is_relative
);
2467 * We need a temporary variable here so the unsigned math
2468 * works correctly (for years > 2036 according to RFC 2030
2471 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2472 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2473 * If bit 0 is not set, the time is in the range 2036-2104 and
2474 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2476 tmpsecs
= tvb_get_ntohl(tvb
, start
);
2477 if ((tmpsecs
& 0x80000000) != 0)
2478 time_stamp
->secs
= (time_t)((int64_t)tmpsecs
- NTP_TIMEDIFF1900TO1970SEC
);
2480 time_stamp
->secs
= (time_t)((int64_t)tmpsecs
+ NTP_TIMEDIFF1970TO2036SEC
);
2481 time_stamp
->nsecs
= 0;
2483 time_stamp
->secs
= 0;
2484 time_stamp
->nsecs
= 0;
2485 report_type_length_mismatch(tree
, "an NTP seconds-only time stamp", length
, (length
< 4));
2489 case ENC_TIME_SECS_NTP
|ENC_LITTLE_ENDIAN
:
2491 * NTP time stamp, with 1-second resolution (i.e.,
2492 * seconds since the NTP epoch), little-endian.
2493 * Only supported for absolute times.
2495 DISSECTOR_ASSERT(!is_relative
);
2498 * We need a temporary variable here so the unsigned math
2499 * works correctly (for years > 2036 according to RFC 2030
2502 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2503 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2504 * If bit 0 is not set, the time is in the range 2036-2104 and
2505 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2508 tmpsecs
= tvb_get_letohl(tvb
, start
);
2509 if ((tmpsecs
& 0x80000000) != 0)
2510 time_stamp
->secs
= (time_t)((int64_t)tmpsecs
- NTP_TIMEDIFF1900TO1970SEC
);
2512 time_stamp
->secs
= (time_t)((int64_t)tmpsecs
+ NTP_TIMEDIFF1970TO2036SEC
);
2513 time_stamp
->nsecs
= 0;
2515 time_stamp
->secs
= 0;
2516 time_stamp
->nsecs
= 0;
2517 report_type_length_mismatch(tree
, "an NTP seconds-only time stamp", length
, (length
< 4));
2521 case ENC_TIME_MSEC_NTP
| ENC_BIG_ENDIAN
:
2523 * Milliseconds, 6 to 8 bytes.
2524 * For absolute times, it's milliseconds since the
2527 * ETSI TS 129.274 8.119 defines this as:
2528 * "a 48 bit unsigned integer in network order format
2529 * ...encoded as the number of milliseconds since
2530 * 00:00:00 January 1, 1900 00:00 UTC, i.e. as the
2531 * rounded value of 1000 x the value of the 64-bit
2532 * timestamp (Seconds + (Fraction / (1<<32))) defined
2533 * in clause 6 of IETF RFC 5905."
2535 * Taken literally, the part after "i.e." would
2536 * mean that the value rolls over before reaching
2537 * 2^32 * 1000 = 4294967296000 = 0x3e800000000
2538 * when the 64 bit timestamp rolls over, and we have
2539 * to pick an NTP Era equivalence class to support
2540 * (such as 1968-01-20 to 2104-02-06).
2542 * OTOH, the extra room might be used to store Era
2543 * information instead, in which case times until
2544 * 10819-08-03 can be represented with 6 bytes without
2545 * ambiguity. We handle both implementations, and assume
2546 * that times before 1968-01-20 are not represented.
2548 * Only 6 bytes or more makes sense as an absolute
2549 * time. 5 bytes or fewer could express a span of
2550 * less than 35 years, either 1900-1934 or 2036-2070.
2552 if (length
>= 6 && length
<= 8) {
2555 msecs
= get_uint64_value(tree
, tvb
, start
, length
, encoding
);
2556 tmp64secs
= (msecs
/ 1000);
2558 * Assume that times in the first half of NTP
2559 * Era 0 really represent times in the NTP
2562 if (tmp64secs
>= 0x80000000)
2563 time_stamp
->secs
= (time_t)((int64_t)tmp64secs
- NTP_TIMEDIFF1900TO1970SEC
);
2565 time_stamp
->secs
= (time_t)((int64_t)tmp64secs
+ NTP_TIMEDIFF1970TO2036SEC
);
2566 time_stamp
->nsecs
= (int)(msecs
% 1000)*1000000;
2569 time_stamp
->secs
= 0;
2570 time_stamp
->nsecs
= 0;
2571 report_type_length_mismatch(tree
, "a time-in-milliseconds NTP time stamp", length
, (length
< 6));
2575 case ENC_TIME_MP4_FILE_SECS
|ENC_BIG_ENDIAN
:
2577 * MP4 file time stamps, big-endian.
2578 * Only supported for absolute times.
2580 DISSECTOR_ASSERT(!is_relative
);
2583 tmp64secs
= tvb_get_ntoh64(tvb
, start
);
2584 time_stamp
->secs
= (time_t)(int64_t)(tmp64secs
- EPOCH_DELTA_1904_01_01_00_00_00_UTC
);
2585 time_stamp
->nsecs
= 0;
2586 } else if (length
== 4) {
2587 tmpsecs
= tvb_get_ntohl(tvb
, start
);
2588 time_stamp
->secs
= (time_t)(int32_t)(tmpsecs
- EPOCH_DELTA_1904_01_01_00_00_00_UTC
);
2589 time_stamp
->nsecs
= 0;
2591 time_stamp
->secs
= 0;
2592 time_stamp
->nsecs
= 0;
2593 report_type_length_mismatch(tree
, "an MP4 time stamp", length
, (length
< 4));
2597 case ENC_TIME_ZBEE_ZCL
| ENC_BIG_ENDIAN
:
2599 * Zigbee ZCL time stamps, big-endian.
2600 * Only supported for absolute times.
2602 DISSECTOR_ASSERT(!is_relative
);
2605 tmp64secs
= tvb_get_ntoh64(tvb
, start
);
2606 time_stamp
->secs
= (time_t)(int64_t)(tmp64secs
- EPOCH_DELTA_2000_01_01_00_00_00_UTC
);
2607 time_stamp
->nsecs
= 0;
2608 } else if (length
== 4) {
2609 tmpsecs
= tvb_get_ntohl(tvb
, start
);
2610 time_stamp
->secs
= (time_t)(int32_t)(tmpsecs
- EPOCH_DELTA_2000_01_01_00_00_00_UTC
);
2611 time_stamp
->nsecs
= 0;
2613 time_stamp
->secs
= 0;
2614 time_stamp
->nsecs
= 0;
2615 report_type_length_mismatch(tree
, "a Zigbee ZCL time stamp", length
, (length
< 4));
2619 case ENC_TIME_ZBEE_ZCL
| ENC_LITTLE_ENDIAN
:
2621 * Zigbee ZCL time stamps, little-endian.
2622 * Only supported for absolute times.
2624 DISSECTOR_ASSERT(!is_relative
);
2627 tmp64secs
= tvb_get_letoh64(tvb
, start
);
2628 time_stamp
->secs
= (time_t)(int64_t)(tmp64secs
- EPOCH_DELTA_2000_01_01_00_00_00_UTC
);
2629 time_stamp
->nsecs
= 0;
2630 } else if (length
== 4) {
2631 tmpsecs
= tvb_get_letohl(tvb
, start
);
2632 time_stamp
->secs
= (time_t)(int32_t)(tmpsecs
- EPOCH_DELTA_2000_01_01_00_00_00_UTC
);
2633 time_stamp
->nsecs
= 0;
2635 time_stamp
->secs
= 0;
2636 time_stamp
->nsecs
= 0;
2637 report_type_length_mismatch(tree
, "a Zigbee ZCL time stamp", length
, (length
< 4));
2642 DISSECTOR_ASSERT_NOT_REACHED();
2648 tree_data_add_maybe_interesting_field(tree_data_t
*tree_data
, field_info
*fi
)
2650 const header_field_info
*hfinfo
= fi
->hfinfo
;
2652 if (hfinfo
->ref_type
== HF_REF_TYPE_DIRECT
|| hfinfo
->ref_type
== HF_REF_TYPE_PRINT
) {
2653 GPtrArray
*ptrs
= NULL
;
2655 if (tree_data
->interesting_hfids
== NULL
) {
2656 /* Initialize the hash because we now know that it is needed */
2657 tree_data
->interesting_hfids
=
2658 g_hash_table_new(g_direct_hash
, NULL
/* g_direct_equal */);
2659 } else if (g_hash_table_size(tree_data
->interesting_hfids
)) {
2660 ptrs
= (GPtrArray
*)g_hash_table_lookup(tree_data
->interesting_hfids
,
2661 GINT_TO_POINTER(hfinfo
->id
));
2665 /* First element triggers the creation of pointer array */
2666 ptrs
= g_ptr_array_new();
2667 g_hash_table_insert(tree_data
->interesting_hfids
,
2668 GINT_TO_POINTER(hfinfo
->id
), ptrs
);
2671 g_ptr_array_add(ptrs
, fi
);
2677 * Validates that field length bytes are available starting from
2678 * start (pos/neg). Throws an exception if they aren't.
2681 test_length(header_field_info
*hfinfo
, tvbuff_t
*tvb
,
2682 int start
, int length
, const unsigned encoding
)
2689 if ((hfinfo
->type
== FT_STRINGZ
) ||
2690 ((encoding
& ENC_VARINT_MASK
) &&
2691 (FT_IS_UINT(hfinfo
->type
) || FT_IS_INT(hfinfo
->type
)))) {
2692 /* If we're fetching until the end of the TVB, only validate
2693 * that the offset is within range.
2699 tvb_ensure_bytes_exist(tvb
, start
, size
);
2703 detect_trailing_stray_characters(unsigned encoding
, const char *string
, int length
, proto_item
*pi
)
2705 bool found_stray_character
= false;
2710 switch (encoding
& ENC_CHARENCODING_MASK
) {
2713 for (int i
= (int)strlen(string
); i
< length
; i
++) {
2714 if (string
[i
] != '\0') {
2715 found_stray_character
= true;
2725 if (found_stray_character
) {
2726 expert_add_info(NULL
, pi
, &ei_string_trailing_characters
);
2731 free_fvalue_cb(void *data
)
2733 fvalue_t
*fv
= (fvalue_t
*)data
;
2737 /* Add an item to a proto_tree, using the text label registered to that item;
2738 the item is extracted from the tvbuff handed to it. */
2740 proto_tree_new_item(field_info
*new_fi
, proto_tree
*tree
,
2741 tvbuff_t
*tvb
, int start
, int length
,
2747 ws_in4_addr ipv4_value
;
2750 const char *stringval
= NULL
;
2751 nstime_t time_stamp
;
2754 /* Ensure that the newly created fvalue_t is freed if we throw an
2755 * exception before adding it to the tree. (gcc creates clobbering
2756 * when it optimizes the equivalent TRY..EXCEPT implementation.)
2757 * XXX: Move the new_field_info() call inside here?
2759 CLEANUP_PUSH(free_fvalue_cb
, new_fi
->value
);
2761 switch (new_fi
->hfinfo
->type
) {
2763 /* no value to set for FT_NONE */
2767 proto_tree_set_protocol_tvb(new_fi
, tvb
, new_fi
->hfinfo
->name
, length
);
2771 proto_tree_set_bytes_tvb(new_fi
, tvb
, start
, length
);
2775 n
= get_uint_value(tree
, tvb
, start
, length
, encoding
);
2776 proto_tree_set_bytes_tvb(new_fi
, tvb
, start
+ length
, n
);
2778 /* Instead of calling proto_item_set_len(), since we don't yet
2779 * have a proto_item, we set the field_info's length ourselves. */
2780 new_fi
->length
= n
+ length
;
2785 * Map all non-zero values to little-endian for
2786 * backwards compatibility.
2789 encoding
= ENC_LITTLE_ENDIAN
;
2790 proto_tree_set_boolean(new_fi
,
2791 get_uint64_value(tree
, tvb
, start
, length
, encoding
));
2795 /* XXX - make these just FT_UINT? */
2800 if (encoding
& ENC_VARINT_MASK
) {
2801 new_fi
->length
= tvb_get_varint(tvb
, start
, (length
== -1) ? FT_VARINT_MAX_LEN
: length
, &value64
, encoding
);
2802 value
= (uint32_t)value64
;
2803 if (!(encoding
& ENC_VARINT_QUIC
)) {
2804 new_fi
->flags
|= FI_VARINT
;
2809 * Map all non-zero values to little-endian for
2810 * backwards compatibility.
2813 encoding
= ENC_LITTLE_ENDIAN
;
2815 value
= get_uint_value(tree
, tvb
, start
, length
, encoding
);
2817 proto_tree_set_uint(new_fi
, value
);
2824 if (encoding
& ENC_VARINT_MASK
) {
2825 new_fi
->length
= tvb_get_varint(tvb
, start
, (length
== -1) ? FT_VARINT_MAX_LEN
: length
, &value64
, encoding
);
2826 if (!(encoding
& ENC_VARINT_QUIC
)) {
2827 new_fi
->flags
|= FI_VARINT
;
2832 * Map all other non-zero values to little-endian for
2833 * backwards compatibility.
2836 encoding
= ENC_LITTLE_ENDIAN
;
2838 value64
= get_uint64_value(tree
, tvb
, start
, length
, encoding
);
2840 proto_tree_set_uint64(new_fi
, value64
);
2843 /* XXX - make these just FT_INT? */
2849 * Map all non-zero values to little-endian for
2850 * backwards compatibility.
2853 encoding
= ENC_LITTLE_ENDIAN
;
2854 proto_tree_set_int(new_fi
,
2855 get_int_value(tree
, tvb
, start
, length
, encoding
));
2863 * Map all non-zero values to little-endian for
2864 * backwards compatibility.
2867 encoding
= ENC_LITTLE_ENDIAN
;
2868 proto_tree_set_int64(new_fi
,
2869 get_int64_value(tree
, tvb
, start
, length
, encoding
));
2874 * Map all non-zero values to little-endian for
2875 * backwards compatibility.
2878 encoding
= ENC_LITTLE_ENDIAN
;
2879 if (length
!= FT_IPv4_LEN
) {
2880 length_error
= length
< FT_IPv4_LEN
? true : false;
2881 report_type_length_mismatch(tree
, "an IPv4 address", length
, length_error
);
2883 ipv4_value
= tvb_get_ipv4(tvb
, start
);
2885 * NOTE: to support code written when
2886 * proto_tree_add_item() took a bool as its
2887 * last argument, with false meaning "big-endian"
2888 * and true meaning "little-endian", we treat any
2889 * non-zero value of "encoding" as meaning
2892 proto_tree_set_ipv4(new_fi
, encoding
? GUINT32_SWAP_LE_BE(ipv4_value
) : ipv4_value
);
2896 if (length
!= FT_IPXNET_LEN
) {
2897 length_error
= length
< FT_IPXNET_LEN
? true : false;
2898 report_type_length_mismatch(tree
, "an IPXNET address", length
, length_error
);
2900 proto_tree_set_ipxnet(new_fi
,
2901 get_uint_value(tree
, tvb
, start
, FT_IPXNET_LEN
, ENC_BIG_ENDIAN
));
2905 if (length
!= FT_IPv6_LEN
) {
2906 length_error
= length
< FT_IPv6_LEN
? true : false;
2907 report_type_length_mismatch(tree
, "an IPv6 address", length
, length_error
);
2909 proto_tree_set_ipv6_tvb(new_fi
, tvb
, start
, length
);
2913 if (length
!= FT_FCWWN_LEN
) {
2914 length_error
= length
< FT_FCWWN_LEN
? true : false;
2915 report_type_length_mismatch(tree
, "an FCWWN address", length
, length_error
);
2917 proto_tree_set_fcwwn_tvb(new_fi
, tvb
, start
, length
);
2922 length_error
= length
< 7 ? true : false;
2923 report_type_length_mismatch(tree
, "an AX.25 address", length
, length_error
);
2925 proto_tree_set_ax25_tvb(new_fi
, tvb
, start
);
2929 if (length
!= VINES_ADDR_LEN
) {
2930 length_error
= length
< VINES_ADDR_LEN
? true : false;
2931 report_type_length_mismatch(tree
, "a Vines address", length
, length_error
);
2933 proto_tree_set_vines_tvb(new_fi
, tvb
, start
);
2937 if (length
!= FT_ETHER_LEN
) {
2938 length_error
= length
< FT_ETHER_LEN
? true : false;
2939 report_type_length_mismatch(tree
, "a MAC address", length
, length_error
);
2941 proto_tree_set_ether_tvb(new_fi
, tvb
, start
);
2946 * Map all non-zero values to little-endian for
2947 * backwards compatibility.
2950 encoding
= ENC_LITTLE_ENDIAN
;
2951 if (length
!= FT_EUI64_LEN
) {
2952 length_error
= length
< FT_EUI64_LEN
? true : false;
2953 report_type_length_mismatch(tree
, "an EUI-64 address", length
, length_error
);
2955 proto_tree_set_eui64_tvb(new_fi
, tvb
, start
, encoding
);
2959 * Map all non-zero values to little-endian for
2960 * backwards compatibility.
2963 encoding
= ENC_LITTLE_ENDIAN
;
2964 if (length
!= FT_GUID_LEN
) {
2965 length_error
= length
< FT_GUID_LEN
? true : false;
2966 report_type_length_mismatch(tree
, "a GUID", length
, length_error
);
2968 proto_tree_set_guid_tvb(new_fi
, tvb
, start
, encoding
);
2973 proto_tree_set_oid_tvb(new_fi
, tvb
, start
, length
);
2977 proto_tree_set_system_id_tvb(new_fi
, tvb
, start
, length
);
2982 * NOTE: to support code written when
2983 * proto_tree_add_item() took a bool as its
2984 * last argument, with false meaning "big-endian"
2985 * and true meaning "little-endian", we treat any
2986 * non-zero value of "encoding" as meaning
2989 * At some point in the future, we might
2990 * support non-IEEE-binary floating-point
2991 * formats in the encoding as well
2992 * (IEEE decimal, System/3x0, VAX).
2995 encoding
= ENC_LITTLE_ENDIAN
;
2997 length_error
= length
< 4 ? true : false;
2998 report_type_length_mismatch(tree
, "a single-precision floating point number", length
, length_error
);
3001 floatval
= tvb_get_letohieee_float(tvb
, start
);
3003 floatval
= tvb_get_ntohieee_float(tvb
, start
);
3004 proto_tree_set_float(new_fi
, floatval
);
3009 * NOTE: to support code written when
3010 * proto_tree_add_item() took a bool as its
3011 * last argument, with false meaning "big-endian"
3012 * and true meaning "little-endian", we treat any
3013 * non-zero value of "encoding" as meaning
3016 * At some point in the future, we might
3017 * support non-IEEE-binary floating-point
3018 * formats in the encoding as well
3019 * (IEEE decimal, System/3x0, VAX).
3021 if (encoding
== true)
3022 encoding
= ENC_LITTLE_ENDIAN
;
3024 length_error
= length
< 8 ? true : false;
3025 report_type_length_mismatch(tree
, "a double-precision floating point number", length
, length_error
);
3028 doubleval
= tvb_get_letohieee_double(tvb
, start
);
3030 doubleval
= tvb_get_ntohieee_double(tvb
, start
);
3031 proto_tree_set_double(new_fi
, doubleval
);
3035 stringval
= get_string_value(PNODE_POOL(tree
),
3036 tvb
, start
, length
, &length
, encoding
);
3037 proto_tree_set_string(new_fi
, stringval
);
3039 /* Instead of calling proto_item_set_len(), since we
3040 * don't yet have a proto_item, we set the
3041 * field_info's length ourselves.
3043 * XXX - our caller can't use that length to
3044 * advance an offset unless they arrange that
3045 * there always be a protocol tree into which
3046 * we're putting this item.
3048 new_fi
->length
= length
;
3052 stringval
= get_stringz_value(PNODE_POOL(tree
),
3053 tree
, tvb
, start
, length
, &length
, encoding
);
3054 proto_tree_set_string(new_fi
, stringval
);
3056 /* Instead of calling proto_item_set_len(),
3057 * since we don't yet have a proto_item, we
3058 * set the field_info's length ourselves.
3060 * XXX - our caller can't use that length to
3061 * advance an offset unless they arrange that
3062 * there always be a protocol tree into which
3063 * we're putting this item.
3065 new_fi
->length
= length
;
3068 case FT_UINT_STRING
:
3070 * NOTE: to support code written when
3071 * proto_tree_add_item() took a bool as its
3072 * last argument, with false meaning "big-endian"
3073 * and true meaning "little-endian", if the
3074 * encoding value is true, treat that as
3075 * ASCII with a little-endian length.
3077 * This won't work for code that passes
3078 * arbitrary non-zero values; that code
3079 * will need to be fixed.
3081 if (encoding
== true)
3082 encoding
= ENC_ASCII
|ENC_LITTLE_ENDIAN
;
3083 stringval
= get_uint_string_value(PNODE_POOL(tree
),
3084 tree
, tvb
, start
, length
, &length
, encoding
);
3085 proto_tree_set_string(new_fi
, stringval
);
3087 /* Instead of calling proto_item_set_len(), since we
3088 * don't yet have a proto_item, we set the
3089 * field_info's length ourselves.
3091 * XXX - our caller can't use that length to
3092 * advance an offset unless they arrange that
3093 * there always be a protocol tree into which
3094 * we're putting this item.
3096 new_fi
->length
= length
;
3100 stringval
= get_stringzpad_value(PNODE_POOL(tree
),
3101 tvb
, start
, length
, &length
, encoding
);
3102 proto_tree_set_string(new_fi
, stringval
);
3104 /* Instead of calling proto_item_set_len(), since we
3105 * don't yet have a proto_item, we set the
3106 * field_info's length ourselves.
3108 * XXX - our caller can't use that length to
3109 * advance an offset unless they arrange that
3110 * there always be a protocol tree into which
3111 * we're putting this item.
3113 new_fi
->length
= length
;
3116 case FT_STRINGZTRUNC
:
3117 stringval
= get_stringztrunc_value(PNODE_POOL(tree
),
3118 tvb
, start
, length
, &length
, encoding
);
3119 proto_tree_set_string(new_fi
, stringval
);
3121 /* Instead of calling proto_item_set_len(), since we
3122 * don't yet have a proto_item, we set the
3123 * field_info's length ourselves.
3125 * XXX - our caller can't use that length to
3126 * advance an offset unless they arrange that
3127 * there always be a protocol tree into which
3128 * we're putting this item.
3130 new_fi
->length
= length
;
3133 case FT_ABSOLUTE_TIME
:
3135 * Absolute times can be in any of a number of
3136 * formats, and they can be big-endian or
3139 * Historically FT_TIMEs were only timespecs;
3140 * the only question was whether they were stored
3141 * in big- or little-endian format.
3143 * For backwards compatibility, we interpret an
3144 * encoding of 1 as meaning "little-endian timespec",
3145 * so that passing true is interpreted as that.
3147 if (encoding
== true)
3148 encoding
= ENC_TIME_SECS_NSECS
|ENC_LITTLE_ENDIAN
;
3150 get_time_value(tree
, tvb
, start
, length
, encoding
, &time_stamp
, false);
3152 proto_tree_set_time(new_fi
, &time_stamp
);
3155 case FT_RELATIVE_TIME
:
3157 * Relative times can be in any of a number of
3158 * formats, and they can be big-endian or
3161 * Historically FT_TIMEs were only timespecs;
3162 * the only question was whether they were stored
3163 * in big- or little-endian format.
3165 * For backwards compatibility, we interpret an
3166 * encoding of 1 as meaning "little-endian timespec",
3167 * so that passing true is interpreted as that.
3169 if (encoding
== true)
3170 encoding
= ENC_TIME_SECS_NSECS
|ENC_LITTLE_ENDIAN
;
3172 get_time_value(tree
, tvb
, start
, length
, encoding
, &time_stamp
, true);
3174 proto_tree_set_time(new_fi
, &time_stamp
);
3176 case FT_IEEE_11073_SFLOAT
:
3178 encoding
= ENC_LITTLE_ENDIAN
;
3180 length_error
= length
< 2 ? true : false;
3181 report_type_length_mismatch(tree
, "a IEEE 11073 SFLOAT", length
, length_error
);
3184 fvalue_set_uinteger(new_fi
->value
, tvb_get_uint16(tvb
, start
, encoding
));
3187 case FT_IEEE_11073_FLOAT
:
3189 encoding
= ENC_LITTLE_ENDIAN
;
3191 length_error
= length
< 4 ? true : false;
3192 report_type_length_mismatch(tree
, "a IEEE 11073 FLOAT", length
, length_error
);
3197 REPORT_DISSECTOR_BUG("field %s is of unknown type %d (%s)",
3198 new_fi
->hfinfo
->abbrev
,
3199 new_fi
->hfinfo
->type
,
3200 ftype_name(new_fi
->hfinfo
->type
));
3203 FI_SET_FLAG(new_fi
, (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
);
3205 /* Don't add new node to proto_tree until now so that any exceptions
3206 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
3207 /* XXX. wouldn't be better to add this item to tree, with some special
3208 * flag (FI_EXCEPTION?) to know which item caused exception? For
3209 * strings and bytes, we would have to set new_fi->value to something
3210 * non-NULL, or otherwise ensure that proto_item_fill_display_label
3211 * could handle NULL values. */
3213 pi
= proto_tree_add_node(tree
, new_fi
);
3215 switch (new_fi
->hfinfo
->type
) {
3218 /* XXX: trailing stray character detection should be done
3219 * _before_ conversion to UTF-8, because conversion can change
3220 * the length, or else get_string_length should return a value
3221 * for the "length in bytes of the string after conversion
3222 * including internal nulls." (Noting that we do, for other
3223 * reasons, still need the "length in bytes in the field",
3224 * especially for FT_STRINGZ.)
3226 * This is true even for ASCII and UTF-8, because
3227 * substituting REPLACEMENT CHARACTERS for illegal characters
3228 * can also do so (and for UTF-8 possibly even make the
3229 * string _shorter_).
3231 detect_trailing_stray_characters(encoding
, stringval
, length
, pi
);
3242 proto_tree_add_item_ret_int(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3243 const int start
, int length
,
3244 const unsigned encoding
, int32_t *retval
)
3246 header_field_info
*hfinfo
;
3250 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3252 switch (hfinfo
->type
) {
3259 REPORT_DISSECTOR_BUG("64-bit signed integer field %s used with proto_tree_add_item_ret_int()",
3262 REPORT_DISSECTOR_BUG("Non-signed-integer field %s used with proto_tree_add_item_ret_int()",
3266 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length
,
3274 if (encoding
& ENC_STRING
) {
3275 REPORT_DISSECTOR_BUG("wrong encoding");
3277 /* I believe it's ok if this is called with a NULL tree */
3278 value
= get_int_value(tree
, tvb
, start
, length
, encoding
);
3283 if (hfinfo
->bitmask
) {
3284 /* Mask out irrelevant portions */
3285 *retval
&= (uint32_t)(hfinfo
->bitmask
);
3287 *retval
>>= hfinfo_bitshift(hfinfo
);
3289 no_of_bits
= ws_count_ones(hfinfo
->bitmask
);
3290 *retval
= ws_sign_ext32(*retval
, no_of_bits
);
3293 CHECK_FOR_NULL_TREE(tree
);
3295 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3297 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3299 proto_tree_set_int(new_fi
, value
);
3301 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
3303 return proto_tree_add_node(tree
, new_fi
);
3307 proto_tree_add_item_ret_uint(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3308 const int start
, int length
,
3309 const unsigned encoding
, uint32_t *retval
)
3311 header_field_info
*hfinfo
;
3315 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3317 switch (hfinfo
->type
) {
3325 REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
3329 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length
,
3337 if (encoding
& ENC_STRING
) {
3338 REPORT_DISSECTOR_BUG("wrong encoding");
3340 /* I believe it's ok if this is called with a NULL tree */
3341 /* XXX - modify if we ever support EBCDIC FT_CHAR */
3342 if (encoding
& ENC_VARINT_MASK
) {
3344 tvb_get_varint(tvb
, start
, length
, &temp64
, encoding
);
3345 value
= (uint32_t)temp64
;
3347 value
= get_uint_value(tree
, tvb
, start
, length
, encoding
);
3352 if (hfinfo
->bitmask
) {
3353 /* Mask out irrelevant portions */
3354 *retval
&= (uint32_t)(hfinfo
->bitmask
);
3356 *retval
>>= hfinfo_bitshift(hfinfo
);
3360 CHECK_FOR_NULL_TREE(tree
);
3362 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3364 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3366 proto_tree_set_uint(new_fi
, value
);
3368 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
3369 if (encoding
& (ENC_VARINT_PROTOBUF
|ENC_VARINT_ZIGZAG
|ENC_VARINT_SDNV
)) {
3370 new_fi
->flags
|= FI_VARINT
;
3372 return proto_tree_add_node(tree
, new_fi
);
3375 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3376 * and returns proto_item* and uint value retreived*/
3378 ptvcursor_add_ret_uint(ptvcursor_t
*ptvc
, int hfindex
, int length
,
3379 const unsigned encoding
, uint32_t *retval
)
3382 header_field_info
*hfinfo
;
3387 offset
= ptvc
->offset
;
3388 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3390 switch (hfinfo
->type
) {
3398 REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
3402 get_hfi_length(hfinfo
, ptvc
->tvb
, offset
, &length
, &item_length
, encoding
);
3403 test_length(hfinfo
, ptvc
->tvb
, offset
, item_length
, encoding
);
3405 /* I believe it's ok if this is called with a NULL tree */
3406 /* XXX - modify if we ever support EBCDIC FT_CHAR */
3407 value
= get_uint_value(ptvc
->tree
, ptvc
->tvb
, offset
, item_length
, encoding
);
3411 if (hfinfo
->bitmask
) {
3412 /* Mask out irrelevant portions */
3413 *retval
&= (uint32_t)(hfinfo
->bitmask
);
3415 *retval
>>= hfinfo_bitshift(hfinfo
);
3419 ptvc
->offset
+= get_full_length(hfinfo
, ptvc
->tvb
, offset
, length
,
3420 item_length
, encoding
);
3422 CHECK_FOR_NULL_TREE(ptvc
->tree
);
3424 /* Coast clear. Try and fake it */
3425 TRY_TO_FAKE_THIS_ITEM(ptvc
->tree
, hfindex
, hfinfo
);
3427 new_fi
= new_field_info(ptvc
->tree
, hfinfo
, ptvc
->tvb
, offset
, item_length
);
3429 return proto_tree_new_item(new_fi
, ptvc
->tree
, ptvc
->tvb
,
3430 offset
, length
, encoding
);
3433 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3434 * and returns proto_item* and int value retreived*/
3436 ptvcursor_add_ret_int(ptvcursor_t
*ptvc
, int hfindex
, int length
,
3437 const unsigned encoding
, int32_t *retval
)
3440 header_field_info
*hfinfo
;
3445 offset
= ptvc
->offset
;
3446 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3448 switch (hfinfo
->type
) {
3455 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
3459 get_hfi_length(hfinfo
, ptvc
->tvb
, offset
, &length
, &item_length
, encoding
);
3460 test_length(hfinfo
, ptvc
->tvb
, offset
, item_length
, encoding
);
3462 /* I believe it's ok if this is called with a NULL tree */
3463 /* XXX - modify if we ever support EBCDIC FT_CHAR */
3464 value
= get_int_value(ptvc
->tree
, ptvc
->tvb
, offset
, item_length
, encoding
);
3469 if (hfinfo
->bitmask
) {
3470 /* Mask out irrelevant portions */
3471 *retval
&= (uint32_t)(hfinfo
->bitmask
);
3473 *retval
>>= hfinfo_bitshift(hfinfo
);
3475 no_of_bits
= ws_count_ones(hfinfo
->bitmask
);
3476 *retval
= ws_sign_ext32(*retval
, no_of_bits
);
3479 ptvc
->offset
+= get_full_length(hfinfo
, ptvc
->tvb
, offset
, length
,
3480 item_length
, encoding
);
3482 CHECK_FOR_NULL_TREE(ptvc
->tree
);
3484 /* Coast clear. Try and fake it */
3485 TRY_TO_FAKE_THIS_ITEM(ptvc
->tree
, hfindex
, hfinfo
);
3487 new_fi
= new_field_info(ptvc
->tree
, hfinfo
, ptvc
->tvb
, offset
, item_length
);
3489 return proto_tree_new_item(new_fi
, ptvc
->tree
, ptvc
->tvb
,
3490 offset
, length
, encoding
);
3493 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3494 * and returns proto_item* and string value retreived */
3496 ptvcursor_add_ret_string(ptvcursor_t
* ptvc
, int hf
, int length
, const unsigned encoding
, wmem_allocator_t
*scope
, const uint8_t **retval
)
3498 header_field_info
*hfinfo
;
3500 const uint8_t *value
;
3504 offset
= ptvc
->offset
;
3506 PROTO_REGISTRAR_GET_NTH(hf
, hfinfo
);
3508 switch (hfinfo
->type
) {
3510 value
= get_string_value(scope
, ptvc
->tvb
, offset
, length
, &item_length
, encoding
);
3513 value
= get_stringz_value(scope
, ptvc
->tree
, ptvc
->tvb
, offset
, length
, &item_length
, encoding
);
3515 case FT_UINT_STRING
:
3516 value
= get_uint_string_value(scope
, ptvc
->tree
, ptvc
->tvb
, offset
, length
, &item_length
, encoding
);
3519 value
= get_stringzpad_value(scope
, ptvc
->tvb
, offset
, length
, &item_length
, encoding
);
3521 case FT_STRINGZTRUNC
:
3522 value
= get_stringztrunc_value(scope
, ptvc
->tvb
, offset
, length
, &item_length
, encoding
);
3525 REPORT_DISSECTOR_BUG("field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, FT_STRINGZPAD, or FT_STRINGZTRUNC",
3532 ptvc
->offset
+= item_length
;
3534 CHECK_FOR_NULL_TREE(ptvc
->tree
);
3536 TRY_TO_FAKE_THIS_ITEM(ptvc
->tree
, hfinfo
->id
, hfinfo
);
3538 new_fi
= new_field_info(ptvc
->tree
, hfinfo
, ptvc
->tvb
, offset
, item_length
);
3540 return proto_tree_new_item(new_fi
, ptvc
->tree
, ptvc
->tvb
,
3541 offset
, length
, encoding
);
3544 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3545 * and returns proto_item* and boolean value retreived */
3547 ptvcursor_add_ret_boolean(ptvcursor_t
* ptvc
, int hfindex
, int length
, const unsigned encoding
, bool *retval
)
3549 header_field_info
*hfinfo
;
3553 uint64_t value
, bitval
;
3555 offset
= ptvc
->offset
;
3556 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3558 if (hfinfo
->type
!= FT_BOOLEAN
) {
3559 REPORT_DISSECTOR_BUG("field %s is not of type FT_BOOLEAN",
3563 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length
,
3571 if (encoding
& ENC_STRING
) {
3572 REPORT_DISSECTOR_BUG("wrong encoding");
3575 get_hfi_length(hfinfo
, ptvc
->tvb
, offset
, &length
, &item_length
, encoding
);
3576 test_length(hfinfo
, ptvc
->tvb
, offset
, item_length
, encoding
);
3578 /* I believe it's ok if this is called with a NULL tree */
3579 value
= get_uint64_value(ptvc
->tree
, ptvc
->tvb
, offset
, length
, encoding
);
3583 if (hfinfo
->bitmask
) {
3584 /* Mask out irrelevant portions */
3585 bitval
&= hfinfo
->bitmask
;
3587 *retval
= (bitval
!= 0);
3590 ptvc
->offset
+= get_full_length(hfinfo
, ptvc
->tvb
, offset
, length
,
3591 item_length
, encoding
);
3593 CHECK_FOR_NULL_TREE(ptvc
->tree
);
3595 TRY_TO_FAKE_THIS_ITEM(ptvc
->tree
, hfinfo
->id
, hfinfo
);
3597 new_fi
= new_field_info(ptvc
->tree
, hfinfo
, ptvc
->tvb
, offset
, item_length
);
3599 return proto_tree_new_item(new_fi
, ptvc
->tree
, ptvc
->tvb
,
3600 offset
, length
, encoding
);
3604 proto_tree_add_item_ret_uint64(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3605 const int start
, int length
, const unsigned encoding
, uint64_t *retval
)
3607 header_field_info
*hfinfo
;
3611 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3613 switch (hfinfo
->type
) {
3620 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, or FT_UINT64",
3624 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length
,
3632 if (encoding
& ENC_STRING
) {
3633 REPORT_DISSECTOR_BUG("wrong encoding");
3635 /* I believe it's ok if this is called with a NULL tree */
3636 if (encoding
& ENC_VARINT_MASK
) {
3637 tvb_get_varint(tvb
, start
, length
, &value
, encoding
);
3639 value
= get_uint64_value(tree
, tvb
, start
, length
, encoding
);
3644 if (hfinfo
->bitmask
) {
3645 /* Mask out irrelevant portions */
3646 *retval
&= hfinfo
->bitmask
;
3648 *retval
>>= hfinfo_bitshift(hfinfo
);
3652 CHECK_FOR_NULL_TREE(tree
);
3654 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3656 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3658 proto_tree_set_uint64(new_fi
, value
);
3660 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
3661 if (encoding
& (ENC_VARINT_PROTOBUF
|ENC_VARINT_ZIGZAG
|ENC_VARINT_SDNV
)) {
3662 new_fi
->flags
|= FI_VARINT
;
3665 return proto_tree_add_node(tree
, new_fi
);
3669 proto_tree_add_item_ret_int64(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3670 const int start
, int length
, const unsigned encoding
, int64_t *retval
)
3672 header_field_info
*hfinfo
;
3676 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3678 switch (hfinfo
->type
) {
3685 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
3689 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length
,
3697 if (encoding
& ENC_STRING
) {
3698 REPORT_DISSECTOR_BUG("wrong encoding");
3700 /* I believe it's ok if this is called with a NULL tree */
3701 if (encoding
& ENC_VARINT_MASK
) {
3702 tvb_get_varint(tvb
, start
, length
, &value
, encoding
);
3705 value
= get_int64_value(tree
, tvb
, start
, length
, encoding
);
3712 CHECK_FOR_NULL_TREE(tree
);
3714 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3716 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3718 proto_tree_set_int64(new_fi
, value
);
3720 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
3721 if (encoding
& (ENC_VARINT_PROTOBUF
|ENC_VARINT_ZIGZAG
|ENC_VARINT_SDNV
)) {
3722 new_fi
->flags
|= FI_VARINT
;
3725 return proto_tree_add_node(tree
, new_fi
);
3729 proto_tree_add_item_ret_varint(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3730 const int start
, int length
, const unsigned encoding
, uint64_t *retval
, int *lenretval
)
3732 header_field_info
*hfinfo
;
3736 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3738 if ((!FT_IS_INT(hfinfo
->type
)) && (!FT_IS_UINT(hfinfo
->type
))) {
3739 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT or FT_INT",
3743 /* length validation for native number encoding caught by get_uint64_value() */
3744 /* length has to be -1 or > 0 regardless of encoding */
3746 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_varint",
3749 if (encoding
& ENC_STRING
) {
3750 REPORT_DISSECTOR_BUG("wrong encoding");
3753 length
= tvb_get_varint(tvb
, start
, (length
== -1) ? FT_VARINT_MAX_LEN
: length
, &value
, encoding
);
3757 if (hfinfo
->bitmask
) {
3758 /* Mask out irrelevant portions */
3759 *retval
&= hfinfo
->bitmask
;
3761 *retval
>>= hfinfo_bitshift(hfinfo
);
3766 *lenretval
= length
;
3769 CHECK_FOR_NULL_TREE(tree
);
3771 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3773 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3775 proto_tree_set_uint64(new_fi
, value
);
3777 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
3778 if (encoding
& (ENC_VARINT_PROTOBUF
|ENC_VARINT_ZIGZAG
|ENC_VARINT_SDNV
)) {
3779 new_fi
->flags
|= FI_VARINT
;
3782 return proto_tree_add_node(tree
, new_fi
);
3787 proto_tree_add_item_ret_boolean(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3788 const int start
, int length
,
3789 const unsigned encoding
, bool *retval
)
3791 header_field_info
*hfinfo
;
3793 uint64_t value
, bitval
;
3795 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3797 if (hfinfo
->type
!= FT_BOOLEAN
) {
3798 REPORT_DISSECTOR_BUG("field %s is not of type FT_BOOLEAN",
3802 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length
,
3810 if (encoding
& ENC_STRING
) {
3811 REPORT_DISSECTOR_BUG("wrong encoding");
3813 /* I believe it's ok if this is called with a NULL tree */
3814 value
= get_uint64_value(tree
, tvb
, start
, length
, encoding
);
3818 if (hfinfo
->bitmask
) {
3819 /* Mask out irrelevant portions */
3820 bitval
&= hfinfo
->bitmask
;
3822 *retval
= (bitval
!= 0);
3825 CHECK_FOR_NULL_TREE(tree
);
3827 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3829 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3831 proto_tree_set_boolean(new_fi
, value
);
3833 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
3835 return proto_tree_add_node(tree
, new_fi
);
3839 proto_tree_add_item_ret_float(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3840 const int start
, int length
,
3841 const unsigned encoding
, float *retval
)
3843 header_field_info
*hfinfo
= proto_registrar_get_nth(hfindex
);
3847 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
3849 if (hfinfo
->type
!= FT_FLOAT
) {
3850 REPORT_DISSECTOR_BUG("field %s is not of type FT_FLOAT", hfinfo
->abbrev
);
3854 report_type_length_mismatch(tree
, "a single-precision floating point number", length
, true);
3857 /* treat any nonzero encoding as little endian for backwards compatibility */
3858 value
= encoding
? tvb_get_letohieee_float(tvb
, start
) : tvb_get_ntohieee_float(tvb
, start
);
3863 CHECK_FOR_NULL_TREE(tree
);
3865 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3867 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3869 new_fi
->flags
|= FI_LITTLE_ENDIAN
;
3872 proto_tree_set_float(new_fi
, value
);
3874 return proto_tree_add_node(tree
, new_fi
);
3878 proto_tree_add_item_ret_double(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3879 const int start
, int length
,
3880 const unsigned encoding
, double *retval
)
3882 header_field_info
*hfinfo
= proto_registrar_get_nth(hfindex
);
3886 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
3888 if (hfinfo
->type
!= FT_DOUBLE
) {
3889 REPORT_DISSECTOR_BUG("field %s is not of type FT_DOUBLE", hfinfo
->abbrev
);
3893 report_type_length_mismatch(tree
, "a double-precision floating point number", length
, true);
3896 /* treat any nonzero encoding as little endian for backwards compatibility */
3897 value
= encoding
? tvb_get_letohieee_double(tvb
, start
) : tvb_get_ntohieee_double(tvb
, start
);
3902 CHECK_FOR_NULL_TREE(tree
);
3904 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3906 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3908 new_fi
->flags
|= FI_LITTLE_ENDIAN
;
3911 proto_tree_set_double(new_fi
, value
);
3913 return proto_tree_add_node(tree
, new_fi
);
3917 proto_tree_add_item_ret_ipv4(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3918 const int start
, int length
,
3919 const unsigned encoding
, ws_in4_addr
*retval
)
3921 header_field_info
*hfinfo
;
3925 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
3927 switch (hfinfo
->type
) {
3931 REPORT_DISSECTOR_BUG("field %s is not of type FT_IPv4",
3935 if (length
!= FT_IPv4_LEN
)
3936 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_ipv4",
3939 if (encoding
& (ENC_STRING
| ENC_VARINT_MASK
)) {
3940 REPORT_DISSECTOR_BUG("wrong encoding");
3944 * NOTE: to support code written when proto_tree_add_item() took
3945 * a bool as its last argument, with false meaning "big-endian"
3946 * and true meaning "little-endian", we treat any non-zero value
3947 * of "encoding" as meaning "little-endian".
3949 value
= tvb_get_ipv4(tvb
, start
);
3951 value
= GUINT32_SWAP_LE_BE(value
);
3957 CHECK_FOR_NULL_TREE(tree
);
3959 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
3961 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
3963 proto_tree_set_ipv4(new_fi
, value
);
3965 new_fi
->flags
|= encoding
? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
3966 return proto_tree_add_node(tree
, new_fi
);
3970 proto_tree_add_item_ret_ipv6(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
3971 const int start
, int length
,
3972 const unsigned encoding
, ws_in6_addr
*addr
)
3974 header_field_info
*hfinfo
= proto_registrar_get_nth(hfindex
);
3977 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
3979 switch (hfinfo
->type
) {
3983 REPORT_DISSECTOR_BUG("field %s is not of type FT_IPv6",
3987 if (length
!= FT_IPv6_LEN
)
3988 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_ipv6",
3992 REPORT_DISSECTOR_BUG("Encodings not yet implemented for proto_tree_add_item_ret_ipv6");
3995 tvb_get_ipv6(tvb
, start
, addr
);
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_ipv6(new_fi
, addr
);
4005 return proto_tree_add_node(tree
, new_fi
);
4009 proto_tree_add_item_ret_ether(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4010 const int start
, int length
, const unsigned encoding
, uint8_t *retval
) {
4012 header_field_info
*hfinfo
= proto_registrar_get_nth(hfindex
);
4015 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
4017 switch (hfinfo
->type
) {
4021 REPORT_DISSECTOR_BUG("field %s is not of type FT_ETHER",
4025 if (length
!= FT_ETHER_LEN
)
4026 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_ether",
4030 REPORT_DISSECTOR_BUG("Encodings not yet implemented for proto_tree_add_item_ret_ether");
4033 tvb_memcpy(tvb
, retval
, start
, length
);
4035 CHECK_FOR_NULL_TREE(tree
);
4037 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
4039 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
4041 proto_tree_set_ether(new_fi
, retval
);
4043 return proto_tree_add_node(tree
, new_fi
);
4048 proto_tree_add_item_ret_string_and_length(proto_tree
*tree
, int hfindex
,
4050 const int start
, int length
,
4051 const unsigned encoding
,
4052 wmem_allocator_t
*scope
,
4053 const uint8_t **retval
,
4057 header_field_info
*hfinfo
;
4059 const uint8_t *value
;
4061 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4063 switch (hfinfo
->type
) {
4065 value
= get_string_value(scope
, tvb
, start
, length
, lenretval
, encoding
);
4068 value
= get_stringz_value(scope
, tree
, tvb
, start
, length
, lenretval
, encoding
);
4070 case FT_UINT_STRING
:
4071 value
= get_uint_string_value(scope
, tree
, tvb
, start
, length
, lenretval
, encoding
);
4074 value
= get_stringzpad_value(scope
, tvb
, start
, length
, lenretval
, encoding
);
4076 case FT_STRINGZTRUNC
:
4077 value
= get_stringztrunc_value(scope
, tvb
, start
, length
, lenretval
, encoding
);
4080 REPORT_DISSECTOR_BUG("field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, FT_STRINGZPAD, or FT_STRINGZTRUNC",
4087 CHECK_FOR_NULL_TREE(tree
);
4089 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
4091 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, *lenretval
);
4093 proto_tree_set_string(new_fi
, value
);
4095 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
4097 pi
= proto_tree_add_node(tree
, new_fi
);
4099 switch (hfinfo
->type
) {
4103 case FT_STRINGZTRUNC
:
4104 case FT_UINT_STRING
:
4108 detect_trailing_stray_characters(encoding
, value
, length
, pi
);
4112 ws_assert_not_reached();
4119 proto_tree_add_item_ret_string(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4120 const int start
, int length
,
4121 const unsigned encoding
, wmem_allocator_t
*scope
,
4122 const uint8_t **retval
)
4124 return proto_tree_add_item_ret_string_and_length(tree
, hfindex
,
4125 tvb
, start
, length
, encoding
, scope
, retval
, &length
);
4129 proto_tree_add_item_ret_display_string_and_length(proto_tree
*tree
, int hfindex
,
4131 const int start
, int length
,
4132 const unsigned encoding
,
4133 wmem_allocator_t
*scope
,
4138 header_field_info
*hfinfo
;
4140 const uint8_t *value
;
4143 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4145 switch (hfinfo
->type
) {
4147 value
= get_string_value(scope
, tvb
, start
, length
, lenretval
, encoding
);
4148 *retval
= wmem_alloc(scope
, ITEM_LABEL_LENGTH
);
4149 ws_label_strcpy(*retval
, ITEM_LABEL_LENGTH
, 0, value
, label_strcat_flags(hfinfo
));
4152 value
= get_stringz_value(scope
, tree
, tvb
, start
, length
, lenretval
, encoding
);
4153 *retval
= wmem_alloc(scope
, ITEM_LABEL_LENGTH
);
4154 ws_label_strcpy(*retval
, ITEM_LABEL_LENGTH
, 0, value
, label_strcat_flags(hfinfo
));
4156 case FT_UINT_STRING
:
4157 value
= get_uint_string_value(scope
, tree
, tvb
, start
, length
, lenretval
, encoding
);
4158 *retval
= wmem_alloc(scope
, ITEM_LABEL_LENGTH
);
4159 ws_label_strcpy(*retval
, ITEM_LABEL_LENGTH
, 0, value
, label_strcat_flags(hfinfo
));
4162 value
= get_stringzpad_value(scope
, tvb
, start
, length
, lenretval
, encoding
);
4163 *retval
= wmem_alloc(scope
, ITEM_LABEL_LENGTH
);
4164 ws_label_strcpy(*retval
, ITEM_LABEL_LENGTH
, 0, value
, label_strcat_flags(hfinfo
));
4166 case FT_STRINGZTRUNC
:
4167 value
= get_stringztrunc_value(scope
, tvb
, start
, length
, lenretval
, encoding
);
4168 *retval
= wmem_alloc(scope
, ITEM_LABEL_LENGTH
);
4169 ws_label_strcpy(*retval
, ITEM_LABEL_LENGTH
, 0, value
, label_strcat_flags(hfinfo
));
4172 tvb_ensure_bytes_exist(tvb
, start
, length
);
4173 value
= tvb_get_ptr(tvb
, start
, length
);
4174 *retval
= format_bytes_hfinfo(scope
, hfinfo
, value
, length
);
4175 *lenretval
= length
;
4178 n
= get_uint_value(tree
, tvb
, start
, length
, encoding
);
4179 tvb_ensure_bytes_exist(tvb
, start
+ length
, n
);
4180 value
= tvb_get_ptr(tvb
, start
+ length
, n
);
4181 *retval
= format_bytes_hfinfo(scope
, hfinfo
, value
, n
);
4182 *lenretval
= length
+ n
;
4185 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",
4189 CHECK_FOR_NULL_TREE(tree
);
4191 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
4193 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, *lenretval
);
4195 switch (hfinfo
->type
) {
4199 case FT_UINT_STRING
:
4201 case FT_STRINGZTRUNC
:
4202 proto_tree_set_string(new_fi
, value
);
4206 proto_tree_set_bytes(new_fi
, value
, length
);
4210 proto_tree_set_bytes(new_fi
, value
, n
);
4214 ws_assert_not_reached();
4217 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
4219 pi
= proto_tree_add_node(tree
, new_fi
);
4221 switch (hfinfo
->type
) {
4225 case FT_STRINGZTRUNC
:
4226 case FT_UINT_STRING
:
4230 detect_trailing_stray_characters(encoding
, value
, length
, pi
);
4238 ws_assert_not_reached();
4245 proto_tree_add_item_ret_display_string(proto_tree
*tree
, int hfindex
,
4247 const int start
, int length
,
4248 const unsigned encoding
,
4249 wmem_allocator_t
*scope
,
4252 return proto_tree_add_item_ret_display_string_and_length(tree
, hfindex
,
4253 tvb
, start
, length
, encoding
, scope
, retval
, &length
);
4257 proto_tree_add_item_ret_time_string(proto_tree
*tree
, int hfindex
,
4259 const int start
, int length
, const unsigned encoding
,
4260 wmem_allocator_t
*scope
, char **retval
)
4262 header_field_info
*hfinfo
;
4264 nstime_t time_stamp
;
4267 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4269 switch (hfinfo
->type
) {
4270 case FT_ABSOLUTE_TIME
:
4271 get_time_value(tree
, tvb
, start
, length
, encoding
, &time_stamp
, false);
4272 flags
= ABS_TIME_TO_STR_SHOW_ZONE
;
4273 if (prefs
.display_abs_time_ascii
< ABS_TIME_ASCII_TREE
) {
4274 flags
|= ABS_TIME_TO_STR_ISO8601
;
4276 *retval
= abs_time_to_str_ex(scope
, &time_stamp
, hfinfo
->display
, flags
);
4278 case FT_RELATIVE_TIME
:
4279 get_time_value(tree
, tvb
, start
, length
, encoding
, &time_stamp
, true);
4280 *retval
= rel_time_to_secs_str(scope
, &time_stamp
);
4283 REPORT_DISSECTOR_BUG("field %s is not of type FT_ABSOLUTE_TIME or FT_RELATIVE_TIME",
4287 CHECK_FOR_NULL_TREE(tree
);
4289 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
4291 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
4293 switch (hfinfo
->type
) {
4295 case FT_ABSOLUTE_TIME
:
4296 case FT_RELATIVE_TIME
:
4297 proto_tree_set_time(new_fi
, &time_stamp
);
4300 ws_assert_not_reached();
4303 new_fi
->flags
|= (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
;
4305 return proto_tree_add_node(tree
, new_fi
);
4308 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
4309 and returns proto_item* */
4311 ptvcursor_add(ptvcursor_t
*ptvc
, int hfindex
, int length
,
4312 const unsigned encoding
)
4315 header_field_info
*hfinfo
;
4319 offset
= ptvc
->offset
;
4320 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4321 get_hfi_length(hfinfo
, ptvc
->tvb
, offset
, &length
, &item_length
, encoding
);
4322 test_length(hfinfo
, ptvc
->tvb
, offset
, item_length
, encoding
);
4324 ptvc
->offset
+= get_full_length(hfinfo
, ptvc
->tvb
, offset
, length
,
4325 item_length
, encoding
);
4327 CHECK_FOR_NULL_TREE(ptvc
->tree
);
4329 /* Coast clear. Try and fake it */
4330 TRY_TO_FAKE_THIS_ITEM(ptvc
->tree
, hfindex
, hfinfo
);
4332 new_fi
= new_field_info(ptvc
->tree
, hfinfo
, ptvc
->tvb
, offset
, item_length
);
4334 return proto_tree_new_item(new_fi
, ptvc
->tree
, ptvc
->tvb
,
4335 offset
, length
, encoding
);
4338 /* Add an item to a proto_tree, using the text label registered to that item;
4339 the item is extracted from the tvbuff handed to it. */
4341 proto_tree_add_item_new(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
,
4342 const int start
, int length
, const unsigned encoding
)
4347 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
4349 get_hfi_length(hfinfo
, tvb
, start
, &length
, &item_length
, encoding
);
4350 test_length(hfinfo
, tvb
, start
, item_length
, encoding
);
4352 CHECK_FOR_NULL_TREE(tree
);
4354 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
4356 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, item_length
);
4358 return proto_tree_new_item(new_fi
, tree
, tvb
, start
, length
, encoding
);
4362 proto_tree_add_item(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4363 const int start
, int length
, const unsigned encoding
)
4365 register header_field_info
*hfinfo
;
4367 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4368 return proto_tree_add_item_new(tree
, hfinfo
, tvb
, start
, length
, encoding
);
4371 /* Add an item to a proto_tree, using the text label registered to that item;
4372 the item is extracted from the tvbuff handed to it.
4374 Return the length of the item through the pointer. */
4376 proto_tree_add_item_new_ret_length(proto_tree
*tree
, header_field_info
*hfinfo
,
4377 tvbuff_t
*tvb
, const int start
,
4378 int length
, const unsigned encoding
,
4385 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
4387 get_hfi_length(hfinfo
, tvb
, start
, &length
, &item_length
, encoding
);
4388 test_length(hfinfo
, tvb
, start
, item_length
, encoding
);
4392 * We need to get the correct item length here.
4393 * That's normally done by proto_tree_new_item(),
4394 * but we won't be calling it.
4396 *lenretval
= get_full_length(hfinfo
, tvb
, start
, length
,
4397 item_length
, encoding
);
4401 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree
, hfinfo
->id
, hfinfo
, {
4403 * Even if the tree item is not referenced (and thus faked),
4404 * the caller must still be informed of the actual length.
4406 *lenretval
= get_full_length(hfinfo
, tvb
, start
, length
,
4407 item_length
, encoding
);
4410 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, item_length
);
4412 item
= proto_tree_new_item(new_fi
, tree
, tvb
, start
, length
, encoding
);
4413 *lenretval
= new_fi
->length
;
4418 proto_tree_add_item_ret_length(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4419 const int start
, int length
,
4420 const unsigned encoding
, int *lenretval
)
4422 register header_field_info
*hfinfo
;
4424 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4425 return proto_tree_add_item_new_ret_length(tree
, hfinfo
, tvb
, start
, length
, encoding
, lenretval
);
4428 /* which FT_ types can use proto_tree_add_bytes_item() */
4430 validate_proto_tree_add_bytes_ftype(const enum ftenum type
)
4432 return (type
== FT_BYTES
||
4433 type
== FT_UINT_BYTES
||
4435 type
== FT_REL_OID
||
4436 type
== FT_SYSTEM_ID
);
4439 /* Note: this does no validation that the byte array of an FT_OID or
4440 FT_REL_OID is actually valid; and neither does proto_tree_add_item(),
4441 so I think it's ok to continue not validating it?
4444 proto_tree_add_bytes_item(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4445 const int start
, int length
, const unsigned encoding
,
4446 GByteArray
*retval
, int *endoff
, int *err
)
4449 GByteArray
*bytes
= retval
;
4450 GByteArray
*created_bytes
= NULL
;
4451 bool failed
= false;
4453 header_field_info
*hfinfo
;
4454 bool generate
= (bytes
|| tree
) ? true : false;
4456 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4458 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
4460 DISSECTOR_ASSERT_HINT(validate_proto_tree_add_bytes_ftype(hfinfo
->type
),
4461 "Called proto_tree_add_bytes_item but not a bytes-based FT_XXX type");
4463 CHECK_FOR_ZERO_OR_MINUS_LENGTH(length
);
4465 if (encoding
& ENC_STR_NUM
) {
4466 REPORT_DISSECTOR_BUG("Decoding number strings for byte arrays is not supported");
4469 if (generate
&& (encoding
& ENC_STR_HEX
)) {
4470 if (hfinfo
->type
== FT_UINT_BYTES
) {
4471 /* can't decode FT_UINT_BYTES from strings */
4472 REPORT_DISSECTOR_BUG("proto_tree_add_bytes_item called for "
4473 "FT_UINT_BYTES type, but as ENC_STR_HEX");
4476 unsigned hex_encoding
= encoding
;
4477 if (!(encoding
& ENC_SEP_MASK
)) {
4478 /* If none of the separator values are used,
4479 * assume no separator (the common case). */
4480 hex_encoding
|= ENC_SEP_NONE
;
4482 REPORT_DISSECTOR_BUG("proto_tree_add_bytes_item called "
4483 "with ENC_STR_HEX but no ENC_SEP_XXX value");
4488 /* caller doesn't care about return value, but we need it to
4489 call tvb_get_string_bytes() and set the tree later */
4490 bytes
= created_bytes
= g_byte_array_new();
4494 * bytes might be NULL after this, but can't add expert
4495 * error until later; if it's NULL, just note that
4498 bytes
= tvb_get_string_bytes(tvb
, start
, length
, hex_encoding
, bytes
, endoff
);
4502 else if (generate
) {
4503 tvb_ensure_bytes_exist(tvb
, start
, length
);
4505 if (hfinfo
->type
== FT_UINT_BYTES
) {
4506 n
= length
; /* n is now the "header" length */
4507 length
= get_uint_value(tree
, tvb
, start
, n
, encoding
);
4508 /* length is now the value's length; only store the value in the array */
4509 tvb_ensure_bytes_exist(tvb
, start
+ n
, length
);
4511 /* caller doesn't care about return value, but
4512 * we may need it to set the tree later */
4513 bytes
= created_bytes
= g_byte_array_new();
4515 g_byte_array_append(bytes
, tvb_get_ptr(tvb
, start
+ n
, length
), length
);
4517 else if (length
> 0) {
4519 /* caller doesn't care about return value, but
4520 * we may need it to set the tree later */
4521 bytes
= created_bytes
= g_byte_array_new();
4523 g_byte_array_append(bytes
, tvb_get_ptr(tvb
, start
, length
), length
);
4527 *endoff
= start
+ n
+ length
;
4531 *err
= failed
? EINVAL
: 0;
4533 CHECK_FOR_NULL_TREE_AND_FREE(tree
,
4536 g_byte_array_free(created_bytes
, true);
4537 created_bytes
= NULL
;
4541 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree
, hfinfo
->id
, hfinfo
,
4544 g_byte_array_free(created_bytes
, true);
4545 created_bytes
= NULL
;
4549 /* n will be zero except when it's a FT_UINT_BYTES */
4550 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, n
+ length
);
4552 if (encoding
& ENC_STRING
) {
4554 expert_add_info(NULL
, tree
, &ei_byte_array_string_decoding_failed_error
);
4557 proto_tree_set_bytes_gbytearray(new_fi
, bytes
);
4559 proto_tree_set_bytes(new_fi
, NULL
, 0);
4562 g_byte_array_free(created_bytes
, true);
4565 /* n will be zero except when it's a FT_UINT_BYTES */
4566 proto_tree_set_bytes_tvb(new_fi
, tvb
, start
+ n
, length
);
4568 /* XXX: If we have a non-NULL tree but NULL retval, we don't
4569 * use the byte array created above in this case.
4572 g_byte_array_free(created_bytes
, true);
4575 (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
);
4578 return proto_tree_add_node(tree
, new_fi
);
4583 proto_tree_add_time_item(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4584 const int start
, int length
, const unsigned encoding
,
4585 nstime_t
*retval
, int *endoff
, int *err
)
4588 nstime_t time_stamp
;
4590 header_field_info
*hfinfo
;
4592 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4594 DISSECTOR_ASSERT_HINT(hfinfo
!= NULL
, "Not passed hfi!");
4596 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length
,
4600 nstime_set_zero(retval
);
4604 nstime_set_zero(&time_stamp
);
4606 if (encoding
& ENC_STR_TIME_MASK
) {
4607 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_ABSOLUTE_TIME
);
4608 /* The only string format that could be a relative time is
4609 * ENC_ISO_8601_TIME, and that is treated as an absolute time
4610 * relative to "now" currently.
4612 if (!tvb_get_string_time(tvb
, start
, length
, encoding
, &time_stamp
, endoff
))
4616 DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo
);
4617 const bool is_relative
= (hfinfo
->type
== FT_RELATIVE_TIME
) ? true : false;
4619 tvb_ensure_bytes_exist(tvb
, start
, length
);
4620 get_time_value(tree
, tvb
, start
, length
, encoding
, &time_stamp
, is_relative
);
4621 if (endoff
) *endoff
= start
+ length
;
4624 if (err
) *err
= saved_err
;
4627 retval
->secs
= time_stamp
.secs
;
4628 retval
->nsecs
= time_stamp
.nsecs
;
4631 CHECK_FOR_NULL_TREE(tree
);
4633 TRY_TO_FAKE_THIS_ITEM(tree
, hfinfo
->id
, hfinfo
);
4635 new_fi
= new_field_info(tree
, hfinfo
, tvb
, start
, length
);
4637 proto_tree_set_time(new_fi
, &time_stamp
);
4639 if (encoding
& ENC_STRING
) {
4641 expert_add_info(NULL
, tree
, &ei_date_time_string_decoding_failed_error
);
4645 (encoding
& ENC_LITTLE_ENDIAN
) ? FI_LITTLE_ENDIAN
: FI_BIG_ENDIAN
);
4648 return proto_tree_add_node(tree
, new_fi
);
4651 /* Add a FT_NONE to a proto_tree */
4653 proto_tree_add_none_format(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
4654 const int start
, int length
, const char *format
,
4659 header_field_info
*hfinfo
;
4661 CHECK_FOR_NULL_TREE(tree
);
4663 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
4665 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_NONE
);
4667 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
4669 TRY_TO_FAKE_THIS_REPR(pi
);
4671 va_start(ap
, format
);
4672 proto_tree_set_representation(pi
, format
, ap
);
4675 /* no value to set for FT_NONE */
4679 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
4680 * offset, and returns proto_item* */
4682 ptvcursor_add_no_advance(ptvcursor_t
* ptvc
, int hf
, int length
,
4683 const unsigned encoding
)
4687 item
= proto_tree_add_item(ptvc
->tree
, hf
, ptvc
->tvb
, ptvc
->offset
,
4693 /* Advance the ptvcursor's offset within its tvbuff without
4694 * adding anything to the proto_tree. */
4696 ptvcursor_advance(ptvcursor_t
* ptvc
, int length
)
4698 ptvc
->offset
+= length
;
4703 proto_tree_set_protocol_tvb(field_info
*fi
, tvbuff_t
*tvb
, const char* field_data
, int length
)
4705 fvalue_set_protocol(fi
->value
, tvb
, field_data
, length
);
4708 /* Add a FT_PROTOCOL to a proto_tree */
4710 proto_tree_add_protocol_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4711 int start
, int length
, const char *format
, ...)
4714 tvbuff_t
*protocol_tvb
;
4716 header_field_info
*hfinfo
;
4719 CHECK_FOR_NULL_TREE(tree
);
4721 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
4723 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_PROTOCOL
);
4726 * This can throw an exception, so do it before we allocate anything.
4728 protocol_tvb
= (start
== 0 ? tvb
: tvb_new_subset_length(tvb
, start
, length
));
4730 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
4732 va_start(ap
, format
);
4733 protocol_rep
= ws_strdup_vprintf(format
, ap
);
4734 proto_tree_set_protocol_tvb(PNODE_FINFO(pi
), protocol_tvb
, protocol_rep
, length
);
4735 g_free(protocol_rep
);
4738 TRY_TO_FAKE_THIS_REPR(pi
);
4740 va_start(ap
, format
);
4741 proto_tree_set_representation(pi
, format
, ap
);
4747 /* Add a FT_BYTES to a proto_tree */
4749 proto_tree_add_bytes(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
4750 int length
, const uint8_t *start_ptr
)
4753 header_field_info
*hfinfo
;
4756 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4757 get_hfi_length(hfinfo
, tvb
, start
, &length
, &item_length
, ENC_NA
);
4758 test_length(hfinfo
, tvb
, start
, item_length
, ENC_NA
);
4760 CHECK_FOR_NULL_TREE(tree
);
4762 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
4764 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_BYTES
);
4766 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
4767 proto_tree_set_bytes(PNODE_FINFO(pi
), start_ptr
, length
);
4772 /* Add a FT_BYTES to a proto_tree */
4774 proto_tree_add_bytes_with_length(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
4775 int tvbuff_length
, const uint8_t *start_ptr
, int ptr_length
)
4778 header_field_info
*hfinfo
;
4781 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
4782 get_hfi_length(hfinfo
, tvb
, start
, &tvbuff_length
, &item_length
, ENC_NA
);
4783 test_length(hfinfo
, tvb
, start
, item_length
, ENC_NA
);
4785 CHECK_FOR_NULL_TREE(tree
);
4787 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
4789 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_BYTES
);
4791 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &tvbuff_length
);
4792 proto_tree_set_bytes(PNODE_FINFO(pi
), start_ptr
, ptr_length
);
4798 proto_tree_add_bytes_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4799 int start
, int length
,
4800 const uint8_t *start_ptr
,
4801 const char *format
, ...)
4806 if (start_ptr
== NULL
)
4807 start_ptr
= tvb_get_ptr(tvb
, start
, length
);
4809 pi
= proto_tree_add_bytes(tree
, hfindex
, tvb
, start
, length
, start_ptr
);
4811 TRY_TO_FAKE_THIS_REPR_NESTED(pi
);
4813 va_start(ap
, format
);
4814 proto_tree_set_representation_value(pi
, format
, ap
);
4821 proto_tree_add_bytes_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4822 int start
, int length
, const uint8_t *start_ptr
,
4823 const char *format
, ...)
4828 if (start_ptr
== NULL
)
4829 start_ptr
= tvb_get_ptr(tvb
, start
, length
);
4831 pi
= proto_tree_add_bytes(tree
, hfindex
, tvb
, start
, length
, start_ptr
);
4833 TRY_TO_FAKE_THIS_REPR_NESTED(pi
);
4835 va_start(ap
, format
);
4836 proto_tree_set_representation(pi
, format
, ap
);
4843 proto_tree_set_bytes(field_info
*fi
, const uint8_t* start_ptr
, int length
)
4845 DISSECTOR_ASSERT(length
>= 0);
4846 DISSECTOR_ASSERT(start_ptr
!= NULL
|| length
== 0);
4848 fvalue_set_bytes_data(fi
->value
, start_ptr
, length
);
4853 proto_tree_set_bytes_tvb(field_info
*fi
, tvbuff_t
*tvb
, int offset
, int length
)
4855 tvb_ensure_bytes_exist(tvb
, offset
, length
);
4856 proto_tree_set_bytes(fi
, tvb_get_ptr(tvb
, offset
, length
), length
);
4860 proto_tree_set_bytes_gbytearray(field_info
*fi
, const GByteArray
*value
)
4864 DISSECTOR_ASSERT(value
!= NULL
);
4866 bytes
= byte_array_dup(value
);
4868 fvalue_set_byte_array(fi
->value
, bytes
);
4871 /* Add a FT_*TIME to a proto_tree */
4873 proto_tree_add_time(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
4874 int length
, const nstime_t
*value_ptr
)
4877 header_field_info
*hfinfo
;
4879 CHECK_FOR_NULL_TREE(tree
);
4881 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
4883 DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo
);
4885 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
4886 proto_tree_set_time(PNODE_FINFO(pi
), value_ptr
);
4892 proto_tree_add_time_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4893 int start
, int length
, nstime_t
*value_ptr
,
4894 const char *format
, ...)
4899 pi
= proto_tree_add_time(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
4901 va_start(ap
, format
);
4902 proto_tree_set_representation_value(pi
, format
, ap
);
4910 proto_tree_add_time_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4911 int start
, int length
, nstime_t
*value_ptr
,
4912 const char *format
, ...)
4917 pi
= proto_tree_add_time(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
4919 TRY_TO_FAKE_THIS_REPR(pi
);
4921 va_start(ap
, format
);
4922 proto_tree_set_representation(pi
, format
, ap
);
4929 /* Set the FT_*TIME value */
4931 proto_tree_set_time(field_info
*fi
, const nstime_t
*value_ptr
)
4933 DISSECTOR_ASSERT(value_ptr
!= NULL
);
4935 fvalue_set_time(fi
->value
, value_ptr
);
4938 /* Add a FT_IPXNET to a proto_tree */
4940 proto_tree_add_ipxnet(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
4941 int length
, uint32_t value
)
4944 header_field_info
*hfinfo
;
4946 CHECK_FOR_NULL_TREE(tree
);
4948 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
4950 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_IPXNET
);
4952 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
4953 proto_tree_set_ipxnet(PNODE_FINFO(pi
), value
);
4959 proto_tree_add_ipxnet_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4960 int start
, int length
, uint32_t value
,
4961 const char *format
, ...)
4966 pi
= proto_tree_add_ipxnet(tree
, hfindex
, tvb
, start
, length
, value
);
4968 va_start(ap
, format
);
4969 proto_tree_set_representation_value(pi
, format
, ap
);
4977 proto_tree_add_ipxnet_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
4978 int start
, int length
, uint32_t value
,
4979 const char *format
, ...)
4984 pi
= proto_tree_add_ipxnet(tree
, hfindex
, tvb
, start
, length
, value
);
4986 TRY_TO_FAKE_THIS_REPR(pi
);
4988 va_start(ap
, format
);
4989 proto_tree_set_representation(pi
, format
, ap
);
4996 /* Set the FT_IPXNET value */
4998 proto_tree_set_ipxnet(field_info
*fi
, uint32_t value
)
5000 fvalue_set_uinteger(fi
->value
, value
);
5003 /* Add a FT_IPv4 to a proto_tree */
5005 proto_tree_add_ipv4(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5006 int length
, ws_in4_addr value
)
5009 header_field_info
*hfinfo
;
5011 CHECK_FOR_NULL_TREE(tree
);
5013 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5015 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_IPv4
);
5017 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5018 proto_tree_set_ipv4(PNODE_FINFO(pi
), value
);
5024 proto_tree_add_ipv4_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5025 int start
, int length
, ws_in4_addr value
,
5026 const char *format
, ...)
5031 pi
= proto_tree_add_ipv4(tree
, hfindex
, tvb
, start
, length
, value
);
5033 va_start(ap
, format
);
5034 proto_tree_set_representation_value(pi
, format
, ap
);
5042 proto_tree_add_ipv4_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5043 int start
, int length
, ws_in4_addr value
,
5044 const char *format
, ...)
5049 pi
= proto_tree_add_ipv4(tree
, hfindex
, tvb
, start
, length
, value
);
5051 TRY_TO_FAKE_THIS_REPR(pi
);
5053 va_start(ap
, format
);
5054 proto_tree_set_representation(pi
, format
, ap
);
5061 /* Set the FT_IPv4 value */
5063 proto_tree_set_ipv4(field_info
*fi
, ws_in4_addr value
)
5065 ipv4_addr_and_mask ipv4
;
5066 ws_ipv4_addr_and_mask_init(&ipv4
, value
, 32);
5067 fvalue_set_ipv4(fi
->value
, &ipv4
);
5070 /* Add a FT_IPv6 to a proto_tree */
5072 proto_tree_add_ipv6(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5073 int length
, const ws_in6_addr
*value
)
5076 header_field_info
*hfinfo
;
5078 CHECK_FOR_NULL_TREE(tree
);
5080 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5082 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_IPv6
);
5084 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5085 proto_tree_set_ipv6(PNODE_FINFO(pi
), value
);
5091 proto_tree_add_ipv6_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5092 int start
, int length
,
5093 const ws_in6_addr
*value_ptr
,
5094 const char *format
, ...)
5099 pi
= proto_tree_add_ipv6(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
5101 va_start(ap
, format
);
5102 proto_tree_set_representation_value(pi
, format
, ap
);
5110 proto_tree_add_ipv6_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5111 int start
, int length
,
5112 const ws_in6_addr
*value_ptr
,
5113 const char *format
, ...)
5118 pi
= proto_tree_add_ipv6(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
5120 TRY_TO_FAKE_THIS_REPR(pi
);
5122 va_start(ap
, format
);
5123 proto_tree_set_representation(pi
, format
, ap
);
5130 /* Set the FT_IPv6 value */
5132 proto_tree_set_ipv6(field_info
*fi
, const ws_in6_addr
*value
)
5134 DISSECTOR_ASSERT(value
!= NULL
);
5135 ipv6_addr_and_prefix ipv6
;
5138 fvalue_set_ipv6(fi
->value
, &ipv6
);
5142 proto_tree_set_ipv6_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, int length
)
5144 proto_tree_set_ipv6(fi
, (const ws_in6_addr
*)tvb_get_ptr(tvb
, start
, length
));
5147 /* Set the FT_FCWWN value */
5149 proto_tree_set_fcwwn(field_info
*fi
, const uint8_t* value_ptr
)
5151 DISSECTOR_ASSERT(value_ptr
!= NULL
);
5152 fvalue_set_fcwwn(fi
->value
, value_ptr
);
5156 proto_tree_set_fcwwn_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, int length
)
5158 proto_tree_set_fcwwn(fi
, tvb_get_ptr(tvb
, start
, length
));
5161 /* Add a FT_GUID to a proto_tree */
5163 proto_tree_add_guid(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5164 int length
, const e_guid_t
*value_ptr
)
5167 header_field_info
*hfinfo
;
5169 CHECK_FOR_NULL_TREE(tree
);
5171 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5173 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_GUID
);
5175 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5176 proto_tree_set_guid(PNODE_FINFO(pi
), value_ptr
);
5182 proto_tree_add_guid_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5183 int start
, int length
,
5184 const e_guid_t
*value_ptr
,
5185 const char *format
, ...)
5190 pi
= proto_tree_add_guid(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
5192 va_start(ap
, format
);
5193 proto_tree_set_representation_value(pi
, format
, ap
);
5201 proto_tree_add_guid_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5202 int start
, int length
, const e_guid_t
*value_ptr
,
5203 const char *format
, ...)
5208 pi
= proto_tree_add_guid(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
5210 TRY_TO_FAKE_THIS_REPR(pi
);
5212 va_start(ap
, format
);
5213 proto_tree_set_representation(pi
, format
, ap
);
5220 /* Set the FT_GUID value */
5222 proto_tree_set_guid(field_info
*fi
, const e_guid_t
*value_ptr
)
5224 DISSECTOR_ASSERT(value_ptr
!= NULL
);
5225 fvalue_set_guid(fi
->value
, value_ptr
);
5229 proto_tree_set_guid_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
,
5230 const unsigned encoding
)
5234 tvb_get_guid(tvb
, start
, &guid
, encoding
);
5235 proto_tree_set_guid(fi
, &guid
);
5238 /* Add a FT_OID to a proto_tree */
5240 proto_tree_add_oid(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5241 int length
, const uint8_t* value_ptr
)
5244 header_field_info
*hfinfo
;
5246 CHECK_FOR_NULL_TREE(tree
);
5248 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5250 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_OID
);
5252 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5253 proto_tree_set_oid(PNODE_FINFO(pi
), value_ptr
, length
);
5259 proto_tree_add_oid_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5260 int start
, int length
,
5261 const uint8_t* value_ptr
,
5262 const char *format
, ...)
5267 pi
= proto_tree_add_oid(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
5269 va_start(ap
, format
);
5270 proto_tree_set_representation_value(pi
, format
, ap
);
5278 proto_tree_add_oid_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5279 int start
, int length
, const uint8_t* value_ptr
,
5280 const char *format
, ...)
5285 pi
= proto_tree_add_oid(tree
, hfindex
, tvb
, start
, length
, value_ptr
);
5287 TRY_TO_FAKE_THIS_REPR(pi
);
5289 va_start(ap
, format
);
5290 proto_tree_set_representation(pi
, format
, ap
);
5297 /* Set the FT_OID value */
5299 proto_tree_set_oid(field_info
*fi
, const uint8_t* value_ptr
, int length
)
5303 DISSECTOR_ASSERT(value_ptr
!= NULL
|| length
== 0);
5305 bytes
= g_byte_array_new();
5307 g_byte_array_append(bytes
, value_ptr
, length
);
5309 fvalue_set_byte_array(fi
->value
, bytes
);
5313 proto_tree_set_oid_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, int length
)
5315 proto_tree_set_oid(fi
, tvb_get_ptr(tvb
, start
, length
), length
);
5318 /* Set the FT_SYSTEM_ID value */
5320 proto_tree_set_system_id(field_info
*fi
, const uint8_t* value_ptr
, int length
)
5324 DISSECTOR_ASSERT(value_ptr
!= NULL
|| length
== 0);
5326 bytes
= g_byte_array_new();
5328 g_byte_array_append(bytes
, value_ptr
, length
);
5330 fvalue_set_byte_array(fi
->value
, bytes
);
5334 proto_tree_set_system_id_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, int length
)
5336 proto_tree_set_system_id(fi
, tvb_get_ptr(tvb
, start
, length
), length
);
5339 /* Add a FT_STRING, FT_STRINGZ, FT_STRINGZPAD, or FT_STRINGZTRUNC to a
5340 * proto_tree. Creates own copy of string, and frees it when the proto_tree
5343 proto_tree_add_string(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5344 int length
, const char* value
)
5347 header_field_info
*hfinfo
;
5350 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
5351 get_hfi_length(hfinfo
, tvb
, start
, &length
, &item_length
, ENC_NA
);
5353 * Special case - if the length is 0, skip the test, so that
5354 * we can have an empty string right after the end of the
5355 * packet. (This handles URL-encoded forms where the last field
5356 * has no value so the form ends right after the =.)
5358 if (item_length
!= 0)
5359 test_length(hfinfo
, tvb
, start
, item_length
, ENC_NA
);
5361 CHECK_FOR_NULL_TREE(tree
);
5363 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5365 DISSECTOR_ASSERT_FIELD_TYPE_IS_STRING(hfinfo
);
5367 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5368 DISSECTOR_ASSERT(length
>= 0);
5370 WS_UTF_8_CHECK(value
, -1);
5371 proto_tree_set_string(PNODE_FINFO(pi
), value
);
5377 proto_tree_add_string_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5378 int start
, int length
, const char* value
,
5385 pi
= proto_tree_add_string(tree
, hfindex
, tvb
, start
, length
, value
);
5387 va_start(ap
, format
);
5388 proto_tree_set_representation_value(pi
, format
, ap
);
5396 proto_tree_add_string_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5397 int start
, int length
, const char* value
,
5398 const char *format
, ...)
5403 pi
= proto_tree_add_string(tree
, hfindex
, tvb
, start
, length
, value
);
5405 TRY_TO_FAKE_THIS_REPR(pi
);
5407 va_start(ap
, format
);
5408 proto_tree_set_representation(pi
, format
, ap
);
5415 /* Set the FT_STRING value */
5417 proto_tree_set_string(field_info
*fi
, const char* value
)
5420 fvalue_set_string(fi
->value
, value
);
5423 * XXX - why is a null value for a string field
5426 fvalue_set_string(fi
->value
, "[ Null ]");
5430 /* Set the FT_AX25 value */
5432 proto_tree_set_ax25(field_info
*fi
, const uint8_t* value
)
5434 fvalue_set_ax25(fi
->value
, value
);
5438 proto_tree_set_ax25_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
)
5440 proto_tree_set_ax25(fi
, tvb_get_ptr(tvb
, start
, 7));
5443 /* Set the FT_VINES value */
5445 proto_tree_set_vines(field_info
*fi
, const uint8_t* value
)
5447 fvalue_set_vines(fi
->value
, value
);
5451 proto_tree_set_vines_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
)
5453 proto_tree_set_vines(fi
, tvb_get_ptr(tvb
, start
, FT_VINES_ADDR_LEN
));
5456 /* Add a FT_ETHER to a proto_tree */
5458 proto_tree_add_ether(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5459 int length
, const uint8_t* value
)
5462 header_field_info
*hfinfo
;
5464 CHECK_FOR_NULL_TREE(tree
);
5466 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5468 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_ETHER
);
5470 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5471 proto_tree_set_ether(PNODE_FINFO(pi
), value
);
5477 proto_tree_add_ether_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5478 int start
, int length
, const uint8_t* value
,
5479 const char *format
, ...)
5484 pi
= proto_tree_add_ether(tree
, hfindex
, tvb
, start
, length
, value
);
5486 va_start(ap
, format
);
5487 proto_tree_set_representation_value(pi
, format
, ap
);
5495 proto_tree_add_ether_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5496 int start
, int length
, const uint8_t* value
,
5497 const char *format
, ...)
5502 pi
= proto_tree_add_ether(tree
, hfindex
, tvb
, start
, length
, value
);
5504 TRY_TO_FAKE_THIS_REPR(pi
);
5506 va_start(ap
, format
);
5507 proto_tree_set_representation(pi
, format
, ap
);
5514 /* Set the FT_ETHER value */
5516 proto_tree_set_ether(field_info
*fi
, const uint8_t* value
)
5518 fvalue_set_ether(fi
->value
, value
);
5522 proto_tree_set_ether_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
)
5524 proto_tree_set_ether(fi
, tvb_get_ptr(tvb
, start
, FT_ETHER_LEN
));
5527 /* Add a FT_BOOLEAN to a proto_tree */
5529 proto_tree_add_boolean(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5530 int length
, uint64_t value
)
5533 header_field_info
*hfinfo
;
5535 CHECK_FOR_NULL_TREE(tree
);
5537 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5539 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_BOOLEAN
);
5541 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5542 proto_tree_set_boolean(PNODE_FINFO(pi
), value
);
5548 proto_tree_add_boolean_format_value(proto_tree
*tree
, int hfindex
,
5549 tvbuff_t
*tvb
, int start
, int length
,
5550 uint64_t value
, const char *format
, ...)
5555 pi
= proto_tree_add_boolean(tree
, hfindex
, tvb
, start
, length
, value
);
5557 va_start(ap
, format
);
5558 proto_tree_set_representation_value(pi
, format
, ap
);
5566 proto_tree_add_boolean_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5567 int start
, int length
, uint64_t value
,
5568 const char *format
, ...)
5573 pi
= proto_tree_add_boolean(tree
, hfindex
, tvb
, start
, length
, value
);
5575 TRY_TO_FAKE_THIS_REPR(pi
);
5577 va_start(ap
, format
);
5578 proto_tree_set_representation(pi
, format
, ap
);
5585 /* Set the FT_BOOLEAN value */
5587 proto_tree_set_boolean(field_info
*fi
, uint64_t value
)
5589 proto_tree_set_uint64(fi
, value
);
5592 /* Generate, into "buf", a string showing the bits of a bitfield.
5593 Return a pointer to the character after that string. */
5595 other_decode_bitfield_value(char *buf
, const uint64_t val
, const uint64_t mask
, const int width
)
5603 /* This is a devel error. It is safer to stop here. */
5604 DISSECTOR_ASSERT(width
>= 1);
5606 bit
= UINT64_C(1) << (width
- 1);
5609 /* This bit is part of the field. Show its value. */
5615 /* This bit is not part of the field. */
5630 decode_bitfield_value(char *buf
, const uint64_t val
, const uint64_t mask
, const int width
)
5634 p
= other_decode_bitfield_value(buf
, val
, mask
, width
);
5635 p
= g_stpcpy(p
, " = ");
5641 other_decode_bitfield_varint_value(char *buf
, uint64_t val
, uint64_t mask
, const int width
)
5649 /* This is a devel error. It is safer to stop here. */
5650 DISSECTOR_ASSERT(width
>= 1);
5652 bit
= UINT64_C(1) << (width
- 1);
5654 if (((8-(i
% 8)) != 8) && /* MSB is never used for value. */
5656 /* This bit is part of the field. Show its value. */
5662 /* This bit is not part of the field. */
5678 decode_bitfield_varint_value(char *buf
, const uint64_t val
, const uint64_t mask
, const int width
)
5682 p
= other_decode_bitfield_varint_value(buf
, val
, mask
, width
);
5683 p
= g_stpcpy(p
, " = ");
5688 /* Add a FT_FLOAT to a proto_tree */
5690 proto_tree_add_float(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5691 int length
, float value
)
5694 header_field_info
*hfinfo
;
5696 CHECK_FOR_NULL_TREE(tree
);
5698 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5700 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_FLOAT
);
5702 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5703 proto_tree_set_float(PNODE_FINFO(pi
), value
);
5709 proto_tree_add_float_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5710 int start
, int length
, float value
,
5711 const char *format
, ...)
5716 pi
= proto_tree_add_float(tree
, hfindex
, tvb
, start
, length
, value
);
5718 va_start(ap
, format
);
5719 proto_tree_set_representation_value(pi
, format
, ap
);
5727 proto_tree_add_float_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5728 int start
, int length
, float value
,
5729 const char *format
, ...)
5734 pi
= proto_tree_add_float(tree
, hfindex
, tvb
, start
, length
, value
);
5736 TRY_TO_FAKE_THIS_REPR(pi
);
5738 va_start(ap
, format
);
5739 proto_tree_set_representation(pi
, format
, ap
);
5746 /* Set the FT_FLOAT value */
5748 proto_tree_set_float(field_info
*fi
, float value
)
5750 fvalue_set_floating(fi
->value
, value
);
5753 /* Add a FT_DOUBLE to a proto_tree */
5755 proto_tree_add_double(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5756 int length
, double value
)
5759 header_field_info
*hfinfo
;
5761 CHECK_FOR_NULL_TREE(tree
);
5763 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5765 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_DOUBLE
);
5767 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5768 proto_tree_set_double(PNODE_FINFO(pi
), value
);
5774 proto_tree_add_double_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5775 int start
, int length
, double value
,
5776 const char *format
, ...)
5781 pi
= proto_tree_add_double(tree
, hfindex
, tvb
, start
, length
, value
);
5783 va_start(ap
, format
);
5784 proto_tree_set_representation_value(pi
, format
, ap
);
5792 proto_tree_add_double_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5793 int start
, int length
, double value
,
5794 const char *format
, ...)
5799 pi
= proto_tree_add_double(tree
, hfindex
, tvb
, start
, length
, value
);
5801 TRY_TO_FAKE_THIS_REPR(pi
);
5803 va_start(ap
, format
);
5804 proto_tree_set_representation(pi
, format
, ap
);
5811 /* Set the FT_DOUBLE value */
5813 proto_tree_set_double(field_info
*fi
, double value
)
5815 fvalue_set_floating(fi
->value
, value
);
5818 /* Add FT_CHAR or FT_UINT{8,16,24,32} to a proto_tree */
5820 proto_tree_add_uint(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5821 int length
, uint32_t value
)
5823 proto_item
*pi
= NULL
;
5824 header_field_info
*hfinfo
;
5826 CHECK_FOR_NULL_TREE(tree
);
5828 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5830 switch (hfinfo
->type
) {
5837 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5838 proto_tree_set_uint(PNODE_FINFO(pi
), value
);
5842 REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, FT_UINT32, or FT_FRAMENUM",
5850 proto_tree_add_uint_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5851 int start
, int length
, uint32_t value
,
5852 const char *format
, ...)
5857 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, start
, length
, value
);
5859 va_start(ap
, format
);
5860 proto_tree_set_representation_value(pi
, format
, ap
);
5868 proto_tree_add_uint_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5869 int start
, int length
, uint32_t value
,
5870 const char *format
, ...)
5875 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, start
, length
, value
);
5877 TRY_TO_FAKE_THIS_REPR(pi
);
5879 va_start(ap
, format
);
5880 proto_tree_set_representation(pi
, format
, ap
);
5887 /* Set the FT_UINT{8,16,24,32} value */
5889 proto_tree_set_uint(field_info
*fi
, uint32_t value
)
5891 const header_field_info
*hfinfo
;
5894 hfinfo
= fi
->hfinfo
;
5897 if (hfinfo
->bitmask
) {
5898 /* Mask out irrelevant portions */
5899 integer
&= (uint32_t)(hfinfo
->bitmask
);
5902 integer
>>= hfinfo_bitshift(hfinfo
);
5904 FI_SET_FLAG(fi
, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo
)));
5905 FI_SET_FLAG(fi
, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo
)));
5908 fvalue_set_uinteger(fi
->value
, integer
);
5911 /* Add FT_UINT{40,48,56,64} to a proto_tree */
5913 proto_tree_add_uint64(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
5914 int length
, uint64_t value
)
5916 proto_item
*pi
= NULL
;
5917 header_field_info
*hfinfo
;
5919 CHECK_FOR_NULL_TREE(tree
);
5921 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
5923 switch (hfinfo
->type
) {
5929 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
5930 proto_tree_set_uint64(PNODE_FINFO(pi
), value
);
5934 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, FT_UINT64, or FT_FRAMENUM",
5942 proto_tree_add_uint64_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5943 int start
, int length
, uint64_t value
,
5944 const char *format
, ...)
5949 pi
= proto_tree_add_uint64(tree
, hfindex
, tvb
, start
, length
, value
);
5951 va_start(ap
, format
);
5952 proto_tree_set_representation_value(pi
, format
, ap
);
5960 proto_tree_add_uint64_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
5961 int start
, int length
, uint64_t value
,
5962 const char *format
, ...)
5967 pi
= proto_tree_add_uint64(tree
, hfindex
, tvb
, start
, length
, value
);
5969 TRY_TO_FAKE_THIS_REPR(pi
);
5971 va_start(ap
, format
);
5972 proto_tree_set_representation(pi
, format
, ap
);
5979 /* Set the FT_UINT{40,48,56,64} value */
5981 proto_tree_set_uint64(field_info
*fi
, uint64_t value
)
5983 const header_field_info
*hfinfo
;
5986 hfinfo
= fi
->hfinfo
;
5989 if (hfinfo
->bitmask
) {
5990 /* Mask out irrelevant portions */
5991 integer
&= hfinfo
->bitmask
;
5994 integer
>>= hfinfo_bitshift(hfinfo
);
5996 FI_SET_FLAG(fi
, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo
)));
5997 FI_SET_FLAG(fi
, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo
)));
6000 fvalue_set_uinteger64(fi
->value
, integer
);
6003 /* Add FT_INT{8,16,24,32} to a proto_tree */
6005 proto_tree_add_int(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
6006 int length
, int32_t value
)
6008 proto_item
*pi
= NULL
;
6009 header_field_info
*hfinfo
;
6011 CHECK_FOR_NULL_TREE(tree
);
6013 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
6015 switch (hfinfo
->type
) {
6020 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
6021 proto_tree_set_int(PNODE_FINFO(pi
), value
);
6025 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
6033 proto_tree_add_int_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
6034 int start
, int length
, int32_t value
,
6035 const char *format
, ...)
6040 pi
= proto_tree_add_int(tree
, hfindex
, tvb
, start
, length
, value
);
6042 va_start(ap
, format
);
6043 proto_tree_set_representation_value(pi
, format
, ap
);
6051 proto_tree_add_int_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
6052 int start
, int length
, int32_t value
,
6053 const char *format
, ...)
6058 pi
= proto_tree_add_int(tree
, hfindex
, tvb
, start
, length
, value
);
6060 TRY_TO_FAKE_THIS_REPR(pi
);
6062 va_start(ap
, format
);
6063 proto_tree_set_representation(pi
, format
, ap
);
6070 /* Set the FT_INT{8,16,24,32} value */
6072 proto_tree_set_int(field_info
*fi
, int32_t value
)
6074 const header_field_info
*hfinfo
;
6078 hfinfo
= fi
->hfinfo
;
6079 integer
= (uint32_t) value
;
6081 if (hfinfo
->bitmask
) {
6082 /* Mask out irrelevant portions */
6083 integer
&= (uint32_t)(hfinfo
->bitmask
);
6086 integer
>>= hfinfo_bitshift(hfinfo
);
6088 no_of_bits
= ws_count_ones(hfinfo
->bitmask
);
6089 integer
= ws_sign_ext32(integer
, no_of_bits
);
6091 FI_SET_FLAG(fi
, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo
)));
6092 FI_SET_FLAG(fi
, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo
)));
6095 fvalue_set_sinteger(fi
->value
, integer
);
6098 /* Add FT_INT{40,48,56,64} to a proto_tree */
6100 proto_tree_add_int64(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
6101 int length
, int64_t value
)
6103 proto_item
*pi
= NULL
;
6104 header_field_info
*hfinfo
;
6106 CHECK_FOR_NULL_TREE(tree
);
6108 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
6110 switch (hfinfo
->type
) {
6115 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
6116 proto_tree_set_int64(PNODE_FINFO(pi
), value
);
6120 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
6128 proto_tree_add_int64_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
6129 int start
, int length
, int64_t value
,
6130 const char *format
, ...)
6135 pi
= proto_tree_add_int64(tree
, hfindex
, tvb
, start
, length
, value
);
6137 va_start(ap
, format
);
6138 proto_tree_set_representation_value(pi
, format
, ap
);
6145 /* Set the FT_INT{40,48,56,64} value */
6147 proto_tree_set_int64(field_info
*fi
, int64_t value
)
6149 const header_field_info
*hfinfo
;
6153 hfinfo
= fi
->hfinfo
;
6156 if (hfinfo
->bitmask
) {
6157 /* Mask out irrelevant portions */
6158 integer
&= hfinfo
->bitmask
;
6161 integer
>>= hfinfo_bitshift(hfinfo
);
6163 no_of_bits
= ws_count_ones(hfinfo
->bitmask
);
6164 integer
= ws_sign_ext64(integer
, no_of_bits
);
6166 FI_SET_FLAG(fi
, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo
)));
6167 FI_SET_FLAG(fi
, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo
)));
6170 fvalue_set_sinteger64(fi
->value
, integer
);
6174 proto_tree_add_int64_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
6175 int start
, int length
, int64_t value
,
6176 const char *format
, ...)
6181 pi
= proto_tree_add_int64(tree
, hfindex
, tvb
, start
, length
, value
);
6183 TRY_TO_FAKE_THIS_REPR(pi
);
6185 va_start(ap
, format
);
6186 proto_tree_set_representation(pi
, format
, ap
);
6193 /* Add a FT_EUI64 to a proto_tree */
6195 proto_tree_add_eui64(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
,
6196 int length
, const uint64_t value
)
6199 header_field_info
*hfinfo
;
6201 CHECK_FOR_NULL_TREE(tree
);
6203 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
6205 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_EUI64
);
6207 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, start
, &length
);
6208 proto_tree_set_eui64(PNODE_FINFO(pi
), value
);
6214 proto_tree_add_eui64_format_value(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
6215 int start
, int length
, const uint64_t value
,
6216 const char *format
, ...)
6221 pi
= proto_tree_add_eui64(tree
, hfindex
, tvb
, start
, length
, value
);
6223 va_start(ap
, format
);
6224 proto_tree_set_representation_value(pi
, format
, ap
);
6232 proto_tree_add_eui64_format(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
,
6233 int start
, int length
, const uint64_t value
,
6234 const char *format
, ...)
6239 pi
= proto_tree_add_eui64(tree
, hfindex
, tvb
, start
, length
, value
);
6241 TRY_TO_FAKE_THIS_REPR(pi
);
6243 va_start(ap
, format
);
6244 proto_tree_set_representation(pi
, format
, ap
);
6251 /* Set the FT_EUI64 value */
6253 proto_tree_set_eui64(field_info
*fi
, const uint64_t value
)
6255 fvalue_set_uinteger64(fi
->value
, value
);
6258 proto_tree_set_eui64_tvb(field_info
*fi
, tvbuff_t
*tvb
, int start
, const unsigned encoding
)
6262 proto_tree_set_eui64(fi
, tvb_get_letoh64(tvb
, start
));
6264 proto_tree_set_eui64(fi
, tvb_get_ntoh64(tvb
, start
));
6269 proto_tree_add_mac48_detail(const mac_hf_list_t
*list_specific
,
6270 const mac_hf_list_t
*list_generic
,
6271 int idx
, tvbuff_t
*tvb
,
6272 proto_tree
*tree
, int offset
)
6274 const uint8_t addr
[6];
6275 const char *addr_name
= NULL
;
6276 const char *oui_name
= NULL
;
6277 proto_item
*addr_item
= NULL
;
6278 proto_tree
*addr_tree
= NULL
;
6279 proto_item
*ret_val
= NULL
;
6281 if (tree
== NULL
|| list_specific
== NULL
) {
6285 /* Resolve what we can of the address */
6286 tvb_memcpy(tvb
, (void *)addr
, offset
, 6);
6287 if (list_specific
->hf_addr_resolved
|| (list_generic
&& list_generic
->hf_addr_resolved
)) {
6288 addr_name
= get_ether_name(addr
);
6290 if (list_specific
->hf_oui_resolved
|| (list_generic
&& list_generic
->hf_oui_resolved
)) {
6291 oui_name
= get_manuf_name_if_known(addr
, sizeof(addr
));
6294 /* Add the item for the specific address type */
6295 ret_val
= proto_tree_add_item(tree
, *list_specific
->hf_addr
, tvb
, offset
, 6, ENC_NA
);
6297 addr_tree
= proto_item_add_subtree(ret_val
, idx
);
6303 if (list_specific
->hf_addr_resolved
!= NULL
) {
6304 addr_item
= proto_tree_add_string(addr_tree
, *list_specific
->hf_addr_resolved
,
6305 tvb
, offset
, 6, addr_name
);
6306 proto_item_set_generated(addr_item
);
6307 proto_item_set_hidden(addr_item
);
6310 if (list_specific
->hf_oui
!= NULL
) {
6311 addr_item
= proto_tree_add_item(addr_tree
, *list_specific
->hf_oui
, tvb
, offset
, 3, ENC_NA
);
6312 proto_item_set_generated(addr_item
);
6313 proto_item_set_hidden(addr_item
);
6315 if (oui_name
!= NULL
&& list_specific
->hf_oui_resolved
!= NULL
) {
6316 addr_item
= proto_tree_add_string(addr_tree
, *list_specific
->hf_oui_resolved
, tvb
, offset
, 6, oui_name
);
6317 proto_item_set_generated(addr_item
);
6318 proto_item_set_hidden(addr_item
);
6322 if (list_specific
->hf_lg
!= NULL
) {
6323 proto_tree_add_item(addr_tree
, *list_specific
->hf_lg
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
6325 if (list_specific
->hf_ig
!= NULL
) {
6326 proto_tree_add_item(addr_tree
, *list_specific
->hf_ig
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
6329 /* Were we given a list for generic address fields? If not, stop here */
6330 if (list_generic
== NULL
) {
6334 addr_item
= proto_tree_add_item(addr_tree
, *list_generic
->hf_addr
, tvb
, offset
, 6, ENC_NA
);
6335 proto_item_set_hidden(addr_item
);
6337 if (list_generic
->hf_addr_resolved
!= NULL
) {
6338 addr_item
= proto_tree_add_string(addr_tree
, *list_generic
->hf_addr_resolved
,
6339 tvb
, offset
, 6, addr_name
);
6340 proto_item_set_generated(addr_item
);
6341 proto_item_set_hidden(addr_item
);
6344 if (list_generic
->hf_oui
!= NULL
) {
6345 addr_item
= proto_tree_add_item(addr_tree
, *list_generic
->hf_oui
, tvb
, offset
, 3, ENC_NA
);
6346 proto_item_set_generated(addr_item
);
6347 proto_item_set_hidden(addr_item
);
6349 if (oui_name
!= NULL
&& list_generic
->hf_oui_resolved
!= NULL
) {
6350 addr_item
= proto_tree_add_string(addr_tree
, *list_generic
->hf_oui_resolved
, tvb
, offset
, 6, oui_name
);
6351 proto_item_set_generated(addr_item
);
6352 proto_item_set_hidden(addr_item
);
6356 if (list_generic
->hf_lg
!= NULL
) {
6357 addr_item
= proto_tree_add_item(addr_tree
, *list_generic
->hf_lg
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
6358 proto_item_set_hidden(addr_item
);
6360 if (list_generic
->hf_ig
!= NULL
) {
6361 addr_item
= proto_tree_add_item(addr_tree
, *list_generic
->hf_ig
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
6362 proto_item_set_hidden(addr_item
);
6368 proto_tree_add_fake_node(proto_tree
*tree
, const header_field_info
*hfinfo
)
6370 proto_node
*pnode
, *tnode
, *sibling
;
6377 * Restrict our depth. proto_tree_traverse_pre_order and
6378 * proto_tree_traverse_post_order (and possibly others) are recursive
6379 * so we need to be mindful of our stack size.
6381 if (tree
->first_child
== NULL
) {
6382 for (tnode
= tree
; tnode
!= NULL
; tnode
= tnode
->parent
) {
6384 if (G_UNLIKELY(depth
> prefs
.gui_max_tree_depth
)) {
6385 THROW_MESSAGE(DissectorError
, wmem_strdup_printf(PNODE_POOL(tree
),
6386 "Maximum tree depth %d exceeded for \"%s\" - \"%s\" (%s:%u) (Maximum depth can be increased in advanced preferences)",
6387 prefs
.gui_max_tree_depth
,
6388 hfinfo
->name
, hfinfo
->abbrev
, G_STRFUNC
, __LINE__
));
6394 * Make sure "tree" is ready to have subtrees under it, by
6395 * checking whether it's been given an ett_ value.
6397 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
6398 * node of the protocol tree. That node is not displayed,
6399 * so it doesn't need an ett_ value to remember whether it
6403 tfi
= PNODE_FINFO(tnode
);
6404 if (tfi
!= NULL
&& (tfi
->tree_type
< 0 || tfi
->tree_type
>= num_tree_types
)) {
6405 REPORT_DISSECTOR_BUG("\"%s\" - \"%s\" tfi->tree_type: %d invalid (%s:%u)",
6406 hfinfo
->name
, hfinfo
->abbrev
, tfi
->tree_type
, __FILE__
, __LINE__
);
6407 /* XXX - is it safe to continue here? */
6410 pnode
= wmem_new(PNODE_POOL(tree
), proto_node
);
6411 PROTO_NODE_INIT(pnode
);
6412 pnode
->parent
= tnode
;
6413 PNODE_HFINFO(pnode
) = hfinfo
;
6414 PNODE_FINFO(pnode
) = NULL
; // Faked
6415 pnode
->tree_data
= PTREE_DATA(tree
);
6417 if (tnode
->last_child
!= NULL
) {
6418 sibling
= tnode
->last_child
;
6419 DISSECTOR_ASSERT(sibling
->next
== NULL
);
6420 sibling
->next
= pnode
;
6422 tnode
->first_child
= pnode
;
6423 tnode
->last_child
= pnode
;
6425 /* We should not be adding a fake node for an interesting field */
6426 ws_assert(hfinfo
->ref_type
!= HF_REF_TYPE_DIRECT
&& hfinfo
->ref_type
!= HF_REF_TYPE_PRINT
);
6428 /* XXX - Should the proto_item have a header_field_info member, at least
6429 * for faked items, to know what hfi was faked? (Some dissectors look at
6430 * the tree items directly.)
6432 return (proto_item
*)pnode
;
6435 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
6437 proto_tree_add_node(proto_tree
*tree
, field_info
*fi
)
6439 proto_node
*pnode
, *tnode
, *sibling
;
6446 * Restrict our depth. proto_tree_traverse_pre_order and
6447 * proto_tree_traverse_post_order (and possibly others) are recursive
6448 * so we need to be mindful of our stack size.
6450 if (tree
->first_child
== NULL
) {
6451 for (tnode
= tree
; tnode
!= NULL
; tnode
= tnode
->parent
) {
6453 if (G_UNLIKELY(depth
> prefs
.gui_max_tree_depth
)) {
6454 fvalue_free(fi
->value
);
6456 THROW_MESSAGE(DissectorError
, wmem_strdup_printf(PNODE_POOL(tree
),
6457 "Maximum tree depth %d exceeded for \"%s\" - \"%s\" (%s:%u) (Maximum depth can be increased in advanced preferences)",
6458 prefs
.gui_max_tree_depth
,
6459 fi
->hfinfo
->name
, fi
->hfinfo
->abbrev
, G_STRFUNC
, __LINE__
));
6465 * Make sure "tree" is ready to have subtrees under it, by
6466 * checking whether it's been given an ett_ value.
6468 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
6469 * node of the protocol tree. That node is not displayed,
6470 * so it doesn't need an ett_ value to remember whether it
6474 tfi
= PNODE_FINFO(tnode
);
6475 if (tfi
!= NULL
&& (tfi
->tree_type
< 0 || tfi
->tree_type
>= num_tree_types
)) {
6476 /* Since we are not adding fi to a node, its fvalue won't get
6477 * freed by proto_tree_free_node(), so free it now.
6479 fvalue_free(fi
->value
);
6481 REPORT_DISSECTOR_BUG("\"%s\" - \"%s\" tfi->tree_type: %d invalid (%s:%u)",
6482 fi
->hfinfo
->name
, fi
->hfinfo
->abbrev
, tfi
->tree_type
, __FILE__
, __LINE__
);
6483 /* XXX - is it safe to continue here? */
6486 pnode
= wmem_new(PNODE_POOL(tree
), proto_node
);
6487 PROTO_NODE_INIT(pnode
);
6488 pnode
->parent
= tnode
;
6489 PNODE_HFINFO(pnode
) = fi
->hfinfo
;
6490 PNODE_FINFO(pnode
) = fi
;
6491 pnode
->tree_data
= PTREE_DATA(tree
);
6493 if (tnode
->last_child
!= NULL
) {
6494 sibling
= tnode
->last_child
;
6495 DISSECTOR_ASSERT(sibling
->next
== NULL
);
6496 sibling
->next
= pnode
;
6498 tnode
->first_child
= pnode
;
6499 tnode
->last_child
= pnode
;
6501 tree_data_add_maybe_interesting_field(pnode
->tree_data
, fi
);
6503 return (proto_item
*)pnode
;
6507 /* Generic way to allocate field_info and add to proto_tree.
6508 * Sets *pfi to address of newly-allocated field_info struct */
6510 proto_tree_add_pi(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
, int start
,
6517 get_hfi_length(hfinfo
, tvb
, start
, length
, &item_length
, ENC_NA
);
6518 fi
= new_field_info(tree
, hfinfo
, tvb
, start
, item_length
);
6519 pi
= proto_tree_add_node(tree
, fi
);
6526 get_hfi_length(header_field_info
*hfinfo
, tvbuff_t
*tvb
, const int start
, int *length
,
6527 int *item_length
, const unsigned encoding
)
6529 int length_remaining
;
6532 * We only allow a null tvbuff if the item has a zero length,
6533 * i.e. if there's no data backing it.
6535 DISSECTOR_ASSERT(tvb
!= NULL
|| *length
== 0);
6538 * XXX - in some protocols, there are 32-bit unsigned length
6539 * fields, so lengths in protocol tree and tvbuff routines
6540 * should really be unsigned. We should have, for those
6541 * field types for which "to the end of the tvbuff" makes sense,
6542 * additional routines that take no length argument and
6543 * add fields that run to the end of the tvbuff.
6545 if (*length
== -1) {
6547 * For FT_NONE, FT_PROTOCOL, FT_BYTES, FT_STRING,
6548 * FT_STRINGZPAD, and FT_STRINGZTRUNC fields, a length
6549 * of -1 means "set the length to what remains in the
6552 * The assumption is either that
6554 * 1) the length of the item can only be determined
6555 * by dissection (typically true of items with
6556 * subitems, which are probably FT_NONE or
6561 * 2) if the tvbuff is "short" (either due to a short
6562 * snapshot length or due to lack of reassembly of
6563 * fragments/segments/whatever), we want to display
6564 * what's available in the field (probably FT_BYTES
6565 * or FT_STRING) and then throw an exception later
6569 * 3) the field is defined to be "what's left in the
6572 * so we set the length to what remains in the tvbuff so
6573 * that, if we throw an exception while dissecting, it
6574 * has what is probably the right value.
6576 * For FT_STRINGZ, it means "the string is null-terminated,
6577 * not null-padded; set the length to the actual length
6578 * of the string", and if the tvbuff if short, we just
6579 * throw an exception.
6581 * For ENC_VARINT_PROTOBUF|ENC_VARINT_QUIC|ENC_VARIANT_ZIGZAG|ENC_VARINT_SDNV, it means "find the end of the string",
6582 * and if the tvbuff if short, we just throw an exception.
6584 * It's not valid for any other type of field. For those
6585 * fields, we treat -1 the same way we treat other
6586 * negative values - we assume the length is a Really
6587 * Big Positive Number, and throw a ReportedBoundsError
6588 * exception, under the assumption that the Really Big
6589 * Length would run past the end of the packet.
6591 if ((FT_IS_INT(hfinfo
->type
)) || (FT_IS_UINT(hfinfo
->type
))) {
6592 if (encoding
& (ENC_VARINT_PROTOBUF
|ENC_VARINT_ZIGZAG
|ENC_VARINT_SDNV
)) {
6594 * Leave the length as -1, so our caller knows
6597 *item_length
= *length
;
6599 } else if (encoding
& ENC_VARINT_QUIC
) {
6600 switch (tvb_get_uint8(tvb
, start
) >> 6)
6602 case 0: /* 0b00 => 1 byte length (6 bits Usable) */
6605 case 1: /* 0b01 => 2 bytes length (14 bits Usable) */
6608 case 2: /* 0b10 => 4 bytes length (30 bits Usable) */
6611 case 3: /* 0b11 => 8 bytes length (62 bits Usable) */
6618 switch (hfinfo
->type
) {
6625 case FT_STRINGZTRUNC
:
6627 * We allow FT_PROTOCOLs to be zero-length -
6628 * for example, an ONC RPC NULL procedure has
6629 * neither arguments nor reply, so the
6630 * payload for that protocol is empty.
6632 * We also allow the others to be zero-length -
6633 * because that's the way the code has been for a
6636 * However, we want to ensure that the start
6637 * offset is not *past* the byte past the end
6638 * of the tvbuff: we throw an exception in that
6641 *length
= tvb_captured_length(tvb
) ? tvb_ensure_captured_length_remaining(tvb
, start
) : 0;
6642 DISSECTOR_ASSERT(*length
>= 0);
6647 * Leave the length as -1, so our caller knows
6653 THROW(ReportedBoundsError
);
6654 DISSECTOR_ASSERT_NOT_REACHED();
6656 *item_length
= *length
;
6658 *item_length
= *length
;
6659 if (hfinfo
->type
== FT_PROTOCOL
|| hfinfo
->type
== FT_NONE
) {
6661 * These types are for interior nodes of the
6662 * tree, and don't have data associated with
6663 * them; if the length is negative (XXX - see
6664 * above) or goes past the end of the tvbuff,
6665 * cut it short at the end of the tvbuff.
6666 * That way, if this field is selected in
6667 * Wireshark, we don't highlight stuff past
6668 * the end of the data.
6670 /* XXX - what to do, if we don't have a tvb? */
6672 length_remaining
= tvb_captured_length_remaining(tvb
, start
);
6673 if (*item_length
< 0 ||
6674 (*item_length
> 0 &&
6675 (length_remaining
< *item_length
)))
6676 *item_length
= length_remaining
;
6679 if (*item_length
< 0) {
6680 THROW(ReportedBoundsError
);
6686 get_full_length(header_field_info
*hfinfo
, tvbuff_t
*tvb
, const int start
,
6687 int length
, unsigned item_length
, const int encoding
)
6692 * We need to get the correct item length here.
6693 * That's normally done by proto_tree_new_item(),
6694 * but we won't be calling it.
6696 switch (hfinfo
->type
) {
6702 * The length is the specified length.
6707 n
= get_uint_value(NULL
, tvb
, start
, length
, encoding
);
6709 if ((int)item_length
< length
) {
6710 THROW(ReportedBoundsError
);
6714 /* XXX - make these just FT_UINT? */
6723 /* XXX - make these just FT_INT? */
6732 if (encoding
& ENC_VARINT_MASK
) {
6734 report_type_length_mismatch(NULL
, "a FT_[U]INT", length
, true);
6738 /* This can throw an exception */
6739 /* XXX - do this without fetching the varint? */
6740 length
= tvb_get_varint(tvb
, start
, FT_VARINT_MAX_LEN
, &dummy
, encoding
);
6742 THROW(ReportedBoundsError
);
6745 item_length
= length
;
6750 * The length is the specified length.
6772 * The length is the specified length.
6778 report_type_length_mismatch(NULL
, "a string", length
, true);
6781 /* This can throw an exception */
6782 /* XXX - do this without fetching the string? */
6783 wmem_free(NULL
, tvb_get_stringz_enc(NULL
, tvb
, start
, &length
, encoding
));
6785 item_length
= length
;
6788 case FT_UINT_STRING
:
6789 n
= get_uint_value(NULL
, tvb
, start
, length
, encoding
& ~ENC_CHARENCODING_MASK
);
6791 if ((int)item_length
< length
) {
6792 THROW(ReportedBoundsError
);
6797 case FT_STRINGZTRUNC
:
6798 case FT_ABSOLUTE_TIME
:
6799 case FT_RELATIVE_TIME
:
6800 case FT_IEEE_11073_SFLOAT
:
6801 case FT_IEEE_11073_FLOAT
:
6803 * The length is the specified length.
6808 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in gset_full_length()",
6811 ftype_name(hfinfo
->type
));
6817 // This was arbitrarily chosen, but if you're adding 50K items to the tree
6818 // without advancing the offset you should probably take a long, hard look
6819 // at what you're doing.
6820 // We *could* make this a configurable option, but I (Gerald) would like to
6821 // avoid adding yet another nerd knob.
6822 # define PROTO_TREE_MAX_IDLE 50000
6824 new_field_info(proto_tree
*tree
, header_field_info
*hfinfo
, tvbuff_t
*tvb
,
6825 const int start
, const int item_length
)
6829 FIELD_INFO_NEW(PNODE_POOL(tree
), fi
);
6831 fi
->hfinfo
= hfinfo
;
6833 fi
->start
+= (tvb
)?tvb_raw_offset(tvb
):0;
6834 // If our start offset hasn't advanced after adding many items it probably
6835 // means we're in a large or infinite loop.
6836 if (fi
->start
> 0) {
6837 if (fi
->start
<= PTREE_DATA(tree
)->max_start
) {
6838 PTREE_DATA(tree
)->start_idle_count
++;
6839 DISSECTOR_ASSERT_HINT(PTREE_DATA(tree
)->start_idle_count
< PROTO_TREE_MAX_IDLE
, fi
->hfinfo
->abbrev
);
6841 PTREE_DATA(tree
)->max_start
= fi
->start
;
6842 PTREE_DATA(tree
)->start_idle_count
= 0;
6845 fi
->length
= item_length
;
6848 if (!PTREE_DATA(tree
)->visible
) {
6849 /* If the tree is not visible, set the item hidden, unless we
6850 * need the representation or length and can't fake them.
6852 if (hfinfo
->ref_type
!= HF_REF_TYPE_PRINT
&& (hfinfo
->type
!= FT_PROTOCOL
|| PTREE_DATA(tree
)->fake_protocols
)) {
6853 FI_SET_FLAG(fi
, FI_HIDDEN
);
6856 fi
->value
= fvalue_new(fi
->hfinfo
->type
);
6859 /* add the data source tvbuff */
6860 fi
->ds_tvb
= tvb
? tvb_get_ds_tvb(tvb
) : NULL
;
6862 fi
->appendix_start
= 0;
6863 fi
->appendix_length
= 0;
6865 fi
->total_layer_num
= tree
->tree_data
->pinfo
->curr_layer_num
;
6866 fi
->proto_layer_num
= tree
->tree_data
->pinfo
->curr_proto_layer_num
;
6871 static size_t proto_find_value_pos(const header_field_info
*hfinfo
, const char *representation
)
6873 if (hfinfo
->display
& BASE_NO_DISPLAY_VALUE
) {
6877 /* Search for field name */
6878 char *ptr
= strstr(representation
, hfinfo
->name
);
6883 /* Check if field name ends with the ": " delimiter */
6884 ptr
+= strlen(hfinfo
->name
);
6885 if (strncmp(ptr
, ": ", 2) == 0) {
6889 /* Return offset to after field name */
6890 return ptr
- representation
;
6893 /* If the protocol tree is to be visible, set the representation of a
6894 proto_tree entry with the name of the field for the item and with
6895 the value formatted with the supplied printf-style format and
6898 proto_tree_set_representation_value(proto_item
*pi
, const char *format
, va_list ap
)
6902 /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
6903 * items string representation */
6904 if (PTREE_DATA(pi
)->visible
|| !proto_item_is_hidden(pi
)) {
6905 size_t name_pos
, ret
= 0;
6907 field_info
*fi
= PITEM_FINFO(pi
);
6908 const header_field_info
*hf
;
6910 DISSECTOR_ASSERT(fi
);
6914 ITEM_LABEL_NEW(PNODE_POOL(pi
), fi
->rep
);
6915 if (hf
->bitmask
&& (hf
->type
== FT_BOOLEAN
|| FT_IS_UINT(hf
->type
))) {
6919 if (FT_IS_UINT32(hf
->type
))
6920 val
= fvalue_get_uinteger(fi
->value
);
6922 val
= fvalue_get_uinteger64(fi
->value
);
6924 val
<<= hfinfo_bitshift(hf
);
6926 p
= decode_bitfield_value(fi
->rep
->representation
, val
, hf
->bitmask
, hfinfo_container_bitwidth(hf
));
6927 ret
= (p
- fi
->rep
->representation
);
6930 /* put in the hf name */
6931 name_pos
= ret
= label_concat(fi
->rep
->representation
, ret
, hf
->name
);
6933 ret
= label_concat(fi
->rep
->representation
, ret
, ": ");
6934 /* If possible, Put in the value of the string */
6935 str
= wmem_strdup_vprintf(PNODE_POOL(pi
), format
, ap
);
6936 WS_UTF_8_CHECK(str
, -1);
6937 fi
->rep
->value_pos
= ret
;
6938 ret
= ws_label_strcpy(fi
->rep
->representation
, ITEM_LABEL_LENGTH
, ret
, str
, 0);
6939 if (ret
>= ITEM_LABEL_LENGTH
) {
6940 /* Uh oh, we don't have enough room. Tell the user
6941 * that the field is truncated.
6943 label_mark_truncated(fi
->rep
->representation
, name_pos
, &fi
->rep
->value_pos
);
6945 fi
->rep
->value_len
= strlen(fi
->rep
->representation
) - fi
->rep
->value_pos
;
6949 /* If the protocol tree is to be visible, set the representation of a
6950 proto_tree entry with the representation formatted with the supplied
6951 printf-style format and argument list. */
6953 proto_tree_set_representation(proto_item
*pi
, const char *format
, va_list ap
)
6955 size_t ret
; /*tmp return value */
6957 field_info
*fi
= PITEM_FINFO(pi
);
6959 DISSECTOR_ASSERT(fi
);
6961 if (!proto_item_is_hidden(pi
)) {
6962 ITEM_LABEL_NEW(PNODE_POOL(pi
), fi
->rep
);
6964 str
= wmem_strdup_vprintf(PNODE_POOL(pi
), format
, ap
);
6965 WS_UTF_8_CHECK(str
, -1);
6966 fi
->rep
->value_pos
= proto_find_value_pos(fi
->hfinfo
, str
);
6967 ret
= ws_label_strcpy(fi
->rep
->representation
, ITEM_LABEL_LENGTH
, 0, str
, 0);
6968 if (ret
>= ITEM_LABEL_LENGTH
) {
6969 /* Uh oh, we don't have enough room. Tell the user
6970 * that the field is truncated.
6972 LABEL_MARK_TRUNCATED_START(fi
->rep
->representation
, &fi
->rep
->value_pos
);
6974 fi
->rep
->value_len
= strlen(fi
->rep
->representation
) - fi
->rep
->value_pos
;
6979 protoo_strlcpy(char *dest
, const char *src
, size_t dest_size
)
6981 if (dest_size
== 0) return 0;
6983 size_t res
= g_strlcpy(dest
, src
, dest_size
);
6985 /* At most dest_size - 1 characters will be copied
6986 * (unless dest_size is 0). */
6987 if (res
>= dest_size
)
6988 res
= dest_size
- 1;
6992 static header_field_info
*
6993 hfinfo_same_name_get_prev(const header_field_info
*hfinfo
)
6995 header_field_info
*dup_hfinfo
;
6997 if (hfinfo
->same_name_prev_id
== -1)
6999 PROTO_REGISTRAR_GET_NTH(hfinfo
->same_name_prev_id
, dup_hfinfo
);
7004 hfinfo_remove_from_gpa_name_map(const header_field_info
*hfinfo
)
7006 g_free(last_field_name
);
7007 last_field_name
= NULL
;
7009 if (!hfinfo
->same_name_next
&& hfinfo
->same_name_prev_id
== -1) {
7010 /* No hfinfo with the same name */
7011 g_hash_table_steal(gpa_name_map
, hfinfo
->abbrev
);
7015 if (hfinfo
->same_name_next
) {
7016 hfinfo
->same_name_next
->same_name_prev_id
= hfinfo
->same_name_prev_id
;
7019 if (hfinfo
->same_name_prev_id
!= -1) {
7020 header_field_info
*same_name_prev
= hfinfo_same_name_get_prev(hfinfo
);
7021 same_name_prev
->same_name_next
= hfinfo
->same_name_next
;
7022 if (!hfinfo
->same_name_next
) {
7023 /* It's always the latest added hfinfo which is stored in gpa_name_map */
7024 g_hash_table_insert(gpa_name_map
, (void *) (same_name_prev
->abbrev
), same_name_prev
);
7030 proto_item_fill_display_label(const field_info
*finfo
, char *display_label_str
, const int label_str_size
)
7032 const header_field_info
*hfinfo
= finfo
->hfinfo
;
7036 const uint8_t *bytes
;
7039 const char *hf_str_val
;
7040 char number_buf
[NUMBER_LABEL_LENGTH
];
7041 const char *number_out
;
7043 const ipv4_addr_and_mask
*ipv4
;
7044 const ipv6_addr_and_prefix
*ipv6
;
7046 switch (hfinfo
->type
) {
7050 return protoo_strlcpy(display_label_str
, UTF8_CHECK_MARK
, label_str_size
);
7054 tmp_str
= format_bytes_hfinfo_maxlen(NULL
,
7056 fvalue_get_bytes_data(finfo
->value
),
7057 (unsigned)fvalue_length2(finfo
->value
),
7059 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7060 wmem_free(NULL
, tmp_str
);
7063 case FT_ABSOLUTE_TIME
:
7065 int flags
= ABS_TIME_TO_STR_SHOW_ZONE
;
7066 if (prefs
.display_abs_time_ascii
< ABS_TIME_ASCII_COLUMN
) {
7067 flags
|= ABS_TIME_TO_STR_ISO8601
;
7069 tmp_str
= abs_time_to_str_ex(NULL
, fvalue_get_time(finfo
->value
), hfinfo
->display
, flags
);
7070 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7071 wmem_free(NULL
, tmp_str
);
7075 case FT_RELATIVE_TIME
:
7076 tmp_str
= rel_time_to_secs_str(NULL
, fvalue_get_time(finfo
->value
));
7077 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7078 wmem_free(NULL
, tmp_str
);
7082 number64
= fvalue_get_uinteger64(finfo
->value
);
7083 label_len
= protoo_strlcpy(display_label_str
,
7084 tfs_get_string(!!number64
, hfinfo
->strings
), label_str_size
);
7088 number
= fvalue_get_uinteger(finfo
->value
);
7090 if (FIELD_DISPLAY(hfinfo
->display
) == BASE_CUSTOM
) {
7091 char tmp
[ITEM_LABEL_LENGTH
];
7092 custom_fmt_func_t fmtfunc
= (custom_fmt_func_t
)hfinfo
->strings
;
7094 DISSECTOR_ASSERT(fmtfunc
);
7095 fmtfunc(tmp
, number
);
7097 label_len
= protoo_strlcpy(display_label_str
, tmp
, label_str_size
);
7099 } else if (hfinfo
->strings
) {
7100 number_out
= hf_try_val_to_str(number
, hfinfo
);
7103 number_out
= hfinfo_char_value_format_display(BASE_HEX
, number_buf
, number
);
7106 label_len
= protoo_strlcpy(display_label_str
, number_out
, label_str_size
);
7109 number_out
= hfinfo_char_value_format(hfinfo
, number_buf
, number
);
7111 label_len
= protoo_strlcpy(display_label_str
, number_out
, label_str_size
);
7116 /* XXX - make these just FT_NUMBER? */
7127 number
= FT_IS_INT(hfinfo
->type
) ?
7128 (uint32_t) fvalue_get_sinteger(finfo
->value
) :
7129 fvalue_get_uinteger(finfo
->value
);
7131 if (FIELD_DISPLAY(hfinfo
->display
) == BASE_CUSTOM
) {
7132 char tmp
[ITEM_LABEL_LENGTH
];
7133 custom_fmt_func_t fmtfunc
= (custom_fmt_func_t
)hfinfo
->strings
;
7135 DISSECTOR_ASSERT(fmtfunc
);
7136 fmtfunc(tmp
, number
);
7138 label_len
= protoo_strlcpy(display_label_str
, tmp
, label_str_size
);
7140 } else if (hfinfo
->strings
&& hfinfo
->type
!= FT_FRAMENUM
) {
7141 if (hfinfo
->display
& BASE_UNIT_STRING
) {
7142 number_out
= hfinfo_numeric_value_format(hfinfo
, number_buf
, number
);
7143 label_len
= protoo_strlcpy(display_label_str
, number_out
, label_str_size
);
7144 hf_str_val
= hf_try_val_to_str(number
, hfinfo
);
7145 label_len
+= protoo_strlcpy(display_label_str
+label_len
, hf_str_val
, label_str_size
-label_len
);
7147 number_out
= hf_try_val_to_str(number
, hfinfo
);
7150 number_out
= hfinfo_number_value_format_display(hfinfo
, hfinfo
->display
, number_buf
, number
);
7153 label_len
= protoo_strlcpy(display_label_str
, number_out
, label_str_size
);
7156 number_out
= hfinfo_number_value_format(hfinfo
, number_buf
, number
);
7158 label_len
= protoo_strlcpy(display_label_str
, number_out
, label_str_size
);
7172 number64
= FT_IS_INT(hfinfo
->type
) ?
7173 (uint64_t) fvalue_get_sinteger64(finfo
->value
) :
7174 fvalue_get_uinteger64(finfo
->value
);
7176 if (FIELD_DISPLAY(hfinfo
->display
) == BASE_CUSTOM
) {
7177 char tmp
[ITEM_LABEL_LENGTH
];
7178 custom_fmt_func_64_t fmtfunc64
= (custom_fmt_func_64_t
)hfinfo
->strings
;
7180 DISSECTOR_ASSERT(fmtfunc64
);
7181 fmtfunc64(tmp
, number64
);
7183 label_len
= protoo_strlcpy(display_label_str
, tmp
, label_str_size
);
7184 } else if (hfinfo
->strings
) {
7185 if (hfinfo
->display
& BASE_UNIT_STRING
) {
7186 number_out
= hfinfo_numeric_value_format64(hfinfo
, number_buf
, number64
);
7187 label_len
= protoo_strlcpy(display_label_str
, number_out
, label_str_size
);
7188 hf_str_val
= hf_try_val64_to_str(number64
, hfinfo
);
7189 label_len
+= protoo_strlcpy(display_label_str
+label_len
, hf_str_val
, label_str_size
-label_len
);
7191 number_out
= hf_try_val64_to_str(number64
, hfinfo
);
7194 number_out
= hfinfo_number_value_format_display64(hfinfo
, hfinfo
->display
, number_buf
, number64
);
7196 label_len
= protoo_strlcpy(display_label_str
, number_out
, label_str_size
);
7199 number_out
= hfinfo_number_value_format64(hfinfo
, number_buf
, number64
);
7201 label_len
= protoo_strlcpy(display_label_str
, number_out
, label_str_size
);
7207 tmp_str
= eui64_to_str(NULL
, fvalue_get_uinteger64(finfo
->value
));
7208 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7209 wmem_free(NULL
, tmp_str
);
7213 ipv4
= fvalue_get_ipv4(finfo
->value
);
7214 //XXX: Should we ignore the mask?
7215 set_address_ipv4(&addr
, ipv4
);
7216 tmp_str
= address_to_display(NULL
, &addr
);
7217 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7218 wmem_free(NULL
, tmp_str
);
7219 free_address(&addr
);
7223 ipv6
= fvalue_get_ipv6(finfo
->value
);
7224 set_address_ipv6(&addr
, ipv6
);
7225 tmp_str
= address_to_display(NULL
, &addr
);
7226 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7227 wmem_free(NULL
, tmp_str
);
7228 free_address(&addr
);
7232 set_address (&addr
, AT_FCWWN
, FCWWN_ADDR_LEN
, fvalue_get_bytes_data(finfo
->value
));
7233 tmp_str
= address_to_display(NULL
, &addr
);
7234 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7235 wmem_free(NULL
, tmp_str
);
7239 set_address (&addr
, AT_ETHER
, FT_ETHER_LEN
, fvalue_get_bytes_data(finfo
->value
));
7240 tmp_str
= address_to_display(NULL
, &addr
);
7241 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7242 wmem_free(NULL
, tmp_str
);
7246 tmp_str
= guid_to_str(NULL
, fvalue_get_guid(finfo
->value
));
7247 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7248 wmem_free(NULL
, tmp_str
);
7252 bytes
= fvalue_get_bytes_data(finfo
->value
);
7253 tmp_str
= rel_oid_resolved_from_encoded(NULL
, bytes
, (int)fvalue_length2(finfo
->value
));
7254 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7255 wmem_free(NULL
, tmp_str
);
7259 bytes
= fvalue_get_bytes_data(finfo
->value
);
7260 tmp_str
= oid_resolved_from_encoded(NULL
, bytes
, (int)fvalue_length2(finfo
->value
));
7261 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7262 wmem_free(NULL
, tmp_str
);
7266 bytes
= fvalue_get_bytes_data(finfo
->value
);
7267 tmp_str
= print_system_id(NULL
, bytes
, (int)fvalue_length2(finfo
->value
));
7268 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7269 wmem_free(NULL
, tmp_str
);
7274 label_len
= (int)fill_display_label_float(finfo
, display_label_str
);
7279 case FT_UINT_STRING
:
7281 case FT_STRINGZTRUNC
:
7282 str
= fvalue_get_string(finfo
->value
);
7283 label_len
= (int)ws_label_strcpy(display_label_str
, label_str_size
, 0, str
, label_strcat_flags(hfinfo
));
7284 if (label_len
>= label_str_size
) {
7285 /* Truncation occurred. Get the real length
7286 * copied (not including '\0') */
7287 label_len
= label_str_size
? label_str_size
- 1 : 0;
7292 /* First try ftype string representation */
7293 tmp_str
= fvalue_to_string_repr(NULL
, finfo
->value
, FTREPR_DISPLAY
, hfinfo
->display
);
7295 /* Default to show as bytes */
7296 bytes
= fvalue_get_bytes_data(finfo
->value
);
7297 tmp_str
= bytes_to_str(NULL
, bytes
, fvalue_length2(finfo
->value
));
7299 label_len
= protoo_strlcpy(display_label_str
, tmp_str
, label_str_size
);
7300 wmem_free(NULL
, tmp_str
);
7306 /* -------------------------- */
7307 /* Sets the text for a custom column from proto fields.
7309 * @param[out] result The "resolved" column text (human readable, uses strings)
7310 * @param[out] expr The "unresolved" column text (values, display repr)
7311 * @return The filter (abbrev) for the field (XXX: Only the first if multifield)
7314 proto_custom_set(proto_tree
* tree
, GSList
*field_ids
, int occurrence
, bool display_details
,
7315 char *result
, char *expr
, const int size
)
7317 int len
, prev_len
, last
, i
, offset_r
= 0, offset_e
= 0;
7319 field_info
*finfo
= NULL
;
7320 header_field_info
* hfinfo
;
7321 const char *abbrev
= NULL
;
7323 const char *hf_str_val
;
7325 col_custom_t
*field_idx
;
7329 ws_assert(field_ids
!= NULL
);
7330 while ((field_idx
= (col_custom_t
*) g_slist_nth_data(field_ids
, ii
++))) {
7331 field_id
= field_idx
->field_id
;
7332 if (field_id
== 0) {
7333 GPtrArray
*fvals
= NULL
;
7334 bool passed
= dfilter_apply_full(field_idx
->dfilter
, tree
, &fvals
);
7335 if (fvals
!= NULL
) {
7337 // XXX - Handling occurrences is unusual when more
7338 // than one field is involved, e.g. there's four
7339 // results for tcp.port + tcp.port. We may really
7340 // want to apply it to the operands, not the output.
7341 // Note that occurrences are not quite the same as
7342 // the layer operator (should the grammar support
7344 /* Calculate single index or set outer boundaries */
7345 len
= g_ptr_array_len(fvals
);
7346 if (occurrence
< 0) {
7347 i
= occurrence
+ len
;
7349 } else if (occurrence
> 0) {
7356 if (i
< 0 || i
>= len
) {
7357 g_ptr_array_unref(fvals
);
7360 for (; i
<= last
; i
++) {
7361 /* XXX - We could have a "resolved" result
7362 * for types where the value depends only
7363 * on the type, e.g. FT_IPv4, and not on
7364 * hfinfo->strings. Supporting the latter
7365 * requires knowing which hfinfo matched
7366 * if there are multiple with the same
7367 * abbreviation. In any case, we need to
7368 * know the expected return type of the
7371 str
= fvalue_to_string_repr(NULL
, fvals
->pdata
[i
], FTREPR_DISPLAY
, BASE_NONE
);
7372 if (offset_r
&& (offset_r
< (size
- 1)))
7373 result
[offset_r
++] = ',';
7374 if (offset_e
&& (offset_e
< (size
- 1)))
7375 expr
[offset_e
++] = ',';
7376 offset_r
+= protoo_strlcpy(result
+offset_r
, str
, size
-offset_r
);
7377 offset_e
+= protoo_strlcpy(expr
+offset_e
, str
, size
-offset_e
);
7380 g_ptr_array_unref(fvals
);
7381 } else if (passed
) {
7382 // XXX - Occurrence doesn't make sense for a test
7383 // output, it should be applied to the operands.
7384 if (offset_r
&& (offset_r
< (size
- 1)))
7385 result
[offset_r
++] = ',';
7386 if (offset_e
&& (offset_e
< (size
- 1)))
7387 expr
[offset_e
++] = ',';
7388 /* Prevent multiple check marks */
7389 if (strstr(result
, UTF8_CHECK_MARK
",") == NULL
) {
7390 offset_r
+= protoo_strlcpy(result
+offset_r
, UTF8_CHECK_MARK
, size
-offset_r
);
7392 result
[--offset_r
] = '\0'; /* Remove the added trailing ',' */
7394 if (strstr(expr
, UTF8_CHECK_MARK
",") == NULL
) {
7395 offset_e
+= protoo_strlcpy(expr
+offset_e
, UTF8_CHECK_MARK
, size
-offset_e
);
7397 expr
[--offset_e
] = '\0'; /* Remove the added trailing ',' */
7402 PROTO_REGISTRAR_GET_NTH((unsigned)field_id
, hfinfo
);
7404 /* do we need to rewind ? */
7408 if (occurrence
< 0) {
7409 /* Search other direction */
7410 while (hfinfo
->same_name_prev_id
!= -1) {
7411 PROTO_REGISTRAR_GET_NTH(hfinfo
->same_name_prev_id
, hfinfo
);
7415 prev_len
= 0; /* Reset handled occurrences */
7418 finfos
= proto_get_finfo_ptr_array(tree
, hfinfo
->id
);
7420 if (!finfos
|| !(len
= g_ptr_array_len(finfos
))) {
7421 if (occurrence
< 0) {
7422 hfinfo
= hfinfo
->same_name_next
;
7424 hfinfo
= hfinfo_same_name_get_prev(hfinfo
);
7429 /* Are there enough occurrences of the field? */
7430 if (((occurrence
- prev_len
) > len
) || ((occurrence
+ prev_len
) < -len
)) {
7431 if (occurrence
< 0) {
7432 hfinfo
= hfinfo
->same_name_next
;
7434 hfinfo
= hfinfo_same_name_get_prev(hfinfo
);
7440 /* Calculate single index or set outer boundaries */
7441 if (occurrence
< 0) {
7442 i
= occurrence
+ len
+ prev_len
;
7444 } else if (occurrence
> 0) {
7445 i
= occurrence
- 1 - prev_len
;
7452 prev_len
+= len
; /* Count handled occurrences */
7455 finfo
= (field_info
*)g_ptr_array_index(finfos
, i
);
7457 if (offset_r
&& (offset_r
< (size
- 1)))
7458 result
[offset_r
++] = ',';
7460 if (display_details
) {
7461 char representation
[ITEM_LABEL_LENGTH
];
7464 if (finfo
->rep
&& finfo
->rep
->value_len
) {
7465 g_strlcpy(representation
, &finfo
->rep
->representation
[finfo
->rep
->value_pos
],
7466 MIN(finfo
->rep
->value_len
+ 1, ITEM_LABEL_LENGTH
));
7468 proto_item_fill_label(finfo
, representation
, &offset
);
7470 offset_r
+= protoo_strlcpy(result
+offset_r
, &representation
[offset
], size
-offset_r
);
7472 switch (hfinfo
->type
) {
7476 /* Prevent multiple check marks */
7477 if (strstr(result
, UTF8_CHECK_MARK
",") == NULL
) {
7478 offset_r
+= proto_item_fill_display_label(finfo
, result
+offset_r
, size
-offset_r
);
7480 result
[--offset_r
] = '\0'; /* Remove the added trailing ',' again */
7485 offset_r
+= proto_item_fill_display_label(finfo
, result
+offset_r
, size
-offset_r
);
7490 if (offset_e
&& (offset_e
< (size
- 1)))
7491 expr
[offset_e
++] = ',';
7493 if (hfinfo
->strings
&& hfinfo
->type
!= FT_FRAMENUM
&& FIELD_DISPLAY(hfinfo
->display
) == BASE_NONE
&& (FT_IS_INT(hfinfo
->type
) || FT_IS_UINT(hfinfo
->type
))) {
7494 /* Integer types with BASE_NONE never get the numeric value. */
7495 if (FT_IS_INT32(hfinfo
->type
)) {
7496 hf_str_val
= hf_try_val_to_str_const(fvalue_get_sinteger(finfo
->value
), hfinfo
, "Unknown");
7497 } else if (FT_IS_UINT32(hfinfo
->type
)) {
7498 hf_str_val
= hf_try_val_to_str_const(fvalue_get_uinteger(finfo
->value
), hfinfo
, "Unknown");
7499 } else if (FT_IS_INT64(hfinfo
->type
)) {
7500 hf_str_val
= hf_try_val64_to_str_const(fvalue_get_sinteger64(finfo
->value
), hfinfo
, "Unknown");
7501 } else { // if (FT_IS_UINT64(hfinfo->type)) {
7502 hf_str_val
= hf_try_val64_to_str_const(fvalue_get_uinteger64(finfo
->value
), hfinfo
, "Unknown");
7504 snprintf(expr
+offset_e
, size
-offset_e
, "\"%s\"", hf_str_val
);
7505 offset_e
= (int)strlen(expr
);
7506 } else if (hfinfo
->type
== FT_NONE
|| hfinfo
->type
== FT_PROTOCOL
) {
7507 /* Prevent multiple check marks */
7508 if (strstr(expr
, UTF8_CHECK_MARK
",") == NULL
) {
7509 offset_e
+= proto_item_fill_display_label(finfo
, expr
+offset_e
, size
-offset_e
);
7511 expr
[--offset_e
] = '\0'; /* Remove the added trailing ',' again */
7514 str
= fvalue_to_string_repr(NULL
, finfo
->value
, FTREPR_RAW
, finfo
->hfinfo
->display
);
7515 offset_e
+= protoo_strlcpy(expr
+offset_e
, str
, size
-offset_e
);
7516 wmem_free(NULL
, str
);
7521 /* XXX: Why is only the first abbreviation returned for a multifield
7524 /* Store abbrev for return value */
7525 abbrev
= hfinfo
->abbrev
;
7528 if (occurrence
== 0) {
7529 /* Fetch next hfinfo with same name (abbrev) */
7530 hfinfo
= hfinfo_same_name_get_prev(hfinfo
);
7537 if (offset_r
>= (size
- 1)) {
7538 mark_truncated(result
, 0, size
, NULL
);
7540 if (offset_e
>= (size
- 1)) {
7541 mark_truncated(expr
, 0, size
, NULL
);
7543 return abbrev
? abbrev
: "";
7547 proto_custom_get_filter(epan_dissect_t
* edt
, GSList
*field_ids
, int occurrence
)
7549 int len
, prev_len
, last
, i
;
7551 field_info
*finfo
= NULL
;
7552 header_field_info
* hfinfo
;
7554 char *filter
= NULL
;
7555 GPtrArray
*filter_array
;
7557 col_custom_t
*col_custom
;
7560 ws_assert(field_ids
!= NULL
);
7561 filter_array
= g_ptr_array_new_full(g_slist_length(field_ids
), g_free
);
7562 for (GSList
*iter
= field_ids
; iter
; iter
= iter
->next
) {
7563 col_custom
= (col_custom_t
*)iter
->data
;
7564 field_id
= col_custom
->field_id
;
7565 if (field_id
== 0) {
7566 GPtrArray
*fvals
= NULL
;
7567 bool passed
= dfilter_apply_full(col_custom
->dfilter
, edt
->tree
, &fvals
);
7568 if (fvals
!= NULL
) {
7569 // XXX - Handling occurrences is unusual when more
7570 // than one field is involved, e.g. there's four
7571 // results for tcp.port + tcp.port. We really
7572 // want to apply it to the operands, not the output.
7573 /* Calculate single index or set outer boundaries */
7574 len
= g_ptr_array_len(fvals
);
7575 if (occurrence
< 0) {
7576 i
= occurrence
+ len
;
7578 } else if (occurrence
> 0) {
7585 if (i
< 0 || i
>= len
) {
7586 g_ptr_array_unref(fvals
);
7589 for (; i
<= last
; i
++) {
7590 /* XXX - Should multiple values for one
7591 * field use set membership to reduce
7592 * verbosity, here and below? */
7593 char *str
= fvalue_to_string_repr(NULL
, fvals
->pdata
[i
], FTREPR_DFILTER
, BASE_NONE
);
7594 filter
= wmem_strdup_printf(NULL
, "%s == %s", col_custom
->dftext
, str
);
7595 wmem_free(NULL
, str
);
7596 if (!g_ptr_array_find_with_equal_func(filter_array
, filter
, g_str_equal
, NULL
)) {
7597 g_ptr_array_add(filter_array
, filter
);
7600 g_ptr_array_unref(fvals
);
7601 } else if (passed
) {
7602 filter
= wmem_strdup(NULL
, col_custom
->dftext
);
7603 if (!g_ptr_array_find_with_equal_func(filter_array
, filter
, g_str_equal
, NULL
)) {
7604 g_ptr_array_add(filter_array
, filter
);
7607 filter
= wmem_strdup_printf(NULL
, "!(%s)", col_custom
->dftext
);
7608 if (!g_ptr_array_find_with_equal_func(filter_array
, filter
, g_str_equal
, NULL
)) {
7609 g_ptr_array_add(filter_array
, filter
);
7615 PROTO_REGISTRAR_GET_NTH((unsigned)field_id
, hfinfo
);
7617 /* do we need to rewind ? */
7621 if (occurrence
< 0) {
7622 /* Search other direction */
7623 while (hfinfo
->same_name_prev_id
!= -1) {
7624 PROTO_REGISTRAR_GET_NTH(hfinfo
->same_name_prev_id
, hfinfo
);
7628 prev_len
= 0; /* Reset handled occurrences */
7631 finfos
= proto_get_finfo_ptr_array(edt
->tree
, hfinfo
->id
);
7633 if (!finfos
|| !(len
= g_ptr_array_len(finfos
))) {
7634 if (occurrence
< 0) {
7635 hfinfo
= hfinfo
->same_name_next
;
7637 hfinfo
= hfinfo_same_name_get_prev(hfinfo
);
7642 /* Are there enough occurrences of the field? */
7643 if (((occurrence
- prev_len
) > len
) || ((occurrence
+ prev_len
) < -len
)) {
7644 if (occurrence
< 0) {
7645 hfinfo
= hfinfo
->same_name_next
;
7647 hfinfo
= hfinfo_same_name_get_prev(hfinfo
);
7653 /* Calculate single index or set outer boundaries */
7654 if (occurrence
< 0) {
7655 i
= occurrence
+ len
+ prev_len
;
7657 } else if (occurrence
> 0) {
7658 i
= occurrence
- 1 - prev_len
;
7665 prev_len
+= len
; /* Count handled occurrences */
7668 finfo
= (field_info
*)g_ptr_array_index(finfos
, i
);
7670 filter
= proto_construct_match_selected_string(finfo
, edt
);
7672 /* Only add the same expression once (especially for FT_PROTOCOL).
7673 * The ptr array doesn't have NULL entries so g_str_equal is fine.
7675 if (!g_ptr_array_find_with_equal_func(filter_array
, filter
, g_str_equal
, NULL
)) {
7676 g_ptr_array_add(filter_array
, filter
);
7682 if (occurrence
== 0) {
7683 /* Fetch next hfinfo with same name (abbrev) */
7684 hfinfo
= hfinfo_same_name_get_prev(hfinfo
);
7691 g_ptr_array_add(filter_array
, NULL
);
7693 /* XXX: Should this be || or && ? */
7694 char *output
= g_strjoinv(" || ", (char **)filter_array
->pdata
);
7696 g_ptr_array_free(filter_array
, true);
7701 /* Set text of proto_item after having already been created. */
7703 proto_item_set_text(proto_item
*pi
, const char *format
, ...)
7705 field_info
*fi
= NULL
;
7708 TRY_TO_FAKE_THIS_REPR_VOID(pi
);
7710 fi
= PITEM_FINFO(pi
);
7715 ITEM_LABEL_FREE(PNODE_POOL(pi
), fi
->rep
);
7719 va_start(ap
, format
);
7720 proto_tree_set_representation(pi
, format
, ap
);
7724 /* Append to text of proto_item after having already been created. */
7726 proto_item_append_text(proto_item
*pi
, const char *format
, ...)
7728 field_info
*fi
= NULL
;
7733 TRY_TO_FAKE_THIS_REPR_VOID(pi
);
7735 fi
= PITEM_FINFO(pi
);
7740 if (!proto_item_is_hidden(pi
)) {
7742 * If we don't already have a representation,
7743 * generate the default representation.
7745 if (fi
->rep
== NULL
) {
7746 ITEM_LABEL_NEW(PNODE_POOL(pi
), fi
->rep
);
7747 proto_item_fill_label(fi
, fi
->rep
->representation
, &fi
->rep
->value_pos
);
7748 /* Check for special case append value to FT_NONE or FT_PROTOCOL */
7749 if ((fi
->hfinfo
->type
== FT_NONE
|| fi
->hfinfo
->type
== FT_PROTOCOL
) &&
7750 (strncmp(format
, ": ", 2) == 0)) {
7751 fi
->rep
->value_pos
+= 2;
7755 curlen
= strlen(fi
->rep
->representation
);
7756 /* curlen doesn't include the \0 byte.
7757 * XXX: If curlen + 4 > ITEM_LABEL_LENGTH, we can't tell if
7758 * the representation has already been truncated (of an up
7759 * to 4 byte UTF-8 character) or is just at the maximum length
7760 * unless we search for " [truncated]" (which may not be
7762 * It's safer to do nothing.
7764 if (ITEM_LABEL_LENGTH
> (curlen
+ 4)) {
7765 va_start(ap
, format
);
7766 str
= wmem_strdup_vprintf(PNODE_POOL(pi
), format
, ap
);
7768 WS_UTF_8_CHECK(str
, -1);
7769 /* Keep fi->rep->value_pos */
7770 curlen
= ws_label_strcpy(fi
->rep
->representation
, ITEM_LABEL_LENGTH
, curlen
, str
, 0);
7771 if (curlen
>= ITEM_LABEL_LENGTH
) {
7772 /* Uh oh, we don't have enough room. Tell the user
7773 * that the field is truncated.
7775 LABEL_MARK_TRUNCATED_START(fi
->rep
->representation
, &fi
->rep
->value_pos
);
7777 fi
->rep
->value_len
= strlen(fi
->rep
->representation
) - fi
->rep
->value_pos
;
7783 /* Prepend to text of proto_item after having already been created. */
7785 proto_item_prepend_text(proto_item
*pi
, const char *format
, ...)
7787 field_info
*fi
= NULL
;
7789 char representation
[ITEM_LABEL_LENGTH
];
7793 TRY_TO_FAKE_THIS_REPR_VOID(pi
);
7795 fi
= PITEM_FINFO(pi
);
7800 if (!proto_item_is_hidden(pi
)) {
7802 * If we don't already have a representation,
7803 * generate the default representation.
7805 if (fi
->rep
== NULL
) {
7806 ITEM_LABEL_NEW(PNODE_POOL(pi
), fi
->rep
);
7807 proto_item_fill_label(fi
, representation
, &fi
->rep
->value_pos
);
7809 (void) g_strlcpy(representation
, fi
->rep
->representation
, ITEM_LABEL_LENGTH
);
7811 va_start(ap
, format
);
7812 str
= wmem_strdup_vprintf(PNODE_POOL(pi
), format
, ap
);
7814 WS_UTF_8_CHECK(str
, -1);
7815 fi
->rep
->value_pos
+= strlen(str
);
7816 pos
= ws_label_strcpy(fi
->rep
->representation
, ITEM_LABEL_LENGTH
, 0, str
, 0);
7817 pos
= ws_label_strcpy(fi
->rep
->representation
, ITEM_LABEL_LENGTH
, pos
, representation
, 0);
7818 /* XXX: As above, if the old representation is close to the label
7819 * length, it might already be marked as truncated. */
7820 if (pos
>= ITEM_LABEL_LENGTH
&& (strlen(representation
) + 4) <= ITEM_LABEL_LENGTH
) {
7821 /* Uh oh, we don't have enough room. Tell the user
7822 * that the field is truncated.
7824 LABEL_MARK_TRUNCATED_START(fi
->rep
->representation
, &fi
->rep
->value_pos
);
7826 fi
->rep
->value_len
= strlen(fi
->rep
->representation
) - fi
->rep
->value_pos
;
7831 finfo_set_len(field_info
*fi
, const int length
)
7833 int length_remaining
;
7835 DISSECTOR_ASSERT_HINT(length
>= 0, fi
->hfinfo
->abbrev
);
7836 length_remaining
= tvb_captured_length_remaining(fi
->ds_tvb
, fi
->start
);
7837 if (length
> length_remaining
)
7838 fi
->length
= length_remaining
;
7840 fi
->length
= length
;
7842 /* If we have an FT_PROTOCOL we need to set the length of the fvalue tvbuff as well. */
7843 if (fvalue_type_ftenum(fi
->value
) == FT_PROTOCOL
) {
7844 fvalue_set_protocol_length(fi
->value
, fi
->length
);
7848 * You cannot just make the "len" field of a GByteArray
7849 * larger, if there's no data to back that length;
7850 * you can only make it smaller.
7852 if (fvalue_type_ftenum(fi
->value
) == FT_BYTES
&& fi
->length
> 0) {
7853 GBytes
*bytes
= fvalue_get_bytes(fi
->value
);
7855 const void *data
= g_bytes_get_data(bytes
, &size
);
7856 if ((size_t)fi
->length
<= size
) {
7857 fvalue_set_bytes_data(fi
->value
, data
, fi
->length
);
7859 g_bytes_unref(bytes
);
7864 proto_item_set_len(proto_item
*pi
, const int length
)
7871 fi
= PITEM_FINFO(pi
);
7875 finfo_set_len(fi
, length
);
7879 * Sets the length of the item based on its start and on the specified
7880 * offset, which is the offset past the end of the item; as the start
7881 * in the item is relative to the beginning of the data source tvbuff,
7882 * we need to pass in a tvbuff - the end offset is relative to the beginning
7886 proto_item_set_end(proto_item
*pi
, tvbuff_t
*tvb
, int end
)
7894 fi
= PITEM_FINFO(pi
);
7898 end
+= tvb_raw_offset(tvb
);
7899 DISSECTOR_ASSERT(end
>= fi
->start
);
7900 length
= end
- fi
->start
;
7902 finfo_set_len(fi
, length
);
7906 proto_item_get_len(const proto_item
*pi
)
7912 fi
= PITEM_FINFO(pi
);
7913 return fi
? fi
->length
: -1;
7917 proto_item_set_bits_offset_len(proto_item
*ti
, int bits_offset
, int bits_len
) {
7921 FI_SET_FLAG(PNODE_FINFO(ti
), FI_BITS_OFFSET(bits_offset
));
7922 FI_SET_FLAG(PNODE_FINFO(ti
), FI_BITS_SIZE(bits_len
));
7926 proto_item_get_display_repr(wmem_allocator_t
*scope
, proto_item
*pi
)
7931 return wmem_strdup(scope
, "");
7932 fi
= PITEM_FINFO(pi
);
7934 return wmem_strdup(scope
, "");
7935 DISSECTOR_ASSERT(fi
->hfinfo
!= NULL
);
7936 return fvalue_to_string_repr(scope
, fi
->value
, FTREPR_DISPLAY
, fi
->hfinfo
->display
);
7940 proto_tree_create_root(packet_info
*pinfo
)
7944 /* Initialize the proto_node */
7945 pnode
= g_slice_new(proto_tree
);
7946 PROTO_NODE_INIT(pnode
);
7947 pnode
->parent
= NULL
;
7948 PNODE_FINFO(pnode
) = NULL
;
7949 pnode
->tree_data
= g_slice_new(tree_data_t
);
7951 /* Make sure we can access pinfo everywhere */
7952 pnode
->tree_data
->pinfo
= pinfo
;
7954 /* Don't initialize the tree_data_t. Wait until we know we need it */
7955 pnode
->tree_data
->interesting_hfids
= NULL
;
7957 /* Set the default to false so it's easier to
7958 * find errors; if we expect to see the protocol tree
7959 * but for some reason the default 'visible' is not
7960 * changed, then we'll find out very quickly. */
7961 pnode
->tree_data
->visible
= false;
7963 /* Make sure that we fake protocols (if possible) */
7964 pnode
->tree_data
->fake_protocols
= true;
7966 /* Keep track of the number of children */
7967 pnode
->tree_data
->count
= 0;
7969 /* Initialize our loop checks */
7970 pnode
->tree_data
->max_start
= 0;
7971 pnode
->tree_data
->start_idle_count
= 0;
7973 return (proto_tree
*)pnode
;
7977 /* "prime" a proto_tree with a single hfid that a dfilter
7978 * is interested in. */
7980 proto_tree_prime_with_hfid(proto_tree
*tree _U_
, const int hfid
)
7982 header_field_info
*hfinfo
;
7984 PROTO_REGISTRAR_GET_NTH(hfid
, hfinfo
);
7985 /* this field is referenced by a filter so increase the refcount.
7986 also increase the refcount for the parent, i.e the protocol.
7987 Don't increase the refcount if we're already printing the
7988 type, as that is a superset of direct reference.
7990 if (hfinfo
->ref_type
!= HF_REF_TYPE_PRINT
) {
7991 hfinfo
->ref_type
= HF_REF_TYPE_DIRECT
;
7993 /* only increase the refcount if there is a parent.
7994 if this is a protocol and not a field then parent will be -1
7995 and there is no parent to add any refcounting for.
7997 if (hfinfo
->parent
!= -1) {
7998 header_field_info
*parent_hfinfo
;
7999 PROTO_REGISTRAR_GET_NTH(hfinfo
->parent
, parent_hfinfo
);
8001 /* Mark parent as indirectly referenced unless it is already directly
8002 * referenced, i.e. the user has specified the parent in a filter.
8004 if (parent_hfinfo
->ref_type
== HF_REF_TYPE_NONE
)
8005 parent_hfinfo
->ref_type
= HF_REF_TYPE_INDIRECT
;
8009 /* "prime" a proto_tree with a single hfid that a dfilter
8010 * is interested in. */
8012 proto_tree_prime_with_hfid_print(proto_tree
*tree _U_
, const int hfid
)
8014 header_field_info
*hfinfo
;
8016 PROTO_REGISTRAR_GET_NTH(hfid
, hfinfo
);
8017 /* this field is referenced by an (output) filter so increase the refcount.
8018 also increase the refcount for the parent, i.e the protocol.
8020 hfinfo
->ref_type
= HF_REF_TYPE_PRINT
;
8021 /* only increase the refcount if there is a parent.
8022 if this is a protocol and not a field then parent will be -1
8023 and there is no parent to add any refcounting for.
8025 if (hfinfo
->parent
!= -1) {
8026 header_field_info
*parent_hfinfo
;
8027 PROTO_REGISTRAR_GET_NTH(hfinfo
->parent
, parent_hfinfo
);
8029 /* Mark parent as indirectly referenced unless it is already directly
8030 * referenced, i.e. the user has specified the parent in a filter.
8032 if (parent_hfinfo
->ref_type
== HF_REF_TYPE_NONE
)
8033 parent_hfinfo
->ref_type
= HF_REF_TYPE_INDIRECT
;
8038 proto_item_add_subtree(proto_item
*pi
, const int idx
) {
8044 DISSECTOR_ASSERT(idx
>= 0 && idx
< num_tree_types
);
8046 fi
= PITEM_FINFO(pi
);
8048 return (proto_tree
*)pi
;
8050 fi
->tree_type
= idx
;
8052 return (proto_tree
*)pi
;
8056 proto_item_get_subtree(proto_item
*pi
) {
8061 fi
= PITEM_FINFO(pi
);
8062 if ( (fi
) && (fi
->tree_type
== -1) )
8064 return (proto_tree
*)pi
;
8068 proto_item_get_parent(const proto_item
*ti
) {
8075 proto_item_get_parent_nth(proto_item
*ti
, int gen
) {
8088 proto_tree_get_parent(proto_tree
*tree
) {
8091 return (proto_item
*)tree
;
8095 proto_tree_get_parent_tree(proto_tree
*tree
) {
8099 /* we're the root tree, there's no parent
8100 return ourselves so the caller has at least a tree to attach to */
8104 return (proto_tree
*)tree
->parent
;
8108 proto_tree_get_root(proto_tree
*tree
) {
8111 while (tree
->parent
) {
8112 tree
= tree
->parent
;
8118 proto_tree_move_item(proto_tree
*tree
, proto_item
*fixed_item
,
8119 proto_item
*item_to_move
)
8121 /* This function doesn't generate any values. It only reorganizes the prococol tree
8122 * so we can bail out immediately if it isn't visible. */
8123 if (!tree
|| !PTREE_DATA(tree
)->visible
)
8126 DISSECTOR_ASSERT(item_to_move
->parent
== tree
);
8127 DISSECTOR_ASSERT(fixed_item
->parent
== tree
);
8129 /*** cut item_to_move out ***/
8131 /* is item_to_move the first? */
8132 if (tree
->first_child
== item_to_move
) {
8133 /* simply change first child to next */
8134 tree
->first_child
= item_to_move
->next
;
8136 DISSECTOR_ASSERT(tree
->last_child
!= item_to_move
);
8138 proto_item
*curr_item
;
8139 /* find previous and change it's next */
8140 for (curr_item
= tree
->first_child
; curr_item
!= NULL
; curr_item
= curr_item
->next
) {
8141 if (curr_item
->next
== item_to_move
) {
8146 DISSECTOR_ASSERT(curr_item
);
8148 curr_item
->next
= item_to_move
->next
;
8150 /* fix last_child if required */
8151 if (tree
->last_child
== item_to_move
) {
8152 tree
->last_child
= curr_item
;
8156 /*** insert to_move after fixed ***/
8157 item_to_move
->next
= fixed_item
->next
;
8158 fixed_item
->next
= item_to_move
;
8159 if (tree
->last_child
== fixed_item
) {
8160 tree
->last_child
= item_to_move
;
8165 proto_tree_set_appendix(proto_tree
*tree
, tvbuff_t
*tvb
, int start
,
8173 fi
= PTREE_FINFO(tree
);
8177 start
+= tvb_raw_offset(tvb
);
8178 DISSECTOR_ASSERT(start
>= 0);
8179 DISSECTOR_ASSERT(length
>= 0);
8181 fi
->appendix_start
= start
;
8182 fi
->appendix_length
= length
;
8186 check_protocol_filter_name_or_fail(const char *filter_name
)
8188 /* Require at least two characters. */
8189 if (filter_name
[0] == '\0' || filter_name
[1] == '\0') {
8190 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" cannot have length less than two.", filter_name
);
8193 if (proto_check_field_name(filter_name
) != '\0') {
8194 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" has one or more invalid characters."
8195 " Allowed are letters, digits, '-', '_' and non-repeating '.'."
8196 " This might be caused by an inappropriate plugin or a development error.", filter_name
);
8199 /* Check that it doesn't match some very common numeric forms. */
8200 if (filter_name
[0] == '0' &&
8201 (filter_name
[1] == 'x' || filter_name
[1] == 'X' ||
8202 filter_name
[1] == 'b' || filter_name
[1] == 'B')) {
8203 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" cannot start with \"%c%c\".",
8204 filter_name
, filter_name
[0], filter_name
[1]);
8207 /* Names starting with a digit must not contain a minus sign (currently not checked at runtime). */
8209 /* Check that it contains at least one letter. */
8210 bool have_letter
= false;
8211 for (const char *s
= filter_name
; *s
!= '\0'; s
++) {
8212 if (g_ascii_isalpha(*s
)) {
8218 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" must contain at least one letter a-z.",
8222 /* Check for reserved keywords. */
8223 if (g_hash_table_contains(proto_reserved_filter_names
, filter_name
)) {
8224 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" is invalid because it is a reserved keyword."
8225 " This might be caused by an inappropriate plugin or a development error.", filter_name
);
8230 proto_register_protocol(const char *name
, const char *short_name
,
8231 const char *filter_name
)
8233 protocol_t
*protocol
;
8234 header_field_info
*hfinfo
;
8237 * Make sure there's not already a protocol with any of those
8238 * names. Crash if there is, as that's an error in the code
8239 * or an inappropriate plugin.
8240 * This situation has to be fixed to not register more than one
8241 * protocol with the same name.
8244 if (g_hash_table_lookup(proto_names
, name
)) {
8245 /* ws_error will terminate the program */
8246 REPORT_DISSECTOR_BUG("Duplicate protocol name \"%s\"!"
8247 " This might be caused by an inappropriate plugin or a development error.", name
);
8250 if (g_hash_table_lookup(proto_short_names
, short_name
)) {
8251 REPORT_DISSECTOR_BUG("Duplicate protocol short_name \"%s\"!"
8252 " This might be caused by an inappropriate plugin or a development error.", short_name
);
8255 check_protocol_filter_name_or_fail(filter_name
);
8257 if (g_hash_table_lookup(proto_filter_names
, filter_name
)) {
8258 REPORT_DISSECTOR_BUG("Duplicate protocol filter_name \"%s\"!"
8259 " This might be caused by an inappropriate plugin or a development error.", filter_name
);
8263 * Add this protocol to the list of known protocols;
8264 * the list is sorted by protocol short name.
8266 protocol
= g_new(protocol_t
, 1);
8267 protocol
->name
= name
;
8268 protocol
->short_name
= short_name
;
8269 protocol
->filter_name
= filter_name
;
8270 protocol
->fields
= NULL
; /* Delegate until actually needed */
8271 protocol
->is_enabled
= true; /* protocol is enabled by default */
8272 protocol
->enabled_by_default
= true; /* see previous comment */
8273 protocol
->can_toggle
= true;
8274 protocol
->parent_proto_id
= -1;
8275 protocol
->heur_list
= NULL
;
8277 /* List will be sorted later by name, when all protocols completed registering */
8278 protocols
= g_list_prepend(protocols
, protocol
);
8279 g_hash_table_insert(proto_names
, (void *)name
, protocol
);
8280 g_hash_table_insert(proto_filter_names
, (void *)filter_name
, protocol
);
8281 g_hash_table_insert(proto_short_names
, (void *)short_name
, protocol
);
8283 /* Here we allocate a new header_field_info struct */
8284 hfinfo
= g_slice_new(header_field_info
);
8285 hfinfo
->name
= name
;
8286 hfinfo
->abbrev
= filter_name
;
8287 hfinfo
->type
= FT_PROTOCOL
;
8288 hfinfo
->display
= BASE_NONE
;
8289 hfinfo
->strings
= protocol
;
8290 hfinfo
->bitmask
= 0;
8291 hfinfo
->ref_type
= HF_REF_TYPE_NONE
;
8292 hfinfo
->blurb
= NULL
;
8293 hfinfo
->parent
= -1; /* This field differentiates protos and fields */
8295 protocol
->proto_id
= proto_register_field_init(hfinfo
, hfinfo
->parent
);
8296 return protocol
->proto_id
;
8300 proto_register_protocol_in_name_only(const char *name
, const char *short_name
, const char *filter_name
, int parent_proto
, enum ftenum field_type
)
8302 protocol_t
*protocol
;
8303 header_field_info
*hfinfo
;
8306 * Helper protocols don't need the strict rules as a "regular" protocol
8307 * Just register it in a list and make a hf_ field from it
8309 if ((field_type
!= FT_PROTOCOL
) && (field_type
!= FT_BYTES
)) {
8310 REPORT_DISSECTOR_BUG("Pino \"%s\" must be of type FT_PROTOCOL or FT_BYTES.", name
);
8313 if (parent_proto
<= 0) {
8314 REPORT_DISSECTOR_BUG("Must have a valid parent protocol for helper protocol \"%s\"!"
8315 " This might be caused by an inappropriate plugin or a development error.", name
);
8318 check_protocol_filter_name_or_fail(filter_name
);
8320 /* Add this protocol to the list of helper protocols (just so it can be properly freed) */
8321 protocol
= g_new(protocol_t
, 1);
8322 protocol
->name
= name
;
8323 protocol
->short_name
= short_name
;
8324 protocol
->filter_name
= filter_name
;
8325 protocol
->fields
= NULL
; /* Delegate until actually needed */
8327 /* Enabling and toggling is really determined by parent protocol,
8328 but provide default values here */
8329 protocol
->is_enabled
= true;
8330 protocol
->enabled_by_default
= true;
8331 protocol
->can_toggle
= true;
8333 protocol
->parent_proto_id
= parent_proto
;
8334 protocol
->heur_list
= NULL
;
8336 /* List will be sorted later by name, when all protocols completed registering */
8337 protocols
= g_list_prepend(protocols
, protocol
);
8339 /* Here we allocate a new header_field_info struct */
8340 hfinfo
= g_slice_new(header_field_info
);
8341 hfinfo
->name
= name
;
8342 hfinfo
->abbrev
= filter_name
;
8343 hfinfo
->type
= field_type
;
8344 hfinfo
->display
= BASE_NONE
;
8345 if (field_type
== FT_BYTES
) {
8346 hfinfo
->display
|= (BASE_NO_DISPLAY_VALUE
|BASE_PROTOCOL_INFO
);
8348 hfinfo
->strings
= protocol
;
8349 hfinfo
->bitmask
= 0;
8350 hfinfo
->ref_type
= HF_REF_TYPE_NONE
;
8351 hfinfo
->blurb
= NULL
;
8352 hfinfo
->parent
= -1; /* This field differentiates protos and fields */
8354 protocol
->proto_id
= proto_register_field_init(hfinfo
, hfinfo
->parent
);
8355 return protocol
->proto_id
;
8359 proto_deregister_protocol(const char *short_name
)
8361 protocol_t
*protocol
;
8362 header_field_info
*hfinfo
;
8366 proto_id
= proto_get_id_by_short_name(short_name
);
8367 protocol
= find_protocol_by_id(proto_id
);
8368 if (protocol
== NULL
)
8371 g_hash_table_remove(proto_names
, protocol
->name
);
8372 g_hash_table_remove(proto_short_names
, (void *)short_name
);
8373 g_hash_table_remove(proto_filter_names
, (void *)protocol
->filter_name
);
8375 if (protocol
->fields
) {
8376 for (i
= 0; i
< protocol
->fields
->len
; i
++) {
8377 hfinfo
= (header_field_info
*)g_ptr_array_index(protocol
->fields
, i
);
8378 hfinfo_remove_from_gpa_name_map(hfinfo
);
8379 expert_deregister_expertinfo(hfinfo
->abbrev
);
8380 g_ptr_array_add(deregistered_fields
, gpa_hfinfo
.hfi
[hfinfo
->id
]);
8382 g_ptr_array_free(protocol
->fields
, true);
8383 protocol
->fields
= NULL
;
8386 g_list_free(protocol
->heur_list
);
8388 /* Remove this protocol from the list of known protocols */
8389 protocols
= g_list_remove(protocols
, protocol
);
8391 g_ptr_array_add(deregistered_fields
, gpa_hfinfo
.hfi
[proto_id
]);
8392 g_hash_table_steal(gpa_name_map
, protocol
->filter_name
);
8394 g_free(last_field_name
);
8395 last_field_name
= NULL
;
8401 proto_register_alias(const int proto_id
, const char *alias_name
)
8403 protocol_t
*protocol
;
8405 protocol
= find_protocol_by_id(proto_id
);
8406 if (alias_name
&& protocol
) {
8407 g_hash_table_insert(gpa_protocol_aliases
, (void *) alias_name
, (void *)protocol
->filter_name
);
8412 * Routines to use to iterate over the protocols.
8413 * The argument passed to the iterator routines is an opaque cookie to
8414 * their callers; it's the GList pointer for the current element in
8416 * The ID of the protocol is returned, or -1 if there is no protocol.
8419 proto_get_first_protocol(void **cookie
)
8421 protocol_t
*protocol
;
8423 if (protocols
== NULL
)
8425 *cookie
= protocols
;
8426 protocol
= (protocol_t
*)protocols
->data
;
8427 return protocol
->proto_id
;
8431 proto_get_data_protocol(void *cookie
)
8433 GList
*list_item
= (GList
*)cookie
;
8435 protocol_t
*protocol
= (protocol_t
*)list_item
->data
;
8436 return protocol
->proto_id
;
8440 proto_get_next_protocol(void **cookie
)
8442 GList
*list_item
= (GList
*)*cookie
;
8443 protocol_t
*protocol
;
8445 list_item
= g_list_next(list_item
);
8446 if (list_item
== NULL
)
8448 *cookie
= list_item
;
8449 protocol
= (protocol_t
*)list_item
->data
;
8450 return protocol
->proto_id
;
8454 proto_get_first_protocol_field(const int proto_id
, void **cookie
)
8456 protocol_t
*protocol
= find_protocol_by_id(proto_id
);
8458 if ((protocol
== NULL
) || (protocol
->fields
== NULL
) || (protocol
->fields
->len
== 0))
8461 *cookie
= GUINT_TO_POINTER(0);
8462 return (header_field_info
*)g_ptr_array_index(protocol
->fields
, 0);
8466 proto_get_next_protocol_field(const int proto_id
, void **cookie
)
8468 protocol_t
*protocol
= find_protocol_by_id(proto_id
);
8469 unsigned i
= GPOINTER_TO_UINT(*cookie
);
8473 if ((protocol
->fields
== NULL
) || (i
>= protocol
->fields
->len
))
8476 *cookie
= GUINT_TO_POINTER(i
);
8477 return (header_field_info
*)g_ptr_array_index(protocol
->fields
, i
);
8481 find_protocol_by_id(const int proto_id
)
8483 header_field_info
*hfinfo
;
8488 PROTO_REGISTRAR_GET_NTH(proto_id
, hfinfo
);
8489 if (hfinfo
->type
!= FT_PROTOCOL
) {
8490 DISSECTOR_ASSERT(hfinfo
->display
& BASE_PROTOCOL_INFO
);
8492 return (protocol_t
*)hfinfo
->strings
;
8496 proto_get_id(const protocol_t
*protocol
)
8498 return protocol
->proto_id
;
8502 proto_name_already_registered(const char *name
)
8504 DISSECTOR_ASSERT_HINT(name
, "No name present");
8506 if (g_hash_table_lookup(proto_names
, name
) != NULL
)
8512 proto_get_id_by_filter_name(const char *filter_name
)
8514 const protocol_t
*protocol
= NULL
;
8516 DISSECTOR_ASSERT_HINT(filter_name
, "No filter name present");
8518 protocol
= (const protocol_t
*)g_hash_table_lookup(proto_filter_names
, filter_name
);
8520 if (protocol
== NULL
)
8522 return protocol
->proto_id
;
8526 proto_get_id_by_short_name(const char *short_name
)
8528 const protocol_t
*protocol
= NULL
;
8530 DISSECTOR_ASSERT_HINT(short_name
, "No short name present");
8532 protocol
= (const protocol_t
*)g_hash_table_lookup(proto_short_names
, short_name
);
8534 if (protocol
== NULL
)
8536 return protocol
->proto_id
;
8540 proto_get_protocol_name(const int proto_id
)
8542 protocol_t
*protocol
;
8544 protocol
= find_protocol_by_id(proto_id
);
8546 if (protocol
== NULL
)
8548 return protocol
->name
;
8552 proto_get_protocol_short_name(const protocol_t
*protocol
)
8554 if (protocol
== NULL
)
8556 return protocol
->short_name
;
8560 proto_get_protocol_long_name(const protocol_t
*protocol
)
8562 if (protocol
== NULL
)
8564 return protocol
->name
;
8568 proto_get_protocol_filter_name(const int proto_id
)
8570 protocol_t
*protocol
;
8572 protocol
= find_protocol_by_id(proto_id
);
8573 if (protocol
== NULL
)
8575 return protocol
->filter_name
;
8578 void proto_add_heuristic_dissector(protocol_t
*protocol
, const char *short_name
)
8580 heur_dtbl_entry_t
* heuristic_dissector
;
8582 if (protocol
== NULL
)
8585 heuristic_dissector
= find_heur_dissector_by_unique_short_name(short_name
);
8586 if (heuristic_dissector
!= NULL
)
8588 protocol
->heur_list
= g_list_prepend (protocol
->heur_list
, heuristic_dissector
);
8592 void proto_heuristic_dissector_foreach(const protocol_t
*protocol
, GFunc func
, void *user_data
)
8594 if (protocol
== NULL
)
8597 g_list_foreach(protocol
->heur_list
, func
, user_data
);
8601 proto_get_frame_protocols(const wmem_list_t
*layers
, bool *is_ip
,
8602 bool *is_tcp
, bool *is_udp
,
8603 bool *is_sctp
, bool *is_tls
,
8607 wmem_list_frame_t
*protos
= wmem_list_head(layers
);
8609 const char *proto_name
;
8611 /* Walk the list of a available protocols in the packet and
8612 attempt to find "major" ones. */
8613 /* It might make more sense to assemble and return a bitfield. */
8614 while (protos
!= NULL
)
8616 proto_id
= GPOINTER_TO_INT(wmem_list_frame_data(protos
));
8617 proto_name
= proto_get_protocol_filter_name(proto_id
);
8619 if (is_ip
&& ((!strcmp(proto_name
, "ip")) ||
8620 (!strcmp(proto_name
, "ipv6")))) {
8622 } else if (is_tcp
&& !strcmp(proto_name
, "tcp")) {
8624 } else if (is_udp
&& !strcmp(proto_name
, "udp")) {
8626 } else if (is_sctp
&& !strcmp(proto_name
, "sctp")) {
8628 } else if (is_tls
&& !strcmp(proto_name
, "tls")) {
8630 } else if (is_rtp
&& !strcmp(proto_name
, "rtp")) {
8632 } else if (is_lte_rlc
&& (!strcmp(proto_name
, "rlc-lte") || !strcmp(proto_name
, "rlc-nr"))) {
8636 protos
= wmem_list_frame_next(protos
);
8641 proto_is_frame_protocol(const wmem_list_t
*layers
, const char* proto_name
)
8643 wmem_list_frame_t
*protos
= wmem_list_head(layers
);
8647 /* Walk the list of a available protocols in the packet and
8648 attempt to find the specified protocol. */
8649 while (protos
!= NULL
)
8651 proto_id
= GPOINTER_TO_INT(wmem_list_frame_data(protos
));
8652 name
= proto_get_protocol_filter_name(proto_id
);
8654 if (!strcmp(name
, proto_name
))
8659 protos
= wmem_list_frame_next(protos
);
8666 proto_list_layers(const packet_info
*pinfo
)
8669 wmem_list_frame_t
*layers
= wmem_list_head(pinfo
->layers
);
8671 buf
= wmem_strbuf_new_sized(pinfo
->pool
, 128);
8673 /* Walk the list of layers in the packet and
8674 return a string of all entries. */
8675 while (layers
!= NULL
)
8677 wmem_strbuf_append(buf
, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(layers
))));
8679 layers
= wmem_list_frame_next(layers
);
8680 if (layers
!= NULL
) {
8681 wmem_strbuf_append_c(buf
, ':');
8685 return wmem_strbuf_finalize(buf
);
8689 proto_is_pino(const protocol_t
*protocol
)
8691 return (protocol
->parent_proto_id
!= -1);
8695 // NOLINTNEXTLINE(misc-no-recursion)
8696 proto_is_protocol_enabled(const protocol_t
*protocol
)
8698 if (protocol
== NULL
)
8701 //parent protocol determines enable/disable for helper dissectors
8702 if (proto_is_pino(protocol
))
8703 return proto_is_protocol_enabled(find_protocol_by_id(protocol
->parent_proto_id
));
8705 return protocol
->is_enabled
;
8709 // NOLINTNEXTLINE(misc-no-recursion)
8710 proto_is_protocol_enabled_by_default(const protocol_t
*protocol
)
8712 //parent protocol determines enable/disable for helper dissectors
8713 if (proto_is_pino(protocol
))
8714 return proto_is_protocol_enabled_by_default(find_protocol_by_id(protocol
->parent_proto_id
));
8716 return protocol
->enabled_by_default
;
8720 // NOLINTNEXTLINE(misc-no-recursion)
8721 proto_can_toggle_protocol(const int proto_id
)
8723 protocol_t
*protocol
;
8725 protocol
= find_protocol_by_id(proto_id
);
8726 //parent protocol determines toggling for helper dissectors
8727 if (proto_is_pino(protocol
))
8728 return proto_can_toggle_protocol(protocol
->parent_proto_id
);
8730 return protocol
->can_toggle
;
8734 proto_disable_by_default(const int proto_id
)
8736 protocol_t
*protocol
;
8738 protocol
= find_protocol_by_id(proto_id
);
8739 DISSECTOR_ASSERT(protocol
->can_toggle
);
8740 DISSECTOR_ASSERT(proto_is_pino(protocol
) == false);
8741 protocol
->is_enabled
= false;
8742 protocol
->enabled_by_default
= false;
8746 proto_set_decoding(const int proto_id
, const bool enabled
)
8748 protocol_t
*protocol
;
8750 protocol
= find_protocol_by_id(proto_id
);
8751 DISSECTOR_ASSERT(protocol
->can_toggle
);
8752 DISSECTOR_ASSERT(proto_is_pino(protocol
) == false);
8753 protocol
->is_enabled
= enabled
;
8757 proto_disable_all(void)
8759 /* This doesn't explicitly disable heuristic protocols,
8760 * but the heuristic doesn't get called if the parent
8761 * protocol isn't enabled.
8763 protocol_t
*protocol
;
8764 GList
*list_item
= protocols
;
8766 if (protocols
== NULL
)
8770 protocol
= (protocol_t
*)list_item
->data
;
8771 if (protocol
->can_toggle
) {
8772 protocol
->is_enabled
= false;
8774 list_item
= g_list_next(list_item
);
8779 heur_reenable_cb(void *data
, void *user_data _U_
)
8781 heur_dtbl_entry_t
*heur
= (heur_dtbl_entry_t
*)data
;
8783 heur
->enabled
= heur
->enabled_by_default
;
8787 proto_reenable_all(void)
8789 protocol_t
*protocol
;
8790 GList
*list_item
= protocols
;
8792 if (protocols
== NULL
)
8796 protocol
= (protocol_t
*)list_item
->data
;
8797 if (protocol
->can_toggle
)
8798 protocol
->is_enabled
= protocol
->enabled_by_default
;
8799 proto_heuristic_dissector_foreach(protocol
, heur_reenable_cb
, NULL
);
8800 list_item
= g_list_next(list_item
);
8805 proto_set_cant_toggle(const int proto_id
)
8807 protocol_t
*protocol
;
8809 protocol
= find_protocol_by_id(proto_id
);
8810 protocol
->can_toggle
= false;
8814 proto_register_field_common(protocol_t
*proto
, header_field_info
*hfi
, const int parent
)
8816 if (proto
!= NULL
) {
8817 g_ptr_array_add(proto
->fields
, hfi
);
8820 return proto_register_field_init(hfi
, parent
);
8823 /* for use with static arrays only, since we don't allocate our own copies
8824 of the header_field_info struct contained within the hf_register_info struct */
8826 proto_register_field_array(const int parent
, hf_register_info
*hf
, const int num_records
)
8828 hf_register_info
*ptr
= hf
;
8832 proto
= find_protocol_by_id(parent
);
8834 if (proto
->fields
== NULL
) {
8835 proto
->fields
= g_ptr_array_sized_new(num_records
);
8838 for (i
= 0; i
< num_records
; i
++, ptr
++) {
8840 * Make sure we haven't registered this yet.
8841 * Most fields have variables associated with them
8842 * that are initialized to -1; some have array elements,
8843 * or possibly uninitialized variables, so we also allow
8844 * 0 (which is unlikely to be the field ID we get back
8845 * from "proto_register_field_init()").
8847 if (*ptr
->p_id
!= -1 && *ptr
->p_id
!= 0) {
8848 REPORT_DISSECTOR_BUG(
8849 "Duplicate field detected in call to proto_register_field_array: %s is already registered",
8850 ptr
->hfinfo
.abbrev
);
8854 *ptr
->p_id
= proto_register_field_common(proto
, &ptr
->hfinfo
, parent
);
8858 /* deregister already registered fields */
8860 proto_deregister_field (const int parent
, int hf_id
)
8862 header_field_info
*hfi
;
8866 g_free(last_field_name
);
8867 last_field_name
= NULL
;
8869 if (hf_id
== -1 || hf_id
== 0)
8872 proto
= find_protocol_by_id (parent
);
8873 if (!proto
|| proto
->fields
== NULL
) {
8877 for (i
= 0; i
< proto
->fields
->len
; i
++) {
8878 hfi
= (header_field_info
*)g_ptr_array_index(proto
->fields
, i
);
8879 if (hfi
->id
== hf_id
) {
8880 /* Found the hf_id in this protocol */
8881 g_hash_table_steal(gpa_name_map
, hfi
->abbrev
);
8882 g_ptr_array_remove_index_fast(proto
->fields
, i
);
8883 g_ptr_array_add(deregistered_fields
, gpa_hfinfo
.hfi
[hf_id
]);
8890 proto_add_deregistered_data (void *data
)
8892 g_ptr_array_add(deregistered_data
, data
);
8896 proto_add_deregistered_slice (size_t block_size
, void *mem_block
)
8898 struct g_slice_data
*slice_data
= g_slice_new(struct g_slice_data
);
8900 slice_data
->block_size
= block_size
;
8901 slice_data
->mem_block
= mem_block
;
8903 g_ptr_array_add(deregistered_slice
, slice_data
);
8906 void proto_free_field_strings (ftenum_t field_type
, unsigned int field_display
, const void *field_strings
)
8908 if (field_strings
== NULL
) {
8912 switch (field_type
) {
8914 /* This is just an integer represented as a pointer */
8917 protocol_t
*protocol
= (protocol_t
*)field_strings
;
8918 g_free((char *)protocol
->short_name
);
8922 true_false_string
*tf
= (true_false_string
*)field_strings
;
8923 g_free((char *)tf
->true_string
);
8924 g_free((char *)tf
->false_string
);
8935 if (field_display
& BASE_UNIT_STRING
) {
8936 unit_name_string
*unit
= (unit_name_string
*)field_strings
;
8937 g_free((char *)unit
->singular
);
8938 g_free((char *)unit
->plural
);
8939 } else if (field_display
& BASE_RANGE_STRING
) {
8940 range_string
*rs
= (range_string
*)field_strings
;
8941 while (rs
->strptr
) {
8942 g_free((char *)rs
->strptr
);
8945 } else if (field_display
& BASE_EXT_STRING
) {
8946 val64_string_ext
*vse
= (val64_string_ext
*)field_strings
;
8947 val64_string
*vs
= (val64_string
*)vse
->_vs_p
;
8948 while (vs
->strptr
) {
8949 g_free((char *)vs
->strptr
);
8952 val64_string_ext_free(vse
);
8953 field_strings
= NULL
;
8954 } else if (field_display
== BASE_CUSTOM
) {
8955 /* this will be a pointer to a function, don't free that */
8956 field_strings
= NULL
;
8958 val64_string
*vs64
= (val64_string
*)field_strings
;
8959 while (vs64
->strptr
) {
8960 g_free((char *)vs64
->strptr
);
8977 if (field_display
& BASE_UNIT_STRING
) {
8978 unit_name_string
*unit
= (unit_name_string
*)field_strings
;
8979 g_free((char *)unit
->singular
);
8980 g_free((char *)unit
->plural
);
8981 } else if (field_display
& BASE_RANGE_STRING
) {
8982 range_string
*rs
= (range_string
*)field_strings
;
8983 while (rs
->strptr
) {
8984 g_free((char *)rs
->strptr
);
8987 } else if (field_display
& BASE_EXT_STRING
) {
8988 value_string_ext
*vse
= (value_string_ext
*)field_strings
;
8989 value_string
*vs
= (value_string
*)vse
->_vs_p
;
8990 while (vs
->strptr
) {
8991 g_free((char *)vs
->strptr
);
8994 value_string_ext_free(vse
);
8995 field_strings
= NULL
;
8996 } else if (field_display
== BASE_CUSTOM
) {
8997 /* this will be a pointer to a function, don't free that */
8998 field_strings
= NULL
;
9000 value_string
*vs
= (value_string
*)field_strings
;
9001 while (vs
->strptr
) {
9002 g_free((char *)vs
->strptr
);
9012 if (field_type
!= FT_FRAMENUM
) {
9013 g_free((void *)field_strings
);
9018 free_deregistered_field (void *data
, void *user_data _U_
)
9020 header_field_info
*hfi
= (header_field_info
*) data
;
9021 int hf_id
= hfi
->id
;
9023 g_free((char *)hfi
->name
);
9024 g_free((char *)hfi
->abbrev
);
9025 g_free((char *)hfi
->blurb
);
9027 proto_free_field_strings(hfi
->type
, hfi
->display
, hfi
->strings
);
9029 if (hfi
->parent
== -1)
9030 g_slice_free(header_field_info
, hfi
);
9032 gpa_hfinfo
.hfi
[hf_id
] = NULL
; /* Invalidate this hf_id / proto_id */
9036 free_deregistered_data (void *data
, void *user_data _U_
)
9042 free_deregistered_slice (void *data
, void *user_data _U_
)
9044 struct g_slice_data
*slice_data
= (struct g_slice_data
*)data
;
9046 g_slice_free1(slice_data
->block_size
, slice_data
->mem_block
);
9047 g_slice_free(struct g_slice_data
, slice_data
);
9050 /* free deregistered fields and data */
9052 proto_free_deregistered_fields (void)
9054 expert_free_deregistered_expertinfos();
9056 g_ptr_array_foreach(deregistered_fields
, free_deregistered_field
, NULL
);
9057 g_ptr_array_free(deregistered_fields
, true);
9058 deregistered_fields
= g_ptr_array_new();
9060 g_ptr_array_foreach(deregistered_data
, free_deregistered_data
, NULL
);
9061 g_ptr_array_free(deregistered_data
, true);
9062 deregistered_data
= g_ptr_array_new();
9064 g_ptr_array_foreach(deregistered_slice
, free_deregistered_slice
, NULL
);
9065 g_ptr_array_free(deregistered_slice
, true);
9066 deregistered_slice
= g_ptr_array_new();
9069 static const value_string hf_display
[] = {
9070 { BASE_NONE
, "BASE_NONE" },
9071 { BASE_DEC
, "BASE_DEC" },
9072 { BASE_HEX
, "BASE_HEX" },
9073 { BASE_OCT
, "BASE_OCT" },
9074 { BASE_DEC_HEX
, "BASE_DEC_HEX" },
9075 { BASE_HEX_DEC
, "BASE_HEX_DEC" },
9076 { BASE_CUSTOM
, "BASE_CUSTOM" },
9077 { BASE_NONE
|BASE_RANGE_STRING
, "BASE_NONE|BASE_RANGE_STRING" },
9078 { BASE_DEC
|BASE_RANGE_STRING
, "BASE_DEC|BASE_RANGE_STRING" },
9079 { BASE_HEX
|BASE_RANGE_STRING
, "BASE_HEX|BASE_RANGE_STRING" },
9080 { BASE_OCT
|BASE_RANGE_STRING
, "BASE_OCT|BASE_RANGE_STRING" },
9081 { BASE_DEC_HEX
|BASE_RANGE_STRING
, "BASE_DEC_HEX|BASE_RANGE_STRING" },
9082 { BASE_HEX_DEC
|BASE_RANGE_STRING
, "BASE_HEX_DEC|BASE_RANGE_STRING" },
9083 { BASE_CUSTOM
|BASE_RANGE_STRING
, "BASE_CUSTOM|BASE_RANGE_STRING" },
9084 { BASE_NONE
|BASE_VAL64_STRING
, "BASE_NONE|BASE_VAL64_STRING" },
9085 { BASE_DEC
|BASE_VAL64_STRING
, "BASE_DEC|BASE_VAL64_STRING" },
9086 { BASE_HEX
|BASE_VAL64_STRING
, "BASE_HEX|BASE_VAL64_STRING" },
9087 { BASE_OCT
|BASE_VAL64_STRING
, "BASE_OCT|BASE_VAL64_STRING" },
9088 { BASE_DEC_HEX
|BASE_VAL64_STRING
, "BASE_DEC_HEX|BASE_VAL64_STRING" },
9089 { BASE_HEX_DEC
|BASE_VAL64_STRING
, "BASE_HEX_DEC|BASE_VAL64_STRING" },
9090 { BASE_CUSTOM
|BASE_VAL64_STRING
, "BASE_CUSTOM|BASE_VAL64_STRING" },
9091 { ABSOLUTE_TIME_LOCAL
, "ABSOLUTE_TIME_LOCAL" },
9092 { ABSOLUTE_TIME_UTC
, "ABSOLUTE_TIME_UTC" },
9093 { ABSOLUTE_TIME_DOY_UTC
, "ABSOLUTE_TIME_DOY_UTC" },
9094 { BASE_PT_UDP
, "BASE_PT_UDP" },
9095 { BASE_PT_TCP
, "BASE_PT_TCP" },
9096 { BASE_PT_DCCP
, "BASE_PT_DCCP" },
9097 { BASE_PT_SCTP
, "BASE_PT_SCTP" },
9098 { BASE_OUI
, "BASE_OUI" },
9101 const char* proto_field_display_to_string(int field_display
)
9103 return val_to_str_const(field_display
, hf_display
, "Unknown");
9106 static inline port_type
9107 display_to_port_type(field_display_e e
)
9124 /* temporary function containing assert part for easier profiling */
9126 tmp_fld_check_assert(header_field_info
*hfinfo
)
9130 /* The field must have a name (with length > 0) */
9131 if (!hfinfo
->name
|| !hfinfo
->name
[0]) {
9133 /* Try to identify the field */
9134 REPORT_DISSECTOR_BUG("Field (abbrev='%s') does not have a name",
9138 REPORT_DISSECTOR_BUG("Field does not have a name (nor an abbreviation)");
9141 /* fields with an empty string for an abbreviation aren't filterable */
9142 if (!hfinfo
->abbrev
|| !hfinfo
->abbrev
[0])
9143 REPORT_DISSECTOR_BUG("Field '%s' does not have an abbreviation", hfinfo
->name
);
9145 /* These types of fields are allowed to have value_strings,
9146 * true_false_strings or a protocol_t struct
9148 if (hfinfo
->strings
!= NULL
&& FIELD_DISPLAY(hfinfo
->display
) != BASE_CUSTOM
) {
9149 switch (hfinfo
->type
) {
9152 * These types are allowed to support display value_strings,
9153 * value64_strings, the extended versions of the previous
9154 * two, range strings, or unit strings.
9178 * This is allowed to have a value of type
9179 * enum ft_framenum_type to indicate what relationship
9180 * the frame in question has to the frame in which
9187 * These types are allowed to support only unit strings.
9191 if (!(hfinfo
->display
& BASE_UNIT_STRING
)) {
9192 REPORT_DISSECTOR_BUG("Field '%s' (%s) has a non-unit-strings 'strings' value but is of type %s"
9193 " (which is only allowed to have unit strings)",
9194 hfinfo
->name
, hfinfo
->abbrev
, ftype_name(hfinfo
->type
));
9199 * This type is only allowed to support a string if it's
9200 * a protocol (for pinos).
9203 if (!(hfinfo
->display
& BASE_PROTOCOL_INFO
)) {
9204 REPORT_DISSECTOR_BUG("Field '%s' (%s) has a non-protocol-info 'strings' value but is of type %s"
9205 " (which is only allowed to have protocol-info strings)",
9206 hfinfo
->name
, hfinfo
->abbrev
, ftype_name(hfinfo
->type
));
9211 REPORT_DISSECTOR_BUG("Field '%s' (%s) has a 'strings' value but is of type %s"
9212 " (which is not allowed to have strings)",
9213 hfinfo
->name
, hfinfo
->abbrev
, ftype_name(hfinfo
->type
));
9217 /* TODO: This check may slow down startup, and output quite a few warnings.
9218 It would be good to be able to enable this (and possibly other checks?)
9219 in non-release builds. */
9220 #ifdef ENABLE_CHECK_FILTER
9221 /* Check for duplicate value_string values.
9222 There are lots that have the same value *and* string, so for now only
9223 report those that have same value but different string. */
9224 if ((hfinfo
->strings
!= NULL
) &&
9225 !(hfinfo
->display
& BASE_RANGE_STRING
) &&
9226 !(hfinfo
->display
& BASE_UNIT_STRING
) &&
9227 !((hfinfo
->display
& FIELD_DISPLAY_E_MASK
) == BASE_CUSTOM
) &&
9229 (hfinfo
->type
== FT_CHAR
) ||
9230 (hfinfo
->type
== FT_UINT8
) ||
9231 (hfinfo
->type
== FT_UINT16
) ||
9232 (hfinfo
->type
== FT_UINT24
) ||
9233 (hfinfo
->type
== FT_UINT32
) ||
9234 (hfinfo
->type
== FT_INT8
) ||
9235 (hfinfo
->type
== FT_INT16
) ||
9236 (hfinfo
->type
== FT_INT24
) ||
9237 (hfinfo
->type
== FT_INT32
) )) {
9239 if (hfinfo
->display
& BASE_EXT_STRING
) {
9240 if (hfinfo
->display
& BASE_VAL64_STRING
) {
9241 const val64_string
*start_values
= VAL64_STRING_EXT_VS_P((const val64_string_ext
*)hfinfo
->strings
);
9242 CHECK_HF_VALUE(val64_string
, PRIu64
, start_values
);
9244 const value_string
*start_values
= VALUE_STRING_EXT_VS_P((const value_string_ext
*)hfinfo
->strings
);
9245 CHECK_HF_VALUE(value_string
, "u", start_values
);
9248 const value_string
*start_values
= (const value_string
*)hfinfo
->strings
;
9249 CHECK_HF_VALUE(value_string
, "u", start_values
);
9253 if (hfinfo
->type
== FT_BOOLEAN
) {
9254 const true_false_string
*tfs
= (const true_false_string
*)hfinfo
->strings
;
9256 if (strcmp(tfs
->false_string
, tfs
->true_string
) == 0) {
9257 ws_warning("Field '%s' (%s) has identical true and false strings (\"%s\", \"%s\")",
9258 hfinfo
->name
, hfinfo
->abbrev
,
9259 tfs
->false_string
, tfs
->true_string
);
9264 if (hfinfo
->display
& BASE_RANGE_STRING
) {
9265 const range_string
*rs
= (const range_string
*)(hfinfo
->strings
);
9267 const range_string
*this_it
= rs
;
9270 if (this_it
->value_max
< this_it
->value_min
) {
9271 ws_warning("value_range_string error: %s (%s) entry for \"%s\" - max(%"PRIu64
" 0x%"PRIx64
") is less than min(%"PRIu64
" 0x%"PRIx64
")",
9272 hfinfo
->name
, hfinfo
->abbrev
,
9274 this_it
->value_max
, this_it
->value_max
,
9275 this_it
->value_min
, this_it
->value_min
);
9280 for (const range_string
*prev_it
=rs
; prev_it
< this_it
; ++prev_it
) {
9281 /* Not OK if this one is completely hidden by an earlier one! */
9282 if ((prev_it
->value_min
<= this_it
->value_min
) && (prev_it
->value_max
>= this_it
->value_max
)) {
9283 ws_warning("value_range_string error: %s (%s) hidden by earlier entry "
9284 "(prev=\"%s\": %"PRIu64
" 0x%"PRIx64
" -> %"PRIu64
" 0x%"PRIx64
") (this=\"%s\": %"PRIu64
" 0x%"PRIx64
" -> %"PRIu64
" 0x%"PRIx64
")",
9285 hfinfo
->name
, hfinfo
->abbrev
,
9286 prev_it
->strptr
, prev_it
->value_min
, prev_it
->value_min
,
9287 prev_it
->value_max
, prev_it
->value_max
,
9288 this_it
->strptr
, this_it
->value_min
, this_it
->value_min
,
9289 this_it
->value_max
, this_it
->value_max
);
9293 } while (this_it
->strptr
);
9298 switch (hfinfo
->type
) {
9301 /* Require the char type to have BASE_HEX, BASE_OCT,
9302 * BASE_CUSTOM, or BASE_NONE as its base.
9304 * If the display value is BASE_NONE and there is a
9305 * strings conversion then the dissector writer is
9306 * telling us that the field's numerical value is
9307 * meaningless; we'll avoid showing the value to the
9310 switch (FIELD_DISPLAY(hfinfo
->display
)) {
9313 case BASE_CUSTOM
: /* hfinfo_numeric_value_format() treats this as decimal */
9316 if (hfinfo
->strings
== NULL
)
9317 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an integral value (%s)"
9318 " but is being displayed as BASE_NONE but"
9319 " without a strings conversion",
9320 hfinfo
->name
, hfinfo
->abbrev
,
9321 ftype_name(hfinfo
->type
));
9324 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Unknown: 0x%x)");
9325 REPORT_DISSECTOR_BUG("Field '%s' (%s) is a character value (%s)"
9326 " but is being displayed as %s",
9327 hfinfo
->name
, hfinfo
->abbrev
,
9328 ftype_name(hfinfo
->type
), tmp_str
);
9329 //wmem_free(NULL, tmp_str);
9331 if (hfinfo
->display
& BASE_UNIT_STRING
) {
9332 REPORT_DISSECTOR_BUG("Field '%s' (%s) is a character value (%s) but has a unit string",
9333 hfinfo
->name
, hfinfo
->abbrev
,
9334 ftype_name(hfinfo
->type
));
9345 /* Hexadecimal and octal are, in printf() and everywhere
9346 * else, unsigned so don't allow dissectors to register a
9347 * signed field to be displayed unsigned. (Else how would
9348 * we display negative values?)
9350 switch (FIELD_DISPLAY(hfinfo
->display
)) {
9355 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Bit count: %d)");
9356 REPORT_DISSECTOR_BUG("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)",
9357 hfinfo
->name
, hfinfo
->abbrev
,
9358 ftype_name(hfinfo
->type
), tmp_str
);
9359 //wmem_free(NULL, tmp_str);
9370 if (IS_BASE_PORT(hfinfo
->display
)) {
9371 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Unknown: 0x%x)");
9372 if (hfinfo
->type
!= FT_UINT16
) {
9373 REPORT_DISSECTOR_BUG("Field '%s' (%s) has 'display' value %s but it can only be used with FT_UINT16, not %s",
9374 hfinfo
->name
, hfinfo
->abbrev
,
9375 tmp_str
, ftype_name(hfinfo
->type
));
9377 if (hfinfo
->strings
!= NULL
) {
9378 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s (%s) but has a strings value",
9379 hfinfo
->name
, hfinfo
->abbrev
,
9380 ftype_name(hfinfo
->type
), tmp_str
);
9382 if (hfinfo
->bitmask
!= 0) {
9383 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s (%s) but has a bitmask",
9384 hfinfo
->name
, hfinfo
->abbrev
,
9385 ftype_name(hfinfo
->type
), tmp_str
);
9387 wmem_free(NULL
, tmp_str
);
9391 if (hfinfo
->display
== BASE_OUI
) {
9392 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Unknown: 0x%x)");
9393 if (hfinfo
->type
!= FT_UINT24
) {
9394 REPORT_DISSECTOR_BUG("Field '%s' (%s) has 'display' value %s but it can only be used with FT_UINT24, not %s",
9395 hfinfo
->name
, hfinfo
->abbrev
,
9396 tmp_str
, ftype_name(hfinfo
->type
));
9398 if (hfinfo
->strings
!= NULL
) {
9399 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s (%s) but has a strings value",
9400 hfinfo
->name
, hfinfo
->abbrev
,
9401 ftype_name(hfinfo
->type
), tmp_str
);
9403 if (hfinfo
->bitmask
!= 0) {
9404 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s (%s) but has a bitmask",
9405 hfinfo
->name
, hfinfo
->abbrev
,
9406 ftype_name(hfinfo
->type
), tmp_str
);
9408 wmem_free(NULL
, tmp_str
);
9412 /* Require integral types (other than frame number,
9413 * which is always displayed in decimal) to have a
9416 * If the display value is BASE_NONE and there is a
9417 * strings conversion then the dissector writer is
9418 * telling us that the field's numerical value is
9419 * meaningless; we'll avoid showing the value to the
9422 switch (FIELD_DISPLAY(hfinfo
->display
)) {
9428 case BASE_CUSTOM
: /* hfinfo_numeric_value_format() treats this as decimal */
9431 if (hfinfo
->strings
== NULL
) {
9432 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an integral value (%s)"
9433 " but is being displayed as BASE_NONE but"
9434 " without a strings conversion",
9435 hfinfo
->name
, hfinfo
->abbrev
,
9436 ftype_name(hfinfo
->type
));
9438 if (hfinfo
->display
& BASE_SPECIAL_VALS
) {
9439 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an integral value (%s)"
9440 " that is being displayed as BASE_NONE but"
9441 " with BASE_SPECIAL_VALS",
9442 hfinfo
->name
, hfinfo
->abbrev
,
9443 ftype_name(hfinfo
->type
));
9448 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Unknown: 0x%x)");
9449 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an integral value (%s)"
9450 " but is being displayed as %s",
9451 hfinfo
->name
, hfinfo
->abbrev
,
9452 ftype_name(hfinfo
->type
), tmp_str
);
9453 //wmem_free(NULL, tmp_str);
9458 /* Require bytes to have a "display type" that could
9459 * add a character between displayed bytes.
9461 switch (FIELD_DISPLAY(hfinfo
->display
)) {
9469 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Bit count: %d)");
9470 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",
9471 hfinfo
->name
, hfinfo
->abbrev
, tmp_str
);
9472 //wmem_free(NULL, tmp_str);
9474 if (hfinfo
->bitmask
!= 0)
9475 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9476 hfinfo
->name
, hfinfo
->abbrev
,
9477 ftype_name(hfinfo
->type
));
9478 //allowed to support string if its a protocol (for pinos)
9479 if ((hfinfo
->strings
!= NULL
) && (!(hfinfo
->display
& BASE_PROTOCOL_INFO
)))
9480 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a strings value",
9481 hfinfo
->name
, hfinfo
->abbrev
,
9482 ftype_name(hfinfo
->type
));
9487 if (hfinfo
->display
!= BASE_NONE
) {
9488 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Bit count: %d)");
9489 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE",
9490 hfinfo
->name
, hfinfo
->abbrev
,
9491 ftype_name(hfinfo
->type
), tmp_str
);
9492 //wmem_free(NULL, tmp_str);
9494 if (hfinfo
->bitmask
!= 0)
9495 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9496 hfinfo
->name
, hfinfo
->abbrev
,
9497 ftype_name(hfinfo
->type
));
9503 case FT_ABSOLUTE_TIME
:
9504 if (!FIELD_DISPLAY_IS_ABSOLUTE_TIME(hfinfo
->display
)) {
9505 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Bit count: %d)");
9506 REPORT_DISSECTOR_BUG("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time",
9507 hfinfo
->name
, hfinfo
->abbrev
, ftype_name(hfinfo
->type
), tmp_str
);
9508 //wmem_free(NULL, tmp_str);
9510 if (hfinfo
->bitmask
!= 0)
9511 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9512 hfinfo
->name
, hfinfo
->abbrev
,
9513 ftype_name(hfinfo
->type
));
9518 case FT_UINT_STRING
:
9520 case FT_STRINGZTRUNC
:
9521 switch (FIELD_DISPLAY(hfinfo
->display
)) {
9527 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Unknown: 0x%x)");
9528 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an string value (%s)"
9529 " but is being displayed as %s",
9530 hfinfo
->name
, hfinfo
->abbrev
,
9531 ftype_name(hfinfo
->type
), tmp_str
);
9532 //wmem_free(NULL, tmp_str);
9535 if (hfinfo
->bitmask
!= 0)
9536 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9537 hfinfo
->name
, hfinfo
->abbrev
,
9538 ftype_name(hfinfo
->type
));
9539 if (hfinfo
->strings
!= NULL
)
9540 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a strings value",
9541 hfinfo
->name
, hfinfo
->abbrev
,
9542 ftype_name(hfinfo
->type
));
9546 switch (hfinfo
->display
) {
9552 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Unknown: 0x%x)");
9553 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an IPv4 value (%s)"
9554 " but is being displayed as %s",
9555 hfinfo
->name
, hfinfo
->abbrev
,
9556 ftype_name(hfinfo
->type
), tmp_str
);
9557 //wmem_free(NULL, tmp_str);
9563 switch (FIELD_DISPLAY(hfinfo
->display
)) {
9571 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Unknown: 0x%x)");
9572 REPORT_DISSECTOR_BUG("Field '%s' (%s) is a float value (%s)"
9573 " but is being displayed as %s",
9574 hfinfo
->name
, hfinfo
->abbrev
,
9575 ftype_name(hfinfo
->type
), tmp_str
);
9576 //wmem_free(NULL, tmp_str);
9578 if (hfinfo
->bitmask
!= 0)
9579 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9580 hfinfo
->name
, hfinfo
->abbrev
,
9581 ftype_name(hfinfo
->type
));
9582 if (FIELD_DISPLAY(hfinfo
->display
) != BASE_CUSTOM
&& (hfinfo
->strings
!= NULL
) && !(hfinfo
->display
& BASE_UNIT_STRING
))
9583 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a strings value",
9584 hfinfo
->name
, hfinfo
->abbrev
,
9585 ftype_name(hfinfo
->type
));
9588 if (hfinfo
->display
!= BASE_NONE
) {
9589 tmp_str
= val_to_str_wmem(NULL
, hfinfo
->display
, hf_display
, "(Bit count: %d)");
9590 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE",
9591 hfinfo
->name
, hfinfo
->abbrev
,
9592 ftype_name(hfinfo
->type
),
9594 //wmem_free(NULL, tmp_str);
9596 if (hfinfo
->bitmask
!= 0)
9597 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9598 hfinfo
->name
, hfinfo
->abbrev
,
9599 ftype_name(hfinfo
->type
));
9600 if (hfinfo
->strings
!= NULL
)
9601 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a strings value",
9602 hfinfo
->name
, hfinfo
->abbrev
,
9603 ftype_name(hfinfo
->type
));
9609 register_type_length_mismatch(void)
9611 static ei_register_info ei
[] = {
9612 { &ei_type_length_mismatch_error
, { "_ws.type_length.mismatch", PI_MALFORMED
, PI_ERROR
, "Trying to fetch X with length Y", EXPFILL
}},
9613 { &ei_type_length_mismatch_warn
, { "_ws.type_length.mismatch", PI_MALFORMED
, PI_WARN
, "Trying to fetch X with length Y", EXPFILL
}},
9616 expert_module_t
* expert_type_length_mismatch
;
9618 proto_type_length_mismatch
= proto_register_protocol("Type Length Mismatch", "Type length mismatch", "_ws.type_length");
9620 expert_type_length_mismatch
= expert_register_protocol(proto_type_length_mismatch
);
9621 expert_register_field_array(expert_type_length_mismatch
, ei
, array_length(ei
));
9623 /* "Type Length Mismatch" isn't really a protocol, it's an error indication;
9624 disabling them makes no sense. */
9625 proto_set_cant_toggle(proto_type_length_mismatch
);
9629 register_byte_array_string_decodinws_error(void)
9631 static ei_register_info ei
[] = {
9632 { &ei_byte_array_string_decoding_failed_error
,
9633 { "_ws.byte_array_string.decoding_error.failed", PI_MALFORMED
, PI_ERROR
,
9634 "Failed to decode byte array from string", EXPFILL
9639 expert_module_t
* expert_byte_array_string_decoding_error
;
9641 proto_byte_array_string_decoding_error
=
9642 proto_register_protocol("Byte Array-String Decoding Error",
9643 "Byte Array-string decoding error",
9644 "_ws.byte_array_string.decoding_error");
9646 expert_byte_array_string_decoding_error
=
9647 expert_register_protocol(proto_byte_array_string_decoding_error
);
9648 expert_register_field_array(expert_byte_array_string_decoding_error
, ei
, array_length(ei
));
9650 /* "Byte Array-String Decoding Error" isn't really a protocol, it's an error indication;
9651 disabling them makes no sense. */
9652 proto_set_cant_toggle(proto_byte_array_string_decoding_error
);
9656 register_date_time_string_decodinws_error(void)
9658 static ei_register_info ei
[] = {
9659 { &ei_date_time_string_decoding_failed_error
,
9660 { "_ws.date_time_string.decoding_error.failed", PI_MALFORMED
, PI_ERROR
,
9661 "Failed to decode date and time from string", EXPFILL
9666 expert_module_t
* expert_date_time_string_decoding_error
;
9668 proto_date_time_string_decoding_error
=
9669 proto_register_protocol("Date and Time-String Decoding Error",
9670 "Date and Time-string decoding error",
9671 "_ws.date_time_string.decoding_error");
9673 expert_date_time_string_decoding_error
=
9674 expert_register_protocol(proto_date_time_string_decoding_error
);
9675 expert_register_field_array(expert_date_time_string_decoding_error
, ei
, array_length(ei
));
9677 /* "Date and Time-String Decoding Error" isn't really a protocol, it's an error indication;
9678 disabling them makes no sense. */
9679 proto_set_cant_toggle(proto_date_time_string_decoding_error
);
9683 register_string_errors(void)
9685 static ei_register_info ei
[] = {
9686 { &ei_string_trailing_characters
,
9687 { "_ws.string.trailing_stray_characters", PI_UNDECODED
, PI_WARN
, "Trailing stray characters", EXPFILL
}
9691 expert_module_t
* expert_string_errors
;
9693 proto_string_errors
= proto_register_protocol("String Errors", "String errors", "_ws.string");
9695 expert_string_errors
= expert_register_protocol(proto_string_errors
);
9696 expert_register_field_array(expert_string_errors
, ei
, array_length(ei
));
9698 /* "String Errors" isn't really a protocol, it's an error indication;
9699 disabling them makes no sense. */
9700 proto_set_cant_toggle(proto_string_errors
);
9703 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM (300000+PRE_ALLOC_EXPERT_FIELDS_MEM)
9705 proto_register_field_init(header_field_info
*hfinfo
, const int parent
)
9708 tmp_fld_check_assert(hfinfo
);
9710 hfinfo
->parent
= parent
;
9711 hfinfo
->same_name_next
= NULL
;
9712 hfinfo
->same_name_prev_id
= -1;
9714 /* if we always add and never delete, then id == len - 1 is correct */
9715 if (gpa_hfinfo
.len
>= gpa_hfinfo
.allocated_len
) {
9716 if (!gpa_hfinfo
.hfi
) {
9717 gpa_hfinfo
.allocated_len
= PROTO_PRE_ALLOC_HF_FIELDS_MEM
;
9718 gpa_hfinfo
.hfi
= (header_field_info
**)g_malloc(sizeof(header_field_info
*)*PROTO_PRE_ALLOC_HF_FIELDS_MEM
);
9719 /* The entry with index 0 is not used. */
9720 gpa_hfinfo
.hfi
[0] = NULL
;
9723 gpa_hfinfo
.allocated_len
+= 1000;
9724 gpa_hfinfo
.hfi
= (header_field_info
**)g_realloc(gpa_hfinfo
.hfi
,
9725 sizeof(header_field_info
*)*gpa_hfinfo
.allocated_len
);
9726 /*ws_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
9729 gpa_hfinfo
.hfi
[gpa_hfinfo
.len
] = hfinfo
;
9731 hfinfo
->id
= gpa_hfinfo
.len
- 1;
9733 /* if we have real names, enter this field in the name tree */
9734 if ((hfinfo
->name
[0] != 0) && (hfinfo
->abbrev
[0] != 0 )) {
9736 header_field_info
*same_name_next_hfinfo
;
9739 /* Check that the filter name (abbreviation) is legal;
9740 * it must contain only alphanumerics, '-', "_", and ".". */
9741 c
= proto_check_field_name(hfinfo
->abbrev
);
9744 REPORT_DISSECTOR_BUG("Invalid leading, duplicated or trailing '.' found in filter name '%s'", hfinfo
->abbrev
);
9745 } else if (g_ascii_isprint(c
)) {
9746 REPORT_DISSECTOR_BUG("Invalid character '%c' in filter name '%s'", c
, hfinfo
->abbrev
);
9748 REPORT_DISSECTOR_BUG("Invalid byte \\%03o in filter name '%s'", c
, hfinfo
->abbrev
);
9752 /* We allow multiple hfinfo's to be registered under the same
9753 * abbreviation. This was done for X.25, as, depending
9754 * on whether it's modulo-8 or modulo-128 operation,
9755 * some bitfield fields may be in different bits of
9756 * a byte, and we want to be able to refer to that field
9757 * with one name regardless of whether the packets
9758 * are modulo-8 or modulo-128 packets. */
9760 same_name_hfinfo
= NULL
;
9762 g_hash_table_insert(gpa_name_map
, (void *) (hfinfo
->abbrev
), hfinfo
);
9763 /* GLIB 2.x - if it is already present
9764 * the previous hfinfo with the same name is saved
9765 * to same_name_hfinfo by value destroy callback */
9766 if (same_name_hfinfo
) {
9767 /* There's already a field with this name.
9768 * Put the current field *before* that field
9769 * in the list of fields with this name, Thus,
9770 * we end up with an effectively
9771 * doubly-linked-list of same-named hfinfo's,
9772 * with the head of the list (stored in the
9773 * hash) being the last seen hfinfo.
9775 same_name_next_hfinfo
=
9776 same_name_hfinfo
->same_name_next
;
9778 hfinfo
->same_name_next
= same_name_next_hfinfo
;
9779 if (same_name_next_hfinfo
)
9780 same_name_next_hfinfo
->same_name_prev_id
= hfinfo
->id
;
9782 same_name_hfinfo
->same_name_next
= hfinfo
;
9783 hfinfo
->same_name_prev_id
= same_name_hfinfo
->id
;
9784 #ifdef ENABLE_CHECK_FILTER
9785 while (same_name_hfinfo
) {
9786 if (!ftype_similar_types(hfinfo
->type
, same_name_hfinfo
->type
))
9787 ws_warning("'%s' exists multiple times with incompatible types: %s and %s", hfinfo
->abbrev
, ftype_name(hfinfo
->type
), ftype_name(same_name_hfinfo
->type
));
9788 same_name_hfinfo
= same_name_hfinfo
->same_name_next
;
9798 proto_register_subtree_array(int * const *indices
, const int num_indices
)
9801 int *const *ptr
= indices
;
9804 * If we've already allocated the array of tree types, expand
9805 * it; this lets plugins such as mate add tree types after
9806 * the initial startup. (If we haven't already allocated it,
9807 * we don't allocate it; on the first pass, we just assign
9808 * ett values and keep track of how many we've assigned, and
9809 * when we're finished registering all dissectors we allocate
9810 * the array, so that we do only one allocation rather than
9811 * wasting CPU time and memory by growing the array for each
9812 * dissector that registers ett values.)
9814 if (tree_is_expanded
!= NULL
) {
9815 tree_is_expanded
= (uint32_t *)g_realloc(tree_is_expanded
, (1+((num_tree_types
+ num_indices
)/32)) * sizeof(uint32_t));
9817 /* set new items to 0 */
9818 /* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of uint32_t to 0) */
9819 for (i
= num_tree_types
; i
< num_tree_types
+ num_indices
; i
++)
9820 tree_is_expanded
[i
>> 5] &= ~(1U << (i
& 31));
9824 * Assign "num_indices" subtree numbers starting at "num_tree_types",
9825 * returning the indices through the pointers in the array whose
9826 * first element is pointed to by "indices", and update
9827 * "num_tree_types" appropriately.
9829 for (i
= 0; i
< num_indices
; i
++, ptr
++, num_tree_types
++) {
9830 if (**ptr
!= -1 && **ptr
!= 0) {
9831 REPORT_DISSECTOR_BUG("register_subtree_array: subtree item type (ett_...) not -1 or 0 !"
9832 " This is a development error:"
9833 " Either the subtree item type has already been assigned or"
9834 " was not initialized to -1 or 0.");
9836 **ptr
= num_tree_types
;
9841 mark_truncated(char *label_str
, size_t name_pos
, const size_t size
, size_t *value_pos
)
9843 static const char trunc_str
[] = " [" UTF8_HORIZONTAL_ELLIPSIS
"]";
9844 const size_t trunc_len
= sizeof(trunc_str
)-1;
9847 /* ..... field_name: dataaaaaaaaaaaaa
9851 * ..... field_name […]: dataaaaaaaaaaaaa
9853 * name_pos==0 means that we have only data or only a field_name
9856 if (name_pos
< size
- trunc_len
) {
9857 memmove(label_str
+ name_pos
+ trunc_len
, label_str
+ name_pos
, size
- name_pos
- trunc_len
);
9858 memcpy(label_str
+ name_pos
, trunc_str
, trunc_len
);
9860 /* in general, label_str is UTF-8
9861 we can truncate it only at the beginning of a new character
9862 we go backwards from the byte right after our buffer and
9863 find the next starting byte of a UTF-8 character, this is
9865 there's no need to use g_utf8_find_prev_char(), the search
9866 will always succeed since we copied trunc_str into the
9868 /* g_utf8_prev_char does not deference the memory address
9869 * passed in (until after decrementing it, so it is perfectly
9870 * legal to pass in a pointer one past the last element.
9872 last_char
= g_utf8_prev_char(label_str
+ size
);
9875 if (value_pos
&& *value_pos
> 0) {
9876 if (name_pos
== 0) {
9877 *value_pos
+= trunc_len
;
9879 /* Move one back to include trunc_str in the value. */
9883 } else if (name_pos
< size
)
9884 (void) g_strlcpy(label_str
+ name_pos
, trunc_str
, size
- name_pos
);
9888 label_mark_truncated(char *label_str
, size_t name_pos
, size_t *value_pos
)
9890 mark_truncated(label_str
, name_pos
, ITEM_LABEL_LENGTH
, value_pos
);
9894 label_fill(char *label_str
, size_t pos
, const header_field_info
*hfinfo
, const char *text
, size_t *value_pos
)
9898 /* "%s: %s", hfinfo->name, text */
9899 name_pos
= pos
= label_concat(label_str
, pos
, hfinfo
->name
);
9900 if (!(hfinfo
->display
& BASE_NO_DISPLAY_VALUE
)) {
9901 pos
= label_concat(label_str
, pos
, ": ");
9905 pos
= ws_label_strcpy(label_str
, ITEM_LABEL_LENGTH
, pos
, text
? text
: "(null)", label_strcat_flags(hfinfo
));
9908 if (pos
>= ITEM_LABEL_LENGTH
) {
9909 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
9910 label_mark_truncated(label_str
, name_pos
, value_pos
);
9917 label_fill_descr(char *label_str
, size_t pos
, const header_field_info
*hfinfo
, const char *text
, const char *descr
, size_t *value_pos
)
9921 /* "%s: %s (%s)", hfinfo->name, text, descr */
9922 name_pos
= pos
= label_concat(label_str
, pos
, hfinfo
->name
);
9923 if (!(hfinfo
->display
& BASE_NO_DISPLAY_VALUE
)) {
9924 pos
= label_concat(label_str
, pos
, ": ");
9928 if (hfinfo
->display
& BASE_UNIT_STRING
) {
9929 pos
= label_concat(label_str
, pos
, descr
? descr
: "(null)");
9930 pos
= label_concat(label_str
, pos
, text
? text
: "(null)");
9932 pos
= label_concat(label_str
, pos
, text
? text
: "(null)");
9933 pos
= label_concat(label_str
, pos
, " (");
9934 pos
= label_concat(label_str
, pos
, descr
? descr
: "(null)");
9935 pos
= label_concat(label_str
, pos
, ")");
9939 if (pos
>= ITEM_LABEL_LENGTH
) {
9940 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
9941 label_mark_truncated(label_str
, name_pos
, value_pos
);
9948 proto_item_fill_label(const field_info
*fi
, char *label_str
, size_t *value_pos
)
9950 const header_field_info
*hfinfo
;
9952 const uint8_t *bytes
;
9955 const ipv4_addr_and_mask
*ipv4
;
9956 const ipv6_addr_and_prefix
*ipv6
;
9957 const e_guid_t
*guid
;
9964 ws_warning("NULL label_str passed to proto_item_fill_label.");
9974 hfinfo
= fi
->hfinfo
;
9976 switch (hfinfo
->type
) {
9979 (void) g_strlcpy(label_str
, hfinfo
->name
, ITEM_LABEL_LENGTH
);
9981 *value_pos
= strlen(hfinfo
->name
);
9986 fill_label_boolean(fi
, label_str
, value_pos
);
9991 tmp
= format_bytes_hfinfo(NULL
, hfinfo
,
9992 fvalue_get_bytes_data(fi
->value
),
9993 (unsigned)fvalue_length2(fi
->value
));
9994 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
9995 wmem_free(NULL
, tmp
);
9999 if (hfinfo
->bitmask
) {
10000 fill_label_bitfield_char(fi
, label_str
, value_pos
);
10002 fill_label_char(fi
, label_str
, value_pos
);
10006 /* Four types of integers to take care of:
10007 * Bitfield, with val_string
10008 * Bitfield, w/o val_string
10009 * Non-bitfield, with val_string
10010 * Non-bitfield, w/o val_string
10016 if (hfinfo
->bitmask
) {
10017 fill_label_bitfield(fi
, label_str
, value_pos
, false);
10019 fill_label_number(fi
, label_str
, value_pos
, false);
10024 fill_label_number(fi
, label_str
, value_pos
, false);
10031 if (hfinfo
->bitmask
) {
10032 fill_label_bitfield64(fi
, label_str
, value_pos
, false);
10034 fill_label_number64(fi
, label_str
, value_pos
, false);
10042 if (hfinfo
->bitmask
) {
10043 fill_label_bitfield(fi
, label_str
, value_pos
, true);
10045 fill_label_number(fi
, label_str
, value_pos
, true);
10053 if (hfinfo
->bitmask
) {
10054 fill_label_bitfield64(fi
, label_str
, value_pos
, true);
10056 fill_label_number64(fi
, label_str
, value_pos
, true);
10062 fill_label_float(fi
, label_str
, value_pos
);
10065 case FT_ABSOLUTE_TIME
:
10067 int flags
= ABS_TIME_TO_STR_SHOW_ZONE
;
10068 if (prefs
.display_abs_time_ascii
< ABS_TIME_ASCII_TREE
) {
10069 flags
|= ABS_TIME_TO_STR_ISO8601
;
10071 tmp
= abs_time_to_str_ex(NULL
, fvalue_get_time(fi
->value
), hfinfo
->display
, flags
);
10072 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10073 wmem_free(NULL
, tmp
);
10076 case FT_RELATIVE_TIME
:
10077 tmp
= rel_time_to_str(NULL
, fvalue_get_time(fi
->value
));
10078 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10079 wmem_free(NULL
, tmp
);
10083 integer
= fvalue_get_uinteger(fi
->value
);
10084 tmp
= get_ipxnet_name(NULL
, integer
);
10085 addr_str
= wmem_strdup_printf(NULL
, "0x%08X", integer
);
10086 label_fill_descr(label_str
, 0, hfinfo
, tmp
, addr_str
, value_pos
);
10087 wmem_free(NULL
, tmp
);
10088 wmem_free(NULL
, addr_str
);
10092 addr
.type
= AT_VINES
;
10093 addr
.len
= VINES_ADDR_LEN
;
10094 addr
.data
= fvalue_get_bytes_data(fi
->value
);
10096 addr_str
= (char*)address_to_str(NULL
, &addr
);
10097 label_fill(label_str
, 0, hfinfo
, addr_str
, value_pos
);
10098 wmem_free(NULL
, addr_str
);
10102 bytes
= fvalue_get_bytes_data(fi
->value
);
10104 addr
.type
= AT_ETHER
;
10108 addr_str
= (char*)address_with_resolution_to_str(NULL
, &addr
);
10109 label_fill(label_str
, 0, hfinfo
, addr_str
, value_pos
);
10110 wmem_free(NULL
, addr_str
);
10114 ipv4
= fvalue_get_ipv4(fi
->value
);
10115 set_address_ipv4(&addr
, ipv4
);
10117 if (hfinfo
->display
== BASE_NETMASK
) {
10118 addr_str
= (char*)address_to_str(NULL
, &addr
);
10120 addr_str
= (char*)address_with_resolution_to_str(NULL
, &addr
);
10122 label_fill(label_str
, 0, hfinfo
, addr_str
, value_pos
);
10123 wmem_free(NULL
, addr_str
);
10124 free_address(&addr
);
10128 ipv6
= fvalue_get_ipv6(fi
->value
);
10129 set_address_ipv6(&addr
, ipv6
);
10131 addr_str
= (char*)address_with_resolution_to_str(NULL
, &addr
);
10132 label_fill(label_str
, 0, hfinfo
, addr_str
, value_pos
);
10133 wmem_free(NULL
, addr_str
);
10134 free_address(&addr
);
10138 bytes
= fvalue_get_bytes_data(fi
->value
);
10139 addr
.type
= AT_FCWWN
;
10140 addr
.len
= FCWWN_ADDR_LEN
;
10143 addr_str
= (char*)address_with_resolution_to_str(NULL
, &addr
);
10144 label_fill(label_str
, 0, hfinfo
, addr_str
, value_pos
);
10145 wmem_free(NULL
, addr_str
);
10149 guid
= fvalue_get_guid(fi
->value
);
10150 tmp
= guid_to_str(NULL
, guid
);
10151 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10152 wmem_free(NULL
, tmp
);
10156 bytes
= fvalue_get_bytes_data(fi
->value
);
10157 name
= oid_resolved_from_encoded(NULL
, bytes
, (int)fvalue_length2(fi
->value
));
10158 tmp
= oid_encoded2string(NULL
, bytes
, (unsigned)fvalue_length2(fi
->value
));
10160 label_fill_descr(label_str
, 0, hfinfo
, tmp
, name
, value_pos
);
10161 wmem_free(NULL
, name
);
10163 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10165 wmem_free(NULL
, tmp
);
10169 bytes
= fvalue_get_bytes_data(fi
->value
);
10170 name
= rel_oid_resolved_from_encoded(NULL
, bytes
, (int)fvalue_length2(fi
->value
));
10171 tmp
= rel_oid_encoded2string(NULL
, bytes
, (unsigned)fvalue_length2(fi
->value
));
10173 label_fill_descr(label_str
, 0, hfinfo
, tmp
, name
, value_pos
);
10174 wmem_free(NULL
, name
);
10176 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10178 wmem_free(NULL
, tmp
);
10182 bytes
= fvalue_get_bytes_data(fi
->value
);
10183 tmp
= print_system_id(NULL
, bytes
, (int)fvalue_length2(fi
->value
));
10184 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10185 wmem_free(NULL
, tmp
);
10189 integer64
= fvalue_get_uinteger64(fi
->value
);
10190 addr_str
= eui64_to_str(NULL
, integer64
);
10191 tmp
= (char*)eui64_to_display(NULL
, integer64
);
10192 label_fill_descr(label_str
, 0, hfinfo
, tmp
, addr_str
, value_pos
);
10193 wmem_free(NULL
, tmp
);
10194 wmem_free(NULL
, addr_str
);
10198 case FT_UINT_STRING
:
10199 case FT_STRINGZPAD
:
10200 case FT_STRINGZTRUNC
:
10202 str
= fvalue_get_string(fi
->value
);
10203 label_fill(label_str
, 0, hfinfo
, str
, value_pos
);
10206 case FT_IEEE_11073_SFLOAT
:
10207 case FT_IEEE_11073_FLOAT
:
10208 tmp
= fvalue_to_string_repr(NULL
, fi
->value
, FTREPR_DISPLAY
, hfinfo
->display
);
10209 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10210 wmem_free(NULL
, tmp
);
10214 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_item_fill_label()",
10217 ftype_name(hfinfo
->type
));
10223 fill_label_boolean(const field_info
*fi
, char *label_str
, size_t *value_pos
)
10226 int bitfield_byte_length
= 0, bitwidth
;
10227 uint64_t unshifted_value
;
10230 const header_field_info
*hfinfo
= fi
->hfinfo
;
10232 value
= fvalue_get_uinteger64(fi
->value
);
10233 if (hfinfo
->bitmask
) {
10234 /* Figure out the bit width */
10235 bitwidth
= hfinfo_container_bitwidth(hfinfo
);
10237 /* Un-shift bits */
10238 unshifted_value
= value
;
10239 unshifted_value
<<= hfinfo_bitshift(hfinfo
);
10241 /* Create the bitfield first */
10242 p
= decode_bitfield_value(label_str
, unshifted_value
, hfinfo
->bitmask
, bitwidth
);
10243 bitfield_byte_length
= (int) (p
- label_str
);
10246 /* Fill in the textual info */
10247 label_fill(label_str
, bitfield_byte_length
, hfinfo
, tfs_get_string(!!value
, hfinfo
->strings
), value_pos
);
10250 static const char *
10251 hf_try_val_to_str(uint32_t value
, const header_field_info
*hfinfo
)
10253 if (hfinfo
->display
& BASE_RANGE_STRING
)
10254 return try_rval_to_str(value
, (const range_string
*) hfinfo
->strings
);
10256 if (hfinfo
->display
& BASE_EXT_STRING
) {
10257 if (hfinfo
->display
& BASE_VAL64_STRING
)
10258 return try_val64_to_str_ext(value
, (val64_string_ext
*) hfinfo
->strings
);
10260 return try_val_to_str_ext(value
, (value_string_ext
*) hfinfo
->strings
);
10263 if (hfinfo
->display
& BASE_VAL64_STRING
)
10264 return try_val64_to_str(value
, (const val64_string
*) hfinfo
->strings
);
10266 if (hfinfo
->display
& BASE_UNIT_STRING
)
10267 return unit_name_string_get_value(value
, (const struct unit_name_string
*) hfinfo
->strings
);
10269 return try_val_to_str(value
, (const value_string
*) hfinfo
->strings
);
10272 static const char *
10273 hf_try_val64_to_str(uint64_t value
, const header_field_info
*hfinfo
)
10275 if (hfinfo
->display
& BASE_VAL64_STRING
) {
10276 if (hfinfo
->display
& BASE_EXT_STRING
)
10277 return try_val64_to_str_ext(value
, (val64_string_ext
*) hfinfo
->strings
);
10279 return try_val64_to_str(value
, (const val64_string
*) hfinfo
->strings
);
10282 if (hfinfo
->display
& BASE_RANGE_STRING
)
10283 return try_rval64_to_str(value
, (const range_string
*) hfinfo
->strings
);
10285 if (hfinfo
->display
& BASE_UNIT_STRING
)
10286 return unit_name_string_get_value64(value
, (const struct unit_name_string
*) hfinfo
->strings
);
10288 /* If this is reached somebody registered a 64-bit field with a 32-bit
10289 * value-string, which isn't right. */
10290 REPORT_DISSECTOR_BUG("field %s is a 64-bit field with a 32-bit value_string",
10293 /* This is necessary to squelch MSVC errors; is there
10294 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
10299 static const char *
10300 hf_try_double_val_to_str(double value
, const header_field_info
*hfinfo
)
10302 if (hfinfo
->display
& BASE_UNIT_STRING
)
10303 return unit_name_string_get_double(value
, (const struct unit_name_string
*)hfinfo
->strings
);
10305 REPORT_DISSECTOR_BUG("field %s (FT_DOUBLE) has no base_unit_string", hfinfo
->abbrev
);
10307 /* This is necessary to squelch MSVC errors; is there
10308 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
10313 static const char *
10314 hf_try_val_to_str_const(uint32_t value
, const header_field_info
*hfinfo
, const char *unknown_str
)
10316 const char *str
= hf_try_val_to_str(value
, hfinfo
);
10318 return (str
) ? str
: unknown_str
;
10321 static const char *
10322 hf_try_val64_to_str_const(uint64_t value
, const header_field_info
*hfinfo
, const char *unknown_str
)
10324 const char *str
= hf_try_val64_to_str(value
, hfinfo
);
10326 return (str
) ? str
: unknown_str
;
10329 /* Fills data for bitfield chars with val_strings */
10331 fill_label_bitfield_char(const field_info
*fi
, char *label_str
, size_t *value_pos
)
10334 int bitfield_byte_length
, bitwidth
;
10335 uint32_t unshifted_value
;
10341 const header_field_info
*hfinfo
= fi
->hfinfo
;
10343 /* Figure out the bit width */
10344 bitwidth
= hfinfo_container_bitwidth(hfinfo
);
10346 /* Un-shift bits */
10347 value
= fvalue_get_uinteger(fi
->value
);
10349 unshifted_value
= value
;
10350 if (hfinfo
->bitmask
) {
10351 unshifted_value
<<= hfinfo_bitshift(hfinfo
);
10354 /* Create the bitfield first */
10355 p
= decode_bitfield_value(label_str
, unshifted_value
, hfinfo
->bitmask
, bitwidth
);
10356 bitfield_byte_length
= (int) (p
- label_str
);
10358 /* Fill in the textual info using stored (shifted) value */
10359 if (hfinfo
->display
== BASE_CUSTOM
) {
10360 char tmp
[ITEM_LABEL_LENGTH
];
10361 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hfinfo
->strings
;
10363 DISSECTOR_ASSERT(fmtfunc
);
10364 fmtfunc(tmp
, value
);
10365 label_fill(label_str
, bitfield_byte_length
, hfinfo
, tmp
, value_pos
);
10367 else if (hfinfo
->strings
) {
10368 const char *val_str
= hf_try_val_to_str_const(value
, hfinfo
, "Unknown");
10370 out
= hfinfo_char_vals_format(hfinfo
, buf
, value
);
10371 if (out
== NULL
) /* BASE_NONE so don't put integer in descr */
10372 label_fill(label_str
, bitfield_byte_length
, hfinfo
, val_str
, value_pos
);
10374 label_fill_descr(label_str
, bitfield_byte_length
, hfinfo
, val_str
, out
, value_pos
);
10377 out
= hfinfo_char_value_format(hfinfo
, buf
, value
);
10379 label_fill(label_str
, bitfield_byte_length
, hfinfo
, out
, value_pos
);
10383 /* Fills data for bitfield ints with val_strings */
10385 fill_label_bitfield(const field_info
*fi
, char *label_str
, size_t *value_pos
, bool is_signed
)
10388 int bitfield_byte_length
, bitwidth
;
10389 uint32_t value
, unshifted_value
;
10390 char buf
[NUMBER_LABEL_LENGTH
];
10393 const header_field_info
*hfinfo
= fi
->hfinfo
;
10395 /* Figure out the bit width */
10396 if (fi
->flags
& FI_VARINT
)
10397 bitwidth
= fi
->length
*8;
10399 bitwidth
= hfinfo_container_bitwidth(hfinfo
);
10401 /* Un-shift bits */
10403 value
= fvalue_get_sinteger(fi
->value
);
10405 value
= fvalue_get_uinteger(fi
->value
);
10407 unshifted_value
= value
;
10408 if (hfinfo
->bitmask
) {
10409 unshifted_value
<<= hfinfo_bitshift(hfinfo
);
10412 /* Create the bitfield first */
10413 if (fi
->flags
& FI_VARINT
)
10414 p
= decode_bitfield_varint_value(label_str
, unshifted_value
, hfinfo
->bitmask
, bitwidth
);
10416 p
= decode_bitfield_value(label_str
, unshifted_value
, hfinfo
->bitmask
, bitwidth
);
10417 bitfield_byte_length
= (int) (p
- label_str
);
10419 /* Fill in the textual info using stored (shifted) value */
10420 if (hfinfo
->display
== BASE_CUSTOM
) {
10421 char tmp
[ITEM_LABEL_LENGTH
];
10422 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hfinfo
->strings
;
10424 DISSECTOR_ASSERT(fmtfunc
);
10425 fmtfunc(tmp
, value
);
10426 label_fill(label_str
, bitfield_byte_length
, hfinfo
, tmp
, value_pos
);
10428 else if (hfinfo
->strings
) {
10429 const char *val_str
= hf_try_val_to_str(value
, hfinfo
);
10431 out
= hfinfo_number_vals_format(hfinfo
, buf
, value
);
10432 if (hfinfo
->display
& BASE_SPECIAL_VALS
) {
10434 * Unique values only display value_string string
10435 * if there is a match. Otherwise it's just a number
10438 label_fill_descr(label_str
, bitfield_byte_length
, hfinfo
, val_str
, out
, value_pos
);
10440 label_fill(label_str
, bitfield_byte_length
, hfinfo
, out
, value_pos
);
10443 if (val_str
== NULL
)
10444 val_str
= "Unknown";
10446 if (out
== NULL
) /* BASE_NONE so don't put integer in descr */
10447 label_fill(label_str
, bitfield_byte_length
, hfinfo
, val_str
, value_pos
);
10449 label_fill_descr(label_str
, bitfield_byte_length
, hfinfo
, val_str
, out
, value_pos
);
10453 out
= hfinfo_number_value_format(hfinfo
, buf
, value
);
10455 label_fill(label_str
, bitfield_byte_length
, hfinfo
, out
, value_pos
);
10460 fill_label_bitfield64(const field_info
*fi
, char *label_str
, size_t *value_pos
, bool is_signed
)
10463 int bitfield_byte_length
, bitwidth
;
10464 uint64_t value
, unshifted_value
;
10465 char buf
[NUMBER_LABEL_LENGTH
];
10468 const header_field_info
*hfinfo
= fi
->hfinfo
;
10470 /* Figure out the bit width */
10471 if (fi
->flags
& FI_VARINT
)
10472 bitwidth
= fi
->length
*8;
10474 bitwidth
= hfinfo_container_bitwidth(hfinfo
);
10476 /* Un-shift bits */
10478 value
= fvalue_get_sinteger64(fi
->value
);
10480 value
= fvalue_get_uinteger64(fi
->value
);
10482 unshifted_value
= value
;
10483 if (hfinfo
->bitmask
) {
10484 unshifted_value
<<= hfinfo_bitshift(hfinfo
);
10487 /* Create the bitfield first */
10488 if (fi
->flags
& FI_VARINT
)
10489 p
= decode_bitfield_varint_value(label_str
, unshifted_value
, hfinfo
->bitmask
, bitwidth
);
10491 p
= decode_bitfield_value(label_str
, unshifted_value
, hfinfo
->bitmask
, bitwidth
);
10492 bitfield_byte_length
= (int) (p
- label_str
);
10494 /* Fill in the textual info using stored (shifted) value */
10495 if (hfinfo
->display
== BASE_CUSTOM
) {
10496 char tmp
[ITEM_LABEL_LENGTH
];
10497 const custom_fmt_func_64_t fmtfunc64
= (const custom_fmt_func_64_t
)hfinfo
->strings
;
10499 DISSECTOR_ASSERT(fmtfunc64
);
10500 fmtfunc64(tmp
, value
);
10501 label_fill(label_str
, bitfield_byte_length
, hfinfo
, tmp
, value_pos
);
10503 else if (hfinfo
->strings
) {
10504 const char *val_str
= hf_try_val64_to_str(value
, hfinfo
);
10506 out
= hfinfo_number_vals_format64(hfinfo
, buf
, value
);
10507 if (hfinfo
->display
& BASE_SPECIAL_VALS
) {
10509 * Unique values only display value_string string
10510 * if there is a match. Otherwise it's just a number
10513 label_fill_descr(label_str
, bitfield_byte_length
, hfinfo
, val_str
, out
, value_pos
);
10515 label_fill(label_str
, bitfield_byte_length
, hfinfo
, out
, value_pos
);
10518 if (val_str
== NULL
)
10519 val_str
= "Unknown";
10521 if (out
== NULL
) /* BASE_NONE so don't put integer in descr */
10522 label_fill(label_str
, bitfield_byte_length
, hfinfo
, val_str
, value_pos
);
10524 label_fill_descr(label_str
, bitfield_byte_length
, hfinfo
, val_str
, out
, value_pos
);
10528 out
= hfinfo_number_value_format64(hfinfo
, buf
, value
);
10530 label_fill(label_str
, bitfield_byte_length
, hfinfo
, out
, value_pos
);
10535 fill_label_char(const field_info
*fi
, char *label_str
, size_t *value_pos
)
10537 const header_field_info
*hfinfo
= fi
->hfinfo
;
10543 value
= fvalue_get_uinteger(fi
->value
);
10545 /* Fill in the textual info */
10546 if (hfinfo
->display
== BASE_CUSTOM
) {
10547 char tmp
[ITEM_LABEL_LENGTH
];
10548 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hfinfo
->strings
;
10550 DISSECTOR_ASSERT(fmtfunc
);
10551 fmtfunc(tmp
, value
);
10552 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10554 else if (hfinfo
->strings
) {
10555 const char *val_str
= hf_try_val_to_str_const(value
, hfinfo
, "Unknown");
10557 out
= hfinfo_char_vals_format(hfinfo
, buf
, value
);
10558 label_fill_descr(label_str
, 0, hfinfo
, val_str
, out
, value_pos
);
10561 out
= hfinfo_char_value_format(hfinfo
, buf
, value
);
10563 label_fill(label_str
, 0, hfinfo
, out
, value_pos
);
10568 fill_label_number(const field_info
*fi
, char *label_str
, size_t *value_pos
, bool is_signed
)
10570 const header_field_info
*hfinfo
= fi
->hfinfo
;
10573 char buf
[NUMBER_LABEL_LENGTH
];
10577 value
= fvalue_get_sinteger(fi
->value
);
10579 value
= fvalue_get_uinteger(fi
->value
);
10581 /* Fill in the textual info */
10582 if (hfinfo
->display
== BASE_CUSTOM
) {
10583 char tmp
[ITEM_LABEL_LENGTH
];
10584 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hfinfo
->strings
;
10586 DISSECTOR_ASSERT(fmtfunc
);
10587 fmtfunc(tmp
, value
);
10588 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10590 else if (hfinfo
->strings
&& hfinfo
->type
!= FT_FRAMENUM
) {
10592 * It makes no sense to have a value-string table for a
10593 * frame-number field - they're just integers giving
10594 * the ordinal frame number.
10596 const char *val_str
= hf_try_val_to_str(value
, hfinfo
);
10598 out
= hfinfo_number_vals_format(hfinfo
, buf
, value
);
10599 if (hfinfo
->display
& BASE_SPECIAL_VALS
) {
10601 * Unique values only display value_string string
10602 * if there is a match. Otherwise it's just a number
10605 label_fill_descr(label_str
, 0, hfinfo
, val_str
, out
, value_pos
);
10607 label_fill(label_str
, 0, hfinfo
, out
, value_pos
);
10610 if (val_str
== NULL
)
10611 val_str
= "Unknown";
10613 if (out
== NULL
) /* BASE_NONE so don't put integer in descr */
10614 label_fill(label_str
, 0, hfinfo
, val_str
, value_pos
);
10616 label_fill_descr(label_str
, 0, hfinfo
, val_str
, out
, value_pos
);
10619 else if (IS_BASE_PORT(hfinfo
->display
)) {
10620 char tmp
[ITEM_LABEL_LENGTH
];
10622 port_with_resolution_to_str_buf(tmp
, sizeof(tmp
),
10623 display_to_port_type((field_display_e
)hfinfo
->display
), value
);
10624 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10627 out
= hfinfo_number_value_format(hfinfo
, buf
, value
);
10629 label_fill(label_str
, 0, hfinfo
, out
, value_pos
);
10634 fill_label_number64(const field_info
*fi
, char *label_str
, size_t *value_pos
, bool is_signed
)
10636 const header_field_info
*hfinfo
= fi
->hfinfo
;
10639 char buf
[NUMBER_LABEL_LENGTH
];
10643 value
= fvalue_get_sinteger64(fi
->value
);
10645 value
= fvalue_get_uinteger64(fi
->value
);
10647 /* Fill in the textual info */
10648 if (hfinfo
->display
== BASE_CUSTOM
) {
10649 char tmp
[ITEM_LABEL_LENGTH
];
10650 const custom_fmt_func_64_t fmtfunc64
= (const custom_fmt_func_64_t
)hfinfo
->strings
;
10652 DISSECTOR_ASSERT(fmtfunc64
);
10653 fmtfunc64(tmp
, value
);
10654 label_fill(label_str
, 0, hfinfo
, tmp
, value_pos
);
10656 else if (hfinfo
->strings
) {
10657 const char *val_str
= hf_try_val64_to_str(value
, hfinfo
);
10659 out
= hfinfo_number_vals_format64(hfinfo
, buf
, value
);
10660 if (hfinfo
->display
& BASE_SPECIAL_VALS
) {
10662 * Unique values only display value_string string
10663 * if there is a match. Otherwise it's just a number
10666 label_fill_descr(label_str
, 0, hfinfo
, val_str
, out
, value_pos
);
10668 label_fill(label_str
, 0, hfinfo
, out
, value_pos
);
10671 if (val_str
== NULL
)
10672 val_str
= "Unknown";
10674 if (out
== NULL
) /* BASE_NONE so don't put integer in descr */
10675 label_fill(label_str
, 0, hfinfo
, val_str
, value_pos
);
10677 label_fill_descr(label_str
, 0, hfinfo
, val_str
, out
, value_pos
);
10681 out
= hfinfo_number_value_format64(hfinfo
, buf
, value
);
10683 label_fill(label_str
, 0, hfinfo
, out
, value_pos
);
10688 fill_display_label_float(const field_info
*fi
, char *label_str
)
10695 display
= FIELD_DISPLAY(fi
->hfinfo
->display
);
10696 value
= fvalue_get_floating(fi
->value
);
10698 if (display
== BASE_CUSTOM
) {
10699 const custom_fmt_func_double_t fmtfunc
= (const custom_fmt_func_double_t
)fi
->hfinfo
->strings
;
10700 DISSECTOR_ASSERT(fmtfunc
);
10701 fmtfunc(label_str
, value
);
10702 return strlen(label_str
);
10707 if (fi
->hfinfo
->type
== FT_FLOAT
)
10712 n
= snprintf(label_str
, ITEM_LABEL_LENGTH
, "%.*g", digits
, value
);
10715 n
= snprintf(label_str
, ITEM_LABEL_LENGTH
, "%f", value
);
10718 n
= snprintf(label_str
, ITEM_LABEL_LENGTH
, "%a", value
);
10721 n
= snprintf(label_str
, ITEM_LABEL_LENGTH
, "%e", value
);
10724 ws_assert_not_reached();
10727 return 0; /* error */
10729 if ((fi
->hfinfo
->strings
) && (fi
->hfinfo
->display
& BASE_UNIT_STRING
)) {
10730 const char *hf_str_val
;
10731 hf_str_val
= hf_try_double_val_to_str(value
, fi
->hfinfo
);
10732 n
+= protoo_strlcpy(label_str
+ n
, hf_str_val
, ITEM_LABEL_LENGTH
- n
);
10734 if (n
> ITEM_LABEL_LENGTH
) {
10735 ws_warning("label length too small");
10736 return strlen(label_str
);
10743 fill_label_float(const field_info
*fi
, char *label_str
, size_t *value_pos
)
10745 char tmp
[ITEM_LABEL_LENGTH
];
10747 fill_display_label_float(fi
, tmp
);
10748 label_fill(label_str
, 0, fi
->hfinfo
, tmp
, value_pos
);
10752 hfinfo_bitshift(const header_field_info
*hfinfo
)
10754 return ws_ctz(hfinfo
->bitmask
);
10759 hfinfo_bitoffset(const header_field_info
*hfinfo
)
10761 if (!hfinfo
->bitmask
) {
10765 /* ilog2 = first set bit, counting 0 as the last bit; we want 0
10766 * as the first bit */
10767 return hfinfo_container_bitwidth(hfinfo
) - 1 - ws_ilog2(hfinfo
->bitmask
);
10771 hfinfo_mask_bitwidth(const header_field_info
*hfinfo
)
10773 if (!hfinfo
->bitmask
) {
10777 /* ilog2 = first set bit, ctz = last set bit */
10778 return ws_ilog2(hfinfo
->bitmask
) - ws_ctz(hfinfo
->bitmask
) + 1;
10782 hfinfo_type_bitwidth(enum ftenum type
)
10821 DISSECTOR_ASSERT_NOT_REACHED();
10829 hfinfo_container_bitwidth(const header_field_info
*hfinfo
)
10831 if (!hfinfo
->bitmask
) {
10835 if (hfinfo
->type
== FT_BOOLEAN
) {
10836 return hfinfo
->display
; /* hacky? :) */
10839 return hfinfo_type_bitwidth(hfinfo
->type
);
10843 hfinfo_hex_digits(const header_field_info
*hfinfo
)
10847 /* If we have a bitmask, hfinfo->type is the width of the container, so not
10848 * appropriate to determine the number of hex digits for the field.
10849 * So instead, we compute it from the bitmask.
10851 if (hfinfo
->bitmask
!= 0) {
10852 bitwidth
= hfinfo_mask_bitwidth(hfinfo
);
10854 bitwidth
= hfinfo_type_bitwidth(hfinfo
->type
);
10857 /* Divide by 4, rounding up, to get number of hex digits. */
10858 return (bitwidth
+ 3) / 4;
10862 hfinfo_char_value_format_display(int display
, char buf
[7], uint32_t value
)
10864 char *ptr
= &buf
[6];
10865 static const char hex_digits
[16] =
10866 { '0', '1', '2', '3', '4', '5', '6', '7',
10867 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
10871 /* Properly format value */
10872 if (g_ascii_isprint(value
)) {
10874 * Printable, so just show the character, and, if it needs
10875 * to be escaped, escape it.
10878 if (value
== '\\' || value
== '\'')
10882 * Non-printable; show it as an escape sequence.
10888 * Show a NUL with only one digit.
10922 switch (FIELD_DISPLAY(display
)) {
10925 *(--ptr
) = (value
& 0x7) + '0';
10927 *(--ptr
) = (value
& 0x7) + '0';
10929 *(--ptr
) = (value
& 0x7) + '0';
10933 *(--ptr
) = hex_digits
[value
& 0x0F];
10935 *(--ptr
) = hex_digits
[value
& 0x0F];
10940 REPORT_DISSECTOR_BUG("Invalid base: %d", FIELD_DISPLAY(display
));
10949 static const char *
10950 hfinfo_number_value_format_display(const header_field_info
*hfinfo
, int display
, char buf
[NUMBER_LABEL_LENGTH
], uint32_t value
)
10952 char *ptr
= &buf
[NUMBER_LABEL_LENGTH
-1];
10953 bool isint
= FT_IS_INT(hfinfo
->type
);
10956 /* Properly format value */
10957 switch (FIELD_DISPLAY(display
)) {
10959 return isint
? int_to_str_back(ptr
, (int32_t) value
) : uint_to_str_back(ptr
, value
);
10963 ptr
= hex_to_str_back_len(ptr
, value
, hfinfo_hex_digits(hfinfo
));
10966 ptr
= isint
? int_to_str_back(ptr
, (int32_t) value
) : uint_to_str_back(ptr
, value
);
10970 return oct_to_str_back(ptr
, value
);
10973 return hex_to_str_back_len(ptr
, value
, hfinfo_hex_digits(hfinfo
));
10977 ptr
= isint
? int_to_str_back(ptr
, (int32_t) value
) : uint_to_str_back(ptr
, value
);
10980 ptr
= hex_to_str_back_len(ptr
, value
, hfinfo_hex_digits(hfinfo
));
10987 port_with_resolution_to_str_buf(buf
, NUMBER_LABEL_LENGTH
,
10988 display_to_port_type((field_display_e
)display
), value
);
10993 const char *manuf_name
;
10995 p_oui
[0] = value
>> 16 & 0xFF;
10996 p_oui
[1] = value
>> 8 & 0xFF;
10997 p_oui
[2] = value
& 0xFF;
10999 /* Attempt an OUI lookup. */
11000 manuf_name
= uint_get_manuf_name_if_known(value
);
11001 if (manuf_name
== NULL
) {
11002 /* Could not find an OUI. */
11003 snprintf(buf
, NUMBER_LABEL_LENGTH
, "%02x:%02x:%02x", p_oui
[0], p_oui
[1], p_oui
[2]);
11006 /* Found an address string. */
11007 snprintf(buf
, NUMBER_LABEL_LENGTH
, "%02x:%02x:%02x (%s)", p_oui
[0], p_oui
[1], p_oui
[2], manuf_name
);
11013 REPORT_DISSECTOR_BUG("Invalid base: %d", FIELD_DISPLAY(display
));
11018 static const char *
11019 hfinfo_number_value_format_display64(const header_field_info
*hfinfo
, int display
, char buf
[NUMBER_LABEL_LENGTH
], uint64_t value
)
11021 char *ptr
= &buf
[NUMBER_LABEL_LENGTH
-1];
11022 bool isint
= FT_IS_INT(hfinfo
->type
);
11025 /* Properly format value */
11026 switch (FIELD_DISPLAY(display
)) {
11028 return isint
? int64_to_str_back(ptr
, (int64_t) value
) : uint64_to_str_back(ptr
, value
);
11032 ptr
= hex64_to_str_back_len(ptr
, value
, hfinfo_hex_digits(hfinfo
));
11035 ptr
= isint
? int64_to_str_back(ptr
, (int64_t) value
) : uint64_to_str_back(ptr
, value
);
11039 return oct64_to_str_back(ptr
, value
);
11042 return hex64_to_str_back_len(ptr
, value
, hfinfo_hex_digits(hfinfo
));
11046 ptr
= isint
? int64_to_str_back(ptr
, (int64_t) value
) : uint64_to_str_back(ptr
, value
);
11049 ptr
= hex64_to_str_back_len(ptr
, value
, hfinfo_hex_digits(hfinfo
));
11053 REPORT_DISSECTOR_BUG("Invalid base: %d", FIELD_DISPLAY(display
));
11059 static const char *
11060 hfinfo_number_value_format(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint32_t value
)
11062 int display
= hfinfo
->display
;
11064 if (hfinfo
->type
== FT_FRAMENUM
) {
11066 * Frame numbers are always displayed in decimal.
11068 display
= BASE_DEC
;
11071 return hfinfo_number_value_format_display(hfinfo
, display
, buf
, value
);
11074 static const char *
11075 hfinfo_number_value_format64(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint64_t value
)
11077 int display
= hfinfo
->display
;
11079 if (hfinfo
->type
== FT_FRAMENUM
) {
11081 * Frame numbers are always displayed in decimal.
11083 display
= BASE_DEC
;
11086 return hfinfo_number_value_format_display64(hfinfo
, display
, buf
, value
);
11089 static const char *
11090 hfinfo_char_value_format(const header_field_info
*hfinfo
, char buf
[32], uint32_t value
)
11092 /* Get the underlying BASE_ value */
11093 int display
= FIELD_DISPLAY(hfinfo
->display
);
11095 return hfinfo_char_value_format_display(display
, buf
, value
);
11098 static const char *
11099 hfinfo_numeric_value_format(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint32_t value
)
11101 /* Get the underlying BASE_ value */
11102 int display
= FIELD_DISPLAY(hfinfo
->display
);
11104 if (hfinfo
->type
== FT_FRAMENUM
) {
11106 * Frame numbers are always displayed in decimal.
11108 display
= BASE_DEC
;
11111 if (IS_BASE_PORT(display
)) {
11112 display
= BASE_DEC
;
11113 } else if (display
== BASE_OUI
) {
11114 display
= BASE_HEX
;
11119 /* case BASE_DEC: */
11121 case BASE_OCT
: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
11123 display
= BASE_DEC
;
11126 /* case BASE_HEX: */
11128 display
= BASE_HEX
;
11132 return hfinfo_number_value_format_display(hfinfo
, display
, buf
, value
);
11135 static const char *
11136 hfinfo_numeric_value_format64(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint64_t value
)
11138 /* Get the underlying BASE_ value */
11139 int display
= FIELD_DISPLAY(hfinfo
->display
);
11141 if (hfinfo
->type
== FT_FRAMENUM
) {
11143 * Frame numbers are always displayed in decimal.
11145 display
= BASE_DEC
;
11150 /* case BASE_DEC: */
11152 case BASE_OCT
: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
11154 display
= BASE_DEC
;
11157 /* case BASE_HEX: */
11159 display
= BASE_HEX
;
11163 return hfinfo_number_value_format_display64(hfinfo
, display
, buf
, value
);
11166 static const char *
11167 hfinfo_char_vals_format(const header_field_info
*hfinfo
, char buf
[32], uint32_t value
)
11169 /* Get the underlying BASE_ value */
11170 int display
= FIELD_DISPLAY(hfinfo
->display
);
11172 return hfinfo_char_value_format_display(display
, buf
, value
);
11175 static const char *
11176 hfinfo_number_vals_format(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint32_t value
)
11178 /* Get the underlying BASE_ value */
11179 int display
= FIELD_DISPLAY(hfinfo
->display
);
11181 if (display
== BASE_NONE
)
11184 if (display
== BASE_DEC_HEX
)
11185 display
= BASE_DEC
;
11186 if (display
== BASE_HEX_DEC
)
11187 display
= BASE_HEX
;
11189 return hfinfo_number_value_format_display(hfinfo
, display
, buf
, value
);
11192 static const char *
11193 hfinfo_number_vals_format64(const header_field_info
*hfinfo
, char buf
[NUMBER_LABEL_LENGTH
], uint64_t value
)
11195 /* Get the underlying BASE_ value */
11196 int display
= FIELD_DISPLAY(hfinfo
->display
);
11198 if (display
== BASE_NONE
)
11201 if (display
== BASE_DEC_HEX
)
11202 display
= BASE_DEC
;
11203 if (display
== BASE_HEX_DEC
)
11204 display
= BASE_HEX
;
11206 return hfinfo_number_value_format_display64(hfinfo
, display
, buf
, value
);
11210 proto_registrar_get_name(const int n
)
11212 header_field_info
*hfinfo
;
11214 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
11215 return hfinfo
->name
;
11219 proto_registrar_get_abbrev(const int n
)
11221 header_field_info
*hfinfo
;
11223 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
11224 return hfinfo
->abbrev
;
11228 proto_registrar_get_ftype(const int n
)
11230 header_field_info
*hfinfo
;
11232 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
11233 return hfinfo
->type
;
11237 proto_registrar_get_parent(const int n
)
11239 header_field_info
*hfinfo
;
11241 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
11242 return hfinfo
->parent
;
11246 proto_registrar_is_protocol(const int n
)
11248 header_field_info
*hfinfo
;
11250 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
11251 return (((hfinfo
->id
!= hf_text_only
) && (hfinfo
->parent
== -1)) ? true : false);
11254 /* Returns length of field in packet (not necessarily the length
11255 * in our internal representation, as in the case of IPv4).
11256 * 0 means undeterminable at time of registration
11257 * -1 means the field is not registered. */
11259 proto_registrar_get_length(const int n
)
11261 header_field_info
*hfinfo
;
11263 PROTO_REGISTRAR_GET_NTH(n
, hfinfo
);
11264 return ftype_wire_size(hfinfo
->type
);
11267 /* Looks for a protocol or a field in a proto_tree. Returns true if
11268 * it exists anywhere, or false if it exists nowhere. */
11270 proto_check_for_protocol_or_field(const proto_tree
* tree
, const int id
)
11272 GPtrArray
*ptrs
= proto_get_finfo_ptr_array(tree
, id
);
11274 if (g_ptr_array_len(ptrs
) > 0) {
11282 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
11283 * This only works if the hfindex was "primed" before the dissection
11284 * took place, as we just pass back the already-created GPtrArray*.
11285 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
11288 proto_get_finfo_ptr_array(const proto_tree
*tree
, const int id
)
11293 if (PTREE_DATA(tree
)->interesting_hfids
!= NULL
)
11294 return (GPtrArray
*)g_hash_table_lookup(PTREE_DATA(tree
)->interesting_hfids
,
11295 GINT_TO_POINTER(id
));
11301 proto_tracking_interesting_fields(const proto_tree
*tree
)
11303 GHashTable
*interesting_hfids
;
11308 interesting_hfids
= PTREE_DATA(tree
)->interesting_hfids
;
11310 return (interesting_hfids
!= NULL
) && g_hash_table_size(interesting_hfids
);
11313 /* Helper struct for proto_find_info() and proto_all_finfos() */
11319 /* Helper function for proto_find_info() */
11321 find_finfo(proto_node
*node
, void * data
)
11323 field_info
*fi
= PNODE_FINFO(node
);
11324 if (fi
&& fi
->hfinfo
) {
11325 if (fi
->hfinfo
->id
== ((ffdata_t
*)data
)->id
) {
11326 g_ptr_array_add(((ffdata_t
*)data
)->array
, fi
);
11330 /* Don't stop traversing. */
11334 /* Helper function for proto_find_first_info() */
11336 find_first_finfo(proto_node
*node
, void *data
)
11338 field_info
*fi
= PNODE_FINFO(node
);
11339 if (fi
&& fi
->hfinfo
) {
11340 if (fi
->hfinfo
->id
== ((ffdata_t
*)data
)->id
) {
11341 g_ptr_array_add(((ffdata_t
*)data
)->array
, fi
);
11343 /* Stop traversing. */
11348 /* Continue traversing. */
11352 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
11353 * This works on any proto_tree, primed or unprimed, but actually searches
11354 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
11355 * The caller does need to free the returned GPtrArray with
11356 * g_ptr_array_free(<array>, true).
11359 proto_find_finfo(proto_tree
*tree
, const int id
)
11363 ffdata
.array
= g_ptr_array_new();
11366 proto_tree_traverse_pre_order(tree
, find_finfo
, &ffdata
);
11368 return ffdata
.array
;
11371 /* Return GPtrArray* of first field_info pointers for the searched hfindex that appear in a tree.
11372 * This works on any proto_tree, primed or unprimed, but actually searches
11373 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
11374 * The caller does need to free the returned GPtrArray with
11375 * g_ptr_array_free(<array>, true).
11378 proto_find_first_finfo(proto_tree
*tree
, const int id
)
11382 ffdata
.array
= g_ptr_array_new();
11385 proto_tree_traverse_pre_order(tree
, find_first_finfo
, &ffdata
);
11387 return ffdata
.array
;
11390 /* Helper function for proto_all_finfos() */
11392 every_finfo(proto_node
*node
, void * data
)
11394 field_info
*fi
= PNODE_FINFO(node
);
11395 if (fi
&& fi
->hfinfo
) {
11396 g_ptr_array_add(((ffdata_t
*)data
)->array
, fi
);
11399 /* Don't stop traversing. */
11403 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree.
11404 * The caller does need to free the returned GPtrArray with
11405 * g_ptr_array_free(<array>, true).
11408 proto_all_finfos(proto_tree
*tree
)
11412 /* Pre allocate enough space to hold all fields in most cases */
11413 ffdata
.array
= g_ptr_array_sized_new(512);
11416 proto_tree_traverse_pre_order(tree
, every_finfo
, &ffdata
);
11418 return ffdata
.array
;
11429 check_for_offset(proto_node
*node
, void * data
)
11431 field_info
*fi
= PNODE_FINFO(node
);
11432 offset_search_t
*offsearch
= (offset_search_t
*)data
;
11434 /* !fi == the top most container node which holds nothing */
11435 if (fi
&& !proto_item_is_hidden(node
) && !proto_item_is_generated(node
) && fi
->ds_tvb
&& offsearch
->tvb
== fi
->ds_tvb
) {
11436 if (offsearch
->offset
>= (unsigned) fi
->start
&&
11437 offsearch
->offset
< (unsigned) (fi
->start
+ fi
->length
)) {
11439 offsearch
->finfo
= fi
;
11440 return false; /* keep traversing */
11443 return false; /* keep traversing */
11446 /* Search a proto_tree backwards (from leaves to root) looking for the field
11447 * whose start/length occupies 'offset' */
11448 /* XXX - I couldn't find an easy way to search backwards, so I search
11449 * forwards, w/o stopping. Therefore, the last finfo I find will the be
11450 * the one I want to return to the user. This algorithm is inefficient
11451 * and could be re-done, but I'd have to handle all the children and
11452 * siblings of each node myself. When I have more time I'll do that.
11455 proto_find_field_from_offset(proto_tree
*tree
, unsigned offset
, tvbuff_t
*tvb
)
11457 offset_search_t offsearch
;
11459 offsearch
.offset
= offset
;
11460 offsearch
.finfo
= NULL
;
11461 offsearch
.tvb
= tvb
;
11463 proto_tree_traverse_pre_order(tree
, check_for_offset
, &offsearch
);
11465 return offsearch
.finfo
;
11474 check_for_undecoded(proto_node
*node
, void * data
)
11476 field_info
*fi
= PNODE_FINFO(node
);
11477 decoded_data_t
* decoded
= (decoded_data_t
*)data
;
11482 if (fi
&& fi
->hfinfo
->type
!= FT_PROTOCOL
) {
11483 for (i
= fi
->start
; i
< fi
->start
+ fi
->length
&& i
< decoded
->length
; i
++) {
11486 decoded
->buf
[byte
] |= (1 << bit
);
11494 proto_find_undecoded_data(proto_tree
*tree
, unsigned length
)
11496 decoded_data_t decoded
;
11497 decoded
.length
= length
;
11498 decoded
.buf
= (char*)wmem_alloc0(PNODE_POOL(tree
), length
/ 8 + 1);
11500 proto_tree_traverse_pre_order(tree
, check_for_undecoded
, &decoded
);
11501 return decoded
.buf
;
11504 /* Dumps the protocols in the registration database to stdout. An independent
11505 * program can take this output and format it into nice tables or HTML or
11508 * There is one record per line. The fields are tab-delimited.
11510 * Field 1 = protocol name
11511 * Field 2 = protocol short name
11512 * Field 3 = protocol filter name
11513 * Field 4 = protocol enabled
11514 * Field 5 = protocol enabled by default
11515 * Field 6 = protocol can toggle
11518 proto_registrar_dump_protocols(void)
11520 protocol_t
*protocol
;
11522 void *cookie
= NULL
;
11525 i
= proto_get_first_protocol(&cookie
);
11527 protocol
= find_protocol_by_id(i
);
11528 printf("%s\t%s\t%s\t%c\t%c\t%c\n",
11530 protocol
->short_name
,
11531 protocol
->filter_name
,
11532 (proto_is_protocol_enabled_by_default(protocol
) ? 'T' : 'F'),
11533 (proto_is_protocol_enabled(protocol
) ? 'T' : 'F'),
11534 (proto_can_toggle_protocol(protocol
->proto_id
) ? 'T' : 'F'));
11535 i
= proto_get_next_protocol(&cookie
);
11539 /* Dumps the value_strings, extended value string headers, range_strings
11540 * or true/false strings for fields that have them.
11541 * There is one record per line. Fields are tab-delimited.
11542 * There are four types of records: Value String, Extended Value String Header,
11543 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
11544 * the type of record.
11546 * Note that a record will be generated only if the value_string,... is referenced
11547 * in a registered hfinfo entry.
11553 * Field 2 = Field abbreviation to which this value string corresponds
11554 * Field 3 = Integer value
11557 * Extended Value String Headers
11558 * -----------------------------
11560 * Field 2 = Field abbreviation to which this extended value string header corresponds
11561 * Field 3 = Extended Value String "Name"
11562 * Field 4 = Number of entries in the associated value_string array
11563 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
11568 * Field 2 = Field abbreviation to which this range string corresponds
11569 * Field 3 = Integer value: lower bound
11570 * Field 4 = Integer value: upper bound
11573 * True/False Strings
11574 * ------------------
11576 * Field 2 = Field abbreviation to which this true/false string corresponds
11577 * Field 3 = True String
11578 * Field 4 = False String
11581 proto_registrar_dump_values(void)
11583 header_field_info
*hfinfo
;
11585 const value_string
*vals
;
11586 const val64_string
*vals64
;
11587 const range_string
*range
;
11588 const true_false_string
*tfs
;
11589 const unit_name_string
*units
;
11591 len
= gpa_hfinfo
.len
;
11592 for (i
= 0; i
< len
; i
++) {
11593 if (gpa_hfinfo
.hfi
[i
] == NULL
)
11594 continue; /* This is a deregistered protocol or field */
11596 PROTO_REGISTRAR_GET_NTH(i
, hfinfo
);
11598 if (hfinfo
->id
== hf_text_only
) {
11602 /* ignore protocols */
11603 if (proto_registrar_is_protocol(i
)) {
11606 /* process header fields */
11607 #if 0 /* XXX: We apparently allow fields with the same name but with differing "strings" content */
11609 * If this field isn't at the head of the list of
11610 * fields with this name, skip this field - all
11611 * fields with the same name are really just versions
11612 * of the same field stored in different bits, and
11613 * should have the same type/radix/value list, and
11614 * just differ in their bit masks. (If a field isn't
11615 * a bitfield, but can be, say, 1 or 2 bytes long,
11616 * it can just be made FT_UINT16, meaning the
11617 * *maximum* length is 2 bytes, and be used
11618 * for all lengths.)
11620 if (hfinfo
->same_name_prev_id
!= -1)
11629 if (hfinfo
->strings
!= NULL
) {
11630 if (FIELD_DISPLAY(hfinfo
->display
) != BASE_CUSTOM
&&
11631 (hfinfo
->type
== FT_CHAR
||
11632 hfinfo
->type
== FT_UINT8
||
11633 hfinfo
->type
== FT_UINT16
||
11634 hfinfo
->type
== FT_UINT24
||
11635 hfinfo
->type
== FT_UINT32
||
11636 hfinfo
->type
== FT_UINT40
||
11637 hfinfo
->type
== FT_UINT48
||
11638 hfinfo
->type
== FT_UINT56
||
11639 hfinfo
->type
== FT_UINT64
||
11640 hfinfo
->type
== FT_INT8
||
11641 hfinfo
->type
== FT_INT16
||
11642 hfinfo
->type
== FT_INT24
||
11643 hfinfo
->type
== FT_INT32
||
11644 hfinfo
->type
== FT_INT40
||
11645 hfinfo
->type
== FT_INT48
||
11646 hfinfo
->type
== FT_INT56
||
11647 hfinfo
->type
== FT_INT64
||
11648 hfinfo
->type
== FT_FLOAT
||
11649 hfinfo
->type
== FT_DOUBLE
)) {
11651 if (hfinfo
->display
& BASE_RANGE_STRING
) {
11652 range
= (const range_string
*)hfinfo
->strings
;
11653 } else if (hfinfo
->display
& BASE_EXT_STRING
) {
11654 if (hfinfo
->display
& BASE_VAL64_STRING
) {
11655 vals64
= VAL64_STRING_EXT_VS_P((const val64_string_ext
*)hfinfo
->strings
);
11657 vals
= VALUE_STRING_EXT_VS_P((const value_string_ext
*)hfinfo
->strings
);
11659 } else if (hfinfo
->display
& BASE_VAL64_STRING
) {
11660 vals64
= (const val64_string
*)hfinfo
->strings
;
11661 } else if (hfinfo
->display
& BASE_UNIT_STRING
) {
11662 units
= (const unit_name_string
*)hfinfo
->strings
;
11664 vals
= (const value_string
*)hfinfo
->strings
;
11667 else if (hfinfo
->type
== FT_BOOLEAN
) {
11668 tfs
= (const struct true_false_string
*)hfinfo
->strings
;
11672 /* Print value strings? */
11674 if (hfinfo
->display
& BASE_EXT_STRING
) {
11675 if (hfinfo
->display
& BASE_VAL64_STRING
) {
11676 val64_string_ext
*vse_p
= (val64_string_ext
*)hfinfo
->strings
;
11677 if (!val64_string_ext_validate(vse_p
)) {
11678 ws_warning("Invalid val64_string_ext ptr for: %s", hfinfo
->abbrev
);
11681 try_val64_to_str_ext(0, vse_p
); /* "prime" the extended val64_string */
11682 printf("E\t%s\t%u\t%s\t%s\n",
11684 VAL64_STRING_EXT_VS_NUM_ENTRIES(vse_p
),
11685 VAL64_STRING_EXT_VS_NAME(vse_p
),
11686 val64_string_ext_match_type_str(vse_p
));
11688 value_string_ext
*vse_p
= (value_string_ext
*)hfinfo
->strings
;
11689 if (!value_string_ext_validate(vse_p
)) {
11690 ws_warning("Invalid value_string_ext ptr for: %s", hfinfo
->abbrev
);
11693 try_val_to_str_ext(0, vse_p
); /* "prime" the extended value_string */
11694 printf("E\t%s\t%u\t%s\t%s\n",
11696 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p
),
11697 VALUE_STRING_EXT_VS_NAME(vse_p
),
11698 value_string_ext_match_type_str(vse_p
));
11702 while (vals
[vi
].strptr
) {
11703 /* Print in the proper base */
11704 if (hfinfo
->type
== FT_CHAR
) {
11705 if (g_ascii_isprint(vals
[vi
].value
)) {
11706 printf("V\t%s\t'%c'\t%s\n",
11711 if (hfinfo
->display
== BASE_HEX
) {
11712 printf("V\t%s\t'\\x%02x'\t%s\n",
11718 printf("V\t%s\t'\\%03o'\t%s\n",
11725 if (hfinfo
->display
== BASE_HEX
) {
11726 printf("V\t%s\t0x%x\t%s\n",
11732 printf("V\t%s\t%u\t%s\n",
11743 while (vals64
[vi
].strptr
) {
11744 printf("V64\t%s\t%" PRIu64
"\t%s\n",
11747 vals64
[vi
].strptr
);
11752 /* print range strings? */
11755 while (range
[vi
].strptr
) {
11756 /* Print in the proper base */
11757 if (FIELD_DISPLAY(hfinfo
->display
) == BASE_HEX
) {
11758 printf("R\t%s\t0x%"PRIx64
"\t0x%"PRIx64
"\t%s\n",
11760 range
[vi
].value_min
,
11761 range
[vi
].value_max
,
11765 printf("R\t%s\t%"PRIu64
"\t%"PRIu64
"\t%s\n",
11767 range
[vi
].value_min
,
11768 range
[vi
].value_max
,
11775 /* Print true/false strings? */
11777 printf("T\t%s\t%s\t%s\n", hfinfo
->abbrev
,
11778 tfs
->true_string
, tfs
->false_string
);
11780 /* Print unit strings? */
11782 printf("U\t%s\t%s\t%s\n", hfinfo
->abbrev
,
11783 units
->singular
, units
->plural
? units
->plural
: "(no plural)");
11788 /* Prints the number of registered fields.
11789 * Useful for determining an appropriate value for
11790 * PROTO_PRE_ALLOC_HF_FIELDS_MEM.
11792 * Returns false if PROTO_PRE_ALLOC_HF_FIELDS_MEM is larger than or equal to
11793 * the number of fields, true otherwise.
11796 proto_registrar_dump_fieldcount(void)
11799 header_field_info
*hfinfo
;
11800 uint32_t deregistered_count
= 0;
11801 uint32_t same_name_count
= 0;
11802 uint32_t protocol_count
= 0;
11804 for (i
= 0; i
< gpa_hfinfo
.len
; i
++) {
11805 if (gpa_hfinfo
.hfi
[i
] == NULL
) {
11806 deregistered_count
++;
11807 continue; /* This is a deregistered protocol or header field */
11810 PROTO_REGISTRAR_GET_NTH(i
, hfinfo
);
11812 if (proto_registrar_is_protocol(i
))
11815 if (hfinfo
->same_name_prev_id
!= -1)
11819 printf("There are %u header fields registered, of which:\n"
11820 "\t%u are deregistered\n"
11821 "\t%u are protocols\n"
11822 "\t%u have the same name as another field\n\n",
11823 gpa_hfinfo
.len
, deregistered_count
, protocol_count
,
11826 printf("%d fields were pre-allocated.\n%s", PROTO_PRE_ALLOC_HF_FIELDS_MEM
,
11827 (gpa_hfinfo
.allocated_len
> PROTO_PRE_ALLOC_HF_FIELDS_MEM
) ?
11828 "* * Please increase PROTO_PRE_ALLOC_HF_FIELDS_MEM (in epan/proto.c)! * *\n\n" :
11831 printf("The header field table consumes %u KiB of memory.\n",
11832 (unsigned int)(gpa_hfinfo
.allocated_len
* sizeof(header_field_info
*) / 1024));
11833 printf("The fields themselves consume %u KiB of memory.\n",
11834 (unsigned int)(gpa_hfinfo
.len
* sizeof(header_field_info
) / 1024));
11836 return (gpa_hfinfo
.allocated_len
> PROTO_PRE_ALLOC_HF_FIELDS_MEM
);
11840 elastic_add_base_mapping(json_dumper
*dumper
)
11842 json_dumper_set_member_name(dumper
, "settings");
11843 json_dumper_begin_object(dumper
);
11844 json_dumper_set_member_name(dumper
, "index.mapping.total_fields.limit");
11845 json_dumper_value_anyf(dumper
, "%d", 1000000);
11846 json_dumper_end_object(dumper
);
11850 ws_type_to_elastic(unsigned type _U_
)
11867 case FT_UINT64
: // Actually it's not handled by 'long' elastic type.
11877 case FT_ABSOLUTE_TIME
:
11878 case FT_RELATIVE_TIME
:
11881 case FT_UINT_BYTES
:
11891 dot_to_underscore(char* str
)
11894 for (i
= 0; i
< strlen(str
); i
++) {
11901 /* Dumps a mapping file for ElasticSearch
11904 proto_registrar_dump_elastic(const char* filter
)
11906 header_field_info
*hfinfo
;
11907 header_field_info
*parent_hfinfo
;
11909 bool open_object
= true;
11910 const char* prev_proto
= NULL
;
11912 char** protos
= NULL
;
11917 char* prev_item
= NULL
;
11919 /* We have filtering protocols. Extract them. */
11921 protos
= g_strsplit(filter
, ",", -1);
11925 * To help tracking down the json tree, objects have been appended with a comment:
11926 * n.label -> where n is the indentation level and label the name of the object
11929 json_dumper dumper
= {
11930 .output_file
= stdout
,
11931 .flags
= JSON_DUMPER_FLAGS_PRETTY_PRINT
,
11933 json_dumper_begin_object(&dumper
); // 1.root
11934 elastic_add_base_mapping(&dumper
);
11936 json_dumper_set_member_name(&dumper
, "mappings");
11937 json_dumper_begin_object(&dumper
); // 2.mappings
11938 json_dumper_set_member_name(&dumper
, "dynamic");
11939 json_dumper_value_anyf(&dumper
, "false");
11941 json_dumper_set_member_name(&dumper
, "properties");
11942 json_dumper_begin_object(&dumper
); // 3.properties
11943 json_dumper_set_member_name(&dumper
, "timestamp");
11944 json_dumper_begin_object(&dumper
); // 4.timestamp
11945 json_dumper_set_member_name(&dumper
, "type");
11946 json_dumper_value_string(&dumper
, "date");
11947 json_dumper_end_object(&dumper
); // 4.timestamp
11949 json_dumper_set_member_name(&dumper
, "layers");
11950 json_dumper_begin_object(&dumper
); // 4.layers
11951 json_dumper_set_member_name(&dumper
, "properties");
11952 json_dumper_begin_object(&dumper
); // 5.properties
11954 for (i
= 0; i
< gpa_hfinfo
.len
; i
++) {
11955 if (gpa_hfinfo
.hfi
[i
] == NULL
)
11956 continue; /* This is a deregistered protocol or header field */
11958 PROTO_REGISTRAR_GET_NTH(i
, hfinfo
);
11961 * Skip the pseudo-field for "proto_tree_add_text()" since
11962 * we don't want it in the list of filterable protocols.
11964 if (hfinfo
->id
== hf_text_only
)
11967 if (!proto_registrar_is_protocol(i
)) {
11968 PROTO_REGISTRAR_GET_NTH(hfinfo
->parent
, parent_hfinfo
);
11971 * Skip the field if filter protocols have been set and this one's
11972 * parent is not listed.
11979 if (!g_strcmp0(proto
, parent_hfinfo
->abbrev
)) {
11990 if (prev_proto
&& g_strcmp0(parent_hfinfo
->abbrev
, prev_proto
)) {
11991 json_dumper_end_object(&dumper
); // 7.properties
11992 json_dumper_end_object(&dumper
); // 8.parent_hfinfo->abbrev
11993 open_object
= true;
11996 prev_proto
= parent_hfinfo
->abbrev
;
11999 json_dumper_set_member_name(&dumper
, parent_hfinfo
->abbrev
);
12000 json_dumper_begin_object(&dumper
); // 6.parent_hfinfo->abbrev
12001 json_dumper_set_member_name(&dumper
, "properties");
12002 json_dumper_begin_object(&dumper
); // 7.properties
12003 open_object
= false;
12005 /* Skip the fields that would map into string. This is the default in elasticsearch. */
12006 type
= ws_type_to_elastic(hfinfo
->type
);
12007 /* when type is NULL, we have the default mapping: string */
12009 str
= ws_strdup_printf("%s_%s", prev_proto
, hfinfo
->abbrev
);
12010 dot_to_underscore(str
);
12011 if (g_strcmp0(prev_item
, str
)) {
12012 json_dumper_set_member_name(&dumper
, str
);
12013 json_dumper_begin_object(&dumper
); // 8.hfinfo->abbrev
12014 json_dumper_set_member_name(&dumper
, "type");
12015 json_dumper_value_string(&dumper
, type
);
12016 json_dumper_end_object(&dumper
); // 8.hfinfo->abbrev
12026 json_dumper_end_object(&dumper
); // 7.properties
12027 json_dumper_end_object(&dumper
); // 6.parent_hfinfo->abbrev
12030 json_dumper_end_object(&dumper
); // 5.properties
12031 json_dumper_end_object(&dumper
); // 4.layers
12032 json_dumper_end_object(&dumper
); // 3.properties
12033 json_dumper_end_object(&dumper
); // 2.mappings
12034 json_dumper_end_object(&dumper
); // 1.root
12035 bool ret
= json_dumper_finish(&dumper
);
12036 DISSECTOR_ASSERT(ret
);
12038 g_strfreev(protos
);
12041 /* Dumps the contents of the registration database to stdout. An independent
12042 * program can take this output and format it into nice tables or HTML or
12045 * There is one record per line. Each record is either a protocol or a header
12046 * field, differentiated by the first field. The fields are tab-delimited.
12051 * Field 2 = descriptive protocol name
12052 * Field 3 = protocol abbreviation
12057 * Field 2 = descriptive field name
12058 * Field 3 = field abbreviation
12059 * Field 4 = type ( textual representation of the ftenum type )
12060 * Field 5 = parent protocol abbreviation
12061 * Field 6 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
12062 * Field 7 = bitmask: format: hex: 0x....
12063 * Field 8 = blurb describing field
12066 proto_registrar_dump_fields(void)
12068 header_field_info
*hfinfo
, *parent_hfinfo
;
12070 const char *enum_name
;
12071 const char *base_name
;
12075 len
= gpa_hfinfo
.len
;
12076 for (i
= 0; i
< len
; i
++) {
12077 if (gpa_hfinfo
.hfi
[i
] == NULL
)
12078 continue; /* This is a deregistered protocol or header field */
12080 PROTO_REGISTRAR_GET_NTH(i
, hfinfo
);
12083 * Skip the pseudo-field for "proto_tree_add_text()" since
12084 * we don't want it in the list of filterable fields.
12086 if (hfinfo
->id
== hf_text_only
)
12089 /* format for protocols */
12090 if (proto_registrar_is_protocol(i
)) {
12091 printf("P\t%s\t%s\n", hfinfo
->name
, hfinfo
->abbrev
);
12093 /* format for header fields */
12096 * If this field isn't at the head of the list of
12097 * fields with this name, skip this field - all
12098 * fields with the same name are really just versions
12099 * of the same field stored in different bits, and
12100 * should have the same type/radix/value list, and
12101 * just differ in their bit masks. (If a field isn't
12102 * a bitfield, but can be, say, 1 or 2 bytes long,
12103 * it can just be made FT_UINT16, meaning the
12104 * *maximum* length is 2 bytes, and be used
12105 * for all lengths.)
12107 if (hfinfo
->same_name_prev_id
!= -1)
12110 PROTO_REGISTRAR_GET_NTH(hfinfo
->parent
, parent_hfinfo
);
12112 enum_name
= ftype_name(hfinfo
->type
);
12115 if (hfinfo
->type
== FT_CHAR
||
12116 hfinfo
->type
== FT_UINT8
||
12117 hfinfo
->type
== FT_UINT16
||
12118 hfinfo
->type
== FT_UINT24
||
12119 hfinfo
->type
== FT_UINT32
||
12120 hfinfo
->type
== FT_UINT40
||
12121 hfinfo
->type
== FT_UINT48
||
12122 hfinfo
->type
== FT_UINT56
||
12123 hfinfo
->type
== FT_UINT64
||
12124 hfinfo
->type
== FT_INT8
||
12125 hfinfo
->type
== FT_INT16
||
12126 hfinfo
->type
== FT_INT24
||
12127 hfinfo
->type
== FT_INT32
||
12128 hfinfo
->type
== FT_INT40
||
12129 hfinfo
->type
== FT_INT48
||
12130 hfinfo
->type
== FT_INT56
||
12131 hfinfo
->type
== FT_INT64
) {
12133 switch (FIELD_DISPLAY(hfinfo
->display
)) {
12146 base_name
= val_to_str_const(FIELD_DISPLAY(hfinfo
->display
), hf_display
, "????");
12149 base_name
= "????";
12152 } else if (hfinfo
->type
== FT_BOOLEAN
) {
12153 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
12154 snprintf(width
, sizeof(width
), "%d", hfinfo
->display
);
12158 blurb
= hfinfo
->blurb
;
12161 else if (strlen(blurb
) == 0)
12164 printf("F\t%s\t%s\t%s\t%s\t%s\t0x%" PRIx64
"\t%s\n",
12165 hfinfo
->name
, hfinfo
->abbrev
, enum_name
,
12166 parent_hfinfo
->abbrev
, base_name
,
12167 hfinfo
->bitmask
, blurb
);
12172 /* Dumps all abbreviated field and protocol completions of the given string to
12173 * stdout. An independent program may use this for command-line tab completion
12177 proto_registrar_dump_field_completions(const char *prefix
)
12179 header_field_info
*hfinfo
;
12182 bool matched
= false;
12184 prefix_len
= strlen(prefix
);
12185 len
= gpa_hfinfo
.len
;
12186 for (i
= 0; i
< len
; i
++) {
12187 if (gpa_hfinfo
.hfi
[i
] == NULL
)
12188 continue; /* This is a deregistered protocol or header field */
12190 PROTO_REGISTRAR_GET_NTH(i
, hfinfo
);
12193 * Skip the pseudo-field for "proto_tree_add_text()" since
12194 * we don't want it in the list of filterable fields.
12196 if (hfinfo
->id
== hf_text_only
)
12199 /* format for protocols */
12200 if (proto_registrar_is_protocol(i
)) {
12201 if(0 == strncmp(hfinfo
->abbrev
, prefix
, prefix_len
)) {
12203 printf("%s\t%s\n", hfinfo
->abbrev
, hfinfo
->name
);
12206 /* format for header fields */
12209 * If this field isn't at the head of the list of
12210 * fields with this name, skip this field - all
12211 * fields with the same name are really just versions
12212 * of the same field stored in different bits, and
12213 * should have the same type/radix/value list, and
12214 * just differ in their bit masks. (If a field isn't
12215 * a bitfield, but can be, say, 1 or 2 bytes long,
12216 * it can just be made FT_UINT16, meaning the
12217 * *maximum* length is 2 bytes, and be used
12218 * for all lengths.)
12220 if (hfinfo
->same_name_prev_id
!= -1)
12223 if(0 == strncmp(hfinfo
->abbrev
, prefix
, prefix_len
)) {
12225 printf("%s\t%s\n", hfinfo
->abbrev
, hfinfo
->name
);
12232 /* Dumps field types and descriptive names to stdout. An independent
12233 * program can take this output and format it into nice tables or HTML or
12236 * There is one record per line. The fields are tab-delimited.
12238 * Field 1 = field type name, e.g. FT_UINT8
12239 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
12242 proto_registrar_dump_ftypes(void)
12246 for (fte
= 0; fte
< FT_NUM_TYPES
; fte
++) {
12247 printf("%s\t%s\n", ftype_name((ftenum_t
)fte
), ftype_pretty_name((ftenum_t
)fte
));
12251 /* This function indicates whether it's possible to construct a
12252 * "match selected" display filter string for the specified field,
12253 * returns an indication of whether it's possible, and, if it's
12254 * possible and "filter" is non-null, constructs the filter and
12255 * sets "*filter" to point to it.
12256 * You do not need to [g_]free() this string since it will be automatically
12257 * freed once the next packet is dissected.
12260 construct_match_selected_string(const field_info
*finfo
, epan_dissect_t
*edt
,
12263 const header_field_info
*hfinfo
;
12267 int start
, length
, length_remaining
;
12273 hfinfo
= finfo
->hfinfo
;
12274 DISSECTOR_ASSERT(hfinfo
);
12276 /* If we have BASE_NONE and strings (a non-NULL FIELDCONVERT),
12277 * then "the numeric value ... is not used when preparing
12278 * filters for the field in question." If it's any other
12279 * base, we'll generate the filter normally (which will
12280 * be numeric, even though the human-readable string does
12281 * work for filtering.)
12283 * XXX - It might be nice to use fvalue_to_string_repr() in
12284 * "proto_item_fill_label()" as well, although, there, you'd
12285 * have to deal with the base *and* with resolved values for
12288 * Perhaps in addition to taking the repr type (DISPLAY
12289 * or DFILTER) and the display (base), fvalue_to_string_repr()
12290 * should have the the "strings" values in the header_field_info
12291 * structure for the field as a parameter, so it can have
12292 * if the field is Boolean or an enumerated integer type,
12293 * the tables used to generate human-readable values.
12295 if (hfinfo
->strings
&& FIELD_DISPLAY(hfinfo
->display
) == BASE_NONE
) {
12296 const char *str
= NULL
;
12298 switch (hfinfo
->type
) {
12304 str
= hf_try_val_to_str(fvalue_get_sinteger(finfo
->value
), hfinfo
);
12312 str
= hf_try_val_to_str(fvalue_get_uinteger(finfo
->value
), hfinfo
);
12319 if (str
!= NULL
&& filter
!= NULL
) {
12320 *filter
= wmem_strdup_printf(NULL
, "%s == \"%s\"", hfinfo
->abbrev
, str
);
12325 switch (hfinfo
->type
) {
12328 if (filter
!= NULL
)
12329 *filter
= wmem_strdup(NULL
, finfo
->hfinfo
->abbrev
);
12334 * If the length is 0, just match the name of the
12337 * (Also check for negative values, just in case,
12338 * as we'll cast it to an unsigned value later.)
12340 length
= finfo
->length
;
12342 if (filter
!= NULL
)
12343 *filter
= wmem_strdup(NULL
, finfo
->hfinfo
->abbrev
);
12350 * This doesn't have a value, so we'd match
12351 * on the raw bytes at this address.
12353 * Should we be allowed to access to the raw bytes?
12354 * If "edt" is NULL, the answer is "no".
12360 * Is this field part of the raw frame tvbuff?
12361 * If not, we can't use "frame[N:M]" to match
12364 * XXX - should this be frame-relative, or
12365 * protocol-relative?
12367 * XXX - does this fallback for non-registered
12368 * fields even make sense?
12370 if (finfo
->ds_tvb
!= edt
->tvb
)
12371 return false; /* you lose */
12374 * Don't go past the end of that tvbuff.
12376 length_remaining
= tvb_captured_length_remaining(finfo
->ds_tvb
, finfo
->start
);
12377 if (length
> length_remaining
)
12378 length
= length_remaining
;
12382 if (filter
!= NULL
) {
12383 start
= finfo
->start
;
12384 buf_len
= 32 + length
* 3;
12385 *filter
= (char *)wmem_alloc0(NULL
, buf_len
);
12388 ptr
+= snprintf(ptr
, buf_len
-(ptr
-*filter
),
12389 "frame[%d:%d] == ", finfo
->start
, length
);
12390 for (i
=0; i
<length
; i
++) {
12391 c
= tvb_get_uint8(finfo
->ds_tvb
, start
);
12394 ptr
+= snprintf(ptr
, buf_len
-(ptr
-*filter
), "%02x", c
);
12397 ptr
+= snprintf(ptr
, buf_len
-(ptr
-*filter
), ":%02x", c
);
12403 /* By default, use the fvalue's "to_string_repr" method. */
12405 if (filter
!= NULL
) {
12406 char *str
= fvalue_to_string_repr(NULL
, finfo
->value
, FTREPR_DFILTER
, finfo
->hfinfo
->display
);
12407 *filter
= wmem_strdup_printf(NULL
, "%s == %s", hfinfo
->abbrev
, str
);
12408 wmem_free(NULL
, str
);
12417 * Returns true if we can do a "match selected" on the field, false
12421 proto_can_match_selected(const field_info
*finfo
, epan_dissect_t
*edt
)
12423 return construct_match_selected_string(finfo
, edt
, NULL
);
12426 /* This function attempts to construct a "match selected" display filter
12427 * string for the specified field; if it can do so, it returns a pointer
12428 * to the string, otherwise it returns NULL.
12430 * The string is wmem allocated and must be freed with "wmem_free(NULL, ...)".
12433 proto_construct_match_selected_string(const field_info
*finfo
, epan_dissect_t
*edt
)
12435 char *filter
= NULL
;
12437 if (!construct_match_selected_string(finfo
, edt
, &filter
))
12439 wmem_free(NULL
, filter
);
12445 /* This function is common code for all proto_tree_add_bitmask... functions.
12449 proto_item_add_bitmask_tree(proto_item
*item
, tvbuff_t
*tvb
, const int offset
,
12450 const int len
, const int ett
, int * const *fields
,
12451 const int flags
, bool first
,
12452 bool use_parent_tree
,
12453 proto_tree
* tree
, uint64_t value
)
12455 uint64_t available_bits
= UINT64_MAX
;
12456 uint64_t bitmask
= 0;
12458 header_field_info
*hf
;
12459 uint32_t integer32
;
12464 REPORT_DISSECTOR_BUG("Illegal call of proto_item_add_bitmask_tree without fields");
12466 if (len
< 0 || len
> 8)
12467 REPORT_DISSECTOR_BUG("Invalid len: %d", len
);
12469 * packet-frame.c uses len=0 since the value is taken from the packet
12470 * metadata, not the packet bytes. In that case, assume that all bits
12471 * in the provided value are valid.
12474 available_bits
>>= (8 - (unsigned)len
)*8;
12477 if (use_parent_tree
== false)
12478 tree
= proto_item_add_subtree(item
, ett
);
12481 uint64_t present_bits
;
12482 PROTO_REGISTRAR_GET_NTH(**fields
,hf
);
12483 DISSECTOR_ASSERT_HINT(hf
->bitmask
!= 0, hf
->abbrev
);
12485 bitmask
|= hf
->bitmask
;
12487 /* Skip fields that aren't fully present */
12488 present_bits
= available_bits
& hf
->bitmask
;
12489 if (present_bits
!= hf
->bitmask
) {
12494 switch (hf
->type
) {
12500 proto_tree_add_uint(tree
, **fields
, tvb
, offset
, len
, (uint32_t)value
);
12507 proto_tree_add_int(tree
, **fields
, tvb
, offset
, len
, (int32_t)value
);
12514 proto_tree_add_uint64(tree
, **fields
, tvb
, offset
, len
, value
);
12521 proto_tree_add_int64(tree
, **fields
, tvb
, offset
, len
, (int64_t)value
);
12525 proto_tree_add_boolean(tree
, **fields
, tvb
, offset
, len
, value
);
12529 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_item_add_bitmask_tree()",
12532 ftype_name(hf
->type
));
12535 if (flags
& BMT_NO_APPEND
) {
12539 tmpval
= (value
& hf
->bitmask
) >> hfinfo_bitshift(hf
);
12541 /* XXX: README.developer and the comments have always defined
12542 * BMT_NO_INT as "only boolean flags are added to the title /
12543 * don't add non-boolean (integral) fields", but the
12544 * implementation has always added BASE_CUSTOM and fields with
12545 * value_strings, though not fields with unit_strings.
12546 * Possibly this is because some dissectors use a FT_UINT8
12547 * with a value_string for fields that should be a FT_BOOLEAN.
12549 switch (hf
->type
) {
12551 if (hf
->display
== BASE_CUSTOM
) {
12552 char lbl
[ITEM_LABEL_LENGTH
];
12553 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hf
->strings
;
12555 DISSECTOR_ASSERT(fmtfunc
);
12556 fmtfunc(lbl
, (uint32_t) tmpval
);
12557 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12561 else if (hf
->strings
) {
12562 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12563 hf
->name
, hf_try_val_to_str_const((uint32_t) tmpval
, hf
, "Unknown"));
12566 else if (!(flags
& BMT_NO_INT
)) {
12571 proto_item_append_text(item
, ", ");
12574 out
= hfinfo_char_value_format(hf
, buf
, (uint32_t) tmpval
);
12575 proto_item_append_text(item
, "%s: %s", hf
->name
, out
);
12585 if (hf
->display
== BASE_CUSTOM
) {
12586 char lbl
[ITEM_LABEL_LENGTH
];
12587 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hf
->strings
;
12589 DISSECTOR_ASSERT(fmtfunc
);
12590 fmtfunc(lbl
, (uint32_t) tmpval
);
12591 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12595 else if ((hf
->strings
) &&(!(hf
->display
& (BASE_UNIT_STRING
|BASE_SPECIAL_VALS
)))) {
12596 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12597 hf
->name
, hf_try_val_to_str_const((uint32_t) tmpval
, hf
, "Unknown"));
12600 else if (!(flags
& BMT_NO_INT
)) {
12601 char buf
[NUMBER_LABEL_LENGTH
];
12602 const char *out
= NULL
;
12605 proto_item_append_text(item
, ", ");
12608 if (hf
->strings
&& hf
->display
& BASE_SPECIAL_VALS
) {
12609 out
= hf_try_val_to_str((uint32_t) tmpval
, hf
);
12612 out
= hfinfo_number_value_format(hf
, buf
, (uint32_t) tmpval
);
12614 proto_item_append_text(item
, "%s: %s", hf
->name
, out
);
12615 if (hf
->strings
&& hf
->display
& BASE_UNIT_STRING
) {
12616 proto_item_append_text(item
, "%s", unit_name_string_get_value((uint32_t) tmpval
, (const unit_name_string
*)hf
->strings
));
12627 integer32
= (uint32_t) tmpval
;
12629 no_of_bits
= ws_count_ones(hf
->bitmask
);
12630 integer32
= ws_sign_ext32(integer32
, no_of_bits
);
12632 if (hf
->display
== BASE_CUSTOM
) {
12633 char lbl
[ITEM_LABEL_LENGTH
];
12634 const custom_fmt_func_t fmtfunc
= (const custom_fmt_func_t
)hf
->strings
;
12636 DISSECTOR_ASSERT(fmtfunc
);
12637 fmtfunc(lbl
, (int32_t) integer32
);
12638 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12642 else if ((hf
->strings
) &&(!(hf
->display
& (BASE_UNIT_STRING
|BASE_SPECIAL_VALS
)))) {
12643 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12644 hf
->name
, hf_try_val_to_str_const((int32_t) integer32
, hf
, "Unknown"));
12647 else if (!(flags
& BMT_NO_INT
)) {
12648 char buf
[NUMBER_LABEL_LENGTH
];
12649 const char *out
= NULL
;
12652 proto_item_append_text(item
, ", ");
12655 if (hf
->strings
&& hf
->display
& BASE_SPECIAL_VALS
) {
12656 out
= hf_try_val_to_str((int32_t) integer32
, hf
);
12659 out
= hfinfo_number_value_format(hf
, buf
, (int32_t) integer32
);
12661 proto_item_append_text(item
, "%s: %s", hf
->name
, out
);
12662 if (hf
->display
& BASE_UNIT_STRING
) {
12663 proto_item_append_text(item
, "%s", unit_name_string_get_value((uint32_t) tmpval
, (const unit_name_string
*)hf
->strings
));
12674 if (hf
->display
== BASE_CUSTOM
) {
12675 char lbl
[ITEM_LABEL_LENGTH
];
12676 const custom_fmt_func_64_t fmtfunc
= (const custom_fmt_func_64_t
)hf
->strings
;
12678 DISSECTOR_ASSERT(fmtfunc
);
12679 fmtfunc(lbl
, tmpval
);
12680 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12684 else if ((hf
->strings
) &&(!(hf
->display
& (BASE_UNIT_STRING
|BASE_SPECIAL_VALS
)))) {
12685 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12686 hf
->name
, hf_try_val64_to_str_const(tmpval
, hf
, "Unknown"));
12689 else if (!(flags
& BMT_NO_INT
)) {
12690 char buf
[NUMBER_LABEL_LENGTH
];
12691 const char *out
= NULL
;
12694 proto_item_append_text(item
, ", ");
12697 if (hf
->strings
&& hf
->display
& BASE_SPECIAL_VALS
) {
12698 out
= hf_try_val64_to_str(tmpval
, hf
);
12701 out
= hfinfo_number_value_format64(hf
, buf
, tmpval
);
12703 proto_item_append_text(item
, "%s: %s", hf
->name
, out
);
12704 if (hf
->strings
&& hf
->display
& BASE_UNIT_STRING
) {
12705 proto_item_append_text(item
, "%s", unit_name_string_get_value64(tmpval
, (const unit_name_string
*)hf
->strings
));
12717 no_of_bits
= ws_count_ones(hf
->bitmask
);
12718 tmpval
= ws_sign_ext64(tmpval
, no_of_bits
);
12720 if (hf
->display
== BASE_CUSTOM
) {
12721 char lbl
[ITEM_LABEL_LENGTH
];
12722 const custom_fmt_func_64_t fmtfunc
= (const custom_fmt_func_64_t
)hf
->strings
;
12724 DISSECTOR_ASSERT(fmtfunc
);
12725 fmtfunc(lbl
, (int64_t) tmpval
);
12726 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12730 else if ((hf
->strings
) &&(!(hf
->display
& (BASE_UNIT_STRING
|BASE_SPECIAL_VALS
)))) {
12731 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12732 hf
->name
, hf_try_val64_to_str_const((int64_t) tmpval
, hf
, "Unknown"));
12735 else if (!(flags
& BMT_NO_INT
)) {
12736 char buf
[NUMBER_LABEL_LENGTH
];
12737 const char *out
= NULL
;
12740 proto_item_append_text(item
, ", ");
12743 if (hf
->strings
&& hf
->display
& BASE_SPECIAL_VALS
) {
12744 out
= hf_try_val64_to_str((int64_t) tmpval
, hf
);
12747 out
= hfinfo_number_value_format64(hf
, buf
, (int64_t) tmpval
);
12749 proto_item_append_text(item
, "%s: %s", hf
->name
, out
);
12750 if (hf
->strings
&& hf
->display
& BASE_UNIT_STRING
) {
12751 proto_item_append_text(item
, "%s", unit_name_string_get_value64(tmpval
, (const unit_name_string
*)hf
->strings
));
12759 if (hf
->strings
&& !(flags
& BMT_NO_TFS
)) {
12760 /* If we have true/false strings, emit full - otherwise messages
12761 might look weird */
12762 const struct true_false_string
*tfs
=
12763 (const struct true_false_string
*)hf
->strings
;
12766 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12767 hf
->name
, tfs
->true_string
);
12769 } else if (!(flags
& BMT_NO_FALSE
)) {
12770 proto_item_append_text(item
, "%s%s: %s", first
? "" : ", ",
12771 hf
->name
, tfs
->false_string
);
12774 } else if (hf
->bitmask
& value
) {
12775 /* If the flag is set, show the name */
12776 proto_item_append_text(item
, "%s%s", first
? "" : ", ", hf
->name
);
12781 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_item_add_bitmask_tree()",
12784 ftype_name(hf
->type
));
12791 /* XXX: We don't pass the hfi into this function. Perhaps we should,
12792 * but then again most dissectors don't set the bitmask field for
12793 * the higher level bitmask hfi, so calculate the bitmask from the
12794 * fields present. */
12796 bit_offset
= len
*8 - 1 - ws_ilog2(bitmask
);
12797 no_of_bits
= ws_ilog2(bitmask
) - ws_ctz(bitmask
) + 1;
12798 FI_SET_FLAG(PNODE_FINFO(item
), FI_BITS_OFFSET(bit_offset
));
12799 FI_SET_FLAG(PNODE_FINFO(item
), FI_BITS_SIZE(no_of_bits
));
12804 /* This function will dissect a sequence of bytes that describe a
12805 * bitmask and supply the value of that sequence through a pointer.
12806 * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
12808 * This field will form an expansion under which the individual fields of the
12809 * bitmask is dissected and displayed.
12810 * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
12812 * fields is an array of pointers to int that lists all the fields of the
12813 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
12814 * or another integer of the same type/size as hf_hdr with a mask specified.
12815 * This array is terminated by a NULL entry.
12817 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
12818 * FT_integer fields that have a value_string attached will have the
12819 * matched string displayed on the expansion line.
12822 proto_tree_add_bitmask_ret_uint64(proto_tree
*parent_tree
, tvbuff_t
*tvb
,
12823 const unsigned offset
, const int hf_hdr
,
12824 const int ett
, int * const *fields
,
12825 const unsigned encoding
, uint64_t *retval
)
12827 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
);
12830 /* This function will dissect a sequence of bytes that describe a
12832 * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
12834 * This field will form an expansion under which the individual fields of the
12835 * bitmask is dissected and displayed.
12836 * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
12838 * fields is an array of pointers to int that lists all the fields of the
12839 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
12840 * or another integer of the same type/size as hf_hdr with a mask specified.
12841 * This array is terminated by a NULL entry.
12843 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
12844 * FT_integer fields that have a value_string attached will have the
12845 * matched string displayed on the expansion line.
12848 proto_tree_add_bitmask(proto_tree
*parent_tree
, tvbuff_t
*tvb
,
12849 const unsigned offset
, const int hf_hdr
,
12850 const int ett
, int * const *fields
,
12851 const unsigned encoding
)
12853 return proto_tree_add_bitmask_with_flags(parent_tree
, tvb
, offset
, hf_hdr
, ett
, fields
, encoding
, BMT_NO_INT
|BMT_NO_TFS
);
12856 /* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
12857 * what data is appended to the header.
12860 proto_tree_add_bitmask_with_flags_ret_uint64(proto_tree
*parent_tree
, tvbuff_t
*tvb
, const unsigned offset
,
12861 const int hf_hdr
, const int ett
, int * const *fields
, const unsigned encoding
, const int flags
,
12864 proto_item
*item
= NULL
;
12865 header_field_info
*hf
;
12869 PROTO_REGISTRAR_GET_NTH(hf_hdr
,hf
);
12870 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf
);
12871 len
= ftype_wire_size(hf
->type
);
12872 value
= get_uint64_value(parent_tree
, tvb
, offset
, len
, encoding
);
12875 item
= proto_tree_add_item(parent_tree
, hf_hdr
, tvb
, offset
, len
, encoding
);
12876 proto_item_add_bitmask_tree(item
, tvb
, offset
, len
, ett
, fields
,
12877 flags
, false, false, NULL
, value
);
12882 /* Mask out irrelevant portions */
12883 *retval
&= hf
->bitmask
;
12885 *retval
>>= hfinfo_bitshift(hf
);
12891 /* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
12892 * what data is appended to the header.
12895 proto_tree_add_bitmask_with_flags(proto_tree
*parent_tree
, tvbuff_t
*tvb
, const unsigned offset
,
12896 const int hf_hdr
, const int ett
, int * const *fields
, const unsigned encoding
, const int flags
)
12898 proto_item
*item
= NULL
;
12899 header_field_info
*hf
;
12903 PROTO_REGISTRAR_GET_NTH(hf_hdr
,hf
);
12904 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf
);
12907 len
= ftype_wire_size(hf
->type
);
12908 item
= proto_tree_add_item(parent_tree
, hf_hdr
, tvb
, offset
, len
, encoding
);
12909 value
= get_uint64_value(parent_tree
, tvb
, offset
, len
, encoding
);
12910 proto_item_add_bitmask_tree(item
, tvb
, offset
, len
, ett
, fields
,
12911 flags
, false, false, NULL
, value
);
12917 /* Similar to proto_tree_add_bitmask(), but with a passed in value (presumably because it
12918 can't be retrieved directly from tvb) */
12920 proto_tree_add_bitmask_value(proto_tree
*parent_tree
, tvbuff_t
*tvb
, const unsigned offset
,
12921 const int hf_hdr
, const int ett
, int * const *fields
, const uint64_t value
)
12923 return proto_tree_add_bitmask_value_with_flags(parent_tree
, tvb
, offset
,
12924 hf_hdr
, ett
, fields
, value
, BMT_NO_INT
|BMT_NO_TFS
);
12927 /* Similar to proto_tree_add_bitmask_value(), but with control of flag values */
12928 WS_DLL_PUBLIC proto_item
*
12929 proto_tree_add_bitmask_value_with_flags(proto_tree
*parent_tree
, tvbuff_t
*tvb
, const unsigned offset
,
12930 const int hf_hdr
, const int ett
, int * const *fields
, const uint64_t value
, const int flags
)
12932 proto_item
*item
= NULL
;
12933 header_field_info
*hf
;
12936 PROTO_REGISTRAR_GET_NTH(hf_hdr
,hf
);
12937 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf
);
12938 /* the proto_tree_add_uint/_uint64() calls below
12939 will fail if tvb==NULL and len!=0 */
12940 len
= tvb
? ftype_wire_size(hf
->type
) : 0;
12944 item
= proto_tree_add_uint(parent_tree
, hf_hdr
, tvb
, offset
, len
, (uint32_t)value
);
12946 item
= proto_tree_add_uint64(parent_tree
, hf_hdr
, tvb
, offset
, len
, value
);
12948 proto_item_add_bitmask_tree(item
, tvb
, offset
, len
, ett
, fields
,
12949 flags
, false, false, NULL
, value
);
12955 /* Similar to proto_tree_add_bitmask(), but with no "header" item to group all of the fields */
12957 proto_tree_add_bitmask_list(proto_tree
*tree
, tvbuff_t
*tvb
, const unsigned offset
,
12958 const int len
, int * const *fields
, const unsigned encoding
)
12963 value
= get_uint64_value(tree
, tvb
, offset
, len
, encoding
);
12964 proto_item_add_bitmask_tree(NULL
, tvb
, offset
, len
, -1, fields
,
12965 BMT_NO_APPEND
, false, true, tree
, value
);
12970 proto_tree_add_bitmask_list_ret_uint64(proto_tree
*tree
, tvbuff_t
*tvb
, const unsigned offset
,
12971 const int len
, int * const *fields
, const unsigned encoding
, uint64_t *retval
)
12975 value
= get_uint64_value(tree
, tvb
, offset
, len
, encoding
);
12977 proto_item_add_bitmask_tree(NULL
, tvb
, offset
, len
, -1, fields
,
12978 BMT_NO_APPEND
, false, true, tree
, value
);
12986 proto_tree_add_bitmask_list_value(proto_tree
*tree
, tvbuff_t
*tvb
, const unsigned offset
,
12987 const int len
, int * const *fields
, const uint64_t value
)
12990 proto_item_add_bitmask_tree(NULL
, tvb
, offset
, len
, -1, fields
,
12991 BMT_NO_APPEND
, false, true, tree
, value
);
12996 /* The same as proto_tree_add_bitmask(), but using a caller-supplied length.
12997 * This is intended to support bitmask fields whose lengths can vary, perhaps
12998 * as the underlying standard evolves over time.
12999 * With this API there is the possibility of being called to display more or
13000 * less data than the dissector was coded to support.
13001 * In such cases, it is assumed that bitmasks are extended on the MSb end.
13002 * Thus when presented with "too much" or "too little" data, MSbits will be
13003 * ignored or MSfields sacrificed.
13005 * Only fields for which all defined bits are available are displayed.
13008 proto_tree_add_bitmask_len(proto_tree
*parent_tree
, tvbuff_t
*tvb
,
13009 const unsigned offset
, const unsigned len
, const int hf_hdr
,
13010 const int ett
, int * const *fields
, struct expert_field
* exp
,
13011 const unsigned encoding
)
13013 proto_item
*item
= NULL
;
13014 header_field_info
*hf
;
13015 unsigned decodable_len
;
13016 unsigned decodable_offset
;
13017 uint32_t decodable_value
;
13020 PROTO_REGISTRAR_GET_NTH(hf_hdr
, hf
);
13021 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf
);
13023 decodable_offset
= offset
;
13024 decodable_len
= MIN(len
, (unsigned) ftype_wire_size(hf
->type
));
13026 /* If we are ftype_wire_size-limited,
13027 * make sure we decode as many LSBs as possible.
13029 if (encoding
== ENC_BIG_ENDIAN
) {
13030 decodable_offset
+= (len
- decodable_len
);
13034 decodable_value
= get_uint_value(parent_tree
, tvb
, decodable_offset
,
13035 decodable_len
, encoding
);
13037 /* The root item covers all the bytes even if we can't decode them all */
13038 item
= proto_tree_add_uint(parent_tree
, hf_hdr
, tvb
, offset
, len
,
13042 if (decodable_len
< len
) {
13043 /* Dissector likely requires updating for new protocol revision */
13044 expert_add_info_format(NULL
, item
, exp
,
13045 "Only least-significant %d of %d bytes decoded",
13046 decodable_len
, len
);
13050 value
= get_uint64_value(parent_tree
, tvb
, decodable_offset
, decodable_len
, encoding
);
13051 proto_item_add_bitmask_tree(item
, tvb
, decodable_offset
, decodable_len
,
13052 ett
, fields
, BMT_NO_INT
|BMT_NO_TFS
, false, false, NULL
, value
);
13058 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
13060 proto_tree_add_bitmask_text(proto_tree
*parent_tree
, tvbuff_t
*tvb
,
13061 const unsigned offset
, const unsigned len
,
13062 const char *name
, const char *fallback
,
13063 const int ett
, int * const *fields
,
13064 const unsigned encoding
, const int flags
)
13066 proto_item
*item
= NULL
;
13070 item
= proto_tree_add_text_internal(parent_tree
, tvb
, offset
, len
, "%s", name
? name
: "");
13071 value
= get_uint64_value(parent_tree
, tvb
, offset
, len
, encoding
);
13072 if (proto_item_add_bitmask_tree(item
, tvb
, offset
, len
, ett
, fields
,
13073 flags
, true, false, NULL
, value
) && fallback
) {
13074 /* Still at first item - append 'fallback' text if any */
13075 proto_item_append_text(item
, "%s", fallback
);
13083 proto_tree_add_bits_item(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
13084 const unsigned bit_offset
, const int no_of_bits
,
13085 const unsigned encoding
)
13087 header_field_info
*hfinfo
;
13091 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
13093 if (no_of_bits
< 0) {
13094 THROW(ReportedBoundsError
);
13096 octet_length
= (no_of_bits
+ 7) >> 3;
13097 octet_offset
= bit_offset
>> 3;
13098 test_length(hfinfo
, tvb
, octet_offset
, octet_length
, encoding
);
13100 /* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
13101 * but only after doing a bunch more work (which we can, in the common
13102 * case, shortcut here).
13104 CHECK_FOR_NULL_TREE(tree
);
13105 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
13107 return proto_tree_add_bits_ret_val(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, NULL
, encoding
);
13111 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
13112 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
13113 * Offset should be given in bits from the start of the tvb.
13116 static proto_item
*
13117 _proto_tree_add_bits_ret_val(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
13118 const unsigned bit_offset
, const int no_of_bits
,
13119 uint64_t *return_value
, const unsigned encoding
)
13123 uint8_t tot_no_bits
;
13125 char lbl_str
[ITEM_LABEL_LENGTH
];
13126 uint64_t value
= 0;
13127 uint8_t *bytes
= NULL
;
13128 size_t bytes_length
= 0;
13131 header_field_info
*hf_field
;
13133 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
13134 PROTO_REGISTRAR_GET_NTH(hfindex
, hf_field
);
13136 if (hf_field
->bitmask
!= 0) {
13137 REPORT_DISSECTOR_BUG("Incompatible use of proto_tree_add_bits_ret_val"
13138 " with field '%s' (%s) with bitmask != 0",
13139 hf_field
->abbrev
, hf_field
->name
);
13142 if (no_of_bits
< 0) {
13143 THROW(ReportedBoundsError
);
13144 } else if (no_of_bits
== 0) {
13145 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_ret_val() has a bit width of 0",
13149 /* Byte align offset */
13150 offset
= bit_offset
>>3;
13153 * Calculate the number of octets used to hold the bits
13155 tot_no_bits
= ((bit_offset
&0x7) + no_of_bits
);
13156 length
= (tot_no_bits
+ 7) >> 3;
13158 if (no_of_bits
< 65) {
13159 value
= tvb_get_bits64(tvb
, bit_offset
, no_of_bits
, encoding
);
13160 } else if (hf_field
->type
!= FT_BYTES
) {
13161 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_ret_val() has a bit width of %u > 65",
13162 hf_field
->abbrev
, no_of_bits
);
13166 /* Sign extend for signed types */
13167 switch (hf_field
->type
) {
13176 value
= ws_sign_ext64(value
, no_of_bits
);
13183 if (return_value
) {
13184 *return_value
= value
;
13187 /* Coast clear. Try and fake it */
13188 CHECK_FOR_NULL_TREE(tree
);
13189 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13191 bf_str
= decode_bits_in_field(PNODE_POOL(tree
), bit_offset
, no_of_bits
, value
, encoding
);
13193 switch (hf_field
->type
) {
13195 /* Boolean field */
13196 return proto_tree_add_boolean_format(tree
, hfindex
, tvb
, offset
, length
, value
,
13198 bf_str
, hf_field
->name
, tfs_get_string(!!value
, hf_field
->strings
));
13202 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, offset
, length
, (uint32_t)value
);
13203 fill_label_char(PITEM_FINFO(pi
), lbl_str
, NULL
);
13210 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, offset
, length
, (uint32_t)value
);
13211 fill_label_number(PITEM_FINFO(pi
), lbl_str
, NULL
, false);
13218 pi
= proto_tree_add_int(tree
, hfindex
, tvb
, offset
, length
, (int32_t)value
);
13219 fill_label_number(PITEM_FINFO(pi
), lbl_str
, NULL
, true);
13226 pi
= proto_tree_add_uint64(tree
, hfindex
, tvb
, offset
, length
, value
);
13227 fill_label_number64(PITEM_FINFO(pi
), lbl_str
, NULL
, false);
13234 pi
= proto_tree_add_int64(tree
, hfindex
, tvb
, offset
, length
, (int64_t)value
);
13235 fill_label_number64(PITEM_FINFO(pi
), lbl_str
, NULL
, true);
13239 bytes
= tvb_get_bits_array(PNODE_POOL(tree
), tvb
, bit_offset
, no_of_bits
, &bytes_length
, encoding
);
13240 pi
= proto_tree_add_bytes_with_length(tree
, hfindex
, tvb
, offset
, length
, bytes
, (int) bytes_length
);
13241 proto_item_fill_label(PITEM_FINFO(pi
), lbl_str
, NULL
);
13242 proto_item_set_text(pi
, "%s", lbl_str
);
13245 /* TODO: should handle FT_UINT_BYTES ? */
13248 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_tree_add_bits_ret_val()",
13251 ftype_name(hf_field
->type
));
13255 proto_item_set_text(pi
, "%s = %s", bf_str
, lbl_str
);
13260 proto_tree_add_split_bits_item_ret_val(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
13261 const unsigned bit_offset
, const crumb_spec_t
*crumb_spec
,
13262 uint64_t *return_value
)
13267 unsigned mask_initial_bit_offset
;
13268 unsigned mask_greatest_bit_offset
;
13269 unsigned octet_length
;
13272 char lbl_str
[ITEM_LABEL_LENGTH
];
13274 uint64_t composite_bitmask
;
13275 uint64_t composite_bitmap
;
13277 header_field_info
*hf_field
;
13279 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
13280 PROTO_REGISTRAR_GET_NTH(hfindex
, hf_field
);
13282 if (hf_field
->bitmask
!= 0) {
13283 REPORT_DISSECTOR_BUG("Incompatible use of proto_tree_add_split_bits_item_ret_val"
13284 " with field '%s' (%s) with bitmask != 0",
13285 hf_field
->abbrev
, hf_field
->name
);
13288 mask_initial_bit_offset
= bit_offset
% 8;
13293 mask_greatest_bit_offset
= 0;
13294 composite_bitmask
= 0;
13295 composite_bitmap
= 0;
13297 while (crumb_spec
[i
].crumb_bit_length
!= 0) {
13298 uint64_t crumb_mask
, crumb_value
;
13299 uint8_t crumb_end_bit_offset
;
13301 crumb_value
= tvb_get_bits64(tvb
,
13302 bit_offset
+ crumb_spec
[i
].crumb_bit_offset
,
13303 crumb_spec
[i
].crumb_bit_length
,
13305 value
+= crumb_value
;
13306 no_of_bits
+= crumb_spec
[i
].crumb_bit_length
;
13307 DISSECTOR_ASSERT_HINT(no_of_bits
<= 64, "a value larger than 64 bits cannot be represented");
13309 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
13310 octet containing the initial offset.
13311 If the mask is beyond 32 bits, then give up on bit map display.
13312 This could be improved in future, probably showing a table
13313 of 32 or 64 bits per row */
13314 if (mask_greatest_bit_offset
< 32) {
13315 crumb_end_bit_offset
= mask_initial_bit_offset
13316 + crumb_spec
[i
].crumb_bit_offset
13317 + crumb_spec
[i
].crumb_bit_length
;
13318 crumb_mask
= (UINT64_C(1) << crumb_spec
[i
].crumb_bit_length
) - 1;
13320 if (crumb_end_bit_offset
> mask_greatest_bit_offset
) {
13321 mask_greatest_bit_offset
= crumb_end_bit_offset
;
13323 /* Currently the bitmap of the crumbs are only shown if
13324 * smaller than 32 bits. Do not bother calculating the
13325 * mask if it is larger than that. */
13326 if (crumb_end_bit_offset
<= 32) {
13327 composite_bitmask
|= (crumb_mask
<< (64 - crumb_end_bit_offset
));
13328 composite_bitmap
|= (crumb_value
<< (64 - crumb_end_bit_offset
));
13331 /* Shift left for the next segment */
13332 value
<<= crumb_spec
[++i
].crumb_bit_length
;
13335 /* Sign extend for signed types */
13336 switch (hf_field
->type
) {
13345 value
= ws_sign_ext64(value
, no_of_bits
);
13351 if (return_value
) {
13352 *return_value
= value
;
13355 /* Coast clear. Try and fake it */
13356 CHECK_FOR_NULL_TREE(tree
);
13357 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13359 /* initialise the format string */
13362 octet_offset
= bit_offset
>> 3;
13364 /* Round up mask length to nearest octet */
13365 octet_length
= ((mask_greatest_bit_offset
+ 7) >> 3);
13366 mask_greatest_bit_offset
= octet_length
<< 3;
13368 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
13369 It would be a useful enhancement to eliminate this restriction. */
13370 if (mask_greatest_bit_offset
> 0 && mask_greatest_bit_offset
<= 32) {
13371 other_decode_bitfield_value(bf_str
,
13372 (uint32_t)(composite_bitmap
>> (64 - mask_greatest_bit_offset
)),
13373 (uint32_t)(composite_bitmask
>> (64 - mask_greatest_bit_offset
)),
13374 mask_greatest_bit_offset
);
13376 /* If the bitmask is too large, try to describe its contents. */
13377 snprintf(bf_str
, sizeof(bf_str
), "%d bits", no_of_bits
);
13380 switch (hf_field
->type
) {
13381 case FT_BOOLEAN
: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
13382 /* Boolean field */
13383 return proto_tree_add_boolean_format(tree
, hfindex
,
13384 tvb
, octet_offset
, octet_length
, value
,
13386 bf_str
, hf_field
->name
, tfs_get_string(!!value
, hf_field
->strings
));
13390 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, octet_offset
, octet_length
, (uint32_t)value
);
13391 fill_label_char(PITEM_FINFO(pi
), lbl_str
, NULL
);
13398 pi
= proto_tree_add_uint(tree
, hfindex
, tvb
, octet_offset
, octet_length
, (uint32_t)value
);
13399 fill_label_number(PITEM_FINFO(pi
), lbl_str
, NULL
, false);
13406 pi
= proto_tree_add_int(tree
, hfindex
, tvb
, octet_offset
, octet_length
, (int32_t)value
);
13407 fill_label_number(PITEM_FINFO(pi
), lbl_str
, NULL
, true);
13414 pi
= proto_tree_add_uint64(tree
, hfindex
, tvb
, octet_offset
, octet_length
, value
);
13415 fill_label_number64(PITEM_FINFO(pi
), lbl_str
, NULL
, false);
13422 pi
= proto_tree_add_int64(tree
, hfindex
, tvb
, octet_offset
, octet_length
, (int64_t)value
);
13423 fill_label_number64(PITEM_FINFO(pi
), lbl_str
, NULL
, true);
13427 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_tree_add_split_bits_item_ret_val()",
13430 ftype_name(hf_field
->type
));
13433 proto_item_set_text(pi
, "%s = %s", bf_str
, lbl_str
);
13438 proto_tree_add_split_bits_crumb(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
, const unsigned bit_offset
,
13439 const crumb_spec_t
*crumb_spec
, uint16_t crumb_index
)
13441 header_field_info
*hfinfo
;
13442 int start
= bit_offset
>> 3;
13443 int length
= ((bit_offset
+ crumb_spec
[crumb_index
].crumb_bit_length
- 1) >> 3) - (bit_offset
>> 3) + 1;
13445 /* We have to duplicate this length check from proto_tree_add_text_internal in order to check for a null tree
13446 * so that we can use the tree's memory scope in calculating the string */
13447 if (length
== -1) {
13448 tvb_captured_length(tvb
) ? tvb_ensure_captured_length_remaining(tvb
, start
) : 0;
13450 tvb_ensure_bytes_exist(tvb
, start
, length
);
13454 PROTO_REGISTRAR_GET_NTH(hfindex
, hfinfo
);
13455 proto_tree_add_text_internal(tree
, tvb
, start
, length
,
13456 "%s crumb %d of %s (decoded above)",
13457 decode_bits_in_field(PNODE_POOL(tree
), bit_offset
, crumb_spec
[crumb_index
].crumb_bit_length
,
13460 crumb_spec
[crumb_index
].crumb_bit_length
,
13468 proto_tree_add_bits_ret_val(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
13469 const unsigned bit_offset
, const int no_of_bits
,
13470 uint64_t *return_value
, const unsigned encoding
)
13474 if ((item
= _proto_tree_add_bits_ret_val(tree
, hfindex
, tvb
,
13475 bit_offset
, no_of_bits
,
13476 return_value
, encoding
))) {
13477 FI_SET_FLAG(PNODE_FINFO(item
), FI_BITS_OFFSET(bit_offset
));
13478 FI_SET_FLAG(PNODE_FINFO(item
), FI_BITS_SIZE(no_of_bits
));
13483 static proto_item
*
13484 _proto_tree_add_bits_format_value(proto_tree
*tree
, const int hfindex
,
13485 tvbuff_t
*tvb
, const unsigned bit_offset
,
13486 const int no_of_bits
, void *value_ptr
,
13487 const unsigned encoding
, char *value_str
)
13491 uint8_t tot_no_bits
;
13493 uint64_t value
= 0;
13494 header_field_info
*hf_field
;
13496 /* We do not have to return a value, try to fake it as soon as possible */
13497 CHECK_FOR_NULL_TREE(tree
);
13498 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13500 if (hf_field
->bitmask
!= 0) {
13501 REPORT_DISSECTOR_BUG("Incompatible use of proto_tree_add_bits_format_value"
13502 " with field '%s' (%s) with bitmask != 0",
13503 hf_field
->abbrev
, hf_field
->name
);
13506 if (no_of_bits
< 0) {
13507 THROW(ReportedBoundsError
);
13508 } else if (no_of_bits
== 0) {
13509 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_format_value() has a bit width of 0",
13513 /* Byte align offset */
13514 offset
= bit_offset
>>3;
13517 * Calculate the number of octets used to hold the bits
13519 tot_no_bits
= ((bit_offset
&0x7) + no_of_bits
);
13520 length
= tot_no_bits
>>3;
13521 /* If we are using part of the next octet, increase length by 1 */
13522 if (tot_no_bits
& 0x07)
13525 if (no_of_bits
< 65) {
13526 value
= tvb_get_bits64(tvb
, bit_offset
, no_of_bits
, encoding
);
13528 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_format_value() has a bit width of %u > 65",
13529 hf_field
->abbrev
, no_of_bits
);
13533 str
= decode_bits_in_field(PNODE_POOL(tree
), bit_offset
, no_of_bits
, value
, encoding
);
13535 (void) g_strlcat(str
, " = ", 256+64);
13536 (void) g_strlcat(str
, hf_field
->name
, 256+64);
13539 * This function does not receive an actual value but a dimensionless pointer to that value.
13540 * For this reason, the type of the header field is examined in order to determine
13541 * what kind of value we should read from this address.
13542 * The caller of this function must make sure that for the specific header field type the address of
13543 * a compatible value is provided.
13545 switch (hf_field
->type
) {
13547 return proto_tree_add_boolean_format(tree
, hfindex
, tvb
, offset
, length
, *(uint64_t *)value_ptr
,
13548 "%s: %s", str
, value_str
);
13556 return proto_tree_add_uint_format(tree
, hfindex
, tvb
, offset
, length
, *(uint32_t *)value_ptr
,
13557 "%s: %s", str
, value_str
);
13564 return proto_tree_add_uint64_format(tree
, hfindex
, tvb
, offset
, length
, *(uint64_t *)value_ptr
,
13565 "%s: %s", str
, value_str
);
13572 return proto_tree_add_int_format(tree
, hfindex
, tvb
, offset
, length
, *(int32_t *)value_ptr
,
13573 "%s: %s", str
, value_str
);
13580 return proto_tree_add_int64_format(tree
, hfindex
, tvb
, offset
, length
, *(int64_t *)value_ptr
,
13581 "%s: %s", str
, value_str
);
13585 return proto_tree_add_float_format(tree
, hfindex
, tvb
, offset
, length
, *(float *)value_ptr
,
13586 "%s: %s", str
, value_str
);
13590 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_tree_add_bits_format_value()",
13593 ftype_name(hf_field
->type
));
13598 static proto_item
*
13599 proto_tree_add_bits_format_value(proto_tree
*tree
, const int hfindex
,
13600 tvbuff_t
*tvb
, const unsigned bit_offset
,
13601 const int no_of_bits
, void *value_ptr
,
13602 const unsigned encoding
, char *value_str
)
13606 if ((item
= _proto_tree_add_bits_format_value(tree
, hfindex
,
13607 tvb
, bit_offset
, no_of_bits
,
13608 value_ptr
, encoding
, value_str
))) {
13609 FI_SET_FLAG(PNODE_FINFO(item
), FI_BITS_OFFSET(bit_offset
));
13610 FI_SET_FLAG(PNODE_FINFO(item
), FI_BITS_SIZE(no_of_bits
));
13615 #define CREATE_VALUE_STRING(tree,dst,format,ap) \
13616 va_start(ap, format); \
13617 dst = wmem_strdup_vprintf(PNODE_POOL(tree), format, ap); \
13621 proto_tree_add_uint_bits_format_value(proto_tree
*tree
, const int hfindex
,
13622 tvbuff_t
*tvb
, const unsigned bit_offset
,
13623 const int no_of_bits
, uint32_t value
,
13624 const unsigned encoding
,
13625 const char *format
, ...)
13629 header_field_info
*hf_field
;
13631 CHECK_FOR_NULL_TREE(tree
);
13633 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13635 switch (hf_field
->type
) {
13643 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
13648 CREATE_VALUE_STRING(tree
, dst
, format
, ap
);
13650 return proto_tree_add_bits_format_value(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, &value
, encoding
, dst
);
13654 proto_tree_add_uint64_bits_format_value(proto_tree
*tree
, const int hfindex
,
13655 tvbuff_t
*tvb
, const unsigned bit_offset
,
13656 const int no_of_bits
, uint64_t value
,
13657 const unsigned encoding
,
13658 const char *format
, ...)
13662 header_field_info
*hf_field
;
13664 CHECK_FOR_NULL_TREE(tree
);
13666 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13668 switch (hf_field
->type
) {
13676 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, or FT_UINT64",
13681 CREATE_VALUE_STRING(tree
, dst
, format
, ap
);
13683 return proto_tree_add_bits_format_value(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, &value
, encoding
, dst
);
13687 proto_tree_add_float_bits_format_value(proto_tree
*tree
, const int hfindex
,
13688 tvbuff_t
*tvb
, const unsigned bit_offset
,
13689 const int no_of_bits
, float value
,
13690 const unsigned encoding
,
13691 const char *format
, ...)
13695 header_field_info
*hf_field
;
13697 CHECK_FOR_NULL_TREE(tree
);
13699 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13701 DISSECTOR_ASSERT_FIELD_TYPE(hf_field
, FT_FLOAT
);
13703 CREATE_VALUE_STRING(tree
, dst
, format
, ap
);
13705 return proto_tree_add_bits_format_value(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, &value
, encoding
, dst
);
13709 proto_tree_add_int_bits_format_value(proto_tree
*tree
, const int hfindex
,
13710 tvbuff_t
*tvb
, const unsigned bit_offset
,
13711 const int no_of_bits
, int32_t value
,
13712 const unsigned encoding
,
13713 const char *format
, ...)
13717 header_field_info
*hf_field
;
13719 CHECK_FOR_NULL_TREE(tree
);
13721 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13723 switch (hf_field
->type
) {
13731 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
13736 CREATE_VALUE_STRING(tree
, dst
, format
, ap
);
13738 return proto_tree_add_bits_format_value(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, &value
, encoding
, dst
);
13742 proto_tree_add_int64_bits_format_value(proto_tree
*tree
, const int hfindex
,
13743 tvbuff_t
*tvb
, const unsigned bit_offset
,
13744 const int no_of_bits
, int64_t value
,
13745 const unsigned encoding
,
13746 const char *format
, ...)
13750 header_field_info
*hf_field
;
13752 CHECK_FOR_NULL_TREE(tree
);
13754 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13756 switch (hf_field
->type
) {
13764 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
13769 CREATE_VALUE_STRING(tree
, dst
, format
, ap
);
13771 return proto_tree_add_bits_format_value(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, &value
, encoding
, dst
);
13775 proto_tree_add_boolean_bits_format_value(proto_tree
*tree
, const int hfindex
,
13776 tvbuff_t
*tvb
, const unsigned bit_offset
,
13777 const int no_of_bits
, uint64_t value
,
13778 const unsigned encoding
,
13779 const char *format
, ...)
13783 header_field_info
*hf_field
;
13785 CHECK_FOR_NULL_TREE(tree
);
13787 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hf_field
);
13789 DISSECTOR_ASSERT_FIELD_TYPE(hf_field
, FT_BOOLEAN
);
13791 CREATE_VALUE_STRING(tree
, dst
, format
, ap
);
13793 return proto_tree_add_bits_format_value(tree
, hfindex
, tvb
, bit_offset
, no_of_bits
, &value
, encoding
, dst
);
13797 proto_tree_add_ts_23_038_7bits_packed_item(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
13798 const unsigned bit_offset
, const int no_of_chars
)
13801 header_field_info
*hfinfo
;
13806 CHECK_FOR_NULL_TREE(tree
);
13808 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
13810 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_STRING
);
13812 byte_length
= (((no_of_chars
+ 1) * 7) + (bit_offset
& 0x07)) >> 3;
13813 byte_offset
= bit_offset
>> 3;
13815 string
= tvb_get_ts_23_038_7bits_string_packed(PNODE_POOL(tree
), tvb
, bit_offset
, no_of_chars
);
13817 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, byte_offset
, &byte_length
);
13818 DISSECTOR_ASSERT(byte_length
>= 0);
13819 proto_tree_set_string(PNODE_FINFO(pi
), string
);
13825 proto_tree_add_ascii_7bits_item(proto_tree
*tree
, const int hfindex
, tvbuff_t
*tvb
,
13826 const unsigned bit_offset
, const int no_of_chars
)
13829 header_field_info
*hfinfo
;
13834 CHECK_FOR_NULL_TREE(tree
);
13836 TRY_TO_FAKE_THIS_ITEM(tree
, hfindex
, hfinfo
);
13838 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo
, FT_STRING
);
13840 byte_length
= (((no_of_chars
+ 1) * 7) + (bit_offset
& 0x07)) >> 3;
13841 byte_offset
= bit_offset
>> 3;
13843 string
= tvb_get_ascii_7bits_string(PNODE_POOL(tree
), tvb
, bit_offset
, no_of_chars
);
13845 pi
= proto_tree_add_pi(tree
, hfinfo
, tvb
, byte_offset
, &byte_length
);
13846 DISSECTOR_ASSERT(byte_length
>= 0);
13847 proto_tree_set_string(PNODE_FINFO(pi
), string
);
13852 const value_string proto_checksum_vals
[] = {
13853 { PROTO_CHECKSUM_E_BAD
, "Bad" },
13854 { PROTO_CHECKSUM_E_GOOD
, "Good" },
13855 { PROTO_CHECKSUM_E_UNVERIFIED
, "Unverified" },
13856 { PROTO_CHECKSUM_E_NOT_PRESENT
, "Not present" },
13857 { PROTO_CHECKSUM_E_ILLEGAL
, "Illegal" },
13863 proto_tree_add_checksum(proto_tree
*tree
, tvbuff_t
*tvb
, const unsigned offset
,
13864 const int hf_checksum
, const int hf_checksum_status
, struct expert_field
* bad_checksum_expert
,
13865 packet_info
*pinfo
, uint32_t computed_checksum
, const unsigned encoding
, const unsigned flags
)
13867 header_field_info
*hfinfo
;
13870 proto_item
* ti
= NULL
;
13872 bool incorrect_checksum
= true;
13874 PROTO_REGISTRAR_GET_NTH(hf_checksum
, hfinfo
);
13876 switch (hfinfo
->type
) {
13890 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
13894 if (flags
& PROTO_CHECKSUM_NOT_PRESENT
) {
13895 ti
= proto_tree_add_uint_format_value(tree
, hf_checksum
, tvb
, offset
, len
, 0, "[missing]");
13896 proto_item_set_generated(ti
);
13897 if (hf_checksum_status
!= -1) {
13898 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, len
, PROTO_CHECKSUM_E_NOT_PRESENT
);
13899 proto_item_set_generated(ti2
);
13904 if (flags
& PROTO_CHECKSUM_GENERATED
) {
13905 ti
= proto_tree_add_uint(tree
, hf_checksum
, tvb
, offset
, len
, computed_checksum
);
13906 proto_item_set_generated(ti
);
13908 ti
= proto_tree_add_item_ret_uint(tree
, hf_checksum
, tvb
, offset
, len
, encoding
, &checksum
);
13909 if (flags
& PROTO_CHECKSUM_VERIFY
) {
13910 if (flags
& (PROTO_CHECKSUM_IN_CKSUM
|PROTO_CHECKSUM_ZERO
)) {
13911 if (computed_checksum
== 0) {
13912 proto_item_append_text(ti
, " [correct]");
13913 if (hf_checksum_status
!= -1) {
13914 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, 0, PROTO_CHECKSUM_E_GOOD
);
13915 proto_item_set_generated(ti2
);
13917 incorrect_checksum
= false;
13918 } else if (flags
& PROTO_CHECKSUM_IN_CKSUM
) {
13919 computed_checksum
= in_cksum_shouldbe(checksum
, computed_checksum
);
13922 if (checksum
== computed_checksum
) {
13923 proto_item_append_text(ti
, " [correct]");
13924 if (hf_checksum_status
!= -1) {
13925 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, 0, PROTO_CHECKSUM_E_GOOD
);
13926 proto_item_set_generated(ti2
);
13928 incorrect_checksum
= false;
13932 if (incorrect_checksum
) {
13933 if (hf_checksum_status
!= -1) {
13934 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, 0, PROTO_CHECKSUM_E_BAD
);
13935 proto_item_set_generated(ti2
);
13937 if (flags
& PROTO_CHECKSUM_ZERO
) {
13938 proto_item_append_text(ti
, " [incorrect]");
13939 if (bad_checksum_expert
!= NULL
)
13940 expert_add_info_format(pinfo
, ti
, bad_checksum_expert
, "%s", expert_get_summary(bad_checksum_expert
));
13942 proto_item_append_text(ti
, " incorrect, should be 0x%0*x", len
*2, computed_checksum
);
13943 if (bad_checksum_expert
!= NULL
)
13944 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
);
13948 if (hf_checksum_status
!= -1) {
13949 proto_item_append_text(ti
, " [unverified]");
13950 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, 0, PROTO_CHECKSUM_E_UNVERIFIED
);
13951 proto_item_set_generated(ti2
);
13960 proto_tree_add_checksum_bytes(proto_tree
*tree
, tvbuff_t
*tvb
, const unsigned offset
,
13961 const int hf_checksum
, const int hf_checksum_status
, struct expert_field
* bad_checksum_expert
,
13962 packet_info
*pinfo
, const uint8_t *computed_checksum
, size_t checksum_len
, const unsigned flags
)
13964 header_field_info
*hfinfo
;
13965 uint8_t *checksum
= NULL
;
13966 proto_item
* ti
= NULL
;
13968 bool incorrect_checksum
= true;
13970 PROTO_REGISTRAR_GET_NTH(hf_checksum
, hfinfo
);
13972 if (hfinfo
->type
!= FT_BYTES
) {
13973 REPORT_DISSECTOR_BUG("field %s is not of type FT_BYTES",
13977 if (flags
& PROTO_CHECKSUM_NOT_PRESENT
) {
13978 ti
= proto_tree_add_bytes_format_value(tree
, hf_checksum
, tvb
, offset
, (int)checksum_len
, 0, "[missing]");
13979 proto_item_set_generated(ti
);
13980 if (hf_checksum_status
!= -1) {
13981 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, (int)checksum_len
, PROTO_CHECKSUM_E_NOT_PRESENT
);
13982 proto_item_set_generated(ti2
);
13987 if (flags
& PROTO_CHECKSUM_GENERATED
) {
13988 ti
= proto_tree_add_bytes(tree
, hf_checksum
, tvb
, offset
, (int)checksum_len
, computed_checksum
);
13989 proto_item_set_generated(ti
);
13991 checksum
= (uint8_t*)wmem_alloc0_array(wmem_packet_scope(), uint8_t, checksum_len
);
13992 tvb_memcpy(tvb
, checksum
, offset
, checksum_len
);
13993 ti
= proto_tree_add_bytes(tree
, hf_checksum
, tvb
, offset
, (int)checksum_len
, checksum
);
13994 if (flags
& PROTO_CHECKSUM_VERIFY
) {
13995 if (flags
& (PROTO_CHECKSUM_IN_CKSUM
|PROTO_CHECKSUM_ZERO
)) {
13996 if (computed_checksum
== 0) {
13997 proto_item_append_text(ti
, " [correct]");
13998 if (hf_checksum_status
!= -1) {
13999 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, 0, PROTO_CHECKSUM_E_GOOD
);
14000 proto_item_set_generated(ti2
);
14002 incorrect_checksum
= false;
14005 if (memcmp(computed_checksum
, checksum
, checksum_len
) == 0) {
14006 proto_item_append_text(ti
, " [correct]");
14007 if (hf_checksum_status
!= -1) {
14008 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, 0, PROTO_CHECKSUM_E_GOOD
);
14009 proto_item_set_generated(ti2
);
14011 incorrect_checksum
= false;
14015 if (incorrect_checksum
) {
14016 if (hf_checksum_status
!= -1) {
14017 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, 0, PROTO_CHECKSUM_E_BAD
);
14018 proto_item_set_generated(ti2
);
14020 if (flags
& PROTO_CHECKSUM_ZERO
) {
14021 proto_item_append_text(ti
, " [incorrect]");
14022 if (bad_checksum_expert
!= NULL
)
14023 expert_add_info_format(pinfo
, ti
, bad_checksum_expert
, "%s", expert_get_summary(bad_checksum_expert
));
14025 size_t computed_checksum_str_len
= (2 * checksum_len
* sizeof(char)) + 1;
14026 char *computed_checksum_str
= (char*)wmem_alloc0_array(wmem_packet_scope(), char, computed_checksum_str_len
);
14027 for (size_t counter
= 0; counter
< checksum_len
; ++counter
) {
14029 /* On ecah iteration inserts two characters */
14030 (char*)&computed_checksum_str
[counter
<< 1],
14031 computed_checksum_str_len
- (counter
<< 1),
14033 computed_checksum
[counter
]);
14035 proto_item_append_text(ti
, " incorrect, should be 0x%s", computed_checksum_str
);
14036 if (bad_checksum_expert
!= NULL
)
14037 expert_add_info_format(pinfo
, ti
, bad_checksum_expert
, "%s [should be 0x%s]", expert_get_summary(bad_checksum_expert
), computed_checksum_str
);
14041 if (hf_checksum_status
!= -1) {
14042 proto_item_append_text(ti
, " [unverified]");
14043 ti2
= proto_tree_add_uint(tree
, hf_checksum_status
, tvb
, offset
, 0, PROTO_CHECKSUM_E_UNVERIFIED
);
14044 proto_item_set_generated(ti2
);
14053 proto_check_field_name(const char *field_name
)
14055 return module_check_valid_name(field_name
, false);
14059 proto_check_field_name_lower(const char *field_name
)
14061 return module_check_valid_name(field_name
, true);
14065 tree_expanded(int tree_type
)
14067 if (tree_type
<= 0) {
14070 ws_assert(tree_type
>= 0 && tree_type
< num_tree_types
);
14071 return tree_is_expanded
[tree_type
>> 5] & (1U << (tree_type
& 31));
14075 tree_expanded_set(int tree_type
, bool value
)
14077 ws_assert(tree_type
>= 0 && tree_type
< num_tree_types
);
14080 tree_is_expanded
[tree_type
>> 5] |= (1U << (tree_type
& 31));
14082 tree_is_expanded
[tree_type
>> 5] &= ~(1U << (tree_type
& 31));
14086 * Editor modelines - https://www.wireshark.org/tools/modelines.html
14089 * c-basic-offset: 8
14091 * indent-tabs-mode: t
14094 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
14095 * :indentSize=8:tabSize=8:noTabs=false: