update epan/dissectors/pidl/drsuapi/drsuapi.idl from samba
[wireshark-sm.git] / epan / proto.c
blob1e2dfe28bf5f58da907ce8c7959c49e384dab68c
1 /* proto.c
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
9 */
11 #include "config.h"
12 #define WS_LOG_DOMAIN LOG_DOMAIN_EPAN
14 #include <stdio.h>
15 #include <string.h>
16 #include <glib.h>
17 #include <float.h>
18 #include <inttypes.h>
19 #include <errno.h>
21 #include <epan/tfs.h>
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>
36 #include "packet.h"
37 #include "exceptions.h"
38 #include "ptvcursor.h"
39 #include "strutil.h"
40 #include "addr_resolv.h"
41 #include "address_types.h"
42 #include "oids.h"
43 #include "proto.h"
44 #include "epan_dissect.h"
45 #include "dfilter/dfilter.h"
46 #include "tvbuff.h"
47 #include <epan/wmem_scopes.h>
48 #include "charsets.h"
49 #include "column-info.h"
50 #include "to_str.h"
51 #include "osi-utils.h"
52 #include "expert.h"
53 #include "show_exception.h"
54 #include "in_cksum.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 {
65 int cursor_offset;
66 proto_item *it;
67 proto_tree *tree;
68 } subtree_lvl;
70 struct ptvcursor {
71 wmem_allocator_t *scope;
72 subtree_lvl *pushed_tree;
73 uint8_t pushed_tree_index;
74 uint8_t pushed_tree_max;
75 proto_tree *tree;
76 tvbuff_t *tvb;
77 int offset;
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) \
87 if (!tree) { \
88 free_block; \
89 return NULL; \
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 ) { \
105 cleanup_block; \
106 return NULL; \
109 /** See inlined comments.
110 @param length the length of this item
111 @return NULL if 'length' is lower -1 or equal 0 */
112 #define CHECK_FOR_ZERO_OR_MINUS_LENGTH(length) \
113 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length, ((void)0))
115 /** See inlined comments.
116 @param tree the tree to append this item to
117 @param hfindex field index
118 @param hfinfo header_field
119 @param free_block a code block to call to free resources if this returns
120 @return the header field matching 'hfinfo' */
121 #define TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, free_block) \
122 /* If the tree is not visible and this item is not referenced \
123 we don't have to do much work at all but we should still \
124 return a node so that referenced field items below this node \
125 (think proto_item_add_subtree()) will still have somewhere \
126 to attach to or else filtering will not work (they would be \
127 ignored since tree would be NULL). \
128 DON'T try to fake a node where PTREE_FINFO(tree) is NULL \
129 since dissectors that want to do proto_item_set_len() or \
130 other operations that dereference this would crash. \
131 DON'T try to fake a node where PTREE_FINFO(tree) is visible \
132 because that means we can change its length or repr, and we \
133 don't want to do so with calls intended for this faked new \
134 item, so this item needs a new (hidden) child node. \
135 (PROTO_ITEM_IS_HIDDEN(tree) checks both conditions.) \
136 We fake FT_PROTOCOL unless some clients have requested us \
137 not to do so. \
138 */ \
139 PTREE_DATA(tree)->count++; \
140 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
141 if (PTREE_DATA(tree)->count > prefs.gui_max_tree_items) { \
142 free_block; \
143 if (wireshark_abort_on_too_many_items) \
144 ws_error("Adding %s would put more than %d items in the tree -- possible infinite loop (max number of items can be increased in advanced preferences)", \
145 hfinfo->abbrev, prefs.gui_max_tree_items); \
146 /* Let the exception handler add items to the tree */ \
147 PTREE_DATA(tree)->count = 0; \
148 THROW_MESSAGE(DissectorError, \
149 wmem_strdup_printf(PNODE_POOL(tree), \
150 "Adding %s would put more than %d items in the tree -- possible infinite loop (max number of items can be increased in advanced preferences)", \
151 hfinfo->abbrev, prefs.gui_max_tree_items)); \
153 if (!(PTREE_DATA(tree)->visible)) { \
154 if (PROTO_ITEM_IS_HIDDEN(tree)) { \
155 if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
156 && (hfinfo->ref_type != HF_REF_TYPE_PRINT) \
157 && (hfinfo->type != FT_PROTOCOL || \
158 PTREE_DATA(tree)->fake_protocols)) { \
159 free_block; \
160 /* just return tree back to the caller */\
161 return tree; \
166 /** See inlined comments.
167 @param tree the tree to append this item to
168 @param hfindex field index
169 @param hfinfo header_field
170 @return the header field matching 'hfinfo' */
171 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
172 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, ((void)0))
175 /** See inlined comments.
176 @param pi the created protocol item we're about to return */
177 #define TRY_TO_FAKE_THIS_REPR(pi) \
178 ws_assert(pi); \
179 if (!(PTREE_DATA(pi)->visible) && \
180 PROTO_ITEM_IS_HIDDEN(pi)) { \
181 /* If the tree (GUI) or item isn't visible it's pointless for \
182 * us to generate the protocol item's string representation */ \
183 return pi; \
185 /* Same as above but returning void */
186 #define TRY_TO_FAKE_THIS_REPR_VOID(pi) \
187 if (!pi) \
188 return; \
189 if (!(PTREE_DATA(pi)->visible) && \
190 PROTO_ITEM_IS_HIDDEN(pi)) { \
191 /* If the tree (GUI) or item isn't visible it's pointless for \
192 * us to generate the protocol item's string representation */ \
193 return; \
195 /* Similar to above, but allows a NULL tree */
196 #define TRY_TO_FAKE_THIS_REPR_NESTED(pi) \
197 if ((pi == NULL) || (!(PTREE_DATA(pi)->visible) && \
198 PROTO_ITEM_IS_HIDDEN(pi))) { \
199 /* If the tree (GUI) or item isn't visible it's pointless for \
200 * us to generate the protocol item's string representation */ \
201 return pi; \
204 #ifdef ENABLE_CHECK_FILTER
205 #define CHECK_HF_VALUE(type, spec, start_values) \
207 const type *current; \
208 int n, m; \
209 current = start_values; \
210 for (n=0; current; n++, current++) { \
211 /* Drop out if we reached the end. */ \
212 if ((current->value == 0) && (current->strptr == NULL)) { \
213 break; \
215 /* Check value against all previous */ \
216 for (m=0; m < n; m++) { \
217 /* There are lots of duplicates with the same string, \
218 so only report if different... */ \
219 if ((start_values[m].value == current->value) && \
220 (strcmp(start_values[m].strptr, current->strptr) != 0)) { \
221 ws_warning("Field '%s' (%s) has a conflicting entry in its" \
222 " value_string: %" spec " is at indices %u (%s) and %u (%s)", \
223 hfinfo->name, hfinfo->abbrev, \
224 current->value, m, start_values[m].strptr, n, current->strptr); \
229 #endif
231 /* The longest NUMBER-like field label we have is for BASE_OUI, which
232 * can have up to 64 bytes for the manufacturer name if resolved plus
233 * 11 bytes for the "XX:XX:XX ()" part = 75 octets.
235 #define NUMBER_LABEL_LENGTH 80
237 static const char *hf_try_val_to_str(uint32_t value, const header_field_info *hfinfo);
238 static const char *hf_try_val64_to_str(uint64_t value, const header_field_info *hfinfo);
239 static const char *hf_try_val_to_str_const(uint32_t value, const header_field_info *hfinfo, const char *unknown_str);
240 static const char *hf_try_val64_to_str_const(uint64_t value, const header_field_info *hfinfo, const char *unknown_str);
241 static int hfinfo_bitoffset(const header_field_info *hfinfo);
242 static int hfinfo_mask_bitwidth(const header_field_info *hfinfo);
243 static int hfinfo_container_bitwidth(const header_field_info *hfinfo);
245 #define label_concat(dst, pos, src) \
246 ws_label_strcpy(dst, ITEM_LABEL_LENGTH, pos, src, 0)
248 static void mark_truncated(char *label_str, size_t name_pos, const size_t size, size_t *value_pos);
249 static void label_mark_truncated(char *label_str, size_t name_pos, size_t *value_pos);
250 #define LABEL_MARK_TRUNCATED_START(label_str, value_pos) label_mark_truncated(label_str, 0, value_pos)
252 static void fill_label_boolean(const field_info *fi, char *label_str, size_t *value_pos);
253 static void fill_label_bitfield_char(const field_info *fi, char *label_str, size_t *value_pos);
254 static void fill_label_bitfield(const field_info *fi, char *label_str, size_t *value_pos, bool is_signed);
255 static void fill_label_bitfield64(const field_info *fi, char *label_str, size_t *value_pos, bool is_signed);
256 static void fill_label_char(const field_info *fi, char *label_str, size_t *value_pos);
257 static void fill_label_number(const field_info *fi, char *label_str, size_t *value_pos, bool is_signed);
258 static void fill_label_number64(const field_info *fi, char *label_str, size_t *value_pos, bool is_signed);
260 static size_t fill_display_label_float(const field_info *fi, char *label_str);
261 static void fill_label_float(const field_info *fi, char *label_str, size_t *value_pos);
263 static const char *hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[NUMBER_LABEL_LENGTH], uint32_t value);
264 static const char *hfinfo_number_value_format_display64(const header_field_info *hfinfo, int display, char buf[NUMBER_LABEL_LENGTH], uint64_t value);
265 static const char *hfinfo_char_vals_format(const header_field_info *hfinfo, char buf[32], uint32_t value);
266 static const char *hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint32_t value);
267 static const char *hfinfo_number_vals_format64(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint64_t value);
268 static const char *hfinfo_number_value_format(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint32_t value);
269 static const char *hfinfo_number_value_format64(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint64_t value);
270 static const char *hfinfo_char_value_format(const header_field_info *hfinfo, char buf[32], uint32_t value);
271 static const char *hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint32_t value);
272 static const char *hfinfo_numeric_value_format64(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint64_t value);
274 static void proto_cleanup_base(void);
276 static proto_item *
277 proto_tree_add_node(proto_tree *tree, field_info *fi);
279 static void
280 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const int start, int *length,
281 int *item_length, const unsigned encoding);
283 static int
284 get_full_length(header_field_info *hfinfo, tvbuff_t *tvb, const int start,
285 int length, unsigned item_length, const int encoding);
287 static field_info *
288 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
289 const int start, const int item_length);
291 static proto_item *
292 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
293 int start, int *length);
295 static void
296 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
297 static void
298 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
300 static void
301 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb, const char* field_data, int length);
302 static void
303 proto_tree_set_bytes(field_info *fi, const uint8_t* start_ptr, int length);
304 static void
305 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, int offset, int length);
306 static void
307 proto_tree_set_bytes_gbytearray(field_info *fi, const GByteArray *value);
308 static void
309 proto_tree_set_time(field_info *fi, const nstime_t *value_ptr);
310 static void
311 proto_tree_set_string(field_info *fi, const char* value);
312 static void
313 proto_tree_set_ax25(field_info *fi, const uint8_t* value);
314 static void
315 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, int start);
316 static void
317 proto_tree_set_vines(field_info *fi, const uint8_t* value);
318 static void
319 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, int start);
320 static void
321 proto_tree_set_ether(field_info *fi, const uint8_t* value);
322 static void
323 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, int start);
324 static void
325 proto_tree_set_ipxnet(field_info *fi, uint32_t value);
326 static void
327 proto_tree_set_ipv4(field_info *fi, ws_in4_addr value);
328 static void
329 proto_tree_set_ipv6(field_info *fi, const ws_in6_addr* value);
330 static void
331 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, int start, int length);
332 static void
333 proto_tree_set_fcwwn_tvb(field_info *fi, tvbuff_t *tvb, int start, int length);
334 static void
335 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
336 static void
337 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, int start, const unsigned encoding);
338 static void
339 proto_tree_set_oid(field_info *fi, const uint8_t* value_ptr, int length);
340 static void
341 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, int start, int length);
342 static void
343 proto_tree_set_system_id(field_info *fi, const uint8_t* value_ptr, int length);
344 static void
345 proto_tree_set_system_id_tvb(field_info *fi, tvbuff_t *tvb, int start, int length);
346 static void
347 proto_tree_set_boolean(field_info *fi, uint64_t value);
348 static void
349 proto_tree_set_float(field_info *fi, float value);
350 static void
351 proto_tree_set_double(field_info *fi, double value);
352 static void
353 proto_tree_set_uint(field_info *fi, uint32_t value);
354 static void
355 proto_tree_set_int(field_info *fi, int32_t value);
356 static void
357 proto_tree_set_uint64(field_info *fi, uint64_t value);
358 static void
359 proto_tree_set_int64(field_info *fi, int64_t value);
360 static void
361 proto_tree_set_eui64(field_info *fi, const uint64_t value);
362 static void
363 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, int start, const unsigned encoding);
365 /* Handle type length mismatch (now filterable) expert info */
366 static int proto_type_length_mismatch;
367 static expert_field ei_type_length_mismatch_error;
368 static expert_field ei_type_length_mismatch_warn;
369 static void register_type_length_mismatch(void);
371 /* Handle byte array string decoding errors with expert info */
372 static int proto_byte_array_string_decoding_error;
373 static expert_field ei_byte_array_string_decoding_failed_error;
374 static void register_byte_array_string_decodinws_error(void);
376 /* Handle date and time string decoding errors with expert info */
377 static int proto_date_time_string_decoding_error;
378 static expert_field ei_date_time_string_decoding_failed_error;
379 static void register_date_time_string_decodinws_error(void);
381 /* Handle string errors expert info */
382 static int proto_string_errors;
383 static expert_field ei_string_trailing_characters;
384 static void register_string_errors(void);
386 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
388 /* special-case header field used within proto.c */
389 static header_field_info hfi_text_only =
390 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
391 int hf_text_only;
393 /* Structure for information about a protocol */
394 struct _protocol {
395 const char *name; /* long description */
396 const char *short_name; /* short description */
397 const char *filter_name; /* name of this protocol in filters */
398 GPtrArray *fields; /* fields for this protocol */
399 int proto_id; /* field ID for this protocol */
400 bool is_enabled; /* true if protocol is enabled */
401 bool enabled_by_default; /* true if protocol is enabled by default */
402 bool can_toggle; /* true if is_enabled can be changed */
403 int parent_proto_id; /* Used to identify "pino"s (Protocol In Name Only).
404 For dissectors that need a protocol name so they
405 can be added to a dissector table, but use the
406 parent_proto_id for things like enable/disable */
407 GList *heur_list; /* Heuristic dissectors associated with this protocol */
410 /* List of all protocols */
411 static GList *protocols;
413 /* Structure stored for deregistered g_slice */
414 struct g_slice_data {
415 size_t block_size;
416 void *mem_block;
419 /* Deregistered fields */
420 static GPtrArray *deregistered_fields;
421 static GPtrArray *deregistered_data;
422 static GPtrArray *deregistered_slice;
424 /* indexed by prefix, contains initializers */
425 static GHashTable* prefixes;
427 /* Contains information about a field when a dissector calls
428 * proto_tree_add_item. */
429 #define FIELD_INFO_NEW(pool, fi) fi = wmem_new(pool, field_info)
430 #define FIELD_INFO_FREE(pool, fi) wmem_free(pool, fi)
432 /* Contains the space for proto_nodes. */
433 #define PROTO_NODE_INIT(node) \
434 node->first_child = NULL; \
435 node->last_child = NULL; \
436 node->next = NULL;
438 #define PROTO_NODE_FREE(pool, node) \
439 wmem_free(pool, node)
441 /* String space for protocol and field items for the GUI */
442 #define ITEM_LABEL_NEW(pool, il) \
443 il = wmem_new(pool, item_label_t); \
444 il->value_pos = 0; \
445 il->value_len = 0;
446 #define ITEM_LABEL_FREE(pool, il) \
447 wmem_free(pool, il);
449 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
450 if((hfindex == 0 || (unsigned)hfindex > gpa_hfinfo.len) && wireshark_abort_on_dissector_bug) \
451 ws_error("Unregistered hf! index=%d", hfindex); \
452 DISSECTOR_ASSERT_HINT(hfindex > 0 && (unsigned)hfindex < gpa_hfinfo.len, "Unregistered hf!"); \
453 DISSECTOR_ASSERT_HINT(gpa_hfinfo.hfi[hfindex] != NULL, "Unregistered hf!"); \
454 hfinfo = gpa_hfinfo.hfi[hfindex];
456 /* List which stores protocols and fields that have been registered */
457 typedef struct _gpa_hfinfo_t {
458 uint32_t len;
459 uint32_t allocated_len;
460 header_field_info **hfi;
461 } gpa_hfinfo_t;
463 static gpa_hfinfo_t gpa_hfinfo;
465 /* Hash table of abbreviations and IDs */
466 static GHashTable *gpa_name_map;
467 static header_field_info *same_name_hfinfo;
469 /* Hash table protocol aliases. const char * -> const char * */
470 static GHashTable *gpa_protocol_aliases;
473 * We're called repeatedly with the same field name when sorting a column.
474 * Cache our last gpa_name_map hit for faster lookups.
476 static char *last_field_name;
477 static header_field_info *last_hfinfo;
479 static void save_same_name_hfinfo(void *data)
481 same_name_hfinfo = (header_field_info*)data;
484 /* Points to the first element of an array of bits, indexed by
485 a subtree item type; that array element is true if subtrees of
486 an item of that type are to be expanded. */
487 static uint32_t *tree_is_expanded;
489 /* Number of elements in that array. The entry with index 0 is not used. */
490 int num_tree_types = 1;
492 /* Name hashtables for fast detection of duplicate names */
493 static GHashTable* proto_names;
494 static GHashTable* proto_short_names;
495 static GHashTable* proto_filter_names;
497 static const char *reserved_filter_names[] = {
498 /* Display filter keywords. */
499 "eq",
500 "ne",
501 "all_eq",
502 "any_eq",
503 "all_ne",
504 "any_ne",
505 "gt",
506 "ge",
507 "lt",
508 "le",
509 "bitand",
510 "bitwise_and",
511 "contains",
512 "matches",
513 "not",
514 "and",
515 "or",
516 "xor",
517 "in",
518 "any",
519 "all",
520 "true",
521 "false",
522 "nan",
523 "inf",
524 NULL
527 static GHashTable *proto_reserved_filter_names;
529 static int
530 proto_compare_name(const void *p1_arg, const void *p2_arg)
532 const protocol_t *p1 = (const protocol_t *)p1_arg;
533 const protocol_t *p2 = (const protocol_t *)p2_arg;
535 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
538 static GSList *dissector_plugins;
540 #ifdef HAVE_PLUGINS
541 void
542 proto_register_plugin(const proto_plugin *plug)
544 dissector_plugins = g_slist_prepend(dissector_plugins, (proto_plugin *)plug);
546 #else /* HAVE_PLUGINS */
547 void
548 proto_register_plugin(const proto_plugin *plug _U_)
550 ws_warning("proto_register_plugin: built without support for binary plugins");
552 #endif /* HAVE_PLUGINS */
554 static void
555 call_plugin_register_protoinfo(void *data, void *user_data _U_)
557 proto_plugin *plug = (proto_plugin *)data;
559 if (plug->register_protoinfo) {
560 plug->register_protoinfo();
564 static void
565 call_plugin_register_handoff(void *data, void *user_data _U_)
567 proto_plugin *plug = (proto_plugin *)data;
569 if (plug->register_handoff) {
570 plug->register_handoff();
574 /* initialize data structures and register protocols and fields */
575 void
576 proto_init(GSList *register_all_plugin_protocols_list,
577 GSList *register_all_plugin_handoffs_list,
578 register_cb cb,
579 void *client_data)
581 proto_cleanup_base();
583 proto_names = g_hash_table_new(g_str_hash, g_str_equal);
584 proto_short_names = g_hash_table_new(g_str_hash, g_str_equal);
585 proto_filter_names = g_hash_table_new(g_str_hash, g_str_equal);
587 proto_reserved_filter_names = g_hash_table_new(g_str_hash, g_str_equal);
588 for (const char **ptr = reserved_filter_names; *ptr != NULL; ptr++) {
589 /* GHashTable has no key destructor so the cast is safe. */
590 g_hash_table_add(proto_reserved_filter_names, *(char **)ptr);
593 gpa_hfinfo.len = 0;
594 gpa_hfinfo.allocated_len = 0;
595 gpa_hfinfo.hfi = NULL;
596 gpa_name_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, save_same_name_hfinfo);
597 gpa_protocol_aliases = g_hash_table_new(g_str_hash, g_str_equal);
598 deregistered_fields = g_ptr_array_new();
599 deregistered_data = g_ptr_array_new();
600 deregistered_slice = g_ptr_array_new();
602 /* Initialize the ftype subsystem */
603 ftypes_initialize();
605 /* Initialize the address type subsystem */
606 address_types_initialize();
608 /* Register one special-case FT_TEXT_ONLY field for use when
609 converting wireshark to new-style proto_tree. These fields
610 are merely strings on the GUI tree; they are not filterable */
611 hf_text_only = proto_register_field_init(&hfi_text_only, -1);
613 /* Register the pseudo-protocols used for exceptions. */
614 register_show_exception();
615 register_type_length_mismatch();
616 register_byte_array_string_decodinws_error();
617 register_date_time_string_decodinws_error();
618 register_string_errors();
619 ftypes_register_pseudofields();
620 col_register_protocol();
622 /* Have each built-in dissector register its protocols, fields,
623 dissector tables, and dissectors to be called through a
624 handle, and do whatever one-time initialization it needs to
625 do. */
626 register_all_protocols(cb, client_data);
628 /* Now call the registration routines for all epan plugins. */
629 for (GSList *l = register_all_plugin_protocols_list; l != NULL; l = l->next) {
630 ((void (*)(register_cb, void *))l->data)(cb, client_data);
633 /* Now call the registration routines for all dissector plugins. */
634 if (cb)
635 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
636 g_slist_foreach(dissector_plugins, call_plugin_register_protoinfo, NULL);
638 /* Now call the "handoff registration" routines of all built-in
639 dissectors; those routines register the dissector in other
640 dissectors' handoff tables, and fetch any dissector handles
641 they need. */
642 register_all_protocol_handoffs(cb, client_data);
644 /* Now do the same with epan plugins. */
645 for (GSList *l = register_all_plugin_handoffs_list; l != NULL; l = l->next) {
646 ((void (*)(register_cb, void *))l->data)(cb, client_data);
649 /* Now do the same with dissector plugins. */
650 if (cb)
651 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
652 g_slist_foreach(dissector_plugins, call_plugin_register_handoff, NULL);
654 /* sort the protocols by protocol name */
655 protocols = g_list_sort(protocols, proto_compare_name);
657 /* sort the dissector handles in dissector tables (for -G reports
658 * and -d error messages. The GUI sorts the handles itself.) */
659 packet_all_tables_sort_handles();
661 /* We've assigned all the subtree type values; allocate the array
662 for them, and zero it out. */
663 tree_is_expanded = g_new0(uint32_t, (num_tree_types/32)+1);
666 static void
667 proto_cleanup_base(void)
669 protocol_t *protocol;
670 header_field_info *hfinfo;
672 /* Free the abbrev/ID hash table */
673 if (gpa_name_map) {
674 g_hash_table_destroy(gpa_name_map);
675 gpa_name_map = NULL;
677 if (gpa_protocol_aliases) {
678 g_hash_table_destroy(gpa_protocol_aliases);
679 gpa_protocol_aliases = NULL;
681 g_free(last_field_name);
682 last_field_name = NULL;
684 while (protocols) {
685 protocol = (protocol_t *)protocols->data;
686 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
687 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
689 g_slice_free(header_field_info, hfinfo);
690 if (protocol->parent_proto_id != -1) {
691 // pino protocol
692 DISSECTOR_ASSERT(protocol->fields == NULL); //helpers should not have any registered fields
693 DISSECTOR_ASSERT(protocol->heur_list == NULL); //helpers should not have a heuristic list
694 } else {
695 if (protocol->fields) {
696 g_ptr_array_free(protocol->fields, true);
698 g_list_free(protocol->heur_list);
700 protocols = g_list_remove(protocols, protocol);
701 g_free(protocol);
704 if (proto_names) {
705 g_hash_table_destroy(proto_names);
706 proto_names = NULL;
709 if (proto_short_names) {
710 g_hash_table_destroy(proto_short_names);
711 proto_short_names = NULL;
714 if (proto_filter_names) {
715 g_hash_table_destroy(proto_filter_names);
716 proto_filter_names = NULL;
719 if (proto_reserved_filter_names) {
720 g_hash_table_destroy(proto_reserved_filter_names);
721 proto_reserved_filter_names = NULL;
724 if (gpa_hfinfo.allocated_len) {
725 gpa_hfinfo.len = 0;
726 gpa_hfinfo.allocated_len = 0;
727 g_free(gpa_hfinfo.hfi);
728 gpa_hfinfo.hfi = NULL;
731 if (deregistered_fields) {
732 g_ptr_array_free(deregistered_fields, true);
733 deregistered_fields = NULL;
736 if (deregistered_data) {
737 g_ptr_array_free(deregistered_data, true);
738 deregistered_data = NULL;
741 if (deregistered_slice) {
742 g_ptr_array_free(deregistered_slice, true);
743 deregistered_slice = NULL;
746 g_free(tree_is_expanded);
747 tree_is_expanded = NULL;
749 if (prefixes)
750 g_hash_table_destroy(prefixes);
753 void
754 proto_cleanup(void)
756 proto_free_deregistered_fields();
757 proto_cleanup_base();
759 g_slist_free(dissector_plugins);
760 dissector_plugins = NULL;
763 static bool
764 // NOLINTNEXTLINE(misc-no-recursion)
765 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
766 void *data)
768 proto_node *pnode = tree;
769 proto_node *child;
770 proto_node *current;
772 if (func(pnode, data))
773 return true;
775 child = pnode->first_child;
776 while (child != NULL) {
778 * The routine we call might modify the child, e.g. by
779 * freeing it, so we get the child's successor before
780 * calling that routine.
782 current = child;
783 child = current->next;
784 // We recurse here, but we're limited by prefs.gui_max_tree_depth
785 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
786 return true;
789 return false;
792 void
793 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
794 void *data)
796 proto_node *node = tree;
797 proto_node *current;
799 if (!node)
800 return;
802 node = node->first_child;
803 while (node != NULL) {
804 current = node;
805 node = current->next;
806 func((proto_tree *)current, data);
810 static void
811 free_GPtrArray_value(void *key, void *value, void *user_data _U_)
813 GPtrArray *ptrs = (GPtrArray *)value;
814 int hfid = GPOINTER_TO_UINT(key);
815 header_field_info *hfinfo;
817 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
818 if (hfinfo->ref_type != HF_REF_TYPE_NONE) {
819 /* when a field is referenced by a filter this also
820 affects the refcount for the parent protocol so we need
821 to adjust the refcount for the parent as well
823 if (hfinfo->parent != -1) {
824 header_field_info *parent_hfinfo;
825 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
826 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
828 hfinfo->ref_type = HF_REF_TYPE_NONE;
831 g_ptr_array_free(ptrs, true);
834 static void
835 proto_tree_free_node(proto_node *node, void *data _U_)
837 field_info *finfo = PNODE_FINFO(node);
839 proto_tree_children_foreach(node, proto_tree_free_node, NULL);
841 fvalue_free(finfo->value);
842 finfo->value = NULL;
845 void
846 proto_tree_reset(proto_tree *tree)
848 tree_data_t *tree_data = PTREE_DATA(tree);
850 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
852 /* free tree data */
853 if (tree_data->interesting_hfids) {
854 /* Free all the GPtrArray's in the interesting_hfids hash. */
855 g_hash_table_foreach(tree_data->interesting_hfids,
856 free_GPtrArray_value, NULL);
858 /* And then remove all values. */
859 g_hash_table_remove_all(tree_data->interesting_hfids);
862 /* Reset track of the number of children */
863 tree_data->count = 0;
865 PROTO_NODE_INIT(tree);
868 /* frees the resources that the dissection a proto_tree uses */
869 void
870 proto_tree_free(proto_tree *tree)
872 tree_data_t *tree_data = PTREE_DATA(tree);
874 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
876 /* free tree data */
877 if (tree_data->interesting_hfids) {
878 /* Free all the GPtrArray's in the interesting_hfids hash. */
879 g_hash_table_foreach(tree_data->interesting_hfids,
880 free_GPtrArray_value, NULL);
882 /* And then destroy the hash. */
883 g_hash_table_destroy(tree_data->interesting_hfids);
886 g_slice_free(tree_data_t, tree_data);
888 g_slice_free(proto_tree, tree);
891 /* Is the parsing being done for a visible proto_tree or an invisible one?
892 * By setting this correctly, the proto_tree creation is sped up by not
893 * having to call vsnprintf and copy strings around.
895 bool
896 proto_tree_set_visible(proto_tree *tree, bool visible)
898 bool old_visible = PTREE_DATA(tree)->visible;
900 PTREE_DATA(tree)->visible = visible;
902 return old_visible;
905 void
906 proto_tree_set_fake_protocols(proto_tree *tree, bool fake_protocols)
908 if (tree)
909 PTREE_DATA(tree)->fake_protocols = fake_protocols;
912 /* Assume dissector set only its protocol fields.
913 This function is called by dissectors and allows the speeding up of filtering
914 in wireshark; if this function returns false it is safe to reset tree to NULL
915 and thus skip calling most of the expensive proto_tree_add_...()
916 functions.
917 If the tree is visible we implicitly assume the field is referenced.
919 bool
920 proto_field_is_referenced(proto_tree *tree, int proto_id)
922 register header_field_info *hfinfo;
925 if (!tree)
926 return false;
928 if (PTREE_DATA(tree)->visible)
929 return true;
931 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
932 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
933 return true;
935 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
936 return true;
938 return false;
942 /* Finds a record in the hfinfo array by id. */
943 header_field_info *
944 proto_registrar_get_nth(unsigned hfindex)
946 register header_field_info *hfinfo;
948 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
949 return hfinfo;
953 /* Prefix initialization
954 * this allows for a dissector to register a display filter name prefix
955 * so that it can delay the initialization of the hf array as long as
956 * possible.
959 /* compute a hash for the part before the dot of a display filter */
960 static unsigned
961 prefix_hash (const void *key) {
962 /* end the string at the dot and compute its hash */
963 char* copy = g_strdup((const char *)key);
964 char* c = copy;
965 unsigned tmp;
967 for (; *c; c++) {
968 if (*c == '.') {
969 *c = 0;
970 break;
974 tmp = g_str_hash(copy);
975 g_free(copy);
976 return tmp;
979 /* are both strings equal up to the end or the dot? */
980 static gboolean
981 prefix_equal (const void *ap, const void *bp) {
982 const char* a = (const char *)ap;
983 const char* b = (const char *)bp;
985 do {
986 char ac = *a++;
987 char bc = *b++;
989 if ( (ac == '.' || ac == '\0') && (bc == '.' || bc == '\0') ) return TRUE;
991 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
992 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
994 if (ac != bc) return FALSE;
995 } while (1);
997 return FALSE;
1000 /* Register a new prefix for "delayed" initialization of field arrays */
1001 void
1002 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
1003 if (! prefixes ) {
1004 prefixes = g_hash_table_new(prefix_hash, prefix_equal);
1007 g_hash_table_insert(prefixes, (void *)prefix, (void *)pi);
1010 /* helper to call all prefix initializers */
1011 static gboolean
1012 initialize_prefix(void *k, void *v, void *u _U_) {
1013 ((prefix_initializer_t)v)((const char *)k);
1014 return TRUE;
1017 /** Initialize every remaining uninitialized prefix. */
1018 void
1019 proto_initialize_all_prefixes(void) {
1020 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
1023 /* Finds a record in the hfinfo array by name.
1024 * If it fails to find it in the already registered fields,
1025 * it tries to find and call an initializer in the prefixes
1026 * table and if so it looks again.
1029 header_field_info *
1030 proto_registrar_get_byname(const char *field_name)
1032 header_field_info *hfinfo;
1033 prefix_initializer_t pi;
1035 if (!field_name)
1036 return NULL;
1038 if (g_strcmp0(field_name, last_field_name) == 0) {
1039 return last_hfinfo;
1042 hfinfo = (header_field_info *)g_hash_table_lookup(gpa_name_map, field_name);
1044 if (hfinfo) {
1045 g_free(last_field_name);
1046 last_field_name = g_strdup(field_name);
1047 last_hfinfo = hfinfo;
1048 return hfinfo;
1051 if (!prefixes)
1052 return NULL;
1054 if ((pi = (prefix_initializer_t)g_hash_table_lookup(prefixes, field_name) ) != NULL) {
1055 pi(field_name);
1056 g_hash_table_remove(prefixes, field_name);
1057 } else {
1058 return NULL;
1061 hfinfo = (header_field_info *)g_hash_table_lookup(gpa_name_map, field_name);
1063 if (hfinfo) {
1064 g_free(last_field_name);
1065 last_field_name = g_strdup(field_name);
1066 last_hfinfo = hfinfo;
1068 return hfinfo;
1071 header_field_info*
1072 proto_registrar_get_byalias(const char *alias_name)
1074 if (!alias_name) {
1075 return NULL;
1078 /* Find our aliased protocol. */
1079 char *an_copy = g_strdup(alias_name);
1080 char *dot = strchr(an_copy, '.');
1081 if (dot) {
1082 *dot = '\0';
1084 const char *proto_pfx = (const char *) g_hash_table_lookup(gpa_protocol_aliases, an_copy);
1085 if (!proto_pfx) {
1086 g_free(an_copy);
1087 return NULL;
1090 /* Construct our aliased field and look it up. */
1091 GString *filter_name = g_string_new(proto_pfx);
1092 if (dot) {
1093 g_string_append_printf(filter_name, ".%s", dot+1);
1095 header_field_info *hfinfo = proto_registrar_get_byname(filter_name->str);
1096 g_free(an_copy);
1097 g_string_free(filter_name, TRUE);
1099 return hfinfo;
1103 proto_registrar_get_id_byname(const char *field_name)
1105 header_field_info *hfinfo;
1107 hfinfo = proto_registrar_get_byname(field_name);
1109 if (!hfinfo)
1110 return -1;
1112 return hfinfo->id;
1115 static int
1116 label_strcat_flags(const header_field_info *hfinfo)
1118 if (FIELD_DISPLAY(hfinfo->display) & BASE_STR_WSP)
1119 return FORMAT_LABEL_REPLACE_SPACE;
1121 return 0;
1124 static char *
1125 format_bytes_hfinfo_maxlen(wmem_allocator_t *scope, const header_field_info *hfinfo,
1126 const uint8_t *bytes, unsigned length, size_t max_str_len)
1128 char *str = NULL;
1129 const uint8_t *p;
1130 bool is_printable;
1132 if (bytes) {
1133 if (hfinfo->display & BASE_SHOW_UTF_8_PRINTABLE) {
1135 * If all bytes are valid and printable UTF-8, show the
1136 * bytes as a string - in quotes to indicate that it's
1137 * a string.
1139 if (isprint_utf8_string(bytes, length)) {
1140 str = wmem_strdup_printf(scope, "\"%.*s\"",
1141 (int)length, bytes);
1142 return str;
1144 } else if (hfinfo->display & BASE_SHOW_ASCII_PRINTABLE) {
1146 * Check whether all bytes are printable.
1148 is_printable = true;
1149 for (p = bytes; p < bytes+length; p++) {
1150 if (!g_ascii_isprint(*p)) {
1151 /* Not printable. */
1152 is_printable = false;
1153 break;
1158 * If all bytes are printable ASCII, show the bytes
1159 * as a string - in quotes to indicate that it's
1160 * a string.
1162 if (is_printable) {
1163 str = wmem_strdup_printf(scope, "\"%.*s\"",
1164 (int)length, bytes);
1165 return str;
1170 * Either it's not printable ASCII, or we don't care whether
1171 * it's printable ASCII; show it as hex bytes.
1173 switch (FIELD_DISPLAY(hfinfo->display)) {
1174 case SEP_DOT:
1175 str = bytes_to_str_punct_maxlen(scope, bytes, length, '.', max_str_len/3);
1176 break;
1177 case SEP_DASH:
1178 str = bytes_to_str_punct_maxlen(scope, bytes, length, '-', max_str_len/3);
1179 break;
1180 case SEP_COLON:
1181 str = bytes_to_str_punct_maxlen(scope, bytes, length, ':', max_str_len/3);
1182 break;
1183 case SEP_SPACE:
1184 str = bytes_to_str_punct_maxlen(scope, bytes, length, ' ', max_str_len/3);
1185 break;
1186 case BASE_NONE:
1187 default:
1188 if (prefs.display_byte_fields_with_spaces) {
1189 str = bytes_to_str_punct_maxlen(scope, bytes, length, ' ', max_str_len/3);
1190 } else {
1191 str = bytes_to_str_maxlen(scope, bytes, length, max_str_len/2);
1193 break;
1196 else {
1197 if (hfinfo->display & BASE_ALLOW_ZERO) {
1198 str = wmem_strdup(scope, "<none>");
1199 } else {
1200 str = wmem_strdup(scope, "<MISSING>");
1203 return str;
1206 static char *
1207 format_bytes_hfinfo(wmem_allocator_t *scope, const header_field_info *hfinfo,
1208 const uint8_t *bytes, unsigned length)
1210 return format_bytes_hfinfo_maxlen(scope, hfinfo, bytes, length, ITEM_LABEL_LENGTH);
1213 static void
1214 ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
1216 subtree_lvl *pushed_tree;
1218 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
1219 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
1221 pushed_tree = (subtree_lvl *)wmem_realloc(ptvc->scope, (void *)ptvc->pushed_tree, sizeof(subtree_lvl) * ptvc->pushed_tree_max);
1222 DISSECTOR_ASSERT(pushed_tree != NULL);
1223 ptvc->pushed_tree = pushed_tree;
1226 static void
1227 ptvcursor_free_subtree_levels(ptvcursor_t *ptvc)
1229 ptvc->pushed_tree = NULL;
1230 ptvc->pushed_tree_max = 0;
1231 DISSECTOR_ASSERT(ptvc->pushed_tree_index == 0);
1232 ptvc->pushed_tree_index = 0;
1235 /* Allocates an initializes a ptvcursor_t with 3 variables:
1236 * proto_tree, tvbuff, and offset. */
1237 ptvcursor_t *
1238 ptvcursor_new(wmem_allocator_t *scope, proto_tree *tree, tvbuff_t *tvb, int offset)
1240 ptvcursor_t *ptvc;
1242 ptvc = wmem_new(scope, ptvcursor_t);
1243 ptvc->scope = scope;
1244 ptvc->tree = tree;
1245 ptvc->tvb = tvb;
1246 ptvc->offset = offset;
1247 ptvc->pushed_tree = NULL;
1248 ptvc->pushed_tree_max = 0;
1249 ptvc->pushed_tree_index = 0;
1250 return ptvc;
1254 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
1255 void
1256 ptvcursor_free(ptvcursor_t *ptvc)
1258 ptvcursor_free_subtree_levels(ptvc);
1259 /*g_free(ptvc);*/
1262 /* Returns tvbuff. */
1263 tvbuff_t *
1264 ptvcursor_tvbuff(ptvcursor_t *ptvc)
1266 return ptvc->tvb;
1269 /* Returns current offset. */
1271 ptvcursor_current_offset(ptvcursor_t *ptvc)
1273 return ptvc->offset;
1276 proto_tree *
1277 ptvcursor_tree(ptvcursor_t *ptvc)
1279 if (!ptvc)
1280 return NULL;
1282 return ptvc->tree;
1285 void
1286 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
1288 ptvc->tree = tree;
1291 /* creates a subtree, sets it as the working tree and pushes the old working tree */
1292 proto_tree *
1293 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, int ett_subtree)
1295 subtree_lvl *subtree;
1296 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
1297 ptvcursor_new_subtree_levels(ptvc);
1299 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
1300 subtree->tree = ptvc->tree;
1301 subtree->it= NULL;
1302 ptvc->pushed_tree_index++;
1303 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
1306 /* pops a subtree */
1307 void
1308 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
1310 subtree_lvl *subtree;
1312 if (ptvc->pushed_tree_index <= 0)
1313 return;
1315 ptvc->pushed_tree_index--;
1316 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
1317 if (subtree->it != NULL)
1318 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
1320 ptvc->tree = subtree->tree;
1323 /* saves the current tvb offset and the item in the current subtree level */
1324 static void
1325 ptvcursor_subtree_set_item(ptvcursor_t *ptvc, proto_item *it)
1327 subtree_lvl *subtree;
1329 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
1331 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index - 1;
1332 subtree->it = it;
1333 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
1336 /* Creates a subtree and adds it to the cursor as the working tree but does not
1337 * save the old working tree */
1338 proto_tree *
1339 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, int ett_subtree)
1341 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
1342 return ptvc->tree;
1345 static proto_tree *
1346 ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, int ett_subtree, int length)
1348 ptvcursor_push_subtree(ptvc, it, ett_subtree);
1349 if (length == SUBTREE_UNDEFINED_LENGTH)
1350 ptvcursor_subtree_set_item(ptvc, it);
1351 return ptvcursor_tree(ptvc);
1354 /* Add an item to the tree and create a subtree
1355 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1356 * In this case, when the subtree will be closed, the parent item length will
1357 * be equal to the advancement of the cursor since the creation of the subtree.
1359 proto_tree *
1360 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, int length,
1361 const unsigned encoding, int ett_subtree)
1363 proto_item *it;
1365 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
1366 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
1369 static proto_item *
1370 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, int start, int length);
1372 /* Add a text node to the tree and create a subtree
1373 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1374 * In this case, when the subtree will be closed, the item length will be equal
1375 * to the advancement of the cursor since the creation of the subtree.
1377 proto_tree *
1378 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, int length,
1379 int ett_subtree, const char *format, ...)
1381 proto_item *pi;
1382 va_list ap;
1383 header_field_info *hfinfo;
1384 proto_tree *tree;
1386 tree = ptvcursor_tree(ptvc);
1388 CHECK_FOR_NULL_TREE(tree);
1390 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1392 pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
1393 ptvcursor_current_offset(ptvc), length);
1395 TRY_TO_FAKE_THIS_REPR(pi);
1397 va_start(ap, format);
1398 proto_tree_set_representation(pi, format, ap);
1399 va_end(ap);
1401 return ptvcursor_add_subtree_item(ptvc, pi, ett_subtree, length);
1404 /* Add a text-only node, leaving it to our caller to fill the text in */
1405 static proto_item *
1406 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, int start, int length)
1408 proto_item *pi;
1410 if (tree == NULL)
1411 return NULL;
1413 pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length);
1415 return pi;
1418 /* (INTERNAL USE ONLY) Add a text-only node to the proto_tree */
1419 proto_item *
1420 proto_tree_add_text_internal(proto_tree *tree, tvbuff_t *tvb, int start, int length,
1421 const char *format, ...)
1423 proto_item *pi;
1424 va_list ap;
1425 header_field_info *hfinfo;
1427 if (length == -1) {
1428 length = tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
1429 } else {
1430 tvb_ensure_bytes_exist(tvb, start, length);
1433 CHECK_FOR_NULL_TREE(tree);
1435 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1437 pi = proto_tree_add_text_node(tree, tvb, start, length);
1439 TRY_TO_FAKE_THIS_REPR(pi);
1441 va_start(ap, format);
1442 proto_tree_set_representation(pi, format, ap);
1443 va_end(ap);
1445 return pi;
1448 /* (INTERNAL USE ONLY) Add a text-only node to the proto_tree (va_list version) */
1449 proto_item *
1450 proto_tree_add_text_valist_internal(proto_tree *tree, tvbuff_t *tvb, int start,
1451 int length, const char *format, va_list ap)
1453 proto_item *pi;
1454 header_field_info *hfinfo;
1456 /* proto_tree_add_text_node calls proto_tree_add_pi() with the
1457 * FT_NONE hf_text_only, which calls get_hfi_length, which adjusts
1458 * the length to be what's in the tvbuff if length is -1, and the
1459 * minimum of length and what's in the tvbuff if not.
1462 CHECK_FOR_NULL_TREE(tree);
1464 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1466 pi = proto_tree_add_text_node(tree, tvb, start, length);
1468 TRY_TO_FAKE_THIS_REPR(pi);
1470 proto_tree_set_representation(pi, format, ap);
1472 return pi;
1475 /* Add a text-only node that creates a subtree underneath.
1477 proto_tree *
1478 proto_tree_add_subtree(proto_tree *tree, tvbuff_t *tvb, int start, int length, int idx, proto_item **tree_item, const char *text)
1480 return proto_tree_add_subtree_format(tree, tvb, start, length, idx, tree_item, "%s", text);
1483 /* Add a text-only node that creates a subtree underneath.
1485 proto_tree *
1486 proto_tree_add_subtree_format(proto_tree *tree, tvbuff_t *tvb, int start, int length, int idx, proto_item **tree_item, const char *format, ...)
1488 proto_tree *pt;
1489 proto_item *pi;
1490 va_list ap;
1492 va_start(ap, format);
1493 pi = proto_tree_add_text_valist_internal(tree, tvb, start, length, format, ap);
1494 va_end(ap);
1496 if (tree_item != NULL)
1497 *tree_item = pi;
1499 pt = proto_item_add_subtree(pi, idx);
1501 return pt;
1504 /* Add a text-only node for debugging purposes. The caller doesn't need
1505 * to worry about tvbuff, start, or length. Debug message gets sent to
1506 * STDOUT, too */
1507 proto_item *
1508 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1510 proto_item *pi;
1511 va_list ap;
1513 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1515 if (pi) {
1516 va_start(ap, format);
1517 proto_tree_set_representation(pi, format, ap);
1518 va_end(ap);
1520 va_start(ap, format);
1521 vprintf(format, ap);
1522 va_end(ap);
1523 printf("\n");
1525 return pi;
1528 proto_item *
1529 proto_tree_add_format_text(proto_tree *tree, tvbuff_t *tvb, int start, int length)
1531 proto_item *pi;
1532 header_field_info *hfinfo;
1534 CHECK_FOR_NULL_TREE(tree);
1536 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1538 pi = proto_tree_add_text_node(tree, tvb, start, length);
1540 TRY_TO_FAKE_THIS_REPR(pi);
1542 proto_item_set_text(pi, "%s", tvb_format_text(tree->tree_data->pinfo->pool, tvb, start, length));
1544 return pi;
1547 proto_item *
1548 proto_tree_add_format_wsp_text(proto_tree *tree, tvbuff_t *tvb, int start, int length)
1550 proto_item *pi;
1551 header_field_info *hfinfo;
1552 char *str;
1554 CHECK_FOR_NULL_TREE(tree);
1556 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1558 pi = proto_tree_add_text_node(tree, tvb, start, length);
1560 TRY_TO_FAKE_THIS_REPR(pi);
1562 str = tvb_format_text_wsp(NULL, tvb, start, length);
1563 proto_item_set_text(pi, "%s", str);
1564 wmem_free(NULL, str);
1566 return pi;
1569 void proto_report_dissector_bug(const char *format, ...)
1571 va_list args;
1573 if (wireshark_abort_on_dissector_bug) {
1575 * Try to have the error message show up in the crash
1576 * information.
1578 va_start(args, format);
1579 ws_vadd_crash_info(format, args);
1580 va_end(args);
1583 * Print the error message.
1585 va_start(args, format);
1586 vfprintf(stderr, format, args);
1587 va_end(args);
1588 putc('\n', stderr);
1591 * And crash.
1593 abort();
1594 } else {
1595 va_start(args, format);
1596 VTHROW_FORMATTED(DissectorError, format, args);
1597 va_end(args);
1601 /* We could probably get away with changing is_error to a minimum length value. */
1602 static void
1603 report_type_length_mismatch(proto_tree *tree, const char *descr, int length, bool is_error)
1605 if (is_error) {
1606 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_error, "Trying to fetch %s with length %d", descr, length);
1607 } else {
1608 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_warn, "Trying to fetch %s with length %d", descr, length);
1611 if (is_error) {
1612 THROW(ReportedBoundsError);
1616 static uint32_t
1617 get_uint_value(proto_tree *tree, tvbuff_t *tvb, int offset, int length, const unsigned encoding)
1619 uint32_t value;
1620 bool length_error;
1622 switch (length) {
1624 case 1:
1625 value = tvb_get_uint8(tvb, offset);
1626 if (encoding & ENC_ZIGBEE) {
1627 if (value == 0xFF) { /* Invalid Zigbee length, set to 0 */
1628 value = 0;
1631 break;
1633 case 2:
1634 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1635 : tvb_get_ntohs(tvb, offset);
1636 if (encoding & ENC_ZIGBEE) {
1637 if (value == 0xFFFF) { /* Invalid Zigbee length, set to 0 */
1638 value = 0;
1641 break;
1643 case 3:
1644 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1645 : tvb_get_ntoh24(tvb, offset);
1646 break;
1648 case 4:
1649 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1650 : tvb_get_ntohl(tvb, offset);
1651 break;
1653 default:
1654 if (length < 1) {
1655 length_error = true;
1656 value = 0;
1657 } else {
1658 length_error = false;
1659 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1660 : tvb_get_ntohl(tvb, offset);
1662 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1663 break;
1665 return value;
1668 static inline uint64_t
1669 get_uint64_value(proto_tree *tree, tvbuff_t *tvb, int offset, unsigned length, const unsigned encoding)
1671 uint64_t value;
1672 bool length_error;
1674 switch (length) {
1676 case 1:
1677 value = tvb_get_uint8(tvb, offset);
1678 break;
1680 case 2:
1681 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1682 : tvb_get_ntohs(tvb, offset);
1683 break;
1685 case 3:
1686 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1687 : tvb_get_ntoh24(tvb, offset);
1688 break;
1690 case 4:
1691 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1692 : tvb_get_ntohl(tvb, offset);
1693 break;
1695 case 5:
1696 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh40(tvb, offset)
1697 : tvb_get_ntoh40(tvb, offset);
1698 break;
1700 case 6:
1701 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh48(tvb, offset)
1702 : tvb_get_ntoh48(tvb, offset);
1703 break;
1705 case 7:
1706 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh56(tvb, offset)
1707 : tvb_get_ntoh56(tvb, offset);
1708 break;
1710 case 8:
1711 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh64(tvb, offset)
1712 : tvb_get_ntoh64(tvb, offset);
1713 break;
1715 default:
1716 if (length < 1) {
1717 length_error = true;
1718 value = 0;
1719 } else {
1720 length_error = false;
1721 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh64(tvb, offset)
1722 : tvb_get_ntoh64(tvb, offset);
1724 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1725 break;
1727 return value;
1730 static int32_t
1731 get_int_value(proto_tree *tree, tvbuff_t *tvb, int offset, int length, const unsigned encoding)
1733 int32_t value;
1734 bool length_error;
1736 switch (length) {
1738 case 1:
1739 value = tvb_get_int8(tvb, offset);
1740 break;
1742 case 2:
1743 value = encoding ? tvb_get_letohis(tvb, offset)
1744 : tvb_get_ntohis(tvb, offset);
1745 break;
1747 case 3:
1748 value = encoding ? tvb_get_letohi24(tvb, offset)
1749 : tvb_get_ntohi24(tvb, offset);
1750 break;
1752 case 4:
1753 value = encoding ? tvb_get_letohil(tvb, offset)
1754 : tvb_get_ntohil(tvb, offset);
1755 break;
1757 default:
1758 if (length < 1) {
1759 length_error = true;
1760 value = 0;
1761 } else {
1762 length_error = false;
1763 value = encoding ? tvb_get_letohil(tvb, offset)
1764 : tvb_get_ntohil(tvb, offset);
1766 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1767 break;
1769 return value;
1772 /* Note: this returns an unsigned int64, but with the appropriate bit(s) set to
1773 * be cast-able as a int64_t. This is weird, but what the code has always done.
1775 static inline uint64_t
1776 get_int64_value(proto_tree *tree, tvbuff_t *tvb, int start, unsigned length, const unsigned encoding)
1778 uint64_t value = get_uint64_value(tree, tvb, start, length, encoding);
1780 switch (length) {
1781 case 7:
1782 value = ws_sign_ext64(value, 56);
1783 break;
1784 case 6:
1785 value = ws_sign_ext64(value, 48);
1786 break;
1787 case 5:
1788 value = ws_sign_ext64(value, 40);
1789 break;
1790 case 4:
1791 value = ws_sign_ext64(value, 32);
1792 break;
1793 case 3:
1794 value = ws_sign_ext64(value, 24);
1795 break;
1796 case 2:
1797 value = ws_sign_ext64(value, 16);
1798 break;
1799 case 1:
1800 value = ws_sign_ext64(value, 8);
1801 break;
1804 return value;
1807 /* For FT_STRING */
1808 static inline const uint8_t *
1809 get_string_value(wmem_allocator_t *scope, tvbuff_t *tvb, int start,
1810 int length, int *ret_length, const unsigned encoding)
1812 if (length == -1) {
1813 length = tvb_ensure_captured_length_remaining(tvb, start);
1815 *ret_length = length;
1816 return tvb_get_string_enc(scope, tvb, start, length, encoding);
1819 /* For FT_STRINGZ */
1820 static inline const uint8_t *
1821 get_stringz_value(wmem_allocator_t *scope, proto_tree *tree, tvbuff_t *tvb,
1822 int start, int length, int *ret_length, const unsigned encoding)
1824 const uint8_t *value;
1826 if (length < -1) {
1827 report_type_length_mismatch(tree, "a string", length, true);
1829 if (length == -1) {
1830 /* This can throw an exception */
1831 value = tvb_get_stringz_enc(scope, tvb, start, &length, encoding);
1832 } else {
1833 /* In this case, length signifies the length of the string.
1835 * This could either be a null-padded string, which doesn't
1836 * necessarily have a '\0' at the end, or a null-terminated
1837 * string, with a trailing '\0'. (Yes, there are cases
1838 * where you have a string that's both counted and null-
1839 * terminated.)
1841 * In the first case, we must allocate a buffer of length
1842 * "length+1", to make room for a trailing '\0'.
1844 * In the second case, we don't assume that there is a
1845 * trailing '\0' there, as the packet might be malformed.
1846 * (XXX - should we throw an exception if there's no
1847 * trailing '\0'?) Therefore, we allocate a buffer of
1848 * length "length+1", and put in a trailing '\0', just to
1849 * be safe.
1851 * (XXX - this would change if we made string values counted
1852 * rather than null-terminated.)
1854 value = tvb_get_string_enc(scope, tvb, start, length, encoding);
1856 *ret_length = length;
1857 return value;
1860 /* For FT_UINT_STRING */
1861 static inline const uint8_t *
1862 get_uint_string_value(wmem_allocator_t *scope, proto_tree *tree,
1863 tvbuff_t *tvb, int start, int length, int *ret_length,
1864 const unsigned encoding)
1866 uint32_t n;
1867 const uint8_t *value;
1869 /* I believe it's ok if this is called with a NULL tree */
1870 n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1871 value = tvb_get_string_enc(scope, tvb, start + length, n, encoding);
1872 length += n;
1873 *ret_length = length;
1874 return value;
1877 /* For FT_STRINGZPAD */
1878 static inline const uint8_t *
1879 get_stringzpad_value(wmem_allocator_t *scope, tvbuff_t *tvb, int start,
1880 int length, int *ret_length, const unsigned encoding)
1883 * XXX - currently, string values are null-
1884 * terminated, so a "zero-padded" string
1885 * isn't special. If we represent string
1886 * values as something that includes a counted
1887 * array of bytes, we'll need to strip the
1888 * trailing NULs.
1890 if (length == -1) {
1891 length = tvb_ensure_captured_length_remaining(tvb, start);
1893 *ret_length = length;
1894 return tvb_get_string_enc(scope, tvb, start, length, encoding);
1897 /* For FT_STRINGZTRUNC */
1898 static inline const uint8_t *
1899 get_stringztrunc_value(wmem_allocator_t *scope, tvbuff_t *tvb, int start,
1900 int length, int *ret_length, const unsigned encoding)
1903 * XXX - currently, string values are null-
1904 * terminated, so a "zero-truncated" string
1905 * isn't special. If we represent string
1906 * values as something that includes a counted
1907 * array of bytes, we'll need to strip everything
1908 * starting with the terminating NUL.
1910 if (length == -1) {
1911 length = tvb_ensure_captured_length_remaining(tvb, start);
1913 *ret_length = length;
1914 return tvb_get_string_enc(scope, tvb, start, length, encoding);
1918 * Deltas between the epochs for various non-UN*X time stamp formats and
1919 * the January 1, 1970, 00:00:00 (proleptic?) UTC epoch for the UN*X time
1920 * stamp format.
1924 * NTP Era 0: the epoch is January 1, 1900, 00:00:00 (proleptic?) UTC.
1925 * XXX - if it's OK if this is unsigned, can we just use
1926 * EPOCH_DELTA_1900_01_01_00_00_00_UTC?
1928 #define NTP_TIMEDIFF1900TO1970SEC INT64_C(2208988800)
1931 * NTP Era 1: the epoch is February 7, 2036, 06:28:16 UTC.
1933 #define NTP_TIMEDIFF1970TO2036SEC INT64_C(2085978496)
1935 /* this can be called when there is no tree, so tree may be null */
1936 static void
1937 get_time_value(proto_tree *tree, tvbuff_t *tvb, const int start,
1938 const int length, const unsigned encoding, nstime_t *time_stamp,
1939 const bool is_relative)
1941 uint32_t tmpsecs;
1942 uint64_t tmp64secs;
1943 uint64_t todusecs;
1945 switch (encoding) {
1947 case ENC_TIME_SECS_NSECS|ENC_BIG_ENDIAN:
1949 * If the length is 16, 8-byte seconds, followed
1950 * by 8-byte fractional time in nanoseconds,
1951 * both big-endian.
1953 * If the length is 12, 8-byte seconds, followed
1954 * by 4-byte fractional time in nanoseconds,
1955 * both big-endian.
1957 * If the length is 8, 4-byte seconds, followed
1958 * by 4-byte fractional time in nanoseconds,
1959 * both big-endian.
1961 * For absolute times, the seconds are seconds
1962 * since the UN*X epoch.
1964 if (length == 16) {
1965 time_stamp->secs = (time_t)tvb_get_ntoh64(tvb, start);
1966 time_stamp->nsecs = (uint32_t)tvb_get_ntoh64(tvb, start+8);
1967 } else if (length == 12) {
1968 time_stamp->secs = (time_t)tvb_get_ntoh64(tvb, start);
1969 time_stamp->nsecs = tvb_get_ntohl(tvb, start+8);
1970 } else if (length == 8) {
1971 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
1972 time_stamp->nsecs = tvb_get_ntohl(tvb, start+4);
1973 } else if (length == 4) {
1975 * Backwards compatibility.
1976 * ENC_TIME_SECS_NSECS is 0; using
1977 * ENC_BIG_ENDIAN by itself with a 4-byte
1978 * time-in-seconds value was done in the
1979 * past.
1981 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
1982 time_stamp->nsecs = 0;
1983 } else {
1984 time_stamp->secs = 0;
1985 time_stamp->nsecs = 0;
1986 report_type_length_mismatch(tree, "a timespec", length, (length < 4));
1988 break;
1990 case ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN:
1992 * If the length is 16, 8-byte seconds, followed
1993 * by 8-byte fractional time in nanoseconds,
1994 * both little-endian.
1996 * If the length is 12, 8-byte seconds, followed
1997 * by 4-byte fractional time in nanoseconds,
1998 * both little-endian.
2000 * If the length is 8, 4-byte seconds, followed
2001 * by 4-byte fractional time in nanoseconds,
2002 * both little-endian.
2004 * For absolute times, the seconds are seconds
2005 * since the UN*X epoch.
2007 if (length == 16) {
2008 time_stamp->secs = (time_t)tvb_get_letoh64(tvb, start);
2009 time_stamp->nsecs = (uint32_t)tvb_get_letoh64(tvb, start+8);
2010 } else if (length == 12) {
2011 time_stamp->secs = (time_t)tvb_get_letoh64(tvb, start);
2012 time_stamp->nsecs = tvb_get_letohl(tvb, start+8);
2013 } else if (length == 8) {
2014 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
2015 time_stamp->nsecs = tvb_get_letohl(tvb, start+4);
2016 } else if (length == 4) {
2018 * Backwards compatibility.
2019 * ENC_TIME_SECS_NSECS is 0; using
2020 * ENC_LITTLE_ENDIAN by itself with a 4-byte
2021 * time-in-seconds value was done in the
2022 * past.
2024 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
2025 time_stamp->nsecs = 0;
2026 } else {
2027 time_stamp->secs = 0;
2028 time_stamp->nsecs = 0;
2029 report_type_length_mismatch(tree, "a timespec", length, (length < 4));
2031 break;
2033 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
2035 * NTP time stamp, big-endian.
2036 * Only supported for absolute times.
2038 DISSECTOR_ASSERT(!is_relative);
2040 /* We need a temporary variable here so the unsigned math
2041 * works correctly (for years > 2036 according to RFC 2030
2042 * chapter 3).
2044 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2045 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2046 * If bit 0 is not set, the time is in the range 2036-2104 and
2047 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2049 tmpsecs = tvb_get_ntohl(tvb, start);
2050 if ((tmpsecs & 0x80000000) != 0)
2051 time_stamp->secs = (time_t)((int64_t)tmpsecs - NTP_TIMEDIFF1900TO1970SEC);
2052 else
2053 time_stamp->secs = (time_t)((int64_t)tmpsecs + NTP_TIMEDIFF1970TO2036SEC);
2055 if (length == 8) {
2056 tmp64secs = tvb_get_ntoh64(tvb, start);
2057 if (tmp64secs == 0) {
2058 //This is "NULL" time
2059 time_stamp->secs = 0;
2060 time_stamp->nsecs = 0;
2061 } else {
2063 * Convert 1/2^32s of a second to
2064 * nanoseconds.
2066 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
2068 } else if (length == 4) {
2070 * Backwards compatibility.
2072 if (tmpsecs == 0) {
2073 //This is "NULL" time
2074 time_stamp->secs = 0;
2076 time_stamp->nsecs = 0;
2077 } else {
2078 time_stamp->secs = 0;
2079 time_stamp->nsecs = 0;
2080 report_type_length_mismatch(tree, "an NTP time stamp", length, (length < 4));
2082 break;
2084 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
2086 * NTP time stamp, little-endian.
2087 * Only supported for absolute times.
2089 * NTP doesn't use this, because it's an Internet format
2090 * and hence big-endian. Any implementation must decide
2091 * whether the NTP timestamp is a 64-bit unsigned fixed
2092 * point number (RFC 1305, RFC 4330) or a 64-bit struct
2093 * with a 32-bit unsigned seconds field followed by a
2094 * 32-bit fraction field (cf. RFC 5905, which obsoletes
2095 * the previous two).
2097 * XXX: We do the latter, but no dissector uses this format.
2098 * OTOH, ERF timestamps do the former, so perhaps we
2099 * should switch the interpretation so that packet-erf.c
2100 * could use this directly?
2102 DISSECTOR_ASSERT(!is_relative);
2104 /* We need a temporary variable here so the unsigned math
2105 * works correctly (for years > 2036 according to RFC 2030
2106 * chapter 3).
2108 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2109 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2110 * If bit 0 is not set, the time is in the range 2036-2104 and
2111 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2113 tmpsecs = tvb_get_letohl(tvb, start);
2114 if ((tmpsecs & 0x80000000) != 0)
2115 time_stamp->secs = (time_t)((int64_t)tmpsecs - NTP_TIMEDIFF1900TO1970SEC);
2116 else
2117 time_stamp->secs = (time_t)((int64_t)tmpsecs + NTP_TIMEDIFF1970TO2036SEC);
2119 if (length == 8) {
2120 tmp64secs = tvb_get_letoh64(tvb, start);
2121 if (tmp64secs == 0) {
2122 //This is "NULL" time
2123 time_stamp->secs = 0;
2124 time_stamp->nsecs = 0;
2125 } else {
2127 * Convert 1/2^32s of a second to
2128 * nanoseconds.
2130 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
2132 } else if (length == 4) {
2134 * Backwards compatibility.
2136 if (tmpsecs == 0) {
2137 //This is "NULL" time
2138 time_stamp->secs = 0;
2140 time_stamp->nsecs = 0;
2141 } else {
2142 time_stamp->secs = 0;
2143 time_stamp->nsecs = 0;
2144 report_type_length_mismatch(tree, "an NTP time stamp", length, (length < 4));
2146 break;
2148 case ENC_TIME_TOD|ENC_BIG_ENDIAN:
2150 * S/3x0 and z/Architecture TOD clock time stamp,
2151 * big-endian. The epoch is January 1, 1900,
2152 * 00:00:00 (proleptic?) UTC.
2154 * Only supported for absolute times.
2156 DISSECTOR_ASSERT(!is_relative);
2157 DISSECTOR_ASSERT(length == 8);
2159 if (length == 8) {
2160 todusecs = tvb_get_ntoh64(tvb, start) >> 12;
2161 time_stamp->secs = (time_t)((todusecs / 1000000) - EPOCH_DELTA_1900_01_01_00_00_00_UTC);
2162 time_stamp->nsecs = (int)((todusecs % 1000000) * 1000);
2163 } else {
2164 time_stamp->secs = 0;
2165 time_stamp->nsecs = 0;
2166 report_type_length_mismatch(tree, "a TOD clock time stamp", length, (length < 4));
2168 break;
2170 case ENC_TIME_TOD|ENC_LITTLE_ENDIAN:
2172 * S/3x0 and z/Architecture TOD clock time stamp,
2173 * little-endian. The epoch is January 1, 1900,
2174 * 00:00:00 (proleptic?) UTC.
2176 * Only supported for absolute times.
2178 DISSECTOR_ASSERT(!is_relative);
2180 if (length == 8) {
2181 todusecs = tvb_get_letoh64(tvb, start) >> 12 ;
2182 time_stamp->secs = (time_t)((todusecs / 1000000) - EPOCH_DELTA_1900_01_01_00_00_00_UTC);
2183 time_stamp->nsecs = (int)((todusecs % 1000000) * 1000);
2184 } else {
2185 time_stamp->secs = 0;
2186 time_stamp->nsecs = 0;
2187 report_type_length_mismatch(tree, "a TOD clock time stamp", length, (length < 4));
2189 break;
2191 case ENC_TIME_RTPS|ENC_BIG_ENDIAN:
2193 * Time stamp using the same seconds/fraction format
2194 * as NTP, but with the origin of the time stamp being
2195 * the UNIX epoch rather than the NTP epoch; big-
2196 * endian.
2198 * Only supported for absolute times.
2200 DISSECTOR_ASSERT(!is_relative);
2202 if (length == 8) {
2203 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
2205 * Convert 1/2^32s of a second to nanoseconds.
2207 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
2208 } else {
2209 time_stamp->secs = 0;
2210 time_stamp->nsecs = 0;
2211 report_type_length_mismatch(tree, "an RTPS time stamp", length, (length < 4));
2213 break;
2215 case ENC_TIME_RTPS|ENC_LITTLE_ENDIAN:
2217 * Time stamp using the same seconds/fraction format
2218 * as NTP, but with the origin of the time stamp being
2219 * the UNIX epoch rather than the NTP epoch; little-
2220 * endian.
2222 * Only supported for absolute times.
2224 * The RTPS specification explicitly supports Little
2225 * Endian encoding. In one place, it states that its
2226 * Time_t representation "is the one defined by ...
2227 * RFC 1305", but in another explicitly defines it as
2228 * a struct consisting of an 32 bit unsigned seconds
2229 * field and a 32 bit unsigned fraction field, not a 64
2230 * bit fixed point, so we do that here.
2231 * https://www.omg.org/spec/DDSI-RTPS/2.5/PDF
2233 DISSECTOR_ASSERT(!is_relative);
2235 if (length == 8) {
2236 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
2238 * Convert 1/2^32s of a second to nanoseconds.
2240 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
2241 } else {
2242 time_stamp->secs = 0;
2243 time_stamp->nsecs = 0;
2244 report_type_length_mismatch(tree, "an RTPS time stamp", length, (length < 4));
2246 break;
2248 case ENC_TIME_MIP6 | ENC_BIG_ENDIAN:
2250 * MIP6 time stamp, big-endian.
2251 * A 64-bit unsigned integer field containing a timestamp. The
2252 * value indicates the number of seconds since January 1, 1970,
2253 * 00:00 UTC, by using a fixed point format. In this format, the
2254 * integer number of seconds is contained in the first 48 bits of
2255 * the field, and the remaining 16 bits indicate the number of
2256 * 1/65536 fractions of a second.
2258 * Only supported for absolute times.
2260 DISSECTOR_ASSERT(!is_relative);
2262 if (length == 8) {
2263 /* We need a temporary variable here so the casting and fractions
2264 * of a second work correctly.
2266 tmp64secs = tvb_get_ntoh48(tvb, start);
2267 tmpsecs = tvb_get_ntohs(tvb, start + 6);
2268 tmpsecs <<= 16;
2270 if ((tmp64secs == 0) && (tmpsecs == 0)) {
2271 //This is "NULL" time
2272 time_stamp->secs = 0;
2273 time_stamp->nsecs = 0;
2274 } else {
2275 time_stamp->secs = (time_t)tmp64secs;
2276 time_stamp->nsecs = (int)((tmpsecs / 4294967296.0) * 1000000000);
2278 } else {
2279 time_stamp->secs = 0;
2280 time_stamp->nsecs = 0;
2281 report_type_length_mismatch(tree, "an NTP time stamp", length, (length != 8));
2283 break;
2285 case ENC_TIME_SECS_USECS|ENC_BIG_ENDIAN:
2287 * If the length is 16, 8-byte seconds, followed
2288 * by 8-byte fractional time in microseconds,
2289 * both big-endian.
2291 * If the length is 12, 8-byte seconds, followed
2292 * by 4-byte fractional time in microseconds,
2293 * both big-endian.
2295 * If the length is 8, 4-byte seconds, followed
2296 * by 4-byte fractional time in microseconds,
2297 * both big-endian.
2299 * For absolute times, the seconds are seconds
2300 * since the UN*X epoch.
2302 if (length == 16) {
2303 time_stamp->secs = (time_t)tvb_get_ntoh64(tvb, start);
2304 time_stamp->nsecs = (uint32_t)tvb_get_ntoh64(tvb, start+8)*1000;
2305 } else if (length == 12) {
2306 time_stamp->secs = (time_t)tvb_get_ntoh64(tvb, start);
2307 time_stamp->nsecs = tvb_get_ntohl(tvb, start+8)*1000;
2308 } else if (length == 8) {
2309 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
2310 time_stamp->nsecs = tvb_get_ntohl(tvb, start+4)*1000;
2311 } else {
2312 time_stamp->secs = 0;
2313 time_stamp->nsecs = 0;
2314 report_type_length_mismatch(tree, "a timeval", length, (length < 4));
2316 break;
2318 case ENC_TIME_SECS_USECS|ENC_LITTLE_ENDIAN:
2320 * If the length is 16, 8-byte seconds, followed
2321 * by 8-byte fractional time in microseconds,
2322 * both little-endian.
2324 * If the length is 12, 8-byte seconds, followed
2325 * by 4-byte fractional time in microseconds,
2326 * both little-endian.
2328 * If the length is 8, 4-byte seconds, followed
2329 * by 4-byte fractional time in microseconds,
2330 * both little-endian.
2332 * For absolute times, the seconds are seconds
2333 * since the UN*X epoch.
2335 if (length == 16) {
2336 time_stamp->secs = (time_t)tvb_get_letoh64(tvb, start);
2337 time_stamp->nsecs = (uint32_t)tvb_get_letoh64(tvb, start+8)*1000;
2338 } else if (length == 12) {
2339 time_stamp->secs = (time_t)tvb_get_letoh64(tvb, start);
2340 time_stamp->nsecs = tvb_get_letohl(tvb, start+8)*1000;
2341 } else if (length == 8) {
2342 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
2343 time_stamp->nsecs = tvb_get_letohl(tvb, start+4)*1000;
2344 } else {
2345 time_stamp->secs = 0;
2346 time_stamp->nsecs = 0;
2347 report_type_length_mismatch(tree, "a timeval", length, (length < 4));
2349 break;
2351 case ENC_TIME_SECS|ENC_BIG_ENDIAN:
2352 case ENC_TIME_SECS|ENC_LITTLE_ENDIAN:
2354 * Seconds, 1 to 8 bytes.
2355 * For absolute times, it's seconds since the
2356 * UN*X epoch.
2358 if (length >= 1 && length <= 8) {
2359 time_stamp->secs = (time_t)get_uint64_value(tree, tvb, start, length, encoding);
2360 time_stamp->nsecs = 0;
2361 } else {
2362 time_stamp->secs = 0;
2363 time_stamp->nsecs = 0;
2364 report_type_length_mismatch(tree, "a time-in-seconds time stamp", length, (length < 4));
2366 break;
2368 case ENC_TIME_MSECS|ENC_BIG_ENDIAN:
2369 case ENC_TIME_MSECS|ENC_LITTLE_ENDIAN:
2371 * Milliseconds, 1 to 8 bytes.
2372 * For absolute times, it's milliseconds since the
2373 * UN*X epoch.
2375 if (length >= 1 && length <= 8) {
2376 uint64_t msecs;
2378 msecs = get_uint64_value(tree, tvb, start, length, encoding);
2379 time_stamp->secs = (time_t)(msecs / 1000);
2380 time_stamp->nsecs = (int)(msecs % 1000)*1000000;
2381 } else {
2382 time_stamp->secs = 0;
2383 time_stamp->nsecs = 0;
2384 report_type_length_mismatch(tree, "a time-in-milliseconds time stamp", length, (length < 4));
2386 break;
2388 case ENC_TIME_USECS|ENC_BIG_ENDIAN:
2389 case ENC_TIME_USECS|ENC_LITTLE_ENDIAN:
2391 * Microseconds, 1 to 8 bytes.
2392 * For absolute times, it's microseconds since the
2393 * UN*X epoch.
2395 if (length >= 1 && length <= 8) {
2396 uint64_t usecs;
2398 usecs = get_uint64_value(tree, tvb, start, length, encoding);
2399 time_stamp->secs = (time_t)(usecs / 1000000);
2400 time_stamp->nsecs = (int)(usecs % 1000000)*1000;
2401 } else {
2402 time_stamp->secs = 0;
2403 time_stamp->nsecs = 0;
2404 report_type_length_mismatch(tree, "a time-in-microseconds time stamp", length, (length < 4));
2406 break;
2408 case ENC_TIME_NSECS|ENC_BIG_ENDIAN:
2409 case ENC_TIME_NSECS|ENC_LITTLE_ENDIAN:
2411 * nanoseconds, 1 to 8 bytes.
2412 * For absolute times, it's nanoseconds since the
2413 * UN*X epoch.
2416 if (length >= 1 && length <= 8) {
2417 uint64_t nsecs;
2419 nsecs = get_uint64_value(tree, tvb, start, length, encoding);
2420 time_stamp->secs = (time_t)(nsecs / 1000000000);
2421 time_stamp->nsecs = (int)(nsecs % 1000000000);
2422 } else {
2423 time_stamp->secs = 0;
2424 time_stamp->nsecs = 0;
2425 report_type_length_mismatch(tree, "a time-in-nanoseconds time stamp", length, (length < 4));
2427 break;
2429 case ENC_TIME_RFC_3971|ENC_BIG_ENDIAN:
2431 * 1/64ths of a second since the UN*X epoch,
2432 * big-endian.
2434 * Only supported for absolute times.
2436 DISSECTOR_ASSERT(!is_relative);
2438 if (length == 8) {
2440 * The upper 48 bits are seconds since the
2441 * UN*X epoch.
2443 time_stamp->secs = (time_t)tvb_get_ntoh48(tvb, start);
2445 * The lower 16 bits are 1/2^16s of a second;
2446 * convert them to nanoseconds.
2448 * XXX - this may give the impression of higher
2449 * precision than you actually get.
2451 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohs(tvb, start+6)/65536.0));
2452 } else {
2453 time_stamp->secs = 0;
2454 time_stamp->nsecs = 0;
2455 report_type_length_mismatch(tree, "an RFC 3971-style time stamp", length, (length < 4));
2457 break;
2459 case ENC_TIME_RFC_3971|ENC_LITTLE_ENDIAN:
2461 * 1/64ths of a second since the UN*X epoch,
2462 * little-endian.
2464 * Only supported for absolute times.
2466 DISSECTOR_ASSERT(!is_relative);
2468 if (length == 8) {
2470 * XXX - this is assuming that, if anybody
2471 * were ever to use this format - RFC 3971
2472 * doesn't, because that's an Internet
2473 * protocol, and those use network byte
2474 * order, i.e. big-endian - they'd treat it
2475 * as a 64-bit count of 1/2^16s of a second,
2476 * putting the upper 48 bits at the end.
2478 * The lower 48 bits are seconds since the
2479 * UN*X epoch.
2481 time_stamp->secs = (time_t)tvb_get_letoh48(tvb, start+2);
2483 * The upper 16 bits are 1/2^16s of a second;
2484 * convert them to nanoseconds.
2486 * XXX - this may give the impression of higher
2487 * precision than you actually get.
2489 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohs(tvb, start)/65536.0));
2490 } else {
2491 time_stamp->secs = 0;
2492 time_stamp->nsecs = 0;
2493 report_type_length_mismatch(tree, "an RFC 3971-style time stamp", length, (length < 4));
2495 break;
2497 case ENC_TIME_SECS_NTP|ENC_BIG_ENDIAN:
2499 * NTP time stamp, with 1-second resolution (i.e.,
2500 * seconds since the NTP epoch), big-endian.
2501 * Only supported for absolute times.
2503 DISSECTOR_ASSERT(!is_relative);
2505 if (length == 4) {
2507 * We need a temporary variable here so the unsigned math
2508 * works correctly (for years > 2036 according to RFC 2030
2509 * chapter 3).
2511 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2512 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2513 * If bit 0 is not set, the time is in the range 2036-2104 and
2514 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2516 tmpsecs = tvb_get_ntohl(tvb, start);
2517 if ((tmpsecs & 0x80000000) != 0)
2518 time_stamp->secs = (time_t)((int64_t)tmpsecs - NTP_TIMEDIFF1900TO1970SEC);
2519 else
2520 time_stamp->secs = (time_t)((int64_t)tmpsecs + NTP_TIMEDIFF1970TO2036SEC);
2521 time_stamp->nsecs = 0;
2522 } else {
2523 time_stamp->secs = 0;
2524 time_stamp->nsecs = 0;
2525 report_type_length_mismatch(tree, "an NTP seconds-only time stamp", length, (length < 4));
2527 break;
2529 case ENC_TIME_SECS_NTP|ENC_LITTLE_ENDIAN:
2531 * NTP time stamp, with 1-second resolution (i.e.,
2532 * seconds since the NTP epoch), little-endian.
2533 * Only supported for absolute times.
2535 DISSECTOR_ASSERT(!is_relative);
2538 * We need a temporary variable here so the unsigned math
2539 * works correctly (for years > 2036 according to RFC 2030
2540 * chapter 3).
2542 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2543 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2544 * If bit 0 is not set, the time is in the range 2036-2104 and
2545 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2547 if (length == 4) {
2548 tmpsecs = tvb_get_letohl(tvb, start);
2549 if ((tmpsecs & 0x80000000) != 0)
2550 time_stamp->secs = (time_t)((int64_t)tmpsecs - NTP_TIMEDIFF1900TO1970SEC);
2551 else
2552 time_stamp->secs = (time_t)((int64_t)tmpsecs + NTP_TIMEDIFF1970TO2036SEC);
2553 time_stamp->nsecs = 0;
2554 } else {
2555 time_stamp->secs = 0;
2556 time_stamp->nsecs = 0;
2557 report_type_length_mismatch(tree, "an NTP seconds-only time stamp", length, (length < 4));
2559 break;
2561 case ENC_TIME_MSEC_NTP | ENC_BIG_ENDIAN:
2563 * Milliseconds, 6 to 8 bytes.
2564 * For absolute times, it's milliseconds since the
2565 * NTP epoch.
2567 * ETSI TS 129.274 8.119 defines this as:
2568 * "a 48 bit unsigned integer in network order format
2569 * ...encoded as the number of milliseconds since
2570 * 00:00:00 January 1, 1900 00:00 UTC, i.e. as the
2571 * rounded value of 1000 x the value of the 64-bit
2572 * timestamp (Seconds + (Fraction / (1<<32))) defined
2573 * in clause 6 of IETF RFC 5905."
2575 * Taken literally, the part after "i.e." would
2576 * mean that the value rolls over before reaching
2577 * 2^32 * 1000 = 4294967296000 = 0x3e800000000
2578 * when the 64 bit timestamp rolls over, and we have
2579 * to pick an NTP Era equivalence class to support
2580 * (such as 1968-01-20 to 2104-02-06).
2582 * OTOH, the extra room might be used to store Era
2583 * information instead, in which case times until
2584 * 10819-08-03 can be represented with 6 bytes without
2585 * ambiguity. We handle both implementations, and assume
2586 * that times before 1968-01-20 are not represented.
2588 * Only 6 bytes or more makes sense as an absolute
2589 * time. 5 bytes or fewer could express a span of
2590 * less than 35 years, either 1900-1934 or 2036-2070.
2592 if (length >= 6 && length <= 8) {
2593 uint64_t msecs;
2595 msecs = get_uint64_value(tree, tvb, start, length, encoding);
2596 tmp64secs = (msecs / 1000);
2598 * Assume that times in the first half of NTP
2599 * Era 0 really represent times in the NTP
2600 * Era 1.
2602 if (tmp64secs >= 0x80000000)
2603 time_stamp->secs = (time_t)((int64_t)tmp64secs - NTP_TIMEDIFF1900TO1970SEC);
2604 else
2605 time_stamp->secs = (time_t)((int64_t)tmp64secs + NTP_TIMEDIFF1970TO2036SEC);
2606 time_stamp->nsecs = (int)(msecs % 1000)*1000000;
2608 else {
2609 time_stamp->secs = 0;
2610 time_stamp->nsecs = 0;
2611 report_type_length_mismatch(tree, "a time-in-milliseconds NTP time stamp", length, (length < 6));
2613 break;
2615 case ENC_TIME_MP4_FILE_SECS|ENC_BIG_ENDIAN:
2617 * MP4 file time stamps, big-endian.
2618 * Only supported for absolute times.
2620 DISSECTOR_ASSERT(!is_relative);
2622 if (length == 8) {
2623 tmp64secs = tvb_get_ntoh64(tvb, start);
2624 time_stamp->secs = (time_t)(int64_t)(tmp64secs - EPOCH_DELTA_1904_01_01_00_00_00_UTC);
2625 time_stamp->nsecs = 0;
2626 } else if (length == 4) {
2627 tmpsecs = tvb_get_ntohl(tvb, start);
2628 time_stamp->secs = (time_t)(int32_t)(tmpsecs - EPOCH_DELTA_1904_01_01_00_00_00_UTC);
2629 time_stamp->nsecs = 0;
2630 } else {
2631 time_stamp->secs = 0;
2632 time_stamp->nsecs = 0;
2633 report_type_length_mismatch(tree, "an MP4 time stamp", length, (length < 4));
2635 break;
2637 case ENC_TIME_ZBEE_ZCL | ENC_BIG_ENDIAN:
2639 * Zigbee ZCL time stamps, big-endian.
2640 * Only supported for absolute times.
2642 DISSECTOR_ASSERT(!is_relative);
2644 if (length == 8) {
2645 tmp64secs = tvb_get_ntoh64(tvb, start);
2646 time_stamp->secs = (time_t)(int64_t)(tmp64secs - EPOCH_DELTA_2000_01_01_00_00_00_UTC);
2647 time_stamp->nsecs = 0;
2648 } else if (length == 4) {
2649 tmpsecs = tvb_get_ntohl(tvb, start);
2650 time_stamp->secs = (time_t)(int32_t)(tmpsecs - EPOCH_DELTA_2000_01_01_00_00_00_UTC);
2651 time_stamp->nsecs = 0;
2652 } else {
2653 time_stamp->secs = 0;
2654 time_stamp->nsecs = 0;
2655 report_type_length_mismatch(tree, "a Zigbee ZCL time stamp", length, (length < 4));
2657 break;
2659 case ENC_TIME_ZBEE_ZCL | ENC_LITTLE_ENDIAN:
2661 * Zigbee ZCL time stamps, little-endian.
2662 * Only supported for absolute times.
2664 DISSECTOR_ASSERT(!is_relative);
2666 if (length == 8) {
2667 tmp64secs = tvb_get_letoh64(tvb, start);
2668 time_stamp->secs = (time_t)(int64_t)(tmp64secs - EPOCH_DELTA_2000_01_01_00_00_00_UTC);
2669 time_stamp->nsecs = 0;
2670 } else if (length == 4) {
2671 tmpsecs = tvb_get_letohl(tvb, start);
2672 time_stamp->secs = (time_t)(int32_t)(tmpsecs - EPOCH_DELTA_2000_01_01_00_00_00_UTC);
2673 time_stamp->nsecs = 0;
2674 } else {
2675 time_stamp->secs = 0;
2676 time_stamp->nsecs = 0;
2677 report_type_length_mismatch(tree, "a Zigbee ZCL time stamp", length, (length < 4));
2679 break;
2681 default:
2682 DISSECTOR_ASSERT_NOT_REACHED();
2683 break;
2687 static void
2688 tree_data_add_maybe_interesting_field(tree_data_t *tree_data, field_info *fi)
2690 const header_field_info *hfinfo = fi->hfinfo;
2692 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT || hfinfo->ref_type == HF_REF_TYPE_PRINT) {
2693 GPtrArray *ptrs = NULL;
2695 if (tree_data->interesting_hfids == NULL) {
2696 /* Initialize the hash because we now know that it is needed */
2697 tree_data->interesting_hfids =
2698 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
2699 } else if (g_hash_table_size(tree_data->interesting_hfids)) {
2700 ptrs = (GPtrArray *)g_hash_table_lookup(tree_data->interesting_hfids,
2701 GINT_TO_POINTER(hfinfo->id));
2704 if (!ptrs) {
2705 /* First element triggers the creation of pointer array */
2706 ptrs = g_ptr_array_new();
2707 g_hash_table_insert(tree_data->interesting_hfids,
2708 GINT_TO_POINTER(hfinfo->id), ptrs);
2711 g_ptr_array_add(ptrs, fi);
2717 * Validates that field length bytes are available starting from
2718 * start (pos/neg). Throws an exception if they aren't.
2720 static void
2721 test_length(header_field_info *hfinfo, tvbuff_t *tvb,
2722 int start, int length, const unsigned encoding)
2724 int size = length;
2726 if (!tvb)
2727 return;
2729 if ((hfinfo->type == FT_STRINGZ) ||
2730 ((encoding & ENC_VARINT_MASK) &&
2731 (FT_IS_UINT(hfinfo->type) || FT_IS_INT(hfinfo->type)))) {
2732 /* If we're fetching until the end of the TVB, only validate
2733 * that the offset is within range.
2735 if (length == -1)
2736 size = 0;
2739 tvb_ensure_bytes_exist(tvb, start, size);
2742 static void
2743 detect_trailing_stray_characters(unsigned encoding, const char *string, int length, proto_item *pi)
2745 bool found_stray_character = false;
2747 if (!string)
2748 return;
2750 switch (encoding & ENC_CHARENCODING_MASK) {
2751 case ENC_ASCII:
2752 case ENC_UTF_8:
2753 for (int i = (int)strlen(string); i < length; i++) {
2754 if (string[i] != '\0') {
2755 found_stray_character = true;
2756 break;
2759 break;
2761 default:
2762 break;
2765 if (found_stray_character) {
2766 expert_add_info(NULL, pi, &ei_string_trailing_characters);
2770 static void
2771 free_fvalue_cb(void *data)
2773 fvalue_t *fv = (fvalue_t*)data;
2774 fvalue_free(fv);
2777 /* Add an item to a proto_tree, using the text label registered to that item;
2778 the item is extracted from the tvbuff handed to it. */
2779 static proto_item *
2780 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
2781 tvbuff_t *tvb, int start, int length,
2782 unsigned encoding)
2784 proto_item *pi;
2785 uint32_t value, n;
2786 uint64_t value64;
2787 ws_in4_addr ipv4_value;
2788 float floatval;
2789 double doubleval;
2790 const char *stringval = NULL;
2791 nstime_t time_stamp;
2792 bool length_error;
2794 /* Ensure that the newly created fvalue_t is freed if we throw an
2795 * exception before adding it to the tree. (gcc creates clobbering
2796 * when it optimizes the equivalent TRY..EXCEPT implementation.)
2797 * XXX: Move the new_field_info() call inside here?
2799 CLEANUP_PUSH(free_fvalue_cb, new_fi->value);
2801 switch (new_fi->hfinfo->type) {
2802 case FT_NONE:
2803 /* no value to set for FT_NONE */
2804 break;
2806 case FT_PROTOCOL:
2807 proto_tree_set_protocol_tvb(new_fi, tvb, new_fi->hfinfo->name, length);
2808 break;
2810 case FT_BYTES:
2811 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
2812 break;
2814 case FT_UINT_BYTES:
2815 n = get_uint_value(tree, tvb, start, length, encoding);
2816 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
2818 /* Instead of calling proto_item_set_len(), since we don't yet
2819 * have a proto_item, we set the field_info's length ourselves. */
2820 new_fi->length = n + length;
2821 break;
2823 case FT_BOOLEAN:
2825 * Map all non-zero values to little-endian for
2826 * backwards compatibility.
2828 if (encoding)
2829 encoding = ENC_LITTLE_ENDIAN;
2830 proto_tree_set_boolean(new_fi,
2831 get_uint64_value(tree, tvb, start, length, encoding));
2832 break;
2834 case FT_CHAR:
2835 /* XXX - make these just FT_UINT? */
2836 case FT_UINT8:
2837 case FT_UINT16:
2838 case FT_UINT24:
2839 case FT_UINT32:
2840 if (encoding & ENC_VARINT_MASK) {
2841 new_fi->length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value64, encoding);
2842 value = (uint32_t)value64;
2843 if (!(encoding & ENC_VARINT_QUIC)) {
2844 new_fi->flags |= FI_VARINT;
2847 else {
2849 * Map all non-zero values to little-endian for
2850 * backwards compatibility.
2852 if (encoding)
2853 encoding = ENC_LITTLE_ENDIAN;
2855 value = get_uint_value(tree, tvb, start, length, encoding);
2857 proto_tree_set_uint(new_fi, value);
2858 break;
2860 case FT_UINT40:
2861 case FT_UINT48:
2862 case FT_UINT56:
2863 case FT_UINT64:
2864 if (encoding & ENC_VARINT_MASK) {
2865 new_fi->length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value64, encoding);
2866 if (!(encoding & ENC_VARINT_QUIC)) {
2867 new_fi->flags |= FI_VARINT;
2870 else {
2872 * Map all other non-zero values to little-endian for
2873 * backwards compatibility.
2875 if (encoding)
2876 encoding = ENC_LITTLE_ENDIAN;
2878 value64 = get_uint64_value(tree, tvb, start, length, encoding);
2880 proto_tree_set_uint64(new_fi, value64);
2881 break;
2883 /* XXX - make these just FT_INT? */
2884 case FT_INT8:
2885 case FT_INT16:
2886 case FT_INT24:
2887 case FT_INT32:
2889 * Map all non-zero values to little-endian for
2890 * backwards compatibility.
2892 if (encoding)
2893 encoding = ENC_LITTLE_ENDIAN;
2894 proto_tree_set_int(new_fi,
2895 get_int_value(tree, tvb, start, length, encoding));
2896 break;
2898 case FT_INT40:
2899 case FT_INT48:
2900 case FT_INT56:
2901 case FT_INT64:
2903 * Map all non-zero values to little-endian for
2904 * backwards compatibility.
2906 if (encoding)
2907 encoding = ENC_LITTLE_ENDIAN;
2908 proto_tree_set_int64(new_fi,
2909 get_int64_value(tree, tvb, start, length, encoding));
2910 break;
2912 case FT_IPv4:
2914 * Map all non-zero values to little-endian for
2915 * backwards compatibility.
2917 if (encoding)
2918 encoding = ENC_LITTLE_ENDIAN;
2919 if (length != FT_IPv4_LEN) {
2920 length_error = length < FT_IPv4_LEN ? true : false;
2921 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
2923 ipv4_value = tvb_get_ipv4(tvb, start);
2925 * NOTE: to support code written when
2926 * proto_tree_add_item() took a bool as its
2927 * last argument, with false meaning "big-endian"
2928 * and true meaning "little-endian", we treat any
2929 * non-zero value of "encoding" as meaning
2930 * "little-endian".
2932 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(ipv4_value) : ipv4_value);
2933 break;
2935 case FT_IPXNET:
2936 if (length != FT_IPXNET_LEN) {
2937 length_error = length < FT_IPXNET_LEN ? true : false;
2938 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
2940 proto_tree_set_ipxnet(new_fi,
2941 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, ENC_BIG_ENDIAN));
2942 break;
2944 case FT_IPv6:
2945 if (length != FT_IPv6_LEN) {
2946 length_error = length < FT_IPv6_LEN ? true : false;
2947 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
2949 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
2950 break;
2952 case FT_FCWWN:
2953 if (length != FT_FCWWN_LEN) {
2954 length_error = length < FT_FCWWN_LEN ? true : false;
2955 report_type_length_mismatch(tree, "an FCWWN address", length, length_error);
2957 proto_tree_set_fcwwn_tvb(new_fi, tvb, start, length);
2958 break;
2960 case FT_AX25:
2961 if (length != 7) {
2962 length_error = length < 7 ? true : false;
2963 report_type_length_mismatch(tree, "an AX.25 address", length, length_error);
2965 proto_tree_set_ax25_tvb(new_fi, tvb, start);
2966 break;
2968 case FT_VINES:
2969 if (length != VINES_ADDR_LEN) {
2970 length_error = length < VINES_ADDR_LEN ? true : false;
2971 report_type_length_mismatch(tree, "a Vines address", length, length_error);
2973 proto_tree_set_vines_tvb(new_fi, tvb, start);
2974 break;
2976 case FT_ETHER:
2977 if (length != FT_ETHER_LEN) {
2978 length_error = length < FT_ETHER_LEN ? true : false;
2979 report_type_length_mismatch(tree, "a MAC address", length, length_error);
2981 proto_tree_set_ether_tvb(new_fi, tvb, start);
2982 break;
2984 case FT_EUI64:
2986 * Map all non-zero values to little-endian for
2987 * backwards compatibility.
2989 if (encoding)
2990 encoding = ENC_LITTLE_ENDIAN;
2991 if (length != FT_EUI64_LEN) {
2992 length_error = length < FT_EUI64_LEN ? true : false;
2993 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
2995 proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
2996 break;
2997 case FT_GUID:
2999 * Map all non-zero values to little-endian for
3000 * backwards compatibility.
3002 if (encoding)
3003 encoding = ENC_LITTLE_ENDIAN;
3004 if (length != FT_GUID_LEN) {
3005 length_error = length < FT_GUID_LEN ? true : false;
3006 report_type_length_mismatch(tree, "a GUID", length, length_error);
3008 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
3009 break;
3011 case FT_OID:
3012 case FT_REL_OID:
3013 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
3014 break;
3016 case FT_SYSTEM_ID:
3017 proto_tree_set_system_id_tvb(new_fi, tvb, start, length);
3018 break;
3020 case FT_FLOAT:
3022 * NOTE: to support code written when
3023 * proto_tree_add_item() took a bool as its
3024 * last argument, with false meaning "big-endian"
3025 * and true meaning "little-endian", we treat any
3026 * non-zero value of "encoding" as meaning
3027 * "little-endian".
3029 * At some point in the future, we might
3030 * support non-IEEE-binary floating-point
3031 * formats in the encoding as well
3032 * (IEEE decimal, System/3x0, VAX).
3034 if (encoding)
3035 encoding = ENC_LITTLE_ENDIAN;
3036 if (length != 4) {
3037 length_error = length < 4 ? true : false;
3038 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
3040 if (encoding)
3041 floatval = tvb_get_letohieee_float(tvb, start);
3042 else
3043 floatval = tvb_get_ntohieee_float(tvb, start);
3044 proto_tree_set_float(new_fi, floatval);
3045 break;
3047 case FT_DOUBLE:
3049 * NOTE: to support code written when
3050 * proto_tree_add_item() took a bool as its
3051 * last argument, with false meaning "big-endian"
3052 * and true meaning "little-endian", we treat any
3053 * non-zero value of "encoding" as meaning
3054 * "little-endian".
3056 * At some point in the future, we might
3057 * support non-IEEE-binary floating-point
3058 * formats in the encoding as well
3059 * (IEEE decimal, System/3x0, VAX).
3061 if (encoding == true)
3062 encoding = ENC_LITTLE_ENDIAN;
3063 if (length != 8) {
3064 length_error = length < 8 ? true : false;
3065 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
3067 if (encoding)
3068 doubleval = tvb_get_letohieee_double(tvb, start);
3069 else
3070 doubleval = tvb_get_ntohieee_double(tvb, start);
3071 proto_tree_set_double(new_fi, doubleval);
3072 break;
3074 case FT_STRING:
3075 stringval = get_string_value(PNODE_POOL(tree),
3076 tvb, start, length, &length, encoding);
3077 proto_tree_set_string(new_fi, stringval);
3079 /* Instead of calling proto_item_set_len(), since we
3080 * don't yet have a proto_item, we set the
3081 * field_info's length ourselves.
3083 * XXX - our caller can't use that length to
3084 * advance an offset unless they arrange that
3085 * there always be a protocol tree into which
3086 * we're putting this item.
3088 new_fi->length = length;
3089 break;
3091 case FT_STRINGZ:
3092 stringval = get_stringz_value(PNODE_POOL(tree),
3093 tree, tvb, start, length, &length, encoding);
3094 proto_tree_set_string(new_fi, stringval);
3096 /* Instead of calling proto_item_set_len(),
3097 * since we don't yet have a proto_item, we
3098 * set the field_info's length ourselves.
3100 * XXX - our caller can't use that length to
3101 * advance an offset unless they arrange that
3102 * there always be a protocol tree into which
3103 * we're putting this item.
3105 new_fi->length = length;
3106 break;
3108 case FT_UINT_STRING:
3110 * NOTE: to support code written when
3111 * proto_tree_add_item() took a bool as its
3112 * last argument, with false meaning "big-endian"
3113 * and true meaning "little-endian", if the
3114 * encoding value is true, treat that as
3115 * ASCII with a little-endian length.
3117 * This won't work for code that passes
3118 * arbitrary non-zero values; that code
3119 * will need to be fixed.
3121 if (encoding == true)
3122 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
3123 stringval = get_uint_string_value(PNODE_POOL(tree),
3124 tree, tvb, start, length, &length, encoding);
3125 proto_tree_set_string(new_fi, stringval);
3127 /* Instead of calling proto_item_set_len(), since we
3128 * don't yet have a proto_item, we set the
3129 * field_info's length ourselves.
3131 * XXX - our caller can't use that length to
3132 * advance an offset unless they arrange that
3133 * there always be a protocol tree into which
3134 * we're putting this item.
3136 new_fi->length = length;
3137 break;
3139 case FT_STRINGZPAD:
3140 stringval = get_stringzpad_value(PNODE_POOL(tree),
3141 tvb, start, length, &length, encoding);
3142 proto_tree_set_string(new_fi, stringval);
3144 /* Instead of calling proto_item_set_len(), since we
3145 * don't yet have a proto_item, we set the
3146 * field_info's length ourselves.
3148 * XXX - our caller can't use that length to
3149 * advance an offset unless they arrange that
3150 * there always be a protocol tree into which
3151 * we're putting this item.
3153 new_fi->length = length;
3154 break;
3156 case FT_STRINGZTRUNC:
3157 stringval = get_stringztrunc_value(PNODE_POOL(tree),
3158 tvb, start, length, &length, encoding);
3159 proto_tree_set_string(new_fi, stringval);
3161 /* Instead of calling proto_item_set_len(), since we
3162 * don't yet have a proto_item, we set the
3163 * field_info's length ourselves.
3165 * XXX - our caller can't use that length to
3166 * advance an offset unless they arrange that
3167 * there always be a protocol tree into which
3168 * we're putting this item.
3170 new_fi->length = length;
3171 break;
3173 case FT_ABSOLUTE_TIME:
3175 * Absolute times can be in any of a number of
3176 * formats, and they can be big-endian or
3177 * little-endian.
3179 * Historically FT_TIMEs were only timespecs;
3180 * the only question was whether they were stored
3181 * in big- or little-endian format.
3183 * For backwards compatibility, we interpret an
3184 * encoding of 1 as meaning "little-endian timespec",
3185 * so that passing true is interpreted as that.
3187 if (encoding == true)
3188 encoding = ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN;
3190 get_time_value(tree, tvb, start, length, encoding, &time_stamp, false);
3192 proto_tree_set_time(new_fi, &time_stamp);
3193 break;
3195 case FT_RELATIVE_TIME:
3197 * Relative times can be in any of a number of
3198 * formats, and they can be big-endian or
3199 * little-endian.
3201 * Historically FT_TIMEs were only timespecs;
3202 * the only question was whether they were stored
3203 * in big- or little-endian format.
3205 * For backwards compatibility, we interpret an
3206 * encoding of 1 as meaning "little-endian timespec",
3207 * so that passing true is interpreted as that.
3209 if (encoding == true)
3210 encoding = ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN;
3212 get_time_value(tree, tvb, start, length, encoding, &time_stamp, true);
3214 proto_tree_set_time(new_fi, &time_stamp);
3215 break;
3216 case FT_IEEE_11073_SFLOAT:
3217 if (encoding)
3218 encoding = ENC_LITTLE_ENDIAN;
3219 if (length != 2) {
3220 length_error = length < 2 ? true : false;
3221 report_type_length_mismatch(tree, "a IEEE 11073 SFLOAT", length, length_error);
3224 fvalue_set_uinteger(new_fi->value, tvb_get_uint16(tvb, start, encoding));
3226 break;
3227 case FT_IEEE_11073_FLOAT:
3228 if (encoding)
3229 encoding = ENC_LITTLE_ENDIAN;
3230 if (length != 4) {
3231 length_error = length < 4 ? true : false;
3232 report_type_length_mismatch(tree, "a IEEE 11073 FLOAT", length, length_error);
3235 break;
3236 default:
3237 REPORT_DISSECTOR_BUG("field %s is of unknown type %d (%s)",
3238 new_fi->hfinfo->abbrev,
3239 new_fi->hfinfo->type,
3240 ftype_name(new_fi->hfinfo->type));
3241 break;
3243 FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
3245 /* Don't add new node to proto_tree until now so that any exceptions
3246 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
3247 /* XXX. wouldn't be better to add this item to tree, with some special
3248 * flag (FI_EXCEPTION?) to know which item caused exception? For
3249 * strings and bytes, we would have to set new_fi->value to something
3250 * non-NULL, or otherwise ensure that proto_item_fill_display_label
3251 * could handle NULL values. */
3252 CLEANUP_POP
3253 pi = proto_tree_add_node(tree, new_fi);
3255 switch (new_fi->hfinfo->type) {
3257 case FT_STRING:
3258 /* XXX: trailing stray character detection should be done
3259 * _before_ conversion to UTF-8, because conversion can change
3260 * the length, or else get_string_length should return a value
3261 * for the "length in bytes of the string after conversion
3262 * including internal nulls." (Noting that we do, for other
3263 * reasons, still need the "length in bytes in the field",
3264 * especially for FT_STRINGZ.)
3266 * This is true even for ASCII and UTF-8, because
3267 * substituting REPLACEMENT CHARACTERS for illegal characters
3268 * can also do so (and for UTF-8 possibly even make the
3269 * string _shorter_).
3271 detect_trailing_stray_characters(encoding, stringval, length, pi);
3272 break;
3274 default:
3275 break;
3278 return pi;
3281 proto_item *
3282 proto_tree_add_item_ret_int(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3283 const int start, int length,
3284 const unsigned encoding, int32_t *retval)
3286 header_field_info *hfinfo;
3287 field_info *new_fi;
3288 int32_t value;
3290 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3292 switch (hfinfo->type) {
3293 case FT_INT8:
3294 case FT_INT16:
3295 case FT_INT24:
3296 case FT_INT32:
3297 break;
3298 case FT_INT64:
3299 REPORT_DISSECTOR_BUG("64-bit signed integer field %s used with proto_tree_add_item_ret_int()",
3300 hfinfo->abbrev);
3301 default:
3302 REPORT_DISSECTOR_BUG("Non-signed-integer field %s used with proto_tree_add_item_ret_int()",
3303 hfinfo->abbrev);
3306 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length,
3308 if(retval)
3310 *retval = 0;
3312 } );
3314 if (encoding & ENC_STRING) {
3315 REPORT_DISSECTOR_BUG("wrong encoding");
3317 /* I believe it's ok if this is called with a NULL tree */
3318 value = get_int_value(tree, tvb, start, length, encoding);
3320 if (retval) {
3321 int no_of_bits;
3322 *retval = value;
3323 if (hfinfo->bitmask) {
3324 /* Mask out irrelevant portions */
3325 *retval &= (uint32_t)(hfinfo->bitmask);
3326 /* Shift bits */
3327 *retval >>= hfinfo_bitshift(hfinfo);
3329 no_of_bits = ws_count_ones(hfinfo->bitmask);
3330 *retval = ws_sign_ext32(*retval, no_of_bits);
3333 CHECK_FOR_NULL_TREE(tree);
3335 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3337 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3339 proto_tree_set_int(new_fi, value);
3341 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3343 return proto_tree_add_node(tree, new_fi);
3346 proto_item *
3347 proto_tree_add_item_ret_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3348 const int start, int length,
3349 const unsigned encoding, uint32_t *retval)
3351 header_field_info *hfinfo;
3352 field_info *new_fi;
3353 uint32_t value;
3355 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3357 switch (hfinfo->type) {
3358 case FT_CHAR:
3359 case FT_UINT8:
3360 case FT_UINT16:
3361 case FT_UINT24:
3362 case FT_UINT32:
3363 break;
3364 default:
3365 REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
3366 hfinfo->abbrev);
3369 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length,
3371 if(retval)
3373 *retval = 0;
3375 } );
3377 if (encoding & ENC_STRING) {
3378 REPORT_DISSECTOR_BUG("wrong encoding");
3380 /* I believe it's ok if this is called with a NULL tree */
3381 /* XXX - modify if we ever support EBCDIC FT_CHAR */
3382 if (encoding & ENC_VARINT_MASK) {
3383 uint64_t temp64;
3384 tvb_get_varint(tvb, start, length, &temp64, encoding);
3385 value = (uint32_t)temp64;
3386 } else {
3387 value = get_uint_value(tree, tvb, start, length, encoding);
3390 if (retval) {
3391 *retval = value;
3392 if (hfinfo->bitmask) {
3393 /* Mask out irrelevant portions */
3394 *retval &= (uint32_t)(hfinfo->bitmask);
3395 /* Shift bits */
3396 *retval >>= hfinfo_bitshift(hfinfo);
3400 CHECK_FOR_NULL_TREE(tree);
3402 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3404 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3406 proto_tree_set_uint(new_fi, value);
3408 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3409 if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG|ENC_VARINT_SDNV)) {
3410 new_fi->flags |= FI_VARINT;
3412 return proto_tree_add_node(tree, new_fi);
3415 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3416 * and returns proto_item* and uint value retreived*/
3417 proto_item *
3418 ptvcursor_add_ret_uint(ptvcursor_t *ptvc, int hfindex, int length,
3419 const unsigned encoding, uint32_t *retval)
3421 field_info *new_fi;
3422 header_field_info *hfinfo;
3423 int item_length;
3424 int offset;
3425 uint32_t value;
3427 offset = ptvc->offset;
3428 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3430 switch (hfinfo->type) {
3431 case FT_CHAR:
3432 case FT_UINT8:
3433 case FT_UINT16:
3434 case FT_UINT24:
3435 case FT_UINT32:
3436 break;
3437 default:
3438 REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
3439 hfinfo->abbrev);
3442 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
3443 test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);
3445 /* I believe it's ok if this is called with a NULL tree */
3446 /* XXX - modify if we ever support EBCDIC FT_CHAR */
3447 value = get_uint_value(ptvc->tree, ptvc->tvb, offset, item_length, encoding);
3449 if (retval) {
3450 *retval = value;
3451 if (hfinfo->bitmask) {
3452 /* Mask out irrelevant portions */
3453 *retval &= (uint32_t)(hfinfo->bitmask);
3454 /* Shift bits */
3455 *retval >>= hfinfo_bitshift(hfinfo);
3459 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
3460 item_length, encoding);
3462 CHECK_FOR_NULL_TREE(ptvc->tree);
3464 /* Coast clear. Try and fake it */
3465 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
3467 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
3469 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
3470 offset, length, encoding);
3473 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3474 * and returns proto_item* and int value retreived*/
3475 proto_item *
3476 ptvcursor_add_ret_int(ptvcursor_t *ptvc, int hfindex, int length,
3477 const unsigned encoding, int32_t *retval)
3479 field_info *new_fi;
3480 header_field_info *hfinfo;
3481 int item_length;
3482 int offset;
3483 uint32_t value;
3485 offset = ptvc->offset;
3486 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3488 switch (hfinfo->type) {
3489 case FT_INT8:
3490 case FT_INT16:
3491 case FT_INT24:
3492 case FT_INT32:
3493 break;
3494 default:
3495 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
3496 hfinfo->abbrev);
3499 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
3500 test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);
3502 /* I believe it's ok if this is called with a NULL tree */
3503 /* XXX - modify if we ever support EBCDIC FT_CHAR */
3504 value = get_int_value(ptvc->tree, ptvc->tvb, offset, item_length, encoding);
3506 if (retval) {
3507 int no_of_bits;
3508 *retval = value;
3509 if (hfinfo->bitmask) {
3510 /* Mask out irrelevant portions */
3511 *retval &= (uint32_t)(hfinfo->bitmask);
3512 /* Shift bits */
3513 *retval >>= hfinfo_bitshift(hfinfo);
3515 no_of_bits = ws_count_ones(hfinfo->bitmask);
3516 *retval = ws_sign_ext32(*retval, no_of_bits);
3519 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
3520 item_length, encoding);
3522 CHECK_FOR_NULL_TREE(ptvc->tree);
3524 /* Coast clear. Try and fake it */
3525 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
3527 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
3529 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
3530 offset, length, encoding);
3533 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3534 * and returns proto_item* and string value retreived */
3535 proto_item*
3536 ptvcursor_add_ret_string(ptvcursor_t* ptvc, int hf, int length, const unsigned encoding, wmem_allocator_t *scope, const uint8_t **retval)
3538 header_field_info *hfinfo;
3539 field_info *new_fi;
3540 const uint8_t *value;
3541 int item_length;
3542 int offset;
3544 offset = ptvc->offset;
3546 PROTO_REGISTRAR_GET_NTH(hf, hfinfo);
3548 switch (hfinfo->type) {
3549 case FT_STRING:
3550 value = get_string_value(scope, ptvc->tvb, offset, length, &item_length, encoding);
3551 break;
3552 case FT_STRINGZ:
3553 value = get_stringz_value(scope, ptvc->tree, ptvc->tvb, offset, length, &item_length, encoding);
3554 break;
3555 case FT_UINT_STRING:
3556 value = get_uint_string_value(scope, ptvc->tree, ptvc->tvb, offset, length, &item_length, encoding);
3557 break;
3558 case FT_STRINGZPAD:
3559 value = get_stringzpad_value(scope, ptvc->tvb, offset, length, &item_length, encoding);
3560 break;
3561 case FT_STRINGZTRUNC:
3562 value = get_stringztrunc_value(scope, ptvc->tvb, offset, length, &item_length, encoding);
3563 break;
3564 default:
3565 REPORT_DISSECTOR_BUG("field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, FT_STRINGZPAD, or FT_STRINGZTRUNC",
3566 hfinfo->abbrev);
3569 if (retval)
3570 *retval = value;
3572 ptvc->offset += item_length;
3574 CHECK_FOR_NULL_TREE(ptvc->tree);
3576 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfinfo->id, hfinfo);
3578 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
3580 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
3581 offset, length, encoding);
3584 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3585 * and returns proto_item* and boolean value retreived */
3586 proto_item*
3587 ptvcursor_add_ret_boolean(ptvcursor_t* ptvc, int hfindex, int length, const unsigned encoding, bool *retval)
3589 header_field_info *hfinfo;
3590 field_info *new_fi;
3591 int item_length;
3592 int offset;
3593 uint64_t value, bitval;
3595 offset = ptvc->offset;
3596 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3598 if (hfinfo->type != FT_BOOLEAN) {
3599 REPORT_DISSECTOR_BUG("field %s is not of type FT_BOOLEAN",
3600 hfinfo->abbrev);
3603 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length,
3605 if(retval)
3607 *retval = false;
3609 } );
3611 if (encoding & ENC_STRING) {
3612 REPORT_DISSECTOR_BUG("wrong encoding");
3615 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
3616 test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);
3618 /* I believe it's ok if this is called with a NULL tree */
3619 value = get_uint64_value(ptvc->tree, ptvc->tvb, offset, length, encoding);
3621 if (retval) {
3622 bitval = value;
3623 if (hfinfo->bitmask) {
3624 /* Mask out irrelevant portions */
3625 bitval &= hfinfo->bitmask;
3627 *retval = (bitval != 0);
3630 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
3631 item_length, encoding);
3633 CHECK_FOR_NULL_TREE(ptvc->tree);
3635 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfinfo->id, hfinfo);
3637 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
3639 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
3640 offset, length, encoding);
3643 proto_item *
3644 proto_tree_add_item_ret_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3645 const int start, int length, const unsigned encoding, uint64_t *retval)
3647 header_field_info *hfinfo;
3648 field_info *new_fi;
3649 uint64_t value;
3651 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3653 switch (hfinfo->type) {
3654 case FT_UINT40:
3655 case FT_UINT48:
3656 case FT_UINT56:
3657 case FT_UINT64:
3658 break;
3659 default:
3660 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, or FT_UINT64",
3661 hfinfo->abbrev);
3664 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length,
3666 if(retval)
3668 *retval = 0;
3670 } );
3672 if (encoding & ENC_STRING) {
3673 REPORT_DISSECTOR_BUG("wrong encoding");
3675 /* I believe it's ok if this is called with a NULL tree */
3676 if (encoding & ENC_VARINT_MASK) {
3677 tvb_get_varint(tvb, start, length, &value, encoding);
3678 } else {
3679 value = get_uint64_value(tree, tvb, start, length, encoding);
3682 if (retval) {
3683 *retval = value;
3684 if (hfinfo->bitmask) {
3685 /* Mask out irrelevant portions */
3686 *retval &= hfinfo->bitmask;
3687 /* Shift bits */
3688 *retval >>= hfinfo_bitshift(hfinfo);
3692 CHECK_FOR_NULL_TREE(tree);
3694 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3696 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3698 proto_tree_set_uint64(new_fi, value);
3700 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3701 if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG|ENC_VARINT_SDNV)) {
3702 new_fi->flags |= FI_VARINT;
3705 return proto_tree_add_node(tree, new_fi);
3708 proto_item *
3709 proto_tree_add_item_ret_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3710 const int start, int length, const unsigned encoding, int64_t *retval)
3712 header_field_info *hfinfo;
3713 field_info *new_fi;
3714 int64_t value;
3716 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3718 switch (hfinfo->type) {
3719 case FT_INT40:
3720 case FT_INT48:
3721 case FT_INT56:
3722 case FT_INT64:
3723 break;
3724 default:
3725 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
3726 hfinfo->abbrev);
3729 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length,
3731 if(retval)
3733 *retval = 0;
3735 } );
3737 if (encoding & ENC_STRING) {
3738 REPORT_DISSECTOR_BUG("wrong encoding");
3740 /* I believe it's ok if this is called with a NULL tree */
3741 if (encoding & ENC_VARINT_MASK) {
3742 tvb_get_varint(tvb, start, length, &value, encoding);
3744 else {
3745 value = get_int64_value(tree, tvb, start, length, encoding);
3748 if (retval) {
3749 *retval = value;
3752 CHECK_FOR_NULL_TREE(tree);
3754 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3756 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3758 proto_tree_set_int64(new_fi, value);
3760 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3761 if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG|ENC_VARINT_SDNV)) {
3762 new_fi->flags |= FI_VARINT;
3765 return proto_tree_add_node(tree, new_fi);
3768 proto_item *
3769 proto_tree_add_item_ret_varint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3770 const int start, int length, const unsigned encoding, uint64_t *retval, int *lenretval)
3772 header_field_info *hfinfo;
3773 field_info *new_fi;
3774 uint64_t value;
3776 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3778 if ((!FT_IS_INT(hfinfo->type)) && (!FT_IS_UINT(hfinfo->type))) {
3779 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT or FT_INT",
3780 hfinfo->abbrev);
3783 /* length validation for native number encoding caught by get_uint64_value() */
3784 /* length has to be -1 or > 0 regardless of encoding */
3785 if (length == 0)
3786 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_varint",
3787 length);
3789 if (encoding & ENC_STRING) {
3790 REPORT_DISSECTOR_BUG("wrong encoding");
3793 length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value, encoding);
3795 if (retval) {
3796 *retval = value;
3797 if (hfinfo->bitmask) {
3798 /* Mask out irrelevant portions */
3799 *retval &= hfinfo->bitmask;
3800 /* Shift bits */
3801 *retval >>= hfinfo_bitshift(hfinfo);
3805 if (lenretval) {
3806 *lenretval = length;
3809 CHECK_FOR_NULL_TREE(tree);
3811 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3813 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3815 proto_tree_set_uint64(new_fi, value);
3817 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3818 if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG|ENC_VARINT_SDNV)) {
3819 new_fi->flags |= FI_VARINT;
3822 return proto_tree_add_node(tree, new_fi);
3826 proto_item *
3827 proto_tree_add_item_ret_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3828 const int start, int length,
3829 const unsigned encoding, bool *retval)
3831 header_field_info *hfinfo;
3832 field_info *new_fi;
3833 uint64_t value, bitval;
3835 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3837 if (hfinfo->type != FT_BOOLEAN) {
3838 REPORT_DISSECTOR_BUG("field %s is not of type FT_BOOLEAN",
3839 hfinfo->abbrev);
3842 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length,
3844 if(retval)
3846 *retval = false;
3848 } );
3850 if (encoding & ENC_STRING) {
3851 REPORT_DISSECTOR_BUG("wrong encoding");
3853 /* I believe it's ok if this is called with a NULL tree */
3854 value = get_uint64_value(tree, tvb, start, length, encoding);
3856 if (retval) {
3857 bitval = value;
3858 if (hfinfo->bitmask) {
3859 /* Mask out irrelevant portions */
3860 bitval &= hfinfo->bitmask;
3862 *retval = (bitval != 0);
3865 CHECK_FOR_NULL_TREE(tree);
3867 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3869 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3871 proto_tree_set_boolean(new_fi, value);
3873 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3875 return proto_tree_add_node(tree, new_fi);
3878 proto_item *
3879 proto_tree_add_item_ret_float(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3880 const int start, int length,
3881 const unsigned encoding, float *retval)
3883 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3884 field_info *new_fi;
3885 float value;
3887 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3889 if (hfinfo->type != FT_FLOAT) {
3890 REPORT_DISSECTOR_BUG("field %s is not of type FT_FLOAT", hfinfo->abbrev);
3893 if (length != 4) {
3894 report_type_length_mismatch(tree, "a single-precision floating point number", length, true);
3897 /* treat any nonzero encoding as little endian for backwards compatibility */
3898 value = encoding ? tvb_get_letohieee_float(tvb, start) : tvb_get_ntohieee_float(tvb, start);
3899 if (retval) {
3900 *retval = value;
3903 CHECK_FOR_NULL_TREE(tree);
3905 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3907 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3908 if (encoding) {
3909 new_fi->flags |= FI_LITTLE_ENDIAN;
3912 proto_tree_set_float(new_fi, value);
3914 return proto_tree_add_node(tree, new_fi);
3917 proto_item *
3918 proto_tree_add_item_ret_double(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3919 const int start, int length,
3920 const unsigned encoding, double *retval)
3922 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3923 field_info *new_fi;
3924 double value;
3926 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3928 if (hfinfo->type != FT_DOUBLE) {
3929 REPORT_DISSECTOR_BUG("field %s is not of type FT_DOUBLE", hfinfo->abbrev);
3932 if (length != 8) {
3933 report_type_length_mismatch(tree, "a double-precision floating point number", length, true);
3936 /* treat any nonzero encoding as little endian for backwards compatibility */
3937 value = encoding ? tvb_get_letohieee_double(tvb, start) : tvb_get_ntohieee_double(tvb, start);
3938 if (retval) {
3939 *retval = value;
3942 CHECK_FOR_NULL_TREE(tree);
3944 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3946 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3947 if (encoding) {
3948 new_fi->flags |= FI_LITTLE_ENDIAN;
3951 proto_tree_set_double(new_fi, value);
3953 return proto_tree_add_node(tree, new_fi);
3956 proto_item *
3957 proto_tree_add_item_ret_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3958 const int start, int length,
3959 const unsigned encoding, ws_in4_addr *retval)
3961 header_field_info *hfinfo;
3962 field_info *new_fi;
3963 ws_in4_addr value;
3965 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3967 switch (hfinfo->type) {
3968 case FT_IPv4:
3969 break;
3970 default:
3971 REPORT_DISSECTOR_BUG("field %s is not of type FT_IPv4",
3972 hfinfo->abbrev);
3975 if (length != FT_IPv4_LEN)
3976 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_ipv4",
3977 length);
3979 if (encoding & (ENC_STRING | ENC_VARINT_MASK)) {
3980 REPORT_DISSECTOR_BUG("wrong encoding");
3984 * NOTE: to support code written when proto_tree_add_item() took
3985 * a bool as its last argument, with false meaning "big-endian"
3986 * and true meaning "little-endian", we treat any non-zero value
3987 * of "encoding" as meaning "little-endian".
3989 value = tvb_get_ipv4(tvb, start);
3990 if (encoding)
3991 value = GUINT32_SWAP_LE_BE(value);
3993 if (retval) {
3994 *retval = value;
3997 CHECK_FOR_NULL_TREE(tree);
3999 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
4001 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
4003 proto_tree_set_ipv4(new_fi, value);
4005 new_fi->flags |= encoding ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
4006 return proto_tree_add_node(tree, new_fi);
4009 proto_item *
4010 proto_tree_add_item_ret_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4011 const int start, int length,
4012 const unsigned encoding, ws_in6_addr *addr)
4014 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
4015 field_info *new_fi;
4017 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
4019 switch (hfinfo->type) {
4020 case FT_IPv6:
4021 break;
4022 default:
4023 REPORT_DISSECTOR_BUG("field %s is not of type FT_IPv6",
4024 hfinfo->abbrev);
4027 if (length != FT_IPv6_LEN)
4028 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_ipv6",
4029 length);
4031 if (encoding) {
4032 REPORT_DISSECTOR_BUG("Encodings not yet implemented for proto_tree_add_item_ret_ipv6");
4035 tvb_get_ipv6(tvb, start, addr);
4037 CHECK_FOR_NULL_TREE(tree);
4039 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
4041 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
4043 proto_tree_set_ipv6(new_fi, addr);
4045 return proto_tree_add_node(tree, new_fi);
4048 proto_item *
4049 proto_tree_add_item_ret_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4050 const int start, int length, const unsigned encoding, uint8_t *retval) {
4052 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
4053 field_info *new_fi;
4055 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
4057 switch (hfinfo->type) {
4058 case FT_ETHER:
4059 break;
4060 default:
4061 REPORT_DISSECTOR_BUG("field %s is not of type FT_ETHER",
4062 hfinfo->abbrev);
4065 if (length != FT_ETHER_LEN)
4066 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_ether",
4067 length);
4069 if (encoding) {
4070 REPORT_DISSECTOR_BUG("Encodings not yet implemented for proto_tree_add_item_ret_ether");
4073 tvb_memcpy(tvb, retval, start, length);
4075 CHECK_FOR_NULL_TREE(tree);
4077 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
4079 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
4081 proto_tree_set_ether(new_fi, retval);
4083 return proto_tree_add_node(tree, new_fi);
4087 proto_item *
4088 proto_tree_add_item_ret_string_and_length(proto_tree *tree, int hfindex,
4089 tvbuff_t *tvb,
4090 const int start, int length,
4091 const unsigned encoding,
4092 wmem_allocator_t *scope,
4093 const uint8_t **retval,
4094 int *lenretval)
4096 proto_item *pi;
4097 header_field_info *hfinfo;
4098 field_info *new_fi;
4099 const uint8_t *value;
4101 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4103 switch (hfinfo->type) {
4104 case FT_STRING:
4105 value = get_string_value(scope, tvb, start, length, lenretval, encoding);
4106 break;
4107 case FT_STRINGZ:
4108 value = get_stringz_value(scope, tree, tvb, start, length, lenretval, encoding);
4109 break;
4110 case FT_UINT_STRING:
4111 value = get_uint_string_value(scope, tree, tvb, start, length, lenretval, encoding);
4112 break;
4113 case FT_STRINGZPAD:
4114 value = get_stringzpad_value(scope, tvb, start, length, lenretval, encoding);
4115 break;
4116 case FT_STRINGZTRUNC:
4117 value = get_stringztrunc_value(scope, tvb, start, length, lenretval, encoding);
4118 break;
4119 default:
4120 REPORT_DISSECTOR_BUG("field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, FT_STRINGZPAD, or FT_STRINGZTRUNC",
4121 hfinfo->abbrev);
4124 if (retval)
4125 *retval = value;
4127 CHECK_FOR_NULL_TREE(tree);
4129 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
4131 new_fi = new_field_info(tree, hfinfo, tvb, start, *lenretval);
4133 proto_tree_set_string(new_fi, value);
4135 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
4137 pi = proto_tree_add_node(tree, new_fi);
4139 switch (hfinfo->type) {
4141 case FT_STRINGZ:
4142 case FT_STRINGZPAD:
4143 case FT_STRINGZTRUNC:
4144 case FT_UINT_STRING:
4145 break;
4147 case FT_STRING:
4148 detect_trailing_stray_characters(encoding, value, length, pi);
4149 break;
4151 default:
4152 ws_assert_not_reached();
4155 return pi;
4158 proto_item *
4159 proto_tree_add_item_ret_string(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4160 const int start, int length,
4161 const unsigned encoding, wmem_allocator_t *scope,
4162 const uint8_t **retval)
4164 return proto_tree_add_item_ret_string_and_length(tree, hfindex,
4165 tvb, start, length, encoding, scope, retval, &length);
4168 proto_item *
4169 proto_tree_add_item_ret_display_string_and_length(proto_tree *tree, int hfindex,
4170 tvbuff_t *tvb,
4171 const int start, int length,
4172 const unsigned encoding,
4173 wmem_allocator_t *scope,
4174 char **retval,
4175 int *lenretval)
4177 proto_item *pi;
4178 header_field_info *hfinfo;
4179 field_info *new_fi;
4180 const uint8_t *value;
4181 uint32_t n = 0;
4183 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4185 switch (hfinfo->type) {
4186 case FT_STRING:
4187 value = get_string_value(scope, tvb, start, length, lenretval, encoding);
4188 *retval = wmem_alloc(scope, ITEM_LABEL_LENGTH);
4189 ws_label_strcpy(*retval, ITEM_LABEL_LENGTH, 0, value, label_strcat_flags(hfinfo));
4190 break;
4191 case FT_STRINGZ:
4192 value = get_stringz_value(scope, tree, tvb, start, length, lenretval, encoding);
4193 *retval = wmem_alloc(scope, ITEM_LABEL_LENGTH);
4194 ws_label_strcpy(*retval, ITEM_LABEL_LENGTH, 0, value, label_strcat_flags(hfinfo));
4195 break;
4196 case FT_UINT_STRING:
4197 value = get_uint_string_value(scope, tree, tvb, start, length, lenretval, encoding);
4198 *retval = wmem_alloc(scope, ITEM_LABEL_LENGTH);
4199 ws_label_strcpy(*retval, ITEM_LABEL_LENGTH, 0, value, label_strcat_flags(hfinfo));
4200 break;
4201 case FT_STRINGZPAD:
4202 value = get_stringzpad_value(scope, tvb, start, length, lenretval, encoding);
4203 *retval = wmem_alloc(scope, ITEM_LABEL_LENGTH);
4204 ws_label_strcpy(*retval, ITEM_LABEL_LENGTH, 0, value, label_strcat_flags(hfinfo));
4205 break;
4206 case FT_STRINGZTRUNC:
4207 value = get_stringztrunc_value(scope, tvb, start, length, lenretval, encoding);
4208 *retval = wmem_alloc(scope, ITEM_LABEL_LENGTH);
4209 ws_label_strcpy(*retval, ITEM_LABEL_LENGTH, 0, value, label_strcat_flags(hfinfo));
4210 break;
4211 case FT_BYTES:
4212 tvb_ensure_bytes_exist(tvb, start, length);
4213 value = tvb_get_ptr(tvb, start, length);
4214 *retval = format_bytes_hfinfo(scope, hfinfo, value, length);
4215 *lenretval = length;
4216 break;
4217 case FT_UINT_BYTES:
4218 n = get_uint_value(tree, tvb, start, length, encoding);
4219 tvb_ensure_bytes_exist(tvb, start + length, n);
4220 value = tvb_get_ptr(tvb, start + length, n);
4221 *retval = format_bytes_hfinfo(scope, hfinfo, value, n);
4222 *lenretval = length + n;
4223 break;
4224 default:
4225 REPORT_DISSECTOR_BUG("field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, FT_STRINGZPAD, FT_STRINGZTRUNC, FT_BYTES, or FT_UINT_BYTES",
4226 hfinfo->abbrev);
4229 CHECK_FOR_NULL_TREE(tree);
4231 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
4233 new_fi = new_field_info(tree, hfinfo, tvb, start, *lenretval);
4235 switch (hfinfo->type) {
4237 case FT_STRING:
4238 case FT_STRINGZ:
4239 case FT_UINT_STRING:
4240 case FT_STRINGZPAD:
4241 case FT_STRINGZTRUNC:
4242 proto_tree_set_string(new_fi, value);
4243 break;
4245 case FT_BYTES:
4246 proto_tree_set_bytes(new_fi, value, length);
4247 break;
4249 case FT_UINT_BYTES:
4250 proto_tree_set_bytes(new_fi, value, n);
4251 break;
4253 default:
4254 ws_assert_not_reached();
4257 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
4259 pi = proto_tree_add_node(tree, new_fi);
4261 switch (hfinfo->type) {
4263 case FT_STRINGZ:
4264 case FT_STRINGZPAD:
4265 case FT_STRINGZTRUNC:
4266 case FT_UINT_STRING:
4267 break;
4269 case FT_STRING:
4270 detect_trailing_stray_characters(encoding, value, length, pi);
4271 break;
4273 case FT_BYTES:
4274 case FT_UINT_BYTES:
4275 break;
4277 default:
4278 ws_assert_not_reached();
4281 return pi;
4284 proto_item *
4285 proto_tree_add_item_ret_display_string(proto_tree *tree, int hfindex,
4286 tvbuff_t *tvb,
4287 const int start, int length,
4288 const unsigned encoding,
4289 wmem_allocator_t *scope,
4290 char **retval)
4292 return proto_tree_add_item_ret_display_string_and_length(tree, hfindex,
4293 tvb, start, length, encoding, scope, retval, &length);
4296 proto_item *
4297 proto_tree_add_item_ret_time_string(proto_tree *tree, int hfindex,
4298 tvbuff_t *tvb,
4299 const int start, int length, const unsigned encoding,
4300 wmem_allocator_t *scope, char **retval)
4302 header_field_info *hfinfo;
4303 field_info *new_fi;
4304 nstime_t time_stamp;
4305 int flags;
4307 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4309 switch (hfinfo->type) {
4310 case FT_ABSOLUTE_TIME:
4311 get_time_value(tree, tvb, start, length, encoding, &time_stamp, false);
4312 flags = ABS_TIME_TO_STR_SHOW_ZONE;
4313 if (prefs.display_abs_time_ascii < ABS_TIME_ASCII_TREE) {
4314 flags |= ABS_TIME_TO_STR_ISO8601;
4316 *retval = abs_time_to_str_ex(scope, &time_stamp, hfinfo->display, flags);
4317 break;
4318 case FT_RELATIVE_TIME:
4319 get_time_value(tree, tvb, start, length, encoding, &time_stamp, true);
4320 *retval = rel_time_to_secs_str(scope, &time_stamp);
4321 break;
4322 default:
4323 REPORT_DISSECTOR_BUG("field %s is not of type FT_ABSOLUTE_TIME or FT_RELATIVE_TIME",
4324 hfinfo->abbrev);
4327 CHECK_FOR_NULL_TREE(tree);
4329 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
4331 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
4333 switch (hfinfo->type) {
4335 case FT_ABSOLUTE_TIME:
4336 case FT_RELATIVE_TIME:
4337 proto_tree_set_time(new_fi, &time_stamp);
4338 break;
4339 default:
4340 ws_assert_not_reached();
4343 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
4345 return proto_tree_add_node(tree, new_fi);
4348 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
4349 and returns proto_item* */
4350 proto_item *
4351 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, int length,
4352 const unsigned encoding)
4354 field_info *new_fi;
4355 header_field_info *hfinfo;
4356 int item_length;
4357 int offset;
4359 offset = ptvc->offset;
4360 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4361 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
4362 test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);
4364 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
4365 item_length, encoding);
4367 CHECK_FOR_NULL_TREE(ptvc->tree);
4369 /* Coast clear. Try and fake it */
4370 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
4372 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
4374 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
4375 offset, length, encoding);
4378 /* Add an item to a proto_tree, using the text label registered to that item;
4379 the item is extracted from the tvbuff handed to it. */
4380 proto_item *
4381 proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
4382 const int start, int length, const unsigned encoding)
4384 field_info *new_fi;
4385 int item_length;
4387 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
4389 get_hfi_length(hfinfo, tvb, start, &length, &item_length, encoding);
4390 test_length(hfinfo, tvb, start, item_length, encoding);
4392 CHECK_FOR_NULL_TREE(tree);
4394 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
4396 new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
4398 return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
4401 proto_item *
4402 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4403 const int start, int length, const unsigned encoding)
4405 register header_field_info *hfinfo;
4407 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4408 return proto_tree_add_item_new(tree, hfinfo, tvb, start, length, encoding);
4411 /* Add an item to a proto_tree, using the text label registered to that item;
4412 the item is extracted from the tvbuff handed to it.
4414 Return the length of the item through the pointer. */
4415 proto_item *
4416 proto_tree_add_item_new_ret_length(proto_tree *tree, header_field_info *hfinfo,
4417 tvbuff_t *tvb, const int start,
4418 int length, const unsigned encoding,
4419 int *lenretval)
4421 field_info *new_fi;
4422 int item_length;
4423 proto_item *item;
4425 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
4427 get_hfi_length(hfinfo, tvb, start, &length, &item_length, encoding);
4428 test_length(hfinfo, tvb, start, item_length, encoding);
4430 if (!tree) {
4432 * We need to get the correct item length here.
4433 * That's normally done by proto_tree_new_item(),
4434 * but we won't be calling it.
4436 *lenretval = get_full_length(hfinfo, tvb, start, length,
4437 item_length, encoding);
4438 return NULL;
4441 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfinfo->id, hfinfo, {
4443 * Even if the tree item is not referenced (and thus faked),
4444 * the caller must still be informed of the actual length.
4446 *lenretval = get_full_length(hfinfo, tvb, start, length,
4447 item_length, encoding);
4450 new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
4452 item = proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
4453 *lenretval = new_fi->length;
4454 return item;
4457 proto_item *
4458 proto_tree_add_item_ret_length(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4459 const int start, int length,
4460 const unsigned encoding, int *lenretval)
4462 register header_field_info *hfinfo;
4464 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4465 return proto_tree_add_item_new_ret_length(tree, hfinfo, tvb, start, length, encoding, lenretval);
4468 /* which FT_ types can use proto_tree_add_bytes_item() */
4469 static inline bool
4470 validate_proto_tree_add_bytes_ftype(const enum ftenum type)
4472 return (type == FT_BYTES ||
4473 type == FT_UINT_BYTES ||
4474 type == FT_OID ||
4475 type == FT_REL_OID ||
4476 type == FT_SYSTEM_ID );
4479 /* Note: this does no validation that the byte array of an FT_OID or
4480 FT_REL_OID is actually valid; and neither does proto_tree_add_item(),
4481 so I think it's ok to continue not validating it?
4483 proto_item *
4484 proto_tree_add_bytes_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4485 const int start, int length, const unsigned encoding,
4486 GByteArray *retval, int *endoff, int *err)
4488 field_info *new_fi;
4489 GByteArray *bytes = retval;
4490 GByteArray *created_bytes = NULL;
4491 bool failed = false;
4492 uint32_t n = 0;
4493 header_field_info *hfinfo;
4494 bool generate = (bytes || tree) ? true : false;
4496 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4498 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
4500 DISSECTOR_ASSERT_HINT(validate_proto_tree_add_bytes_ftype(hfinfo->type),
4501 "Called proto_tree_add_bytes_item but not a bytes-based FT_XXX type");
4503 CHECK_FOR_ZERO_OR_MINUS_LENGTH(length);
4505 if (encoding & ENC_STR_NUM) {
4506 REPORT_DISSECTOR_BUG("Decoding number strings for byte arrays is not supported");
4509 if (generate && (encoding & ENC_STR_HEX)) {
4510 if (hfinfo->type == FT_UINT_BYTES) {
4511 /* can't decode FT_UINT_BYTES from strings */
4512 REPORT_DISSECTOR_BUG("proto_tree_add_bytes_item called for "
4513 "FT_UINT_BYTES type, but as ENC_STR_HEX");
4516 if (!bytes) {
4517 /* caller doesn't care about return value, but we need it to
4518 call tvb_get_string_bytes() and set the tree later */
4519 bytes = created_bytes = g_byte_array_new();
4523 * bytes might be NULL after this, but can't add expert
4524 * error until later; if it's NULL, just note that
4525 * it failed.
4527 bytes = tvb_get_string_bytes(tvb, start, length, encoding, bytes, endoff);
4528 if (bytes == NULL)
4529 failed = true;
4531 else if (generate) {
4532 tvb_ensure_bytes_exist(tvb, start, length);
4534 if (hfinfo->type == FT_UINT_BYTES) {
4535 n = length; /* n is now the "header" length */
4536 length = get_uint_value(tree, tvb, start, n, encoding);
4537 /* length is now the value's length; only store the value in the array */
4538 tvb_ensure_bytes_exist(tvb, start + n, length);
4539 if (!bytes) {
4540 /* caller doesn't care about return value, but
4541 * we may need it to set the tree later */
4542 bytes = created_bytes = g_byte_array_new();
4544 g_byte_array_append(bytes, tvb_get_ptr(tvb, start + n, length), length);
4546 else if (length > 0) {
4547 if (!bytes) {
4548 /* caller doesn't care about return value, but
4549 * we may need it to set the tree later */
4550 bytes = created_bytes = g_byte_array_new();
4552 g_byte_array_append(bytes, tvb_get_ptr(tvb, start, length), length);
4555 if (endoff)
4556 *endoff = start + n + length;
4559 if (err)
4560 *err = failed ? EINVAL : 0;
4562 CHECK_FOR_NULL_TREE_AND_FREE(tree,
4564 if (created_bytes)
4565 g_byte_array_free(created_bytes, true);
4566 created_bytes = NULL;
4567 bytes = NULL;
4568 } );
4570 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfinfo->id, hfinfo,
4572 if (created_bytes)
4573 g_byte_array_free(created_bytes, true);
4574 created_bytes = NULL;
4575 bytes = NULL;
4576 } );
4578 /* n will be zero except when it's a FT_UINT_BYTES */
4579 new_fi = new_field_info(tree, hfinfo, tvb, start, n + length);
4581 if (encoding & ENC_STRING) {
4582 if (failed)
4583 expert_add_info(NULL, tree, &ei_byte_array_string_decoding_failed_error);
4585 if (bytes)
4586 proto_tree_set_bytes_gbytearray(new_fi, bytes);
4587 else
4588 proto_tree_set_bytes(new_fi, NULL, 0);
4590 if (created_bytes)
4591 g_byte_array_free(created_bytes, true);
4593 else {
4594 /* n will be zero except when it's a FT_UINT_BYTES */
4595 proto_tree_set_bytes_tvb(new_fi, tvb, start + n, length);
4597 /* XXX: If we have a non-NULL tree but NULL retval, we don't
4598 * use the byte array created above in this case.
4600 if (created_bytes)
4601 g_byte_array_free(created_bytes, true);
4603 FI_SET_FLAG(new_fi,
4604 (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
4607 return proto_tree_add_node(tree, new_fi);
4611 proto_item *
4612 proto_tree_add_time_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4613 const int start, int length, const unsigned encoding,
4614 nstime_t *retval, int *endoff, int *err)
4616 field_info *new_fi;
4617 nstime_t time_stamp;
4618 int saved_err = 0;
4619 header_field_info *hfinfo;
4621 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4623 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
4625 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length,
4627 if(retval)
4629 nstime_set_zero(retval);
4631 } );
4633 nstime_set_zero(&time_stamp);
4635 if (encoding & ENC_STR_TIME_MASK) {
4636 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_ABSOLUTE_TIME);
4637 /* The only string format that could be a relative time is
4638 * ENC_ISO_8601_TIME, and that is treated as an absolute time
4639 * relative to "now" currently.
4641 if (!tvb_get_string_time(tvb, start, length, encoding, &time_stamp, endoff))
4642 saved_err = EINVAL;
4644 else {
4645 DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo);
4646 const bool is_relative = (hfinfo->type == FT_RELATIVE_TIME) ? true : false;
4648 tvb_ensure_bytes_exist(tvb, start, length);
4649 get_time_value(tree, tvb, start, length, encoding, &time_stamp, is_relative);
4650 if (endoff) *endoff = start + length;
4653 if (err) *err = saved_err;
4655 if (retval) {
4656 retval->secs = time_stamp.secs;
4657 retval->nsecs = time_stamp.nsecs;
4660 CHECK_FOR_NULL_TREE(tree);
4662 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
4664 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
4666 proto_tree_set_time(new_fi, &time_stamp);
4668 if (encoding & ENC_STRING) {
4669 if (saved_err)
4670 expert_add_info(NULL, tree, &ei_date_time_string_decoding_failed_error);
4672 else {
4673 FI_SET_FLAG(new_fi,
4674 (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
4677 return proto_tree_add_node(tree, new_fi);
4680 /* Add a FT_NONE to a proto_tree */
4681 proto_item *
4682 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
4683 const int start, int length, const char *format,
4684 ...)
4686 proto_item *pi;
4687 va_list ap;
4688 header_field_info *hfinfo;
4690 CHECK_FOR_NULL_TREE(tree);
4692 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4694 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_NONE);
4696 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4698 TRY_TO_FAKE_THIS_REPR(pi);
4700 va_start(ap, format);
4701 proto_tree_set_representation(pi, format, ap);
4702 va_end(ap);
4704 /* no value to set for FT_NONE */
4705 return pi;
4708 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
4709 * offset, and returns proto_item* */
4710 proto_item *
4711 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, int length,
4712 const unsigned encoding)
4714 proto_item *item;
4716 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
4717 length, encoding);
4719 return item;
4722 /* Advance the ptvcursor's offset within its tvbuff without
4723 * adding anything to the proto_tree. */
4724 void
4725 ptvcursor_advance(ptvcursor_t* ptvc, int length)
4727 ptvc->offset += length;
4731 static void
4732 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb, const char* field_data, int length)
4734 fvalue_set_protocol(fi->value, tvb, field_data, length);
4737 /* Add a FT_PROTOCOL to a proto_tree */
4738 proto_item *
4739 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4740 int start, int length, const char *format, ...)
4742 proto_item *pi;
4743 tvbuff_t *protocol_tvb;
4744 va_list ap;
4745 header_field_info *hfinfo;
4746 char* protocol_rep;
4748 CHECK_FOR_NULL_TREE(tree);
4750 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4752 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_PROTOCOL);
4755 * This can throw an exception, so do it before we allocate anything.
4757 protocol_tvb = (start == 0 ? tvb : tvb_new_subset_length(tvb, start, length));
4759 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4761 va_start(ap, format);
4762 protocol_rep = ws_strdup_vprintf(format, ap);
4763 proto_tree_set_protocol_tvb(PNODE_FINFO(pi), protocol_tvb, protocol_rep, length);
4764 g_free(protocol_rep);
4765 va_end(ap);
4767 TRY_TO_FAKE_THIS_REPR(pi);
4769 va_start(ap, format);
4770 proto_tree_set_representation(pi, format, ap);
4771 va_end(ap);
4773 return pi;
4776 /* Add a FT_BYTES to a proto_tree */
4777 proto_item *
4778 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
4779 int length, const uint8_t *start_ptr)
4781 proto_item *pi;
4782 header_field_info *hfinfo;
4783 int item_length;
4785 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4786 get_hfi_length(hfinfo, tvb, start, &length, &item_length, ENC_NA);
4787 test_length(hfinfo, tvb, start, item_length, ENC_NA);
4789 CHECK_FOR_NULL_TREE(tree);
4791 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4793 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BYTES);
4795 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4796 proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, length);
4798 return pi;
4801 /* Add a FT_BYTES to a proto_tree */
4802 proto_item *
4803 proto_tree_add_bytes_with_length(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
4804 int tvbuff_length, const uint8_t *start_ptr, int ptr_length)
4806 proto_item *pi;
4807 header_field_info *hfinfo;
4808 int item_length;
4810 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4811 get_hfi_length(hfinfo, tvb, start, &tvbuff_length, &item_length, ENC_NA);
4812 test_length(hfinfo, tvb, start, item_length, ENC_NA);
4814 CHECK_FOR_NULL_TREE(tree);
4816 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4818 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BYTES);
4820 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &tvbuff_length);
4821 proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, ptr_length);
4823 return pi;
4826 proto_item *
4827 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4828 int start, int length,
4829 const uint8_t *start_ptr,
4830 const char *format, ...)
4832 proto_item *pi;
4833 va_list ap;
4835 if (start_ptr == NULL)
4836 start_ptr = tvb_get_ptr(tvb, start, length);
4838 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
4840 TRY_TO_FAKE_THIS_REPR_NESTED(pi);
4842 va_start(ap, format);
4843 proto_tree_set_representation_value(pi, format, ap);
4844 va_end(ap);
4846 return pi;
4849 proto_item *
4850 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4851 int start, int length, const uint8_t *start_ptr,
4852 const char *format, ...)
4854 proto_item *pi;
4855 va_list ap;
4857 if (start_ptr == NULL)
4858 start_ptr = tvb_get_ptr(tvb, start, length);
4860 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
4862 TRY_TO_FAKE_THIS_REPR_NESTED(pi);
4864 va_start(ap, format);
4865 proto_tree_set_representation(pi, format, ap);
4866 va_end(ap);
4868 return pi;
4871 static void
4872 proto_tree_set_bytes(field_info *fi, const uint8_t* start_ptr, int length)
4874 DISSECTOR_ASSERT(length >= 0);
4875 DISSECTOR_ASSERT(start_ptr != NULL || length == 0);
4877 fvalue_set_bytes_data(fi->value, start_ptr, length);
4881 static void
4882 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, int offset, int length)
4884 tvb_ensure_bytes_exist(tvb, offset, length);
4885 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
4888 static void
4889 proto_tree_set_bytes_gbytearray(field_info *fi, const GByteArray *value)
4891 GByteArray *bytes;
4893 DISSECTOR_ASSERT(value != NULL);
4895 bytes = byte_array_dup(value);
4897 fvalue_set_byte_array(fi->value, bytes);
4900 /* Add a FT_*TIME to a proto_tree */
4901 proto_item *
4902 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
4903 int length, const nstime_t *value_ptr)
4905 proto_item *pi;
4906 header_field_info *hfinfo;
4908 CHECK_FOR_NULL_TREE(tree);
4910 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4912 DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo);
4914 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4915 proto_tree_set_time(PNODE_FINFO(pi), value_ptr);
4917 return pi;
4920 proto_item *
4921 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4922 int start, int length, nstime_t *value_ptr,
4923 const char *format, ...)
4925 proto_item *pi;
4926 va_list ap;
4928 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
4929 if (pi != tree) {
4930 va_start(ap, format);
4931 proto_tree_set_representation_value(pi, format, ap);
4932 va_end(ap);
4935 return pi;
4938 proto_item *
4939 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4940 int start, int length, nstime_t *value_ptr,
4941 const char *format, ...)
4943 proto_item *pi;
4944 va_list ap;
4946 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
4947 if (pi != tree) {
4948 TRY_TO_FAKE_THIS_REPR(pi);
4950 va_start(ap, format);
4951 proto_tree_set_representation(pi, format, ap);
4952 va_end(ap);
4955 return pi;
4958 /* Set the FT_*TIME value */
4959 static void
4960 proto_tree_set_time(field_info *fi, const nstime_t *value_ptr)
4962 DISSECTOR_ASSERT(value_ptr != NULL);
4964 fvalue_set_time(fi->value, value_ptr);
4967 /* Add a FT_IPXNET to a proto_tree */
4968 proto_item *
4969 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
4970 int length, uint32_t value)
4972 proto_item *pi;
4973 header_field_info *hfinfo;
4975 CHECK_FOR_NULL_TREE(tree);
4977 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4979 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPXNET);
4981 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4982 proto_tree_set_ipxnet(PNODE_FINFO(pi), value);
4984 return pi;
4987 proto_item *
4988 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4989 int start, int length, uint32_t value,
4990 const char *format, ...)
4992 proto_item *pi;
4993 va_list ap;
4995 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
4996 if (pi != tree) {
4997 va_start(ap, format);
4998 proto_tree_set_representation_value(pi, format, ap);
4999 va_end(ap);
5002 return pi;
5005 proto_item *
5006 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5007 int start, int length, uint32_t value,
5008 const char *format, ...)
5010 proto_item *pi;
5011 va_list ap;
5013 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
5014 if (pi != tree) {
5015 TRY_TO_FAKE_THIS_REPR(pi);
5017 va_start(ap, format);
5018 proto_tree_set_representation(pi, format, ap);
5019 va_end(ap);
5022 return pi;
5025 /* Set the FT_IPXNET value */
5026 static void
5027 proto_tree_set_ipxnet(field_info *fi, uint32_t value)
5029 fvalue_set_uinteger(fi->value, value);
5032 /* Add a FT_IPv4 to a proto_tree */
5033 proto_item *
5034 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5035 int length, ws_in4_addr value)
5037 proto_item *pi;
5038 header_field_info *hfinfo;
5040 CHECK_FOR_NULL_TREE(tree);
5042 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5044 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPv4);
5046 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5047 proto_tree_set_ipv4(PNODE_FINFO(pi), value);
5049 return pi;
5052 proto_item *
5053 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5054 int start, int length, ws_in4_addr value,
5055 const char *format, ...)
5057 proto_item *pi;
5058 va_list ap;
5060 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
5061 if (pi != tree) {
5062 va_start(ap, format);
5063 proto_tree_set_representation_value(pi, format, ap);
5064 va_end(ap);
5067 return pi;
5070 proto_item *
5071 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5072 int start, int length, ws_in4_addr value,
5073 const char *format, ...)
5075 proto_item *pi;
5076 va_list ap;
5078 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
5079 if (pi != tree) {
5080 TRY_TO_FAKE_THIS_REPR(pi);
5082 va_start(ap, format);
5083 proto_tree_set_representation(pi, format, ap);
5084 va_end(ap);
5087 return pi;
5090 /* Set the FT_IPv4 value */
5091 static void
5092 proto_tree_set_ipv4(field_info *fi, ws_in4_addr value)
5094 ipv4_addr_and_mask ipv4;
5095 ws_ipv4_addr_and_mask_init(&ipv4, value, 32);
5096 fvalue_set_ipv4(fi->value, &ipv4);
5099 /* Add a FT_IPv6 to a proto_tree */
5100 proto_item *
5101 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5102 int length, const ws_in6_addr *value)
5104 proto_item *pi;
5105 header_field_info *hfinfo;
5107 CHECK_FOR_NULL_TREE(tree);
5109 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5111 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPv6);
5113 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5114 proto_tree_set_ipv6(PNODE_FINFO(pi), value);
5116 return pi;
5119 proto_item *
5120 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5121 int start, int length,
5122 const ws_in6_addr *value_ptr,
5123 const char *format, ...)
5125 proto_item *pi;
5126 va_list ap;
5128 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
5129 if (pi != tree) {
5130 va_start(ap, format);
5131 proto_tree_set_representation_value(pi, format, ap);
5132 va_end(ap);
5135 return pi;
5138 proto_item *
5139 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5140 int start, int length,
5141 const ws_in6_addr *value_ptr,
5142 const char *format, ...)
5144 proto_item *pi;
5145 va_list ap;
5147 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
5148 if (pi != tree) {
5149 TRY_TO_FAKE_THIS_REPR(pi);
5151 va_start(ap, format);
5152 proto_tree_set_representation(pi, format, ap);
5153 va_end(ap);
5156 return pi;
5159 /* Set the FT_IPv6 value */
5160 static void
5161 proto_tree_set_ipv6(field_info *fi, const ws_in6_addr *value)
5163 DISSECTOR_ASSERT(value != NULL);
5164 ipv6_addr_and_prefix ipv6;
5165 ipv6.addr = *value;
5166 ipv6.prefix = 128;
5167 fvalue_set_ipv6(fi->value, &ipv6);
5170 static void
5171 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, int start, int length)
5173 proto_tree_set_ipv6(fi, (const ws_in6_addr *)tvb_get_ptr(tvb, start, length));
5176 /* Set the FT_FCWWN value */
5177 static void
5178 proto_tree_set_fcwwn(field_info *fi, const uint8_t* value_ptr)
5180 DISSECTOR_ASSERT(value_ptr != NULL);
5181 fvalue_set_fcwwn(fi->value, value_ptr);
5184 static void
5185 proto_tree_set_fcwwn_tvb(field_info *fi, tvbuff_t *tvb, int start, int length)
5187 proto_tree_set_fcwwn(fi, tvb_get_ptr(tvb, start, length));
5190 /* Add a FT_GUID to a proto_tree */
5191 proto_item *
5192 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5193 int length, const e_guid_t *value_ptr)
5195 proto_item *pi;
5196 header_field_info *hfinfo;
5198 CHECK_FOR_NULL_TREE(tree);
5200 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5202 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_GUID);
5204 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5205 proto_tree_set_guid(PNODE_FINFO(pi), value_ptr);
5207 return pi;
5210 proto_item *
5211 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5212 int start, int length,
5213 const e_guid_t *value_ptr,
5214 const char *format, ...)
5216 proto_item *pi;
5217 va_list ap;
5219 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
5220 if (pi != tree) {
5221 va_start(ap, format);
5222 proto_tree_set_representation_value(pi, format, ap);
5223 va_end(ap);
5226 return pi;
5229 proto_item *
5230 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5231 int start, int length, const e_guid_t *value_ptr,
5232 const char *format, ...)
5234 proto_item *pi;
5235 va_list ap;
5237 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
5238 if (pi != tree) {
5239 TRY_TO_FAKE_THIS_REPR(pi);
5241 va_start(ap, format);
5242 proto_tree_set_representation(pi, format, ap);
5243 va_end(ap);
5246 return pi;
5249 /* Set the FT_GUID value */
5250 static void
5251 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
5253 DISSECTOR_ASSERT(value_ptr != NULL);
5254 fvalue_set_guid(fi->value, value_ptr);
5257 static void
5258 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, int start,
5259 const unsigned encoding)
5261 e_guid_t guid;
5263 tvb_get_guid(tvb, start, &guid, encoding);
5264 proto_tree_set_guid(fi, &guid);
5267 /* Add a FT_OID to a proto_tree */
5268 proto_item *
5269 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5270 int length, const uint8_t* value_ptr)
5272 proto_item *pi;
5273 header_field_info *hfinfo;
5275 CHECK_FOR_NULL_TREE(tree);
5277 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5279 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_OID);
5281 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5282 proto_tree_set_oid(PNODE_FINFO(pi), value_ptr, length);
5284 return pi;
5287 proto_item *
5288 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5289 int start, int length,
5290 const uint8_t* value_ptr,
5291 const char *format, ...)
5293 proto_item *pi;
5294 va_list ap;
5296 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
5297 if (pi != tree) {
5298 va_start(ap, format);
5299 proto_tree_set_representation_value(pi, format, ap);
5300 va_end(ap);
5303 return pi;
5306 proto_item *
5307 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5308 int start, int length, const uint8_t* value_ptr,
5309 const char *format, ...)
5311 proto_item *pi;
5312 va_list ap;
5314 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
5315 if (pi != tree) {
5316 TRY_TO_FAKE_THIS_REPR(pi);
5318 va_start(ap, format);
5319 proto_tree_set_representation(pi, format, ap);
5320 va_end(ap);
5323 return pi;
5326 /* Set the FT_OID value */
5327 static void
5328 proto_tree_set_oid(field_info *fi, const uint8_t* value_ptr, int length)
5330 GByteArray *bytes;
5332 DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
5334 bytes = g_byte_array_new();
5335 if (length > 0) {
5336 g_byte_array_append(bytes, value_ptr, length);
5338 fvalue_set_byte_array(fi->value, bytes);
5341 static void
5342 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, int start, int length)
5344 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
5347 /* Set the FT_SYSTEM_ID value */
5348 static void
5349 proto_tree_set_system_id(field_info *fi, const uint8_t* value_ptr, int length)
5351 GByteArray *bytes;
5353 DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
5355 bytes = g_byte_array_new();
5356 if (length > 0) {
5357 g_byte_array_append(bytes, value_ptr, length);
5359 fvalue_set_byte_array(fi->value, bytes);
5362 static void
5363 proto_tree_set_system_id_tvb(field_info *fi, tvbuff_t *tvb, int start, int length)
5365 proto_tree_set_system_id(fi, tvb_get_ptr(tvb, start, length), length);
5368 /* Add a FT_STRING, FT_STRINGZ, FT_STRINGZPAD, or FT_STRINGZTRUNC to a
5369 * proto_tree. Creates own copy of string, and frees it when the proto_tree
5370 * is destroyed. */
5371 proto_item *
5372 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5373 int length, const char* value)
5375 proto_item *pi;
5376 header_field_info *hfinfo;
5377 int item_length;
5379 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
5380 get_hfi_length(hfinfo, tvb, start, &length, &item_length, ENC_NA);
5382 * Special case - if the length is 0, skip the test, so that
5383 * we can have an empty string right after the end of the
5384 * packet. (This handles URL-encoded forms where the last field
5385 * has no value so the form ends right after the =.)
5387 if (item_length != 0)
5388 test_length(hfinfo, tvb, start, item_length, ENC_NA);
5390 CHECK_FOR_NULL_TREE(tree);
5392 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5394 DISSECTOR_ASSERT_FIELD_TYPE_IS_STRING(hfinfo);
5396 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5397 DISSECTOR_ASSERT(length >= 0);
5399 WS_UTF_8_CHECK(value, -1);
5400 proto_tree_set_string(PNODE_FINFO(pi), value);
5402 return pi;
5405 proto_item *
5406 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5407 int start, int length, const char* value,
5408 const char *format,
5409 ...)
5411 proto_item *pi;
5412 va_list ap;
5414 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
5415 if (pi != tree) {
5416 va_start(ap, format);
5417 proto_tree_set_representation_value(pi, format, ap);
5418 va_end(ap);
5421 return pi;
5424 proto_item *
5425 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5426 int start, int length, const char* value,
5427 const char *format, ...)
5429 proto_item *pi;
5430 va_list ap;
5432 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
5433 if (pi != tree) {
5434 TRY_TO_FAKE_THIS_REPR(pi);
5436 va_start(ap, format);
5437 proto_tree_set_representation(pi, format, ap);
5438 va_end(ap);
5441 return pi;
5444 /* Set the FT_STRING value */
5445 static void
5446 proto_tree_set_string(field_info *fi, const char* value)
5448 if (value) {
5449 fvalue_set_string(fi->value, value);
5450 } else {
5452 * XXX - why is a null value for a string field
5453 * considered valid?
5455 fvalue_set_string(fi->value, "[ Null ]");
5459 /* Set the FT_AX25 value */
5460 static void
5461 proto_tree_set_ax25(field_info *fi, const uint8_t* value)
5463 fvalue_set_ax25(fi->value, value);
5466 static void
5467 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, int start)
5469 proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
5472 /* Set the FT_VINES value */
5473 static void
5474 proto_tree_set_vines(field_info *fi, const uint8_t* value)
5476 fvalue_set_vines(fi->value, value);
5479 static void
5480 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, int start)
5482 proto_tree_set_vines(fi, tvb_get_ptr(tvb, start, FT_VINES_ADDR_LEN));
5485 /* Add a FT_ETHER to a proto_tree */
5486 proto_item *
5487 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5488 int length, const uint8_t* value)
5490 proto_item *pi;
5491 header_field_info *hfinfo;
5493 CHECK_FOR_NULL_TREE(tree);
5495 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5497 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_ETHER);
5499 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5500 proto_tree_set_ether(PNODE_FINFO(pi), value);
5502 return pi;
5505 proto_item *
5506 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5507 int start, int length, const uint8_t* value,
5508 const char *format, ...)
5510 proto_item *pi;
5511 va_list ap;
5513 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
5514 if (pi != tree) {
5515 va_start(ap, format);
5516 proto_tree_set_representation_value(pi, format, ap);
5517 va_end(ap);
5520 return pi;
5523 proto_item *
5524 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5525 int start, int length, const uint8_t* value,
5526 const char *format, ...)
5528 proto_item *pi;
5529 va_list ap;
5531 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
5532 if (pi != tree) {
5533 TRY_TO_FAKE_THIS_REPR(pi);
5535 va_start(ap, format);
5536 proto_tree_set_representation(pi, format, ap);
5537 va_end(ap);
5540 return pi;
5543 /* Set the FT_ETHER value */
5544 static void
5545 proto_tree_set_ether(field_info *fi, const uint8_t* value)
5547 fvalue_set_ether(fi->value, value);
5550 static void
5551 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, int start)
5553 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
5556 /* Add a FT_BOOLEAN to a proto_tree */
5557 proto_item *
5558 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5559 int length, uint64_t value)
5561 proto_item *pi;
5562 header_field_info *hfinfo;
5564 CHECK_FOR_NULL_TREE(tree);
5566 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5568 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BOOLEAN);
5570 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5571 proto_tree_set_boolean(PNODE_FINFO(pi), value);
5573 return pi;
5576 proto_item *
5577 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
5578 tvbuff_t *tvb, int start, int length,
5579 uint64_t value, const char *format, ...)
5581 proto_item *pi;
5582 va_list ap;
5584 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
5585 if (pi != tree) {
5586 va_start(ap, format);
5587 proto_tree_set_representation_value(pi, format, ap);
5588 va_end(ap);
5591 return pi;
5594 proto_item *
5595 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5596 int start, int length, uint64_t value,
5597 const char *format, ...)
5599 proto_item *pi;
5600 va_list ap;
5602 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
5603 if (pi != tree) {
5604 TRY_TO_FAKE_THIS_REPR(pi);
5606 va_start(ap, format);
5607 proto_tree_set_representation(pi, format, ap);
5608 va_end(ap);
5611 return pi;
5614 /* Set the FT_BOOLEAN value */
5615 static void
5616 proto_tree_set_boolean(field_info *fi, uint64_t value)
5618 proto_tree_set_uint64(fi, value);
5621 /* Generate, into "buf", a string showing the bits of a bitfield.
5622 Return a pointer to the character after that string. */
5623 static char *
5624 other_decode_bitfield_value(char *buf, const uint64_t val, const uint64_t mask, const int width)
5626 int i = 0;
5627 uint64_t bit;
5628 char *p;
5630 p = buf;
5632 /* This is a devel error. It is safer to stop here. */
5633 DISSECTOR_ASSERT(width >= 1);
5635 bit = UINT64_C(1) << (width - 1);
5636 for (;;) {
5637 if (mask & bit) {
5638 /* This bit is part of the field. Show its value. */
5639 if (val & bit)
5640 *p++ = '1';
5641 else
5642 *p++ = '0';
5643 } else {
5644 /* This bit is not part of the field. */
5645 *p++ = '.';
5647 bit >>= 1;
5648 i++;
5649 if (i >= width)
5650 break;
5651 if (i % 4 == 0)
5652 *p++ = ' ';
5654 *p = '\0';
5655 return p;
5658 static char *
5659 decode_bitfield_value(char *buf, const uint64_t val, const uint64_t mask, const int width)
5661 char *p;
5663 p = other_decode_bitfield_value(buf, val, mask, width);
5664 p = g_stpcpy(p, " = ");
5666 return p;
5669 static char *
5670 other_decode_bitfield_varint_value(char *buf, uint64_t val, uint64_t mask, const int width)
5672 int i = 0;
5673 uint64_t bit;
5674 char *p;
5676 p = buf;
5678 /* This is a devel error. It is safer to stop here. */
5679 DISSECTOR_ASSERT(width >= 1);
5681 bit = UINT64_C(1) << (width - 1);
5682 for (;;) {
5683 if (((8-(i % 8)) != 8) && /* MSB is never used for value. */
5684 (mask & bit)) {
5685 /* This bit is part of the field. Show its value. */
5686 if (val & bit)
5687 *p++ = '1';
5688 else
5689 *p++ = '0';
5690 } else {
5691 /* This bit is not part of the field. */
5692 *p++ = '.';
5694 bit >>= 1;
5695 i++;
5696 if (i >= width)
5697 break;
5698 if (i % 4 == 0)
5699 *p++ = ' ';
5702 *p = '\0';
5703 return p;
5706 static char *
5707 decode_bitfield_varint_value(char *buf, const uint64_t val, const uint64_t mask, const int width)
5709 char *p;
5711 p = other_decode_bitfield_varint_value(buf, val, mask, width);
5712 p = g_stpcpy(p, " = ");
5714 return p;
5717 /* Add a FT_FLOAT to a proto_tree */
5718 proto_item *
5719 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5720 int length, float value)
5722 proto_item *pi;
5723 header_field_info *hfinfo;
5725 CHECK_FOR_NULL_TREE(tree);
5727 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5729 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_FLOAT);
5731 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5732 proto_tree_set_float(PNODE_FINFO(pi), value);
5734 return pi;
5737 proto_item *
5738 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5739 int start, int length, float value,
5740 const char *format, ...)
5742 proto_item *pi;
5743 va_list ap;
5745 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
5746 if (pi != tree) {
5747 va_start(ap, format);
5748 proto_tree_set_representation_value(pi, format, ap);
5749 va_end(ap);
5752 return pi;
5755 proto_item *
5756 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5757 int start, int length, float value,
5758 const char *format, ...)
5760 proto_item *pi;
5761 va_list ap;
5763 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
5764 if (pi != tree) {
5765 TRY_TO_FAKE_THIS_REPR(pi);
5767 va_start(ap, format);
5768 proto_tree_set_representation(pi, format, ap);
5769 va_end(ap);
5772 return pi;
5775 /* Set the FT_FLOAT value */
5776 static void
5777 proto_tree_set_float(field_info *fi, float value)
5779 fvalue_set_floating(fi->value, value);
5782 /* Add a FT_DOUBLE to a proto_tree */
5783 proto_item *
5784 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5785 int length, double value)
5787 proto_item *pi;
5788 header_field_info *hfinfo;
5790 CHECK_FOR_NULL_TREE(tree);
5792 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5794 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_DOUBLE);
5796 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5797 proto_tree_set_double(PNODE_FINFO(pi), value);
5799 return pi;
5802 proto_item *
5803 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5804 int start, int length, double value,
5805 const char *format, ...)
5807 proto_item *pi;
5808 va_list ap;
5810 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
5811 if (pi != tree) {
5812 va_start(ap, format);
5813 proto_tree_set_representation_value(pi, format, ap);
5814 va_end(ap);
5817 return pi;
5820 proto_item *
5821 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5822 int start, int length, double value,
5823 const char *format, ...)
5825 proto_item *pi;
5826 va_list ap;
5828 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
5829 if (pi != tree) {
5830 TRY_TO_FAKE_THIS_REPR(pi);
5832 va_start(ap, format);
5833 proto_tree_set_representation(pi, format, ap);
5834 va_end(ap);
5837 return pi;
5840 /* Set the FT_DOUBLE value */
5841 static void
5842 proto_tree_set_double(field_info *fi, double value)
5844 fvalue_set_floating(fi->value, value);
5847 /* Add FT_CHAR or FT_UINT{8,16,24,32} to a proto_tree */
5848 proto_item *
5849 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5850 int length, uint32_t value)
5852 proto_item *pi = NULL;
5853 header_field_info *hfinfo;
5855 CHECK_FOR_NULL_TREE(tree);
5857 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5859 switch (hfinfo->type) {
5860 case FT_CHAR:
5861 case FT_UINT8:
5862 case FT_UINT16:
5863 case FT_UINT24:
5864 case FT_UINT32:
5865 case FT_FRAMENUM:
5866 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5867 proto_tree_set_uint(PNODE_FINFO(pi), value);
5868 break;
5870 default:
5871 REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, FT_UINT32, or FT_FRAMENUM",
5872 hfinfo->abbrev);
5875 return pi;
5878 proto_item *
5879 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5880 int start, int length, uint32_t value,
5881 const char *format, ...)
5883 proto_item *pi;
5884 va_list ap;
5886 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
5887 if (pi != tree) {
5888 va_start(ap, format);
5889 proto_tree_set_representation_value(pi, format, ap);
5890 va_end(ap);
5893 return pi;
5896 proto_item *
5897 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5898 int start, int length, uint32_t value,
5899 const char *format, ...)
5901 proto_item *pi;
5902 va_list ap;
5904 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
5905 if (pi != tree) {
5906 TRY_TO_FAKE_THIS_REPR(pi);
5908 va_start(ap, format);
5909 proto_tree_set_representation(pi, format, ap);
5910 va_end(ap);
5913 return pi;
5916 /* Set the FT_UINT{8,16,24,32} value */
5917 static void
5918 proto_tree_set_uint(field_info *fi, uint32_t value)
5920 const header_field_info *hfinfo;
5921 uint32_t integer;
5923 hfinfo = fi->hfinfo;
5924 integer = value;
5926 if (hfinfo->bitmask) {
5927 /* Mask out irrelevant portions */
5928 integer &= (uint32_t)(hfinfo->bitmask);
5930 /* Shift bits */
5931 integer >>= hfinfo_bitshift(hfinfo);
5933 FI_SET_FLAG(fi, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo)));
5934 FI_SET_FLAG(fi, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo)));
5937 fvalue_set_uinteger(fi->value, integer);
5940 /* Add FT_UINT{40,48,56,64} to a proto_tree */
5941 proto_item *
5942 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5943 int length, uint64_t value)
5945 proto_item *pi = NULL;
5946 header_field_info *hfinfo;
5948 CHECK_FOR_NULL_TREE(tree);
5950 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5952 switch (hfinfo->type) {
5953 case FT_UINT40:
5954 case FT_UINT48:
5955 case FT_UINT56:
5956 case FT_UINT64:
5957 case FT_FRAMENUM:
5958 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5959 proto_tree_set_uint64(PNODE_FINFO(pi), value);
5960 break;
5962 default:
5963 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, FT_UINT64, or FT_FRAMENUM",
5964 hfinfo->abbrev);
5967 return pi;
5970 proto_item *
5971 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5972 int start, int length, uint64_t value,
5973 const char *format, ...)
5975 proto_item *pi;
5976 va_list ap;
5978 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
5979 if (pi != tree) {
5980 va_start(ap, format);
5981 proto_tree_set_representation_value(pi, format, ap);
5982 va_end(ap);
5985 return pi;
5988 proto_item *
5989 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5990 int start, int length, uint64_t value,
5991 const char *format, ...)
5993 proto_item *pi;
5994 va_list ap;
5996 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
5997 if (pi != tree) {
5998 TRY_TO_FAKE_THIS_REPR(pi);
6000 va_start(ap, format);
6001 proto_tree_set_representation(pi, format, ap);
6002 va_end(ap);
6005 return pi;
6008 /* Set the FT_UINT{40,48,56,64} value */
6009 static void
6010 proto_tree_set_uint64(field_info *fi, uint64_t value)
6012 const header_field_info *hfinfo;
6013 uint64_t integer;
6015 hfinfo = fi->hfinfo;
6016 integer = value;
6018 if (hfinfo->bitmask) {
6019 /* Mask out irrelevant portions */
6020 integer &= hfinfo->bitmask;
6022 /* Shift bits */
6023 integer >>= hfinfo_bitshift(hfinfo);
6025 FI_SET_FLAG(fi, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo)));
6026 FI_SET_FLAG(fi, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo)));
6029 fvalue_set_uinteger64(fi->value, integer);
6032 /* Add FT_INT{8,16,24,32} to a proto_tree */
6033 proto_item *
6034 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
6035 int length, int32_t value)
6037 proto_item *pi = NULL;
6038 header_field_info *hfinfo;
6040 CHECK_FOR_NULL_TREE(tree);
6042 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
6044 switch (hfinfo->type) {
6045 case FT_INT8:
6046 case FT_INT16:
6047 case FT_INT24:
6048 case FT_INT32:
6049 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
6050 proto_tree_set_int(PNODE_FINFO(pi), value);
6051 break;
6053 default:
6054 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
6055 hfinfo->abbrev);
6058 return pi;
6061 proto_item *
6062 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
6063 int start, int length, int32_t value,
6064 const char *format, ...)
6066 proto_item *pi;
6067 va_list ap;
6069 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
6070 if (pi != tree) {
6071 va_start(ap, format);
6072 proto_tree_set_representation_value(pi, format, ap);
6073 va_end(ap);
6076 return pi;
6079 proto_item *
6080 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
6081 int start, int length, int32_t value,
6082 const char *format, ...)
6084 proto_item *pi;
6085 va_list ap;
6087 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
6088 if (pi != tree) {
6089 TRY_TO_FAKE_THIS_REPR(pi);
6091 va_start(ap, format);
6092 proto_tree_set_representation(pi, format, ap);
6093 va_end(ap);
6096 return pi;
6099 /* Set the FT_INT{8,16,24,32} value */
6100 static void
6101 proto_tree_set_int(field_info *fi, int32_t value)
6103 const header_field_info *hfinfo;
6104 uint32_t integer;
6105 int no_of_bits;
6107 hfinfo = fi->hfinfo;
6108 integer = (uint32_t) value;
6110 if (hfinfo->bitmask) {
6111 /* Mask out irrelevant portions */
6112 integer &= (uint32_t)(hfinfo->bitmask);
6114 /* Shift bits */
6115 integer >>= hfinfo_bitshift(hfinfo);
6117 no_of_bits = ws_count_ones(hfinfo->bitmask);
6118 integer = ws_sign_ext32(integer, no_of_bits);
6120 FI_SET_FLAG(fi, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo)));
6121 FI_SET_FLAG(fi, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo)));
6124 fvalue_set_sinteger(fi->value, integer);
6127 /* Add FT_INT{40,48,56,64} to a proto_tree */
6128 proto_item *
6129 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
6130 int length, int64_t value)
6132 proto_item *pi = NULL;
6133 header_field_info *hfinfo;
6135 CHECK_FOR_NULL_TREE(tree);
6137 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
6139 switch (hfinfo->type) {
6140 case FT_INT40:
6141 case FT_INT48:
6142 case FT_INT56:
6143 case FT_INT64:
6144 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
6145 proto_tree_set_int64(PNODE_FINFO(pi), value);
6146 break;
6148 default:
6149 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
6150 hfinfo->abbrev);
6153 return pi;
6156 proto_item *
6157 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
6158 int start, int length, int64_t value,
6159 const char *format, ...)
6161 proto_item *pi;
6162 va_list ap;
6164 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
6165 if (pi != tree) {
6166 va_start(ap, format);
6167 proto_tree_set_representation_value(pi, format, ap);
6168 va_end(ap);
6171 return pi;
6174 /* Set the FT_INT{40,48,56,64} value */
6175 static void
6176 proto_tree_set_int64(field_info *fi, int64_t value)
6178 const header_field_info *hfinfo;
6179 uint64_t integer;
6180 int no_of_bits;
6182 hfinfo = fi->hfinfo;
6183 integer = value;
6185 if (hfinfo->bitmask) {
6186 /* Mask out irrelevant portions */
6187 integer &= hfinfo->bitmask;
6189 /* Shift bits */
6190 integer >>= hfinfo_bitshift(hfinfo);
6192 no_of_bits = ws_count_ones(hfinfo->bitmask);
6193 integer = ws_sign_ext64(integer, no_of_bits);
6195 FI_SET_FLAG(fi, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo)));
6196 FI_SET_FLAG(fi, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo)));
6199 fvalue_set_sinteger64(fi->value, integer);
6202 proto_item *
6203 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
6204 int start, int length, int64_t value,
6205 const char *format, ...)
6207 proto_item *pi;
6208 va_list ap;
6210 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
6211 if (pi != tree) {
6212 TRY_TO_FAKE_THIS_REPR(pi);
6214 va_start(ap, format);
6215 proto_tree_set_representation(pi, format, ap);
6216 va_end(ap);
6219 return pi;
6222 /* Add a FT_EUI64 to a proto_tree */
6223 proto_item *
6224 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
6225 int length, const uint64_t value)
6227 proto_item *pi;
6228 header_field_info *hfinfo;
6230 CHECK_FOR_NULL_TREE(tree);
6232 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
6234 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_EUI64);
6236 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
6237 proto_tree_set_eui64(PNODE_FINFO(pi), value);
6239 return pi;
6242 proto_item *
6243 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
6244 int start, int length, const uint64_t value,
6245 const char *format, ...)
6247 proto_item *pi;
6248 va_list ap;
6250 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
6251 if (pi != tree) {
6252 va_start(ap, format);
6253 proto_tree_set_representation_value(pi, format, ap);
6254 va_end(ap);
6257 return pi;
6260 proto_item *
6261 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
6262 int start, int length, const uint64_t value,
6263 const char *format, ...)
6265 proto_item *pi;
6266 va_list ap;
6268 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
6269 if (pi != tree) {
6270 TRY_TO_FAKE_THIS_REPR(pi);
6272 va_start(ap, format);
6273 proto_tree_set_representation(pi, format, ap);
6274 va_end(ap);
6277 return pi;
6280 /* Set the FT_EUI64 value */
6281 static void
6282 proto_tree_set_eui64(field_info *fi, const uint64_t value)
6284 fvalue_set_uinteger64(fi->value, value);
6286 static void
6287 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, int start, const unsigned encoding)
6289 if (encoding)
6291 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
6292 } else {
6293 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
6297 proto_item *
6298 proto_tree_add_mac48_detail(const mac_hf_list_t *list_specific,
6299 const mac_hf_list_t *list_generic,
6300 int idx, tvbuff_t *tvb,
6301 proto_tree *tree, int offset)
6303 const uint8_t addr[6];
6304 const char *addr_name = NULL;
6305 const char *oui_name = NULL;
6306 proto_item *addr_item = NULL;
6307 proto_tree *addr_tree = NULL;
6308 proto_item *ret_val = NULL;
6310 if (tree == NULL || list_specific == NULL) {
6311 return NULL;
6314 /* Resolve what we can of the address */
6315 tvb_memcpy(tvb, (void *)addr, offset, 6);
6316 if (list_specific->hf_addr_resolved || (list_generic && list_generic->hf_addr_resolved)) {
6317 addr_name = get_ether_name(addr);
6319 if (list_specific->hf_oui_resolved || (list_generic && list_generic->hf_oui_resolved)) {
6320 oui_name = get_manuf_name_if_known(addr, sizeof(addr));
6323 /* Add the item for the specific address type */
6324 ret_val = proto_tree_add_item(tree, *list_specific->hf_addr, tvb, offset, 6, ENC_NA);
6325 if (idx >= 0) {
6326 addr_tree = proto_item_add_subtree(ret_val, idx);
6328 else {
6329 addr_tree = tree;
6332 if (list_specific->hf_addr_resolved != NULL) {
6333 addr_item = proto_tree_add_string(addr_tree, *list_specific->hf_addr_resolved,
6334 tvb, offset, 6, addr_name);
6335 proto_item_set_generated(addr_item);
6336 proto_item_set_hidden(addr_item);
6339 if (list_specific->hf_oui != NULL) {
6340 addr_item = proto_tree_add_item(addr_tree, *list_specific->hf_oui, tvb, offset, 3, ENC_NA);
6341 proto_item_set_generated(addr_item);
6342 proto_item_set_hidden(addr_item);
6344 if (oui_name != NULL && list_specific->hf_oui_resolved != NULL) {
6345 addr_item = proto_tree_add_string(addr_tree, *list_specific->hf_oui_resolved, tvb, offset, 6, oui_name);
6346 proto_item_set_generated(addr_item);
6347 proto_item_set_hidden(addr_item);
6351 if (list_specific->hf_lg != NULL) {
6352 proto_tree_add_item(addr_tree, *list_specific->hf_lg, tvb, offset, 3, ENC_BIG_ENDIAN);
6354 if (list_specific->hf_ig != NULL) {
6355 proto_tree_add_item(addr_tree, *list_specific->hf_ig, tvb, offset, 3, ENC_BIG_ENDIAN);
6358 /* Were we given a list for generic address fields? If not, stop here */
6359 if (list_generic == NULL) {
6360 return ret_val;
6363 addr_item = proto_tree_add_item(addr_tree, *list_generic->hf_addr, tvb, offset, 6, ENC_NA);
6364 proto_item_set_hidden(addr_item);
6366 if (list_generic->hf_addr_resolved != NULL) {
6367 addr_item = proto_tree_add_string(addr_tree, *list_generic->hf_addr_resolved,
6368 tvb, offset, 6, addr_name);
6369 proto_item_set_generated(addr_item);
6370 proto_item_set_hidden(addr_item);
6373 if (list_generic->hf_oui != NULL) {
6374 addr_item = proto_tree_add_item(addr_tree, *list_generic->hf_oui, tvb, offset, 3, ENC_NA);
6375 proto_item_set_generated(addr_item);
6376 proto_item_set_hidden(addr_item);
6378 if (oui_name != NULL && list_generic->hf_oui_resolved != NULL) {
6379 addr_item = proto_tree_add_string(addr_tree, *list_generic->hf_oui_resolved, tvb, offset, 6, oui_name);
6380 proto_item_set_generated(addr_item);
6381 proto_item_set_hidden(addr_item);
6385 if (list_generic->hf_lg != NULL) {
6386 addr_item = proto_tree_add_item(addr_tree, *list_generic->hf_lg, tvb, offset, 3, ENC_BIG_ENDIAN);
6387 proto_item_set_hidden(addr_item);
6389 if (list_generic->hf_ig != NULL) {
6390 addr_item = proto_tree_add_item(addr_tree, *list_generic->hf_ig, tvb, offset, 3, ENC_BIG_ENDIAN);
6391 proto_item_set_hidden(addr_item);
6393 return ret_val;
6396 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
6397 static proto_item *
6398 proto_tree_add_node(proto_tree *tree, field_info *fi)
6400 proto_node *pnode, *tnode, *sibling;
6401 field_info *tfi;
6402 unsigned depth = 1;
6405 * Restrict our depth. proto_tree_traverse_pre_order and
6406 * proto_tree_traverse_post_order (and possibly others) are recursive
6407 * so we need to be mindful of our stack size.
6409 if (tree->first_child == NULL) {
6410 for (tnode = tree; tnode != NULL; tnode = tnode->parent) {
6411 depth++;
6412 if (G_UNLIKELY(depth > prefs.gui_max_tree_depth)) {
6413 fvalue_free(fi->value);
6414 fi->value = NULL;
6415 THROW_MESSAGE(DissectorError, wmem_strdup_printf(PNODE_POOL(tree),
6416 "Maximum tree depth %d exceeded for \"%s\" - \"%s\" (%s:%u) (Maximum depth can be increased in advanced preferences)",
6417 prefs.gui_max_tree_depth,
6418 fi->hfinfo->name, fi->hfinfo->abbrev, G_STRFUNC, __LINE__));
6424 * Make sure "tree" is ready to have subtrees under it, by
6425 * checking whether it's been given an ett_ value.
6427 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
6428 * node of the protocol tree. That node is not displayed,
6429 * so it doesn't need an ett_ value to remember whether it
6430 * was expanded.
6432 tnode = tree;
6433 tfi = PNODE_FINFO(tnode);
6434 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
6435 /* Since we are not adding fi to a node, its fvalue won't get
6436 * freed by proto_tree_free_node(), so free it now.
6438 fvalue_free(fi->value);
6439 fi->value = NULL;
6440 REPORT_DISSECTOR_BUG("\"%s\" - \"%s\" tfi->tree_type: %d invalid (%s:%u)",
6441 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__);
6442 /* XXX - is it safe to continue here? */
6445 pnode = wmem_new(PNODE_POOL(tree), proto_node);
6446 PROTO_NODE_INIT(pnode);
6447 pnode->parent = tnode;
6448 PNODE_FINFO(pnode) = fi;
6449 pnode->tree_data = PTREE_DATA(tree);
6451 if (tnode->last_child != NULL) {
6452 sibling = tnode->last_child;
6453 DISSECTOR_ASSERT(sibling->next == NULL);
6454 sibling->next = pnode;
6455 } else
6456 tnode->first_child = pnode;
6457 tnode->last_child = pnode;
6459 tree_data_add_maybe_interesting_field(pnode->tree_data, fi);
6461 return (proto_item *)pnode;
6465 /* Generic way to allocate field_info and add to proto_tree.
6466 * Sets *pfi to address of newly-allocated field_info struct */
6467 static proto_item *
6468 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, int start,
6469 int *length)
6471 proto_item *pi;
6472 field_info *fi;
6473 int item_length;
6475 get_hfi_length(hfinfo, tvb, start, length, &item_length, ENC_NA);
6476 fi = new_field_info(tree, hfinfo, tvb, start, item_length);
6477 pi = proto_tree_add_node(tree, fi);
6479 return pi;
6483 static void
6484 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const int start, int *length,
6485 int *item_length, const unsigned encoding)
6487 int length_remaining;
6490 * We only allow a null tvbuff if the item has a zero length,
6491 * i.e. if there's no data backing it.
6493 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
6496 * XXX - in some protocols, there are 32-bit unsigned length
6497 * fields, so lengths in protocol tree and tvbuff routines
6498 * should really be unsigned. We should have, for those
6499 * field types for which "to the end of the tvbuff" makes sense,
6500 * additional routines that take no length argument and
6501 * add fields that run to the end of the tvbuff.
6503 if (*length == -1) {
6505 * For FT_NONE, FT_PROTOCOL, FT_BYTES, FT_STRING,
6506 * FT_STRINGZPAD, and FT_STRINGZTRUNC fields, a length
6507 * of -1 means "set the length to what remains in the
6508 * tvbuff".
6510 * The assumption is either that
6512 * 1) the length of the item can only be determined
6513 * by dissection (typically true of items with
6514 * subitems, which are probably FT_NONE or
6515 * FT_PROTOCOL)
6517 * or
6519 * 2) if the tvbuff is "short" (either due to a short
6520 * snapshot length or due to lack of reassembly of
6521 * fragments/segments/whatever), we want to display
6522 * what's available in the field (probably FT_BYTES
6523 * or FT_STRING) and then throw an exception later
6525 * or
6527 * 3) the field is defined to be "what's left in the
6528 * packet"
6530 * so we set the length to what remains in the tvbuff so
6531 * that, if we throw an exception while dissecting, it
6532 * has what is probably the right value.
6534 * For FT_STRINGZ, it means "the string is null-terminated,
6535 * not null-padded; set the length to the actual length
6536 * of the string", and if the tvbuff if short, we just
6537 * throw an exception.
6539 * For ENC_VARINT_PROTOBUF|ENC_VARINT_QUIC|ENC_VARIANT_ZIGZAG|ENC_VARINT_SDNV, it means "find the end of the string",
6540 * and if the tvbuff if short, we just throw an exception.
6542 * It's not valid for any other type of field. For those
6543 * fields, we treat -1 the same way we treat other
6544 * negative values - we assume the length is a Really
6545 * Big Positive Number, and throw a ReportedBoundsError
6546 * exception, under the assumption that the Really Big
6547 * Length would run past the end of the packet.
6549 if ((FT_IS_INT(hfinfo->type)) || (FT_IS_UINT(hfinfo->type))) {
6550 if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG|ENC_VARINT_SDNV)) {
6552 * Leave the length as -1, so our caller knows
6553 * it was -1.
6555 *item_length = *length;
6556 return;
6557 } else if (encoding & ENC_VARINT_QUIC) {
6558 switch (tvb_get_uint8(tvb, start) >> 6)
6560 case 0: /* 0b00 => 1 byte length (6 bits Usable) */
6561 *item_length = 1;
6562 break;
6563 case 1: /* 0b01 => 2 bytes length (14 bits Usable) */
6564 *item_length = 2;
6565 break;
6566 case 2: /* 0b10 => 4 bytes length (30 bits Usable) */
6567 *item_length = 4;
6568 break;
6569 case 3: /* 0b11 => 8 bytes length (62 bits Usable) */
6570 *item_length = 8;
6571 break;
6576 switch (hfinfo->type) {
6578 case FT_PROTOCOL:
6579 case FT_NONE:
6580 case FT_BYTES:
6581 case FT_STRING:
6582 case FT_STRINGZPAD:
6583 case FT_STRINGZTRUNC:
6585 * We allow FT_PROTOCOLs to be zero-length -
6586 * for example, an ONC RPC NULL procedure has
6587 * neither arguments nor reply, so the
6588 * payload for that protocol is empty.
6590 * We also allow the others to be zero-length -
6591 * because that's the way the code has been for a
6592 * long, long time.
6594 * However, we want to ensure that the start
6595 * offset is not *past* the byte past the end
6596 * of the tvbuff: we throw an exception in that
6597 * case.
6599 *length = tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
6600 DISSECTOR_ASSERT(*length >= 0);
6601 break;
6603 case FT_STRINGZ:
6605 * Leave the length as -1, so our caller knows
6606 * it was -1.
6608 break;
6610 default:
6611 THROW(ReportedBoundsError);
6612 DISSECTOR_ASSERT_NOT_REACHED();
6614 *item_length = *length;
6615 } else {
6616 *item_length = *length;
6617 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
6619 * These types are for interior nodes of the
6620 * tree, and don't have data associated with
6621 * them; if the length is negative (XXX - see
6622 * above) or goes past the end of the tvbuff,
6623 * cut it short at the end of the tvbuff.
6624 * That way, if this field is selected in
6625 * Wireshark, we don't highlight stuff past
6626 * the end of the data.
6628 /* XXX - what to do, if we don't have a tvb? */
6629 if (tvb) {
6630 length_remaining = tvb_captured_length_remaining(tvb, start);
6631 if (*item_length < 0 ||
6632 (*item_length > 0 &&
6633 (length_remaining < *item_length)))
6634 *item_length = length_remaining;
6637 if (*item_length < 0) {
6638 THROW(ReportedBoundsError);
6643 static int
6644 get_full_length(header_field_info *hfinfo, tvbuff_t *tvb, const int start,
6645 int length, unsigned item_length, const int encoding)
6647 uint32_t n;
6650 * We need to get the correct item length here.
6651 * That's normally done by proto_tree_new_item(),
6652 * but we won't be calling it.
6654 switch (hfinfo->type) {
6656 case FT_NONE:
6657 case FT_PROTOCOL:
6658 case FT_BYTES:
6660 * The length is the specified length.
6662 break;
6664 case FT_UINT_BYTES:
6665 n = get_uint_value(NULL, tvb, start, length, encoding);
6666 item_length += n;
6667 if ((int)item_length < length) {
6668 THROW(ReportedBoundsError);
6670 break;
6672 /* XXX - make these just FT_UINT? */
6673 case FT_UINT8:
6674 case FT_UINT16:
6675 case FT_UINT24:
6676 case FT_UINT32:
6677 case FT_UINT40:
6678 case FT_UINT48:
6679 case FT_UINT56:
6680 case FT_UINT64:
6681 /* XXX - make these just FT_INT? */
6682 case FT_INT8:
6683 case FT_INT16:
6684 case FT_INT24:
6685 case FT_INT32:
6686 case FT_INT40:
6687 case FT_INT48:
6688 case FT_INT56:
6689 case FT_INT64:
6690 if (encoding & ENC_VARINT_MASK) {
6691 if (length < -1) {
6692 report_type_length_mismatch(NULL, "a FT_[U]INT", length, true);
6694 if (length == -1) {
6695 uint64_t dummy;
6696 /* This can throw an exception */
6697 /* XXX - do this without fetching the varint? */
6698 length = tvb_get_varint(tvb, start, FT_VARINT_MAX_LEN, &dummy, encoding);
6699 if (length == 0) {
6700 THROW(ReportedBoundsError);
6703 item_length = length;
6704 break;
6708 * The length is the specified length.
6710 break;
6712 case FT_BOOLEAN:
6713 case FT_CHAR:
6714 case FT_IPv4:
6715 case FT_IPXNET:
6716 case FT_IPv6:
6717 case FT_FCWWN:
6718 case FT_AX25:
6719 case FT_VINES:
6720 case FT_ETHER:
6721 case FT_EUI64:
6722 case FT_GUID:
6723 case FT_OID:
6724 case FT_REL_OID:
6725 case FT_SYSTEM_ID:
6726 case FT_FLOAT:
6727 case FT_DOUBLE:
6728 case FT_STRING:
6730 * The length is the specified length.
6732 break;
6734 case FT_STRINGZ:
6735 if (length < -1) {
6736 report_type_length_mismatch(NULL, "a string", length, true);
6738 if (length == -1) {
6739 /* This can throw an exception */
6740 /* XXX - do this without fetching the string? */
6741 wmem_free(NULL, tvb_get_stringz_enc(NULL, tvb, start, &length, encoding));
6743 item_length = length;
6744 break;
6746 case FT_UINT_STRING:
6747 n = get_uint_value(NULL, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
6748 item_length += n;
6749 if ((int)item_length < length) {
6750 THROW(ReportedBoundsError);
6752 break;
6754 case FT_STRINGZPAD:
6755 case FT_STRINGZTRUNC:
6756 case FT_ABSOLUTE_TIME:
6757 case FT_RELATIVE_TIME:
6758 case FT_IEEE_11073_SFLOAT:
6759 case FT_IEEE_11073_FLOAT:
6761 * The length is the specified length.
6763 break;
6765 default:
6766 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in gset_full_length()",
6767 hfinfo->abbrev,
6768 hfinfo->type,
6769 ftype_name(hfinfo->type));
6770 break;
6772 return item_length;
6775 static field_info *
6776 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
6777 const int start, const int item_length)
6779 field_info *fi;
6781 FIELD_INFO_NEW(PNODE_POOL(tree), fi);
6783 fi->hfinfo = hfinfo;
6784 fi->start = start;
6785 fi->start += (tvb)?tvb_raw_offset(tvb):0;
6786 fi->length = item_length;
6787 fi->tree_type = -1;
6788 fi->flags = 0;
6789 if (!PTREE_DATA(tree)->visible) {
6790 /* If the tree is not visible, set the item hidden, unless we
6791 * need the representation or length and can't fake them.
6793 if (hfinfo->ref_type != HF_REF_TYPE_PRINT && (hfinfo->type != FT_PROTOCOL || PTREE_DATA(tree)->fake_protocols)) {
6794 FI_SET_FLAG(fi, FI_HIDDEN);
6797 fi->value = fvalue_new(fi->hfinfo->type);
6798 fi->rep = NULL;
6800 /* add the data source tvbuff */
6801 fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
6803 fi->appendix_start = 0;
6804 fi->appendix_length = 0;
6806 fi->total_layer_num = tree->tree_data->pinfo->curr_layer_num;
6807 fi->proto_layer_num = tree->tree_data->pinfo->curr_proto_layer_num;
6809 return fi;
6812 static size_t proto_find_value_pos(const header_field_info *hfinfo, const char *representation)
6814 if (hfinfo->display & BASE_NO_DISPLAY_VALUE) {
6815 return 0;
6818 /* Search for field name */
6819 char *ptr = strstr(representation, hfinfo->name);
6820 if (!ptr) {
6821 return 0;
6824 /* Check if field name ends with the ": " delimiter */
6825 ptr += strlen(hfinfo->name);
6826 if (strncmp(ptr, ": ", 2) == 0) {
6827 ptr += 2;
6830 /* Return offset to after field name */
6831 return ptr - representation;
6834 /* If the protocol tree is to be visible, set the representation of a
6835 proto_tree entry with the name of the field for the item and with
6836 the value formatted with the supplied printf-style format and
6837 argument list. */
6838 static void
6839 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
6841 ws_assert(pi);
6843 /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
6844 * items string representation */
6845 if (PTREE_DATA(pi)->visible || !proto_item_is_hidden(pi)) {
6846 size_t name_pos, ret = 0;
6847 char *str;
6848 field_info *fi = PITEM_FINFO(pi);
6849 const header_field_info *hf;
6851 DISSECTOR_ASSERT(fi);
6853 hf = fi->hfinfo;
6855 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
6856 if (hf->bitmask && (hf->type == FT_BOOLEAN || FT_IS_UINT(hf->type))) {
6857 uint64_t val;
6858 char *p;
6860 if (FT_IS_UINT32(hf->type))
6861 val = fvalue_get_uinteger(fi->value);
6862 else
6863 val = fvalue_get_uinteger64(fi->value);
6865 val <<= hfinfo_bitshift(hf);
6867 p = decode_bitfield_value(fi->rep->representation, val, hf->bitmask, hfinfo_container_bitwidth(hf));
6868 ret = (p - fi->rep->representation);
6871 /* put in the hf name */
6872 name_pos = ret = label_concat(fi->rep->representation, ret, hf->name);
6874 ret = label_concat(fi->rep->representation, ret, ": ");
6875 /* If possible, Put in the value of the string */
6876 str = wmem_strdup_vprintf(PNODE_POOL(pi), format, ap);
6877 WS_UTF_8_CHECK(str, -1);
6878 fi->rep->value_pos = ret;
6879 ret = ws_label_strcpy(fi->rep->representation, ITEM_LABEL_LENGTH, ret, str, 0);
6880 if (ret >= ITEM_LABEL_LENGTH) {
6881 /* Uh oh, we don't have enough room. Tell the user
6882 * that the field is truncated.
6884 label_mark_truncated(fi->rep->representation, name_pos, &fi->rep->value_pos);
6886 fi->rep->value_len = strlen(fi->rep->representation) - fi->rep->value_pos;
6890 /* If the protocol tree is to be visible, set the representation of a
6891 proto_tree entry with the representation formatted with the supplied
6892 printf-style format and argument list. */
6893 static void
6894 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
6896 size_t ret; /*tmp return value */
6897 char *str;
6898 field_info *fi = PITEM_FINFO(pi);
6900 DISSECTOR_ASSERT(fi);
6902 if (!proto_item_is_hidden(pi)) {
6903 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
6905 str = wmem_strdup_vprintf(PNODE_POOL(pi), format, ap);
6906 WS_UTF_8_CHECK(str, -1);
6907 fi->rep->value_pos = proto_find_value_pos(fi->hfinfo, str);
6908 ret = ws_label_strcpy(fi->rep->representation, ITEM_LABEL_LENGTH, 0, str, 0);
6909 if (ret >= ITEM_LABEL_LENGTH) {
6910 /* Uh oh, we don't have enough room. Tell the user
6911 * that the field is truncated.
6913 LABEL_MARK_TRUNCATED_START(fi->rep->representation, &fi->rep->value_pos);
6915 fi->rep->value_len = strlen(fi->rep->representation) - fi->rep->value_pos;
6919 static int
6920 protoo_strlcpy(char *dest, const char *src, size_t dest_size)
6922 if (dest_size == 0) return 0;
6924 size_t res = g_strlcpy(dest, src, dest_size);
6926 /* At most dest_size - 1 characters will be copied
6927 * (unless dest_size is 0). */
6928 if (res >= dest_size)
6929 res = dest_size - 1;
6930 return (int) res;
6933 static header_field_info *
6934 hfinfo_same_name_get_prev(const header_field_info *hfinfo)
6936 header_field_info *dup_hfinfo;
6938 if (hfinfo->same_name_prev_id == -1)
6939 return NULL;
6940 PROTO_REGISTRAR_GET_NTH(hfinfo->same_name_prev_id, dup_hfinfo);
6941 return dup_hfinfo;
6944 static void
6945 hfinfo_remove_from_gpa_name_map(const header_field_info *hfinfo)
6947 g_free(last_field_name);
6948 last_field_name = NULL;
6950 if (!hfinfo->same_name_next && hfinfo->same_name_prev_id == -1) {
6951 /* No hfinfo with the same name */
6952 g_hash_table_steal(gpa_name_map, hfinfo->abbrev);
6953 return;
6956 if (hfinfo->same_name_next) {
6957 hfinfo->same_name_next->same_name_prev_id = hfinfo->same_name_prev_id;
6960 if (hfinfo->same_name_prev_id != -1) {
6961 header_field_info *same_name_prev = hfinfo_same_name_get_prev(hfinfo);
6962 same_name_prev->same_name_next = hfinfo->same_name_next;
6963 if (!hfinfo->same_name_next) {
6964 /* It's always the latest added hfinfo which is stored in gpa_name_map */
6965 g_hash_table_insert(gpa_name_map, (void *) (same_name_prev->abbrev), same_name_prev);
6971 proto_item_fill_display_label(const field_info *finfo, char *display_label_str, const int label_str_size)
6973 const header_field_info *hfinfo = finfo->hfinfo;
6974 int label_len = 0;
6975 char *tmp_str;
6976 const char *str;
6977 const uint8_t *bytes;
6978 uint32_t number;
6979 uint64_t number64;
6980 const char *hf_str_val;
6981 char number_buf[NUMBER_LABEL_LENGTH];
6982 const char *number_out;
6983 address addr;
6984 const ipv4_addr_and_mask *ipv4;
6985 const ipv6_addr_and_prefix *ipv6;
6987 switch (hfinfo->type) {
6989 case FT_NONE:
6990 case FT_PROTOCOL:
6991 return protoo_strlcpy(display_label_str, UTF8_CHECK_MARK, label_str_size);
6993 case FT_UINT_BYTES:
6994 case FT_BYTES:
6995 tmp_str = format_bytes_hfinfo_maxlen(NULL,
6996 hfinfo,
6997 fvalue_get_bytes_data(finfo->value),
6998 (unsigned)fvalue_length2(finfo->value),
6999 label_str_size);
7000 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7001 wmem_free(NULL, tmp_str);
7002 break;
7004 case FT_ABSOLUTE_TIME:
7006 int flags = ABS_TIME_TO_STR_SHOW_ZONE;
7007 if (prefs.display_abs_time_ascii < ABS_TIME_ASCII_COLUMN) {
7008 flags |= ABS_TIME_TO_STR_ISO8601;
7010 tmp_str = abs_time_to_str_ex(NULL, fvalue_get_time(finfo->value), hfinfo->display, flags);
7011 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7012 wmem_free(NULL, tmp_str);
7013 break;
7016 case FT_RELATIVE_TIME:
7017 tmp_str = rel_time_to_secs_str(NULL, fvalue_get_time(finfo->value));
7018 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7019 wmem_free(NULL, tmp_str);
7020 break;
7022 case FT_BOOLEAN:
7023 number64 = fvalue_get_uinteger64(finfo->value);
7024 label_len = protoo_strlcpy(display_label_str,
7025 tfs_get_string(!!number64, hfinfo->strings), label_str_size);
7026 break;
7028 case FT_CHAR:
7029 number = fvalue_get_uinteger(finfo->value);
7031 if (FIELD_DISPLAY(hfinfo->display) == BASE_CUSTOM) {
7032 char tmp[ITEM_LABEL_LENGTH];
7033 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
7035 DISSECTOR_ASSERT(fmtfunc);
7036 fmtfunc(tmp, number);
7038 label_len = protoo_strlcpy(display_label_str, tmp, label_str_size);
7040 } else if (hfinfo->strings) {
7041 number_out = hf_try_val_to_str(number, hfinfo);
7043 if (!number_out) {
7044 number_out = hfinfo_char_value_format_display(BASE_HEX, number_buf, number);
7047 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
7049 } else {
7050 number_out = hfinfo_char_value_format(hfinfo, number_buf, number);
7052 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
7055 break;
7057 /* XXX - make these just FT_NUMBER? */
7058 case FT_INT8:
7059 case FT_INT16:
7060 case FT_INT24:
7061 case FT_INT32:
7062 case FT_UINT8:
7063 case FT_UINT16:
7064 case FT_UINT24:
7065 case FT_UINT32:
7066 case FT_FRAMENUM:
7067 hf_str_val = NULL;
7068 number = FT_IS_INT(hfinfo->type) ?
7069 (uint32_t) fvalue_get_sinteger(finfo->value) :
7070 fvalue_get_uinteger(finfo->value);
7072 if (FIELD_DISPLAY(hfinfo->display) == BASE_CUSTOM) {
7073 char tmp[ITEM_LABEL_LENGTH];
7074 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
7076 DISSECTOR_ASSERT(fmtfunc);
7077 fmtfunc(tmp, number);
7079 label_len = protoo_strlcpy(display_label_str, tmp, label_str_size);
7081 } else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) {
7082 if (hfinfo->display & BASE_UNIT_STRING) {
7083 number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
7084 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
7085 hf_str_val = hf_try_val_to_str(number, hfinfo);
7086 label_len += protoo_strlcpy(display_label_str+label_len, hf_str_val, label_str_size-label_len);
7087 } else {
7088 number_out = hf_try_val_to_str(number, hfinfo);
7090 if (!number_out) {
7091 number_out = hfinfo_number_value_format_display(hfinfo, hfinfo->display, number_buf, number);
7094 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
7096 } else {
7097 number_out = hfinfo_number_value_format(hfinfo, number_buf, number);
7099 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
7102 break;
7104 case FT_INT40:
7105 case FT_INT48:
7106 case FT_INT56:
7107 case FT_INT64:
7108 case FT_UINT40:
7109 case FT_UINT48:
7110 case FT_UINT56:
7111 case FT_UINT64:
7112 hf_str_val = NULL;
7113 number64 = FT_IS_INT(hfinfo->type) ?
7114 (uint64_t) fvalue_get_sinteger64(finfo->value) :
7115 fvalue_get_uinteger64(finfo->value);
7117 if (FIELD_DISPLAY(hfinfo->display) == BASE_CUSTOM) {
7118 char tmp[ITEM_LABEL_LENGTH];
7119 custom_fmt_func_64_t fmtfunc64 = (custom_fmt_func_64_t)hfinfo->strings;
7121 DISSECTOR_ASSERT(fmtfunc64);
7122 fmtfunc64(tmp, number64);
7124 label_len = protoo_strlcpy(display_label_str, tmp, label_str_size);
7125 } else if (hfinfo->strings) {
7126 if (hfinfo->display & BASE_UNIT_STRING) {
7127 number_out = hfinfo_numeric_value_format64(hfinfo, number_buf, number64);
7128 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
7129 hf_str_val = hf_try_val64_to_str(number64, hfinfo);
7130 label_len += protoo_strlcpy(display_label_str+label_len, hf_str_val, label_str_size-label_len);
7131 } else {
7132 number_out = hf_try_val64_to_str(number64, hfinfo);
7134 if (!number_out)
7135 number_out = hfinfo_number_value_format_display64(hfinfo, hfinfo->display, number_buf, number64);
7137 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
7139 } else {
7140 number_out = hfinfo_number_value_format64(hfinfo, number_buf, number64);
7142 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
7145 break;
7147 case FT_EUI64:
7148 tmp_str = eui64_to_str(NULL, fvalue_get_uinteger64(finfo->value));
7149 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7150 wmem_free(NULL, tmp_str);
7151 break;
7153 case FT_IPv4:
7154 ipv4 = fvalue_get_ipv4(finfo->value);
7155 //XXX: Should we ignore the mask?
7156 set_address_ipv4(&addr, ipv4);
7157 tmp_str = address_to_display(NULL, &addr);
7158 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7159 wmem_free(NULL, tmp_str);
7160 free_address(&addr);
7161 break;
7163 case FT_IPv6:
7164 ipv6 = fvalue_get_ipv6(finfo->value);
7165 set_address_ipv6(&addr, ipv6);
7166 tmp_str = address_to_display(NULL, &addr);
7167 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7168 wmem_free(NULL, tmp_str);
7169 free_address(&addr);
7170 break;
7172 case FT_FCWWN:
7173 set_address (&addr, AT_FCWWN, FCWWN_ADDR_LEN, fvalue_get_bytes_data(finfo->value));
7174 tmp_str = address_to_display(NULL, &addr);
7175 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7176 wmem_free(NULL, tmp_str);
7177 break;
7179 case FT_ETHER:
7180 set_address (&addr, AT_ETHER, FT_ETHER_LEN, fvalue_get_bytes_data(finfo->value));
7181 tmp_str = address_to_display(NULL, &addr);
7182 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7183 wmem_free(NULL, tmp_str);
7184 break;
7186 case FT_GUID:
7187 tmp_str = guid_to_str(NULL, fvalue_get_guid(finfo->value));
7188 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7189 wmem_free(NULL, tmp_str);
7190 break;
7192 case FT_REL_OID:
7193 bytes = fvalue_get_bytes_data(finfo->value);
7194 tmp_str = rel_oid_resolved_from_encoded(NULL, bytes, (int)fvalue_length2(finfo->value));
7195 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7196 wmem_free(NULL, tmp_str);
7197 break;
7199 case FT_OID:
7200 bytes = fvalue_get_bytes_data(finfo->value);
7201 tmp_str = oid_resolved_from_encoded(NULL, bytes, (int)fvalue_length2(finfo->value));
7202 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7203 wmem_free(NULL, tmp_str);
7204 break;
7206 case FT_SYSTEM_ID:
7207 bytes = fvalue_get_bytes_data(finfo->value);
7208 tmp_str = print_system_id(NULL, bytes, (int)fvalue_length2(finfo->value));
7209 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7210 wmem_free(NULL, tmp_str);
7211 break;
7213 case FT_FLOAT:
7214 case FT_DOUBLE:
7215 label_len = (int)fill_display_label_float(finfo, display_label_str);
7216 break;
7218 case FT_STRING:
7219 case FT_STRINGZ:
7220 case FT_UINT_STRING:
7221 case FT_STRINGZPAD:
7222 case FT_STRINGZTRUNC:
7223 str = fvalue_get_string(finfo->value);
7224 label_len = (int)ws_label_strcpy(display_label_str, label_str_size, 0, str, label_strcat_flags(hfinfo));
7225 if (label_len >= label_str_size) {
7226 /* Truncation occurred. Get the real length
7227 * copied (not including '\0') */
7228 label_len = label_str_size ? label_str_size - 1 : 0;
7230 break;
7232 default:
7233 /* First try ftype string representation */
7234 tmp_str = fvalue_to_string_repr(NULL, finfo->value, FTREPR_DISPLAY, hfinfo->display);
7235 if (!tmp_str) {
7236 /* Default to show as bytes */
7237 bytes = fvalue_get_bytes_data(finfo->value);
7238 tmp_str = bytes_to_str(NULL, bytes, fvalue_length2(finfo->value));
7240 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7241 wmem_free(NULL, tmp_str);
7242 break;
7244 return label_len;
7247 /* -------------------------- */
7248 /* Sets the text for a custom column from proto fields.
7250 * @param[out] result The "resolved" column text (human readable, uses strings)
7251 * @param[out] expr The "unresolved" column text (values, display repr)
7252 * @return The filter (abbrev) for the field (XXX: Only the first if multifield)
7254 const char *
7255 proto_custom_set(proto_tree* tree, GSList *field_ids, int occurrence, bool display_details,
7256 char *result, char *expr, const int size)
7258 int len, prev_len, last, i, offset_r = 0, offset_e = 0;
7259 GPtrArray *finfos;
7260 field_info *finfo = NULL;
7261 header_field_info* hfinfo;
7262 const char *abbrev = NULL;
7264 const char *hf_str_val;
7265 char *str;
7266 col_custom_t *field_idx;
7267 int field_id;
7268 int ii = 0;
7270 ws_assert(field_ids != NULL);
7271 while ((field_idx = (col_custom_t *) g_slist_nth_data(field_ids, ii++))) {
7272 field_id = field_idx->field_id;
7273 if (field_id == 0) {
7274 GPtrArray *fvals = NULL;
7275 bool passed = dfilter_apply_full(field_idx->dfilter, tree, &fvals);
7276 if (fvals != NULL) {
7278 // XXX - Handling occurrences is unusual when more
7279 // than one field is involved, e.g. there's four
7280 // results for tcp.port + tcp.port. We may really
7281 // want to apply it to the operands, not the output.
7282 // Note that occurrences are not quite the same as
7283 // the layer operator (should the grammar support
7284 // both?)
7285 /* Calculate single index or set outer boundaries */
7286 len = g_ptr_array_len(fvals);
7287 if (occurrence < 0) {
7288 i = occurrence + len;
7289 last = i;
7290 } else if (occurrence > 0) {
7291 i = occurrence - 1;
7292 last = i;
7293 } else {
7294 i = 0;
7295 last = len - 1;
7297 if (i < 0 || i >= len) {
7298 g_ptr_array_unref(fvals);
7299 continue;
7301 for (; i <= last; i++) {
7302 /* XXX - We could have a "resolved" result
7303 * for types where the value depends only
7304 * on the type, e.g. FT_IPv4, and not on
7305 * hfinfo->strings. Supporting the latter
7306 * requires knowing which hfinfo matched
7307 * if there are multiple with the same
7308 * abbreviation. In any case, we need to
7309 * know the expected return type of the
7310 * field expression.
7312 str = fvalue_to_string_repr(NULL, fvals->pdata[i], FTREPR_DISPLAY, BASE_NONE);
7313 if (offset_r && (offset_r < (size - 1)))
7314 result[offset_r++] = ',';
7315 if (offset_e && (offset_e < (size - 1)))
7316 expr[offset_e++] = ',';
7317 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
7318 offset_e += protoo_strlcpy(expr+offset_e, str, size-offset_e);
7319 g_free(str);
7321 g_ptr_array_unref(fvals);
7322 } else if (passed) {
7323 // XXX - Occurrence doesn't make sense for a test
7324 // output, it should be applied to the operands.
7325 if (offset_r && (offset_r < (size - 1)))
7326 result[offset_r++] = ',';
7327 if (offset_e && (offset_e < (size - 1)))
7328 expr[offset_e++] = ',';
7329 /* Prevent multiple check marks */
7330 if (strstr(result, UTF8_CHECK_MARK ",") == NULL) {
7331 offset_r += protoo_strlcpy(result+offset_r, UTF8_CHECK_MARK, size-offset_r);
7332 } else {
7333 result[--offset_r] = '\0'; /* Remove the added trailing ',' */
7335 if (strstr(expr, UTF8_CHECK_MARK ",") == NULL) {
7336 offset_e += protoo_strlcpy(expr+offset_e, UTF8_CHECK_MARK, size-offset_e);
7337 } else {
7338 expr[--offset_e] = '\0'; /* Remove the added trailing ',' */
7341 continue;
7343 PROTO_REGISTRAR_GET_NTH((unsigned)field_id, hfinfo);
7345 /* do we need to rewind ? */
7346 if (!hfinfo)
7347 return "";
7349 if (occurrence < 0) {
7350 /* Search other direction */
7351 while (hfinfo->same_name_prev_id != -1) {
7352 PROTO_REGISTRAR_GET_NTH(hfinfo->same_name_prev_id, hfinfo);
7356 prev_len = 0; /* Reset handled occurrences */
7358 while (hfinfo) {
7359 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
7361 if (!finfos || !(len = g_ptr_array_len(finfos))) {
7362 if (occurrence < 0) {
7363 hfinfo = hfinfo->same_name_next;
7364 } else {
7365 hfinfo = hfinfo_same_name_get_prev(hfinfo);
7367 continue;
7370 /* Are there enough occurrences of the field? */
7371 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
7372 if (occurrence < 0) {
7373 hfinfo = hfinfo->same_name_next;
7374 } else {
7375 hfinfo = hfinfo_same_name_get_prev(hfinfo);
7377 prev_len += len;
7378 continue;
7381 /* Calculate single index or set outer boundaries */
7382 if (occurrence < 0) {
7383 i = occurrence + len + prev_len;
7384 last = i;
7385 } else if (occurrence > 0) {
7386 i = occurrence - 1 - prev_len;
7387 last = i;
7388 } else {
7389 i = 0;
7390 last = len - 1;
7393 prev_len += len; /* Count handled occurrences */
7395 while (i <= last) {
7396 finfo = (field_info *)g_ptr_array_index(finfos, i);
7398 if (offset_r && (offset_r < (size - 1)))
7399 result[offset_r++] = ',';
7401 if (display_details) {
7402 char representation[ITEM_LABEL_LENGTH];
7403 size_t offset = 0;
7405 if (finfo->rep && finfo->rep->value_len) {
7406 g_strlcpy(representation, &finfo->rep->representation[finfo->rep->value_pos],
7407 MIN(finfo->rep->value_len + 1, ITEM_LABEL_LENGTH));
7408 } else {
7409 proto_item_fill_label(finfo, representation, &offset);
7411 offset_r += protoo_strlcpy(result+offset_r, &representation[offset], size-offset_r);
7412 } else {
7413 switch (hfinfo->type) {
7415 case FT_NONE:
7416 case FT_PROTOCOL:
7417 /* Prevent multiple check marks */
7418 if (strstr(result, UTF8_CHECK_MARK ",") == NULL) {
7419 offset_r += proto_item_fill_display_label(finfo, result+offset_r, size-offset_r);
7420 } else {
7421 result[--offset_r] = '\0'; /* Remove the added trailing ',' again */
7423 break;
7425 default:
7426 offset_r += proto_item_fill_display_label(finfo, result+offset_r, size-offset_r);
7427 break;
7431 if (offset_e && (offset_e < (size - 1)))
7432 expr[offset_e++] = ',';
7434 if (hfinfo->strings && hfinfo->type != FT_FRAMENUM && FIELD_DISPLAY(hfinfo->display) == BASE_NONE && (FT_IS_INT(hfinfo->type) || FT_IS_UINT(hfinfo->type))) {
7435 /* Integer types with BASE_NONE never get the numeric value. */
7436 if (FT_IS_INT32(hfinfo->type)) {
7437 hf_str_val = hf_try_val_to_str_const(fvalue_get_sinteger(finfo->value), hfinfo, "Unknown");
7438 } else if (FT_IS_UINT32(hfinfo->type)) {
7439 hf_str_val = hf_try_val_to_str_const(fvalue_get_uinteger(finfo->value), hfinfo, "Unknown");
7440 } else if (FT_IS_INT64(hfinfo->type)) {
7441 hf_str_val = hf_try_val64_to_str_const(fvalue_get_sinteger64(finfo->value), hfinfo, "Unknown");
7442 } else { // if (FT_IS_UINT64(hfinfo->type)) {
7443 hf_str_val = hf_try_val64_to_str_const(fvalue_get_uinteger64(finfo->value), hfinfo, "Unknown");
7445 snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
7446 offset_e = (int)strlen(expr);
7447 } else if (hfinfo->type == FT_NONE || hfinfo->type == FT_PROTOCOL) {
7448 /* Prevent multiple check marks */
7449 if (strstr(expr, UTF8_CHECK_MARK ",") == NULL) {
7450 offset_e += proto_item_fill_display_label(finfo, expr+offset_e, size-offset_e);
7451 } else {
7452 expr[--offset_e] = '\0'; /* Remove the added trailing ',' again */
7454 } else {
7455 str = fvalue_to_string_repr(NULL, finfo->value, FTREPR_RAW, finfo->hfinfo->display);
7456 offset_e += protoo_strlcpy(expr+offset_e, str, size-offset_e);
7457 wmem_free(NULL, str);
7459 i++;
7462 /* XXX: Why is only the first abbreviation returned for a multifield
7463 * custom column? */
7464 if (!abbrev) {
7465 /* Store abbrev for return value */
7466 abbrev = hfinfo->abbrev;
7469 if (occurrence == 0) {
7470 /* Fetch next hfinfo with same name (abbrev) */
7471 hfinfo = hfinfo_same_name_get_prev(hfinfo);
7472 } else {
7473 hfinfo = NULL;
7478 if (offset_r >= (size - 1)) {
7479 mark_truncated(result, 0, size, NULL);
7481 if (offset_e >= (size - 1)) {
7482 mark_truncated(expr, 0, size, NULL);
7484 return abbrev ? abbrev : "";
7487 char *
7488 proto_custom_get_filter(epan_dissect_t* edt, GSList *field_ids, int occurrence)
7490 int len, prev_len, last, i;
7491 GPtrArray *finfos;
7492 field_info *finfo = NULL;
7493 header_field_info* hfinfo;
7495 char *filter = NULL;
7496 GPtrArray *filter_array;
7498 col_custom_t *col_custom;
7499 int field_id;
7501 ws_assert(field_ids != NULL);
7502 filter_array = g_ptr_array_new_full(g_slist_length(field_ids), g_free);
7503 for (GSList *iter = field_ids; iter; iter = iter->next) {
7504 col_custom = (col_custom_t*)iter->data;
7505 field_id = col_custom->field_id;
7506 if (field_id == 0) {
7507 GPtrArray *fvals = NULL;
7508 bool passed = dfilter_apply_full(col_custom->dfilter, edt->tree, &fvals);
7509 if (fvals != NULL) {
7510 // XXX - Handling occurrences is unusual when more
7511 // than one field is involved, e.g. there's four
7512 // results for tcp.port + tcp.port. We really
7513 // want to apply it to the operands, not the output.
7514 /* Calculate single index or set outer boundaries */
7515 len = g_ptr_array_len(fvals);
7516 if (occurrence < 0) {
7517 i = occurrence + len;
7518 last = i;
7519 } else if (occurrence > 0) {
7520 i = occurrence - 1;
7521 last = i;
7522 } else {
7523 i = 0;
7524 last = len - 1;
7526 if (i < 0 || i >= len) {
7527 g_ptr_array_unref(fvals);
7528 continue;
7530 for (; i <= last; i++) {
7531 /* XXX - Should multiple values for one
7532 * field use set membership to reduce
7533 * verbosity, here and below? */
7534 char *str = fvalue_to_string_repr(NULL, fvals->pdata[i], FTREPR_DFILTER, BASE_NONE);
7535 filter = wmem_strdup_printf(NULL, "%s == %s", col_custom->dftext, str);
7536 wmem_free(NULL, str);
7537 if (!g_ptr_array_find_with_equal_func(filter_array, filter, g_str_equal, NULL)) {
7538 g_ptr_array_add(filter_array, filter);
7541 g_ptr_array_unref(fvals);
7542 } else if (passed) {
7543 filter = wmem_strdup(NULL, col_custom->dftext);
7544 if (!g_ptr_array_find_with_equal_func(filter_array, filter, g_str_equal, NULL)) {
7545 g_ptr_array_add(filter_array, filter);
7547 } else {
7548 filter = wmem_strdup_printf(NULL, "!(%s)", col_custom->dftext);
7549 if (!g_ptr_array_find_with_equal_func(filter_array, filter, g_str_equal, NULL)) {
7550 g_ptr_array_add(filter_array, filter);
7553 continue;
7556 PROTO_REGISTRAR_GET_NTH((unsigned)field_id, hfinfo);
7558 /* do we need to rewind ? */
7559 if (!hfinfo)
7560 return NULL;
7562 if (occurrence < 0) {
7563 /* Search other direction */
7564 while (hfinfo->same_name_prev_id != -1) {
7565 PROTO_REGISTRAR_GET_NTH(hfinfo->same_name_prev_id, hfinfo);
7569 prev_len = 0; /* Reset handled occurrences */
7571 while (hfinfo) {
7572 finfos = proto_get_finfo_ptr_array(edt->tree, hfinfo->id);
7574 if (!finfos || !(len = g_ptr_array_len(finfos))) {
7575 if (occurrence < 0) {
7576 hfinfo = hfinfo->same_name_next;
7577 } else {
7578 hfinfo = hfinfo_same_name_get_prev(hfinfo);
7580 continue;
7583 /* Are there enough occurrences of the field? */
7584 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
7585 if (occurrence < 0) {
7586 hfinfo = hfinfo->same_name_next;
7587 } else {
7588 hfinfo = hfinfo_same_name_get_prev(hfinfo);
7590 prev_len += len;
7591 continue;
7594 /* Calculate single index or set outer boundaries */
7595 if (occurrence < 0) {
7596 i = occurrence + len + prev_len;
7597 last = i;
7598 } else if (occurrence > 0) {
7599 i = occurrence - 1 - prev_len;
7600 last = i;
7601 } else {
7602 i = 0;
7603 last = len - 1;
7606 prev_len += len; /* Count handled occurrences */
7608 while (i <= last) {
7609 finfo = (field_info *)g_ptr_array_index(finfos, i);
7611 filter = proto_construct_match_selected_string(finfo, edt);
7612 if (filter) {
7613 /* Only add the same expression once (especially for FT_PROTOCOL).
7614 * The ptr array doesn't have NULL entries so g_str_equal is fine.
7616 if (!g_ptr_array_find_with_equal_func(filter_array, filter, g_str_equal, NULL)) {
7617 g_ptr_array_add(filter_array, filter);
7620 i++;
7623 if (occurrence == 0) {
7624 /* Fetch next hfinfo with same name (abbrev) */
7625 hfinfo = hfinfo_same_name_get_prev(hfinfo);
7626 } else {
7627 hfinfo = NULL;
7632 g_ptr_array_add(filter_array, NULL);
7634 /* XXX: Should this be || or && ? */
7635 char *output = g_strjoinv(" || ", (char **)filter_array->pdata);
7637 g_ptr_array_free(filter_array, true);
7639 return output;
7642 /* Set text of proto_item after having already been created. */
7643 void
7644 proto_item_set_text(proto_item *pi, const char *format, ...)
7646 field_info *fi = NULL;
7647 va_list ap;
7649 TRY_TO_FAKE_THIS_REPR_VOID(pi);
7651 fi = PITEM_FINFO(pi);
7652 if (fi == NULL)
7653 return;
7655 if (fi->rep) {
7656 ITEM_LABEL_FREE(PNODE_POOL(pi), fi->rep);
7657 fi->rep = NULL;
7660 va_start(ap, format);
7661 proto_tree_set_representation(pi, format, ap);
7662 va_end(ap);
7665 /* Append to text of proto_item after having already been created. */
7666 void
7667 proto_item_append_text(proto_item *pi, const char *format, ...)
7669 field_info *fi = NULL;
7670 size_t curlen;
7671 char *str;
7672 va_list ap;
7674 TRY_TO_FAKE_THIS_REPR_VOID(pi);
7676 fi = PITEM_FINFO(pi);
7677 if (fi == NULL) {
7678 return;
7681 if (!proto_item_is_hidden(pi)) {
7683 * If we don't already have a representation,
7684 * generate the default representation.
7686 if (fi->rep == NULL) {
7687 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
7688 proto_item_fill_label(fi, fi->rep->representation, &fi->rep->value_pos);
7689 /* Check for special case append value to FT_NONE or FT_PROTOCOL */
7690 if ((fi->hfinfo->type == FT_NONE || fi->hfinfo->type == FT_PROTOCOL) &&
7691 (strncmp(format, ": ", 2) == 0)) {
7692 fi->rep->value_pos += 2;
7695 if (fi->rep) {
7696 curlen = strlen(fi->rep->representation);
7697 /* curlen doesn't include the \0 byte.
7698 * XXX: If curlen + 4 > ITEM_LABEL_LENGTH, we can't tell if
7699 * the representation has already been truncated (of an up
7700 * to 4 byte UTF-8 character) or is just at the maximum length
7701 * unless we search for " [truncated]" (which may not be
7702 * at the start.)
7703 * It's safer to do nothing.
7705 if (ITEM_LABEL_LENGTH > (curlen + 4)) {
7706 va_start(ap, format);
7707 str = wmem_strdup_vprintf(PNODE_POOL(pi), format, ap);
7708 va_end(ap);
7709 WS_UTF_8_CHECK(str, -1);
7710 /* Keep fi->rep->value_pos */
7711 curlen = ws_label_strcpy(fi->rep->representation, ITEM_LABEL_LENGTH, curlen, str, 0);
7712 if (curlen >= ITEM_LABEL_LENGTH) {
7713 /* Uh oh, we don't have enough room. Tell the user
7714 * that the field is truncated.
7716 LABEL_MARK_TRUNCATED_START(fi->rep->representation, &fi->rep->value_pos);
7718 fi->rep->value_len = strlen(fi->rep->representation) - fi->rep->value_pos;
7724 /* Prepend to text of proto_item after having already been created. */
7725 void
7726 proto_item_prepend_text(proto_item *pi, const char *format, ...)
7728 field_info *fi = NULL;
7729 size_t pos;
7730 char representation[ITEM_LABEL_LENGTH];
7731 char *str;
7732 va_list ap;
7734 TRY_TO_FAKE_THIS_REPR_VOID(pi);
7736 fi = PITEM_FINFO(pi);
7737 if (fi == NULL) {
7738 return;
7741 if (!proto_item_is_hidden(pi)) {
7743 * If we don't already have a representation,
7744 * generate the default representation.
7746 if (fi->rep == NULL) {
7747 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
7748 proto_item_fill_label(fi, representation, &fi->rep->value_pos);
7749 } else
7750 (void) g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
7752 va_start(ap, format);
7753 str = wmem_strdup_vprintf(PNODE_POOL(pi), format, ap);
7754 va_end(ap);
7755 WS_UTF_8_CHECK(str, -1);
7756 fi->rep->value_pos += strlen(str);
7757 pos = ws_label_strcpy(fi->rep->representation, ITEM_LABEL_LENGTH, 0, str, 0);
7758 pos = ws_label_strcpy(fi->rep->representation, ITEM_LABEL_LENGTH, pos, representation, 0);
7759 /* XXX: As above, if the old representation is close to the label
7760 * length, it might already be marked as truncated. */
7761 if (pos >= ITEM_LABEL_LENGTH && (strlen(representation) + 4) <= ITEM_LABEL_LENGTH) {
7762 /* Uh oh, we don't have enough room. Tell the user
7763 * that the field is truncated.
7765 LABEL_MARK_TRUNCATED_START(fi->rep->representation, &fi->rep->value_pos);
7767 fi->rep->value_len = strlen(fi->rep->representation) - fi->rep->value_pos;
7771 static void
7772 finfo_set_len(field_info *fi, const int length)
7774 int length_remaining;
7776 DISSECTOR_ASSERT_HINT(length >= 0, fi->hfinfo->abbrev);
7777 length_remaining = tvb_captured_length_remaining(fi->ds_tvb, fi->start);
7778 if (length > length_remaining)
7779 fi->length = length_remaining;
7780 else
7781 fi->length = length;
7783 /* If we have an FT_PROTOCOL we need to set the length of the fvalue tvbuff as well. */
7784 if (fvalue_type_ftenum(fi->value) == FT_PROTOCOL) {
7785 fvalue_set_protocol_length(fi->value, fi->length);
7789 * You cannot just make the "len" field of a GByteArray
7790 * larger, if there's no data to back that length;
7791 * you can only make it smaller.
7793 if (fvalue_type_ftenum(fi->value) == FT_BYTES && fi->length > 0) {
7794 GBytes *bytes = fvalue_get_bytes(fi->value);
7795 size_t size;
7796 const void *data = g_bytes_get_data(bytes, &size);
7797 if ((size_t)fi->length <= size) {
7798 fvalue_set_bytes_data(fi->value, data, fi->length);
7800 g_bytes_unref(bytes);
7804 void
7805 proto_item_set_len(proto_item *pi, const int length)
7807 field_info *fi;
7809 /* If the item is not visible, we can't set the length because
7810 * we can't distinguish which proto item this is being called
7811 * on, since faked items share proto items. (#17877)
7813 TRY_TO_FAKE_THIS_REPR_VOID(pi);
7815 fi = PITEM_FINFO(pi);
7816 if (fi == NULL)
7817 return;
7819 finfo_set_len(fi, length);
7823 * Sets the length of the item based on its start and on the specified
7824 * offset, which is the offset past the end of the item; as the start
7825 * in the item is relative to the beginning of the data source tvbuff,
7826 * we need to pass in a tvbuff - the end offset is relative to the beginning
7827 * of that tvbuff.
7829 void
7830 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, int end)
7832 field_info *fi;
7833 int length;
7835 /* As with proto_item_set_len() above */
7836 TRY_TO_FAKE_THIS_REPR_VOID(pi);
7838 fi = PITEM_FINFO(pi);
7839 if (fi == NULL)
7840 return;
7842 end += tvb_raw_offset(tvb);
7843 DISSECTOR_ASSERT(end >= fi->start);
7844 length = end - fi->start;
7846 finfo_set_len(fi, length);
7850 proto_item_get_len(const proto_item *pi)
7852 field_info *fi;
7854 if (!pi)
7855 return -1;
7856 fi = PITEM_FINFO(pi);
7857 return fi ? fi->length : -1;
7860 void
7861 proto_item_set_bits_offset_len(proto_item *ti, int bits_offset, int bits_len) {
7862 if (!ti) {
7863 return;
7865 FI_SET_FLAG(PNODE_FINFO(ti), FI_BITS_OFFSET(bits_offset));
7866 FI_SET_FLAG(PNODE_FINFO(ti), FI_BITS_SIZE(bits_len));
7869 char *
7870 proto_item_get_display_repr(wmem_allocator_t *scope, proto_item *pi)
7872 field_info *fi;
7874 if (!pi)
7875 return "";
7876 fi = PITEM_FINFO(pi);
7877 DISSECTOR_ASSERT(fi->hfinfo != NULL);
7878 return fvalue_to_string_repr(scope, fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
7881 proto_tree *
7882 proto_tree_create_root(packet_info *pinfo)
7884 proto_node *pnode;
7886 /* Initialize the proto_node */
7887 pnode = g_slice_new(proto_tree);
7888 PROTO_NODE_INIT(pnode);
7889 pnode->parent = NULL;
7890 PNODE_FINFO(pnode) = NULL;
7891 pnode->tree_data = g_slice_new(tree_data_t);
7893 /* Make sure we can access pinfo everywhere */
7894 pnode->tree_data->pinfo = pinfo;
7896 /* Don't initialize the tree_data_t. Wait until we know we need it */
7897 pnode->tree_data->interesting_hfids = NULL;
7899 /* Set the default to false so it's easier to
7900 * find errors; if we expect to see the protocol tree
7901 * but for some reason the default 'visible' is not
7902 * changed, then we'll find out very quickly. */
7903 pnode->tree_data->visible = false;
7905 /* Make sure that we fake protocols (if possible) */
7906 pnode->tree_data->fake_protocols = true;
7908 /* Keep track of the number of children */
7909 pnode->tree_data->count = 0;
7911 return (proto_tree *)pnode;
7915 /* "prime" a proto_tree with a single hfid that a dfilter
7916 * is interested in. */
7917 void
7918 proto_tree_prime_with_hfid(proto_tree *tree _U_, const int hfid)
7920 header_field_info *hfinfo;
7922 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
7923 /* this field is referenced by a filter so increase the refcount.
7924 also increase the refcount for the parent, i.e the protocol.
7925 Don't increase the refcount if we're already printing the
7926 type, as that is a superset of direct reference.
7928 if (hfinfo->ref_type != HF_REF_TYPE_PRINT) {
7929 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
7931 /* only increase the refcount if there is a parent.
7932 if this is a protocol and not a field then parent will be -1
7933 and there is no parent to add any refcounting for.
7935 if (hfinfo->parent != -1) {
7936 header_field_info *parent_hfinfo;
7937 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
7939 /* Mark parent as indirectly referenced unless it is already directly
7940 * referenced, i.e. the user has specified the parent in a filter.
7942 if (parent_hfinfo->ref_type == HF_REF_TYPE_NONE)
7943 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
7947 /* "prime" a proto_tree with a single hfid that a dfilter
7948 * is interested in. */
7949 void
7950 proto_tree_prime_with_hfid_print(proto_tree *tree _U_, const int hfid)
7952 header_field_info *hfinfo;
7954 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
7955 /* this field is referenced by an (output) filter so increase the refcount.
7956 also increase the refcount for the parent, i.e the protocol.
7958 hfinfo->ref_type = HF_REF_TYPE_PRINT;
7959 /* only increase the refcount if there is a parent.
7960 if this is a protocol and not a field then parent will be -1
7961 and there is no parent to add any refcounting for.
7963 if (hfinfo->parent != -1) {
7964 header_field_info *parent_hfinfo;
7965 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
7967 /* Mark parent as indirectly referenced unless it is already directly
7968 * referenced, i.e. the user has specified the parent in a filter.
7970 if (parent_hfinfo->ref_type == HF_REF_TYPE_NONE)
7971 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
7975 proto_tree *
7976 proto_item_add_subtree(proto_item *pi, const int idx) {
7977 field_info *fi;
7979 if (!pi)
7980 return NULL;
7982 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
7984 fi = PITEM_FINFO(pi);
7985 if (!fi)
7986 return (proto_tree *)pi;
7988 fi->tree_type = idx;
7990 return (proto_tree *)pi;
7993 proto_tree *
7994 proto_item_get_subtree(proto_item *pi) {
7995 field_info *fi;
7997 if (!pi)
7998 return NULL;
7999 fi = PITEM_FINFO(pi);
8000 if ( (!fi) || (fi->tree_type == -1) )
8001 return NULL;
8002 return (proto_tree *)pi;
8005 proto_item *
8006 proto_item_get_parent(const proto_item *ti) {
8007 /* XXX: If we're faking items, this will return the parent of the
8008 * faked item, which may not be the logical parent expected.
8009 * We have no way of knowing exactly which real item the fake
8010 * item refers to here (the original item or one of its children
8011 * using it as a fake), and thus whether the parent should be the
8012 * faked item itself or the faked item's parent.
8014 * In that case, there's a good chance we end up returning the
8015 * root node of the protocol tree, which has "PNODE_FINFO()" null.
8017 * If we later add items to _that_, they will not be faked even though
8018 * they _should_ be, hurting performance (#8069). Also protocol
8019 * hierarchy stats (which fakes everything but protocols) may
8020 * behave oddly if unexpected items are added under the root node.
8022 if (!ti)
8023 return NULL;
8024 return ti->parent;
8027 proto_item *
8028 proto_item_get_parent_nth(proto_item *ti, int gen) {
8029 /* XXX: Same issue as above, even more so. */
8030 if (!ti)
8031 return NULL;
8032 while (gen--) {
8033 ti = ti->parent;
8034 if (!ti)
8035 return NULL;
8037 return ti;
8041 proto_item *
8042 proto_tree_get_parent(proto_tree *tree) {
8043 if (!tree)
8044 return NULL;
8045 return (proto_item *)tree;
8048 proto_tree *
8049 proto_tree_get_parent_tree(proto_tree *tree) {
8050 /* XXX: Same issue as proto_item_get_parent */
8051 if (!tree)
8052 return NULL;
8054 /* we're the root tree, there's no parent
8055 return ourselves so the caller has at least a tree to attach to */
8056 if (!tree->parent)
8057 return tree;
8059 return (proto_tree *)tree->parent;
8062 proto_tree *
8063 proto_tree_get_root(proto_tree *tree) {
8064 if (!tree)
8065 return NULL;
8066 while (tree->parent) {
8067 tree = tree->parent;
8069 return tree;
8072 void
8073 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
8074 proto_item *item_to_move)
8076 /* This function doesn't generate any values. It only reorganizes the prococol tree
8077 * so we can bail out immediately if it isn't visible. */
8078 if (!tree || !PTREE_DATA(tree)->visible)
8079 return;
8081 DISSECTOR_ASSERT(item_to_move->parent == tree);
8082 DISSECTOR_ASSERT(fixed_item->parent == tree);
8084 /*** cut item_to_move out ***/
8086 /* is item_to_move the first? */
8087 if (tree->first_child == item_to_move) {
8088 /* simply change first child to next */
8089 tree->first_child = item_to_move->next;
8091 DISSECTOR_ASSERT(tree->last_child != item_to_move);
8092 } else {
8093 proto_item *curr_item;
8094 /* find previous and change it's next */
8095 for (curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
8096 if (curr_item->next == item_to_move) {
8097 break;
8101 DISSECTOR_ASSERT(curr_item);
8103 curr_item->next = item_to_move->next;
8105 /* fix last_child if required */
8106 if (tree->last_child == item_to_move) {
8107 tree->last_child = curr_item;
8111 /*** insert to_move after fixed ***/
8112 item_to_move->next = fixed_item->next;
8113 fixed_item->next = item_to_move;
8114 if (tree->last_child == fixed_item) {
8115 tree->last_child = item_to_move;
8119 void
8120 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, int start,
8121 const int length)
8123 field_info *fi;
8125 if (tree == NULL)
8126 return;
8128 fi = PTREE_FINFO(tree);
8129 if (fi == NULL)
8130 return;
8132 start += tvb_raw_offset(tvb);
8133 DISSECTOR_ASSERT(start >= 0);
8134 DISSECTOR_ASSERT(length >= 0);
8136 fi->appendix_start = start;
8137 fi->appendix_length = length;
8140 static void
8141 check_protocol_filter_name_or_fail(const char *filter_name)
8143 /* Require at least two characters. */
8144 if (filter_name[0] == '\0' || filter_name[1] == '\0') {
8145 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" cannot have length less than two.", filter_name);
8148 if (proto_check_field_name(filter_name) != '\0') {
8149 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" has one or more invalid characters."
8150 " Allowed are letters, digits, '-', '_' and non-repeating '.'."
8151 " This might be caused by an inappropriate plugin or a development error.", filter_name);
8154 /* Check that it doesn't match some very common numeric forms. */
8155 if (filter_name[0] == '0' &&
8156 (filter_name[1] == 'x' || filter_name[1] == 'X' ||
8157 filter_name[1] == 'b' || filter_name[1] == 'B')) {
8158 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" cannot start with \"%c%c\".",
8159 filter_name, filter_name[0], filter_name[1]);
8162 /* Names starting with a digit must not contain a minus sign (currently not checked at runtime). */
8164 /* Check that it contains at least one letter. */
8165 bool have_letter = false;
8166 for (const char *s = filter_name; *s != '\0'; s++) {
8167 if (g_ascii_isalpha(*s)) {
8168 have_letter = true;
8169 break;
8172 if (!have_letter) {
8173 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" must contain at least one letter a-z.",
8174 filter_name);
8177 /* Check for reserved keywords. */
8178 if (g_hash_table_contains(proto_reserved_filter_names, filter_name)) {
8179 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" is invalid because it is a reserved keyword."
8180 " This might be caused by an inappropriate plugin or a development error.", filter_name);
8185 proto_register_protocol(const char *name, const char *short_name,
8186 const char *filter_name)
8188 protocol_t *protocol;
8189 header_field_info *hfinfo;
8192 * Make sure there's not already a protocol with any of those
8193 * names. Crash if there is, as that's an error in the code
8194 * or an inappropriate plugin.
8195 * This situation has to be fixed to not register more than one
8196 * protocol with the same name.
8199 if (g_hash_table_lookup(proto_names, name)) {
8200 /* ws_error will terminate the program */
8201 REPORT_DISSECTOR_BUG("Duplicate protocol name \"%s\"!"
8202 " This might be caused by an inappropriate plugin or a development error.", name);
8205 if (g_hash_table_lookup(proto_short_names, short_name)) {
8206 REPORT_DISSECTOR_BUG("Duplicate protocol short_name \"%s\"!"
8207 " This might be caused by an inappropriate plugin or a development error.", short_name);
8210 check_protocol_filter_name_or_fail(filter_name);
8212 if (g_hash_table_lookup(proto_filter_names, filter_name)) {
8213 REPORT_DISSECTOR_BUG("Duplicate protocol filter_name \"%s\"!"
8214 " This might be caused by an inappropriate plugin or a development error.", filter_name);
8218 * Add this protocol to the list of known protocols;
8219 * the list is sorted by protocol short name.
8221 protocol = g_new(protocol_t, 1);
8222 protocol->name = name;
8223 protocol->short_name = short_name;
8224 protocol->filter_name = filter_name;
8225 protocol->fields = NULL; /* Delegate until actually needed */
8226 protocol->is_enabled = true; /* protocol is enabled by default */
8227 protocol->enabled_by_default = true; /* see previous comment */
8228 protocol->can_toggle = true;
8229 protocol->parent_proto_id = -1;
8230 protocol->heur_list = NULL;
8232 /* List will be sorted later by name, when all protocols completed registering */
8233 protocols = g_list_prepend(protocols, protocol);
8234 g_hash_table_insert(proto_names, (void *)name, protocol);
8235 g_hash_table_insert(proto_filter_names, (void *)filter_name, protocol);
8236 g_hash_table_insert(proto_short_names, (void *)short_name, protocol);
8238 /* Here we allocate a new header_field_info struct */
8239 hfinfo = g_slice_new(header_field_info);
8240 hfinfo->name = name;
8241 hfinfo->abbrev = filter_name;
8242 hfinfo->type = FT_PROTOCOL;
8243 hfinfo->display = BASE_NONE;
8244 hfinfo->strings = protocol;
8245 hfinfo->bitmask = 0;
8246 hfinfo->ref_type = HF_REF_TYPE_NONE;
8247 hfinfo->blurb = NULL;
8248 hfinfo->parent = -1; /* This field differentiates protos and fields */
8250 protocol->proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
8251 return protocol->proto_id;
8255 proto_register_protocol_in_name_only(const char *name, const char *short_name, const char *filter_name, int parent_proto, enum ftenum field_type)
8257 protocol_t *protocol;
8258 header_field_info *hfinfo;
8261 * Helper protocols don't need the strict rules as a "regular" protocol
8262 * Just register it in a list and make a hf_ field from it
8264 if ((field_type != FT_PROTOCOL) && (field_type != FT_BYTES)) {
8265 REPORT_DISSECTOR_BUG("Pino \"%s\" must be of type FT_PROTOCOL or FT_BYTES.", name);
8268 if (parent_proto <= 0) {
8269 REPORT_DISSECTOR_BUG("Must have a valid parent protocol for helper protocol \"%s\"!"
8270 " This might be caused by an inappropriate plugin or a development error.", name);
8273 check_protocol_filter_name_or_fail(filter_name);
8275 /* Add this protocol to the list of helper protocols (just so it can be properly freed) */
8276 protocol = g_new(protocol_t, 1);
8277 protocol->name = name;
8278 protocol->short_name = short_name;
8279 protocol->filter_name = filter_name;
8280 protocol->fields = NULL; /* Delegate until actually needed */
8282 /* Enabling and toggling is really determined by parent protocol,
8283 but provide default values here */
8284 protocol->is_enabled = true;
8285 protocol->enabled_by_default = true;
8286 protocol->can_toggle = true;
8288 protocol->parent_proto_id = parent_proto;
8289 protocol->heur_list = NULL;
8291 /* List will be sorted later by name, when all protocols completed registering */
8292 protocols = g_list_prepend(protocols, protocol);
8294 /* Here we allocate a new header_field_info struct */
8295 hfinfo = g_slice_new(header_field_info);
8296 hfinfo->name = name;
8297 hfinfo->abbrev = filter_name;
8298 hfinfo->type = field_type;
8299 hfinfo->display = BASE_NONE;
8300 if (field_type == FT_BYTES) {
8301 hfinfo->display |= (BASE_NO_DISPLAY_VALUE|BASE_PROTOCOL_INFO);
8303 hfinfo->strings = protocol;
8304 hfinfo->bitmask = 0;
8305 hfinfo->ref_type = HF_REF_TYPE_NONE;
8306 hfinfo->blurb = NULL;
8307 hfinfo->parent = -1; /* This field differentiates protos and fields */
8309 protocol->proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
8310 return protocol->proto_id;
8313 bool
8314 proto_deregister_protocol(const char *short_name)
8316 protocol_t *protocol;
8317 header_field_info *hfinfo;
8318 int proto_id;
8319 unsigned i;
8321 proto_id = proto_get_id_by_short_name(short_name);
8322 protocol = find_protocol_by_id(proto_id);
8323 if (protocol == NULL)
8324 return false;
8326 g_hash_table_remove(proto_names, protocol->name);
8327 g_hash_table_remove(proto_short_names, (void *)short_name);
8328 g_hash_table_remove(proto_filter_names, (void *)protocol->filter_name);
8330 if (protocol->fields) {
8331 for (i = 0; i < protocol->fields->len; i++) {
8332 hfinfo = (header_field_info *)g_ptr_array_index(protocol->fields, i);
8333 hfinfo_remove_from_gpa_name_map(hfinfo);
8334 expert_deregister_expertinfo(hfinfo->abbrev);
8335 g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[hfinfo->id]);
8337 g_ptr_array_free(protocol->fields, true);
8338 protocol->fields = NULL;
8341 g_list_free(protocol->heur_list);
8343 /* Remove this protocol from the list of known protocols */
8344 protocols = g_list_remove(protocols, protocol);
8346 g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[proto_id]);
8347 g_hash_table_steal(gpa_name_map, protocol->filter_name);
8349 g_free(last_field_name);
8350 last_field_name = NULL;
8352 return true;
8355 void
8356 proto_register_alias(const int proto_id, const char *alias_name)
8358 protocol_t *protocol;
8360 protocol = find_protocol_by_id(proto_id);
8361 if (alias_name && protocol) {
8362 g_hash_table_insert(gpa_protocol_aliases, (void *) alias_name, (void *)protocol->filter_name);
8367 * Routines to use to iterate over the protocols.
8368 * The argument passed to the iterator routines is an opaque cookie to
8369 * their callers; it's the GList pointer for the current element in
8370 * the list.
8371 * The ID of the protocol is returned, or -1 if there is no protocol.
8374 proto_get_first_protocol(void **cookie)
8376 protocol_t *protocol;
8378 if (protocols == NULL)
8379 return -1;
8380 *cookie = protocols;
8381 protocol = (protocol_t *)protocols->data;
8382 return protocol->proto_id;
8386 proto_get_data_protocol(void *cookie)
8388 GList *list_item = (GList *)cookie;
8390 protocol_t *protocol = (protocol_t *)list_item->data;
8391 return protocol->proto_id;
8395 proto_get_next_protocol(void **cookie)
8397 GList *list_item = (GList *)*cookie;
8398 protocol_t *protocol;
8400 list_item = g_list_next(list_item);
8401 if (list_item == NULL)
8402 return -1;
8403 *cookie = list_item;
8404 protocol = (protocol_t *)list_item->data;
8405 return protocol->proto_id;
8408 header_field_info *
8409 proto_get_first_protocol_field(const int proto_id, void **cookie)
8411 protocol_t *protocol = find_protocol_by_id(proto_id);
8413 if ((protocol == NULL) || (protocol->fields == NULL) || (protocol->fields->len == 0))
8414 return NULL;
8416 *cookie = GUINT_TO_POINTER(0);
8417 return (header_field_info *)g_ptr_array_index(protocol->fields, 0);
8420 header_field_info *
8421 proto_get_next_protocol_field(const int proto_id, void **cookie)
8423 protocol_t *protocol = find_protocol_by_id(proto_id);
8424 unsigned i = GPOINTER_TO_UINT(*cookie);
8426 i++;
8428 if ((protocol->fields == NULL) || (i >= protocol->fields->len))
8429 return NULL;
8431 *cookie = GUINT_TO_POINTER(i);
8432 return (header_field_info *)g_ptr_array_index(protocol->fields, i);
8435 protocol_t *
8436 find_protocol_by_id(const int proto_id)
8438 header_field_info *hfinfo;
8440 if (proto_id <= 0)
8441 return NULL;
8443 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
8444 if (hfinfo->type != FT_PROTOCOL) {
8445 DISSECTOR_ASSERT(hfinfo->display & BASE_PROTOCOL_INFO);
8447 return (protocol_t *)hfinfo->strings;
8451 proto_get_id(const protocol_t *protocol)
8453 return protocol->proto_id;
8456 bool
8457 proto_name_already_registered(const char *name)
8459 DISSECTOR_ASSERT_HINT(name, "No name present");
8461 if (g_hash_table_lookup(proto_names, name) != NULL)
8462 return true;
8463 return false;
8467 proto_get_id_by_filter_name(const char *filter_name)
8469 const protocol_t *protocol = NULL;
8471 DISSECTOR_ASSERT_HINT(filter_name, "No filter name present");
8473 protocol = (const protocol_t *)g_hash_table_lookup(proto_filter_names, filter_name);
8475 if (protocol == NULL)
8476 return -1;
8477 return protocol->proto_id;
8481 proto_get_id_by_short_name(const char *short_name)
8483 const protocol_t *protocol = NULL;
8485 DISSECTOR_ASSERT_HINT(short_name, "No short name present");
8487 protocol = (const protocol_t *)g_hash_table_lookup(proto_short_names, short_name);
8489 if (protocol == NULL)
8490 return -1;
8491 return protocol->proto_id;
8494 const char *
8495 proto_get_protocol_name(const int proto_id)
8497 protocol_t *protocol;
8499 protocol = find_protocol_by_id(proto_id);
8501 if (protocol == NULL)
8502 return NULL;
8503 return protocol->name;
8506 const char *
8507 proto_get_protocol_short_name(const protocol_t *protocol)
8509 if (protocol == NULL)
8510 return "(none)";
8511 return protocol->short_name;
8514 const char *
8515 proto_get_protocol_long_name(const protocol_t *protocol)
8517 if (protocol == NULL)
8518 return "(none)";
8519 return protocol->name;
8522 const char *
8523 proto_get_protocol_filter_name(const int proto_id)
8525 protocol_t *protocol;
8527 protocol = find_protocol_by_id(proto_id);
8528 if (protocol == NULL)
8529 return "(none)";
8530 return protocol->filter_name;
8533 void proto_add_heuristic_dissector(protocol_t *protocol, const char *short_name)
8535 heur_dtbl_entry_t* heuristic_dissector;
8537 if (protocol == NULL)
8538 return;
8540 heuristic_dissector = find_heur_dissector_by_unique_short_name(short_name);
8541 if (heuristic_dissector != NULL)
8543 protocol->heur_list = g_list_prepend (protocol->heur_list, heuristic_dissector);
8547 void proto_heuristic_dissector_foreach(const protocol_t *protocol, GFunc func, void *user_data)
8549 if (protocol == NULL)
8550 return;
8552 g_list_foreach(protocol->heur_list, func, user_data);
8555 void
8556 proto_get_frame_protocols(const wmem_list_t *layers, bool *is_ip,
8557 bool *is_tcp, bool *is_udp,
8558 bool *is_sctp, bool *is_tls,
8559 bool *is_rtp,
8560 bool *is_lte_rlc)
8562 wmem_list_frame_t *protos = wmem_list_head(layers);
8563 int proto_id;
8564 const char *proto_name;
8566 /* Walk the list of a available protocols in the packet and
8567 attempt to find "major" ones. */
8568 /* It might make more sense to assemble and return a bitfield. */
8569 while (protos != NULL)
8571 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
8572 proto_name = proto_get_protocol_filter_name(proto_id);
8574 if (is_ip && ((!strcmp(proto_name, "ip")) ||
8575 (!strcmp(proto_name, "ipv6")))) {
8576 *is_ip = true;
8577 } else if (is_tcp && !strcmp(proto_name, "tcp")) {
8578 *is_tcp = true;
8579 } else if (is_udp && !strcmp(proto_name, "udp")) {
8580 *is_udp = true;
8581 } else if (is_sctp && !strcmp(proto_name, "sctp")) {
8582 *is_sctp = true;
8583 } else if (is_tls && !strcmp(proto_name, "tls")) {
8584 *is_tls = true;
8585 } else if (is_rtp && !strcmp(proto_name, "rtp")) {
8586 *is_rtp = true;
8587 } else if (is_lte_rlc && (!strcmp(proto_name, "rlc-lte") || !strcmp(proto_name, "rlc-nr"))) {
8588 *is_lte_rlc = true;
8591 protos = wmem_list_frame_next(protos);
8595 bool
8596 proto_is_frame_protocol(const wmem_list_t *layers, const char* proto_name)
8598 wmem_list_frame_t *protos = wmem_list_head(layers);
8599 int proto_id;
8600 const char *name;
8602 /* Walk the list of a available protocols in the packet and
8603 attempt to find the specified protocol. */
8604 while (protos != NULL)
8606 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
8607 name = proto_get_protocol_filter_name(proto_id);
8609 if (!strcmp(name, proto_name))
8611 return true;
8614 protos = wmem_list_frame_next(protos);
8617 return false;
8620 char *
8621 proto_list_layers(const packet_info *pinfo)
8623 wmem_strbuf_t *buf;
8624 wmem_list_frame_t *layers = wmem_list_head(pinfo->layers);
8626 buf = wmem_strbuf_new_sized(pinfo->pool, 128);
8628 /* Walk the list of layers in the packet and
8629 return a string of all entries. */
8630 while (layers != NULL)
8632 wmem_strbuf_append(buf, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(layers))));
8634 layers = wmem_list_frame_next(layers);
8635 if (layers != NULL) {
8636 wmem_strbuf_append_c(buf, ':');
8640 return wmem_strbuf_finalize(buf);
8643 bool
8644 proto_is_pino(const protocol_t *protocol)
8646 return (protocol->parent_proto_id != -1);
8649 bool
8650 // NOLINTNEXTLINE(misc-no-recursion)
8651 proto_is_protocol_enabled(const protocol_t *protocol)
8653 if (protocol == NULL)
8654 return false;
8656 //parent protocol determines enable/disable for helper dissectors
8657 if (proto_is_pino(protocol))
8658 return proto_is_protocol_enabled(find_protocol_by_id(protocol->parent_proto_id));
8660 return protocol->is_enabled;
8663 bool
8664 // NOLINTNEXTLINE(misc-no-recursion)
8665 proto_is_protocol_enabled_by_default(const protocol_t *protocol)
8667 //parent protocol determines enable/disable for helper dissectors
8668 if (proto_is_pino(protocol))
8669 return proto_is_protocol_enabled_by_default(find_protocol_by_id(protocol->parent_proto_id));
8671 return protocol->enabled_by_default;
8674 bool
8675 // NOLINTNEXTLINE(misc-no-recursion)
8676 proto_can_toggle_protocol(const int proto_id)
8678 protocol_t *protocol;
8680 protocol = find_protocol_by_id(proto_id);
8681 //parent protocol determines toggling for helper dissectors
8682 if (proto_is_pino(protocol))
8683 return proto_can_toggle_protocol(protocol->parent_proto_id);
8685 return protocol->can_toggle;
8688 void
8689 proto_disable_by_default(const int proto_id)
8691 protocol_t *protocol;
8693 protocol = find_protocol_by_id(proto_id);
8694 DISSECTOR_ASSERT(protocol->can_toggle);
8695 DISSECTOR_ASSERT(proto_is_pino(protocol) == false);
8696 protocol->is_enabled = false;
8697 protocol->enabled_by_default = false;
8700 void
8701 proto_set_decoding(const int proto_id, const bool enabled)
8703 protocol_t *protocol;
8705 protocol = find_protocol_by_id(proto_id);
8706 DISSECTOR_ASSERT(protocol->can_toggle);
8707 DISSECTOR_ASSERT(proto_is_pino(protocol) == false);
8708 protocol->is_enabled = enabled;
8711 void
8712 proto_disable_all(void)
8714 /* This doesn't explicitly disable heuristic protocols,
8715 * but the heuristic doesn't get called if the parent
8716 * protocol isn't enabled.
8718 protocol_t *protocol;
8719 GList *list_item = protocols;
8721 if (protocols == NULL)
8722 return;
8724 while (list_item) {
8725 protocol = (protocol_t *)list_item->data;
8726 if (protocol->can_toggle) {
8727 protocol->is_enabled = false;
8729 list_item = g_list_next(list_item);
8733 static void
8734 heur_reenable_cb(void *data, void *user_data _U_)
8736 heur_dtbl_entry_t *heur = (heur_dtbl_entry_t*)data;
8738 heur->enabled = heur->enabled_by_default;
8741 void
8742 proto_reenable_all(void)
8744 protocol_t *protocol;
8745 GList *list_item = protocols;
8747 if (protocols == NULL)
8748 return;
8750 while (list_item) {
8751 protocol = (protocol_t *)list_item->data;
8752 if (protocol->can_toggle)
8753 protocol->is_enabled = protocol->enabled_by_default;
8754 proto_heuristic_dissector_foreach(protocol, heur_reenable_cb, NULL);
8755 list_item = g_list_next(list_item);
8759 void
8760 proto_set_cant_toggle(const int proto_id)
8762 protocol_t *protocol;
8764 protocol = find_protocol_by_id(proto_id);
8765 protocol->can_toggle = false;
8768 static int
8769 proto_register_field_common(protocol_t *proto, header_field_info *hfi, const int parent)
8771 if (proto != NULL) {
8772 g_ptr_array_add(proto->fields, hfi);
8775 return proto_register_field_init(hfi, parent);
8778 /* for use with static arrays only, since we don't allocate our own copies
8779 of the header_field_info struct contained within the hf_register_info struct */
8780 void
8781 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
8783 hf_register_info *ptr = hf;
8784 protocol_t *proto;
8785 int i;
8787 proto = find_protocol_by_id(parent);
8789 if (proto->fields == NULL) {
8790 proto->fields = g_ptr_array_sized_new(num_records);
8793 for (i = 0; i < num_records; i++, ptr++) {
8795 * Make sure we haven't registered this yet.
8796 * Most fields have variables associated with them
8797 * that are initialized to -1; some have array elements,
8798 * or possibly uninitialized variables, so we also allow
8799 * 0 (which is unlikely to be the field ID we get back
8800 * from "proto_register_field_init()").
8802 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
8803 REPORT_DISSECTOR_BUG(
8804 "Duplicate field detected in call to proto_register_field_array: %s is already registered",
8805 ptr->hfinfo.abbrev);
8806 return;
8809 *ptr->p_id = proto_register_field_common(proto, &ptr->hfinfo, parent);
8813 /* deregister already registered fields */
8814 void
8815 proto_deregister_field (const int parent, int hf_id)
8817 header_field_info *hfi;
8818 protocol_t *proto;
8819 unsigned i;
8821 g_free(last_field_name);
8822 last_field_name = NULL;
8824 if (hf_id == -1 || hf_id == 0)
8825 return;
8827 proto = find_protocol_by_id (parent);
8828 if (!proto || proto->fields == NULL) {
8829 return;
8832 for (i = 0; i < proto->fields->len; i++) {
8833 hfi = (header_field_info *)g_ptr_array_index(proto->fields, i);
8834 if (hfi->id == hf_id) {
8835 /* Found the hf_id in this protocol */
8836 g_hash_table_steal(gpa_name_map, hfi->abbrev);
8837 g_ptr_array_remove_index_fast(proto->fields, i);
8838 g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[hf_id]);
8839 return;
8844 void
8845 proto_add_deregistered_data (void *data)
8847 g_ptr_array_add(deregistered_data, data);
8850 void
8851 proto_add_deregistered_slice (size_t block_size, void *mem_block)
8853 struct g_slice_data *slice_data = g_slice_new(struct g_slice_data);
8855 slice_data->block_size = block_size;
8856 slice_data->mem_block = mem_block;
8858 g_ptr_array_add(deregistered_slice, slice_data);
8861 void proto_free_field_strings (ftenum_t field_type, unsigned int field_display, const void *field_strings)
8863 if (field_strings == NULL) {
8864 return;
8867 switch (field_type) {
8868 case FT_FRAMENUM:
8869 /* This is just an integer represented as a pointer */
8870 break;
8871 case FT_PROTOCOL: {
8872 protocol_t *protocol = (protocol_t *)field_strings;
8873 g_free((char *)protocol->short_name);
8874 break;
8876 case FT_BOOLEAN: {
8877 true_false_string *tf = (true_false_string *)field_strings;
8878 g_free((char *)tf->true_string);
8879 g_free((char *)tf->false_string);
8880 break;
8882 case FT_UINT40:
8883 case FT_INT40:
8884 case FT_UINT48:
8885 case FT_INT48:
8886 case FT_UINT56:
8887 case FT_INT56:
8888 case FT_UINT64:
8889 case FT_INT64: {
8890 if (field_display & BASE_UNIT_STRING) {
8891 unit_name_string *unit = (unit_name_string *)field_strings;
8892 g_free((char *)unit->singular);
8893 g_free((char *)unit->plural);
8894 } else if (field_display & BASE_RANGE_STRING) {
8895 range_string *rs = (range_string *)field_strings;
8896 while (rs->strptr) {
8897 g_free((char *)rs->strptr);
8898 rs++;
8900 } else if (field_display & BASE_EXT_STRING) {
8901 val64_string_ext *vse = (val64_string_ext *)field_strings;
8902 val64_string *vs = (val64_string *)vse->_vs_p;
8903 while (vs->strptr) {
8904 g_free((char *)vs->strptr);
8905 vs++;
8907 val64_string_ext_free(vse);
8908 field_strings = NULL;
8909 } else if (field_display == BASE_CUSTOM) {
8910 /* this will be a pointer to a function, don't free that */
8911 field_strings = NULL;
8912 } else {
8913 val64_string *vs64 = (val64_string *)field_strings;
8914 while (vs64->strptr) {
8915 g_free((char *)vs64->strptr);
8916 vs64++;
8919 break;
8921 case FT_CHAR:
8922 case FT_UINT8:
8923 case FT_INT8:
8924 case FT_UINT16:
8925 case FT_INT16:
8926 case FT_UINT24:
8927 case FT_INT24:
8928 case FT_UINT32:
8929 case FT_INT32:
8930 case FT_FLOAT:
8931 case FT_DOUBLE: {
8932 if (field_display & BASE_UNIT_STRING) {
8933 unit_name_string *unit = (unit_name_string *)field_strings;
8934 g_free((char *)unit->singular);
8935 g_free((char *)unit->plural);
8936 } else if (field_display & BASE_RANGE_STRING) {
8937 range_string *rs = (range_string *)field_strings;
8938 while (rs->strptr) {
8939 g_free((char *)rs->strptr);
8940 rs++;
8942 } else if (field_display & BASE_EXT_STRING) {
8943 value_string_ext *vse = (value_string_ext *)field_strings;
8944 value_string *vs = (value_string *)vse->_vs_p;
8945 while (vs->strptr) {
8946 g_free((char *)vs->strptr);
8947 vs++;
8949 value_string_ext_free(vse);
8950 field_strings = NULL;
8951 } else if (field_display == BASE_CUSTOM) {
8952 /* this will be a pointer to a function, don't free that */
8953 field_strings = NULL;
8954 } else {
8955 value_string *vs = (value_string *)field_strings;
8956 while (vs->strptr) {
8957 g_free((char *)vs->strptr);
8958 vs++;
8961 break;
8962 default:
8963 break;
8967 if (field_type != FT_FRAMENUM) {
8968 g_free((void *)field_strings);
8972 static void
8973 free_deregistered_field (void *data, void *user_data _U_)
8975 header_field_info *hfi = (header_field_info *) data;
8976 int hf_id = hfi->id;
8978 g_free((char *)hfi->name);
8979 g_free((char *)hfi->abbrev);
8980 g_free((char *)hfi->blurb);
8982 proto_free_field_strings(hfi->type, hfi->display, hfi->strings);
8984 if (hfi->parent == -1)
8985 g_slice_free(header_field_info, hfi);
8987 gpa_hfinfo.hfi[hf_id] = NULL; /* Invalidate this hf_id / proto_id */
8990 static void
8991 free_deregistered_data (void *data, void *user_data _U_)
8993 g_free (data);
8996 static void
8997 free_deregistered_slice (void *data, void *user_data _U_)
8999 struct g_slice_data *slice_data = (struct g_slice_data *)data;
9001 g_slice_free1(slice_data->block_size, slice_data->mem_block);
9002 g_slice_free(struct g_slice_data, slice_data);
9005 /* free deregistered fields and data */
9006 void
9007 proto_free_deregistered_fields (void)
9009 expert_free_deregistered_expertinfos();
9011 g_ptr_array_foreach(deregistered_fields, free_deregistered_field, NULL);
9012 g_ptr_array_free(deregistered_fields, true);
9013 deregistered_fields = g_ptr_array_new();
9015 g_ptr_array_foreach(deregistered_data, free_deregistered_data, NULL);
9016 g_ptr_array_free(deregistered_data, true);
9017 deregistered_data = g_ptr_array_new();
9019 g_ptr_array_foreach(deregistered_slice, free_deregistered_slice, NULL);
9020 g_ptr_array_free(deregistered_slice, true);
9021 deregistered_slice = g_ptr_array_new();
9024 static const value_string hf_display[] = {
9025 { BASE_NONE, "BASE_NONE" },
9026 { BASE_DEC, "BASE_DEC" },
9027 { BASE_HEX, "BASE_HEX" },
9028 { BASE_OCT, "BASE_OCT" },
9029 { BASE_DEC_HEX, "BASE_DEC_HEX" },
9030 { BASE_HEX_DEC, "BASE_HEX_DEC" },
9031 { BASE_CUSTOM, "BASE_CUSTOM" },
9032 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
9033 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
9034 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
9035 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
9036 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
9037 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
9038 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
9039 { BASE_NONE|BASE_VAL64_STRING, "BASE_NONE|BASE_VAL64_STRING" },
9040 { BASE_DEC|BASE_VAL64_STRING, "BASE_DEC|BASE_VAL64_STRING" },
9041 { BASE_HEX|BASE_VAL64_STRING, "BASE_HEX|BASE_VAL64_STRING" },
9042 { BASE_OCT|BASE_VAL64_STRING, "BASE_OCT|BASE_VAL64_STRING" },
9043 { BASE_DEC_HEX|BASE_VAL64_STRING, "BASE_DEC_HEX|BASE_VAL64_STRING" },
9044 { BASE_HEX_DEC|BASE_VAL64_STRING, "BASE_HEX_DEC|BASE_VAL64_STRING" },
9045 { BASE_CUSTOM|BASE_VAL64_STRING, "BASE_CUSTOM|BASE_VAL64_STRING" },
9046 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
9047 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_UTC" },
9048 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_DOY_UTC" },
9049 { BASE_PT_UDP, "BASE_PT_UDP" },
9050 { BASE_PT_TCP, "BASE_PT_TCP" },
9051 { BASE_PT_DCCP, "BASE_PT_DCCP" },
9052 { BASE_PT_SCTP, "BASE_PT_SCTP" },
9053 { BASE_OUI, "BASE_OUI" },
9054 { 0, NULL } };
9056 const char* proto_field_display_to_string(int field_display)
9058 return val_to_str_const(field_display, hf_display, "Unknown");
9061 static inline port_type
9062 display_to_port_type(field_display_e e)
9064 switch (e) {
9065 case BASE_PT_UDP:
9066 return PT_UDP;
9067 case BASE_PT_TCP:
9068 return PT_TCP;
9069 case BASE_PT_DCCP:
9070 return PT_DCCP;
9071 case BASE_PT_SCTP:
9072 return PT_SCTP;
9073 default:
9074 break;
9076 return PT_NONE;
9079 /* temporary function containing assert part for easier profiling */
9080 static void
9081 tmp_fld_check_assert(header_field_info *hfinfo)
9083 char* tmp_str;
9085 /* The field must have a name (with length > 0) */
9086 if (!hfinfo->name || !hfinfo->name[0]) {
9087 if (hfinfo->abbrev)
9088 /* Try to identify the field */
9089 REPORT_DISSECTOR_BUG("Field (abbrev='%s') does not have a name",
9090 hfinfo->abbrev);
9091 else
9092 /* Hum, no luck */
9093 REPORT_DISSECTOR_BUG("Field does not have a name (nor an abbreviation)");
9096 /* fields with an empty string for an abbreviation aren't filterable */
9097 if (!hfinfo->abbrev || !hfinfo->abbrev[0])
9098 REPORT_DISSECTOR_BUG("Field '%s' does not have an abbreviation", hfinfo->name);
9100 /* These types of fields are allowed to have value_strings,
9101 * true_false_strings or a protocol_t struct
9103 if (hfinfo->strings != NULL && FIELD_DISPLAY(hfinfo->display) != BASE_CUSTOM) {
9104 switch (hfinfo->type) {
9107 * These types are allowed to support display value_strings,
9108 * value64_strings, the extended versions of the previous
9109 * two, range strings, or unit strings.
9111 case FT_CHAR:
9112 case FT_UINT8:
9113 case FT_UINT16:
9114 case FT_UINT24:
9115 case FT_UINT32:
9116 case FT_UINT40:
9117 case FT_UINT48:
9118 case FT_UINT56:
9119 case FT_UINT64:
9120 case FT_INT8:
9121 case FT_INT16:
9122 case FT_INT24:
9123 case FT_INT32:
9124 case FT_INT40:
9125 case FT_INT48:
9126 case FT_INT56:
9127 case FT_INT64:
9128 case FT_BOOLEAN:
9129 case FT_PROTOCOL:
9130 break;
9133 * This is allowed to have a value of type
9134 * enum ft_framenum_type to indicate what relationship
9135 * the frame in question has to the frame in which
9136 * the field is put.
9138 case FT_FRAMENUM:
9139 break;
9142 * These types are allowed to support only unit strings.
9144 case FT_FLOAT:
9145 case FT_DOUBLE:
9146 if (!(hfinfo->display & BASE_UNIT_STRING)) {
9147 REPORT_DISSECTOR_BUG("Field '%s' (%s) has a non-unit-strings 'strings' value but is of type %s"
9148 " (which is only allowed to have unit strings)",
9149 hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type));
9151 break;
9154 * This type is only allowed to support a string if it's
9155 * a protocol (for pinos).
9157 case FT_BYTES:
9158 if (!(hfinfo->display & BASE_PROTOCOL_INFO)) {
9159 REPORT_DISSECTOR_BUG("Field '%s' (%s) has a non-protocol-info 'strings' value but is of type %s"
9160 " (which is only allowed to have protocol-info strings)",
9161 hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type));
9163 break;
9165 default:
9166 REPORT_DISSECTOR_BUG("Field '%s' (%s) has a 'strings' value but is of type %s"
9167 " (which is not allowed to have strings)",
9168 hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type));
9172 /* TODO: This check may slow down startup, and output quite a few warnings.
9173 It would be good to be able to enable this (and possibly other checks?)
9174 in non-release builds. */
9175 #ifdef ENABLE_CHECK_FILTER
9176 /* Check for duplicate value_string values.
9177 There are lots that have the same value *and* string, so for now only
9178 report those that have same value but different string. */
9179 if ((hfinfo->strings != NULL) &&
9180 !(hfinfo->display & BASE_RANGE_STRING) &&
9181 !(hfinfo->display & BASE_UNIT_STRING) &&
9182 !((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) &&
9184 (hfinfo->type == FT_CHAR) ||
9185 (hfinfo->type == FT_UINT8) ||
9186 (hfinfo->type == FT_UINT16) ||
9187 (hfinfo->type == FT_UINT24) ||
9188 (hfinfo->type == FT_UINT32) ||
9189 (hfinfo->type == FT_INT8) ||
9190 (hfinfo->type == FT_INT16) ||
9191 (hfinfo->type == FT_INT24) ||
9192 (hfinfo->type == FT_INT32) )) {
9194 if (hfinfo->display & BASE_EXT_STRING) {
9195 if (hfinfo->display & BASE_VAL64_STRING) {
9196 const val64_string *start_values = VAL64_STRING_EXT_VS_P((const val64_string_ext*)hfinfo->strings);
9197 CHECK_HF_VALUE(val64_string, PRIu64, start_values);
9198 } else {
9199 const value_string *start_values = VALUE_STRING_EXT_VS_P((const value_string_ext*)hfinfo->strings);
9200 CHECK_HF_VALUE(value_string, "u", start_values);
9202 } else {
9203 const value_string *start_values = (const value_string*)hfinfo->strings;
9204 CHECK_HF_VALUE(value_string, "u", start_values);
9208 if (hfinfo->type == FT_BOOLEAN) {
9209 const true_false_string *tfs = (const true_false_string*)hfinfo->strings;
9210 if (tfs) {
9211 if (strcmp(tfs->false_string, tfs->true_string) == 0) {
9212 ws_warning("Field '%s' (%s) has identical true and false strings (\"%s\", \"%s\")",
9213 hfinfo->name, hfinfo->abbrev,
9214 tfs->false_string, tfs->true_string);
9219 if (hfinfo->display & BASE_RANGE_STRING) {
9220 const range_string *rs = (const range_string*)(hfinfo->strings);
9221 if (rs) {
9222 const range_string *this_it = rs;
9224 do {
9225 if (this_it->value_max < this_it->value_min) {
9226 ws_warning("value_range_string error: %s (%s) entry for \"%s\" - max(%"PRIu64" 0x%"PRIx64") is less than min(%"PRIu64" 0x%"PRIx64")",
9227 hfinfo->name, hfinfo->abbrev,
9228 this_it->strptr,
9229 this_it->value_max, this_it->value_max,
9230 this_it->value_min, this_it->value_min);
9231 ++this_it;
9232 continue;
9235 for (const range_string *prev_it=rs; prev_it < this_it; ++prev_it) {
9236 /* Not OK if this one is completely hidden by an earlier one! */
9237 if ((prev_it->value_min <= this_it->value_min) && (prev_it->value_max >= this_it->value_max)) {
9238 ws_warning("value_range_string error: %s (%s) hidden by earlier entry "
9239 "(prev=\"%s\": %"PRIu64" 0x%"PRIx64" -> %"PRIu64" 0x%"PRIx64") (this=\"%s\": %"PRIu64" 0x%"PRIx64" -> %"PRIu64" 0x%"PRIx64")",
9240 hfinfo->name, hfinfo->abbrev,
9241 prev_it->strptr, prev_it->value_min, prev_it->value_min,
9242 prev_it->value_max, prev_it->value_max,
9243 this_it->strptr, this_it->value_min, this_it->value_min,
9244 this_it->value_max, this_it->value_max);
9247 ++this_it;
9248 } while (this_it->strptr);
9251 #endif
9253 switch (hfinfo->type) {
9255 case FT_CHAR:
9256 /* Require the char type to have BASE_HEX, BASE_OCT,
9257 * BASE_CUSTOM, or BASE_NONE as its base.
9259 * If the display value is BASE_NONE and there is a
9260 * strings conversion then the dissector writer is
9261 * telling us that the field's numerical value is
9262 * meaningless; we'll avoid showing the value to the
9263 * user.
9265 switch (FIELD_DISPLAY(hfinfo->display)) {
9266 case BASE_HEX:
9267 case BASE_OCT:
9268 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
9269 break;
9270 case BASE_NONE:
9271 if (hfinfo->strings == NULL)
9272 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an integral value (%s)"
9273 " but is being displayed as BASE_NONE but"
9274 " without a strings conversion",
9275 hfinfo->name, hfinfo->abbrev,
9276 ftype_name(hfinfo->type));
9277 break;
9278 default:
9279 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
9280 REPORT_DISSECTOR_BUG("Field '%s' (%s) is a character value (%s)"
9281 " but is being displayed as %s",
9282 hfinfo->name, hfinfo->abbrev,
9283 ftype_name(hfinfo->type), tmp_str);
9284 //wmem_free(NULL, tmp_str);
9286 if (hfinfo->display & BASE_UNIT_STRING) {
9287 REPORT_DISSECTOR_BUG("Field '%s' (%s) is a character value (%s) but has a unit string",
9288 hfinfo->name, hfinfo->abbrev,
9289 ftype_name(hfinfo->type));
9291 break;
9292 case FT_INT8:
9293 case FT_INT16:
9294 case FT_INT24:
9295 case FT_INT32:
9296 case FT_INT40:
9297 case FT_INT48:
9298 case FT_INT56:
9299 case FT_INT64:
9300 /* Hexadecimal and octal are, in printf() and everywhere
9301 * else, unsigned so don't allow dissectors to register a
9302 * signed field to be displayed unsigned. (Else how would
9303 * we display negative values?)
9305 switch (FIELD_DISPLAY(hfinfo->display)) {
9306 case BASE_HEX:
9307 case BASE_OCT:
9308 case BASE_DEC_HEX:
9309 case BASE_HEX_DEC:
9310 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
9311 REPORT_DISSECTOR_BUG("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)",
9312 hfinfo->name, hfinfo->abbrev,
9313 ftype_name(hfinfo->type), tmp_str);
9314 //wmem_free(NULL, tmp_str);
9316 /* FALL THROUGH */
9317 case FT_UINT8:
9318 case FT_UINT16:
9319 case FT_UINT24:
9320 case FT_UINT32:
9321 case FT_UINT40:
9322 case FT_UINT48:
9323 case FT_UINT56:
9324 case FT_UINT64:
9325 if (IS_BASE_PORT(hfinfo->display)) {
9326 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
9327 if (hfinfo->type != FT_UINT16) {
9328 REPORT_DISSECTOR_BUG("Field '%s' (%s) has 'display' value %s but it can only be used with FT_UINT16, not %s",
9329 hfinfo->name, hfinfo->abbrev,
9330 tmp_str, ftype_name(hfinfo->type));
9332 if (hfinfo->strings != NULL) {
9333 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s (%s) but has a strings value",
9334 hfinfo->name, hfinfo->abbrev,
9335 ftype_name(hfinfo->type), tmp_str);
9337 if (hfinfo->bitmask != 0) {
9338 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s (%s) but has a bitmask",
9339 hfinfo->name, hfinfo->abbrev,
9340 ftype_name(hfinfo->type), tmp_str);
9342 wmem_free(NULL, tmp_str);
9343 break;
9346 if (hfinfo->display == BASE_OUI) {
9347 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
9348 if (hfinfo->type != FT_UINT24) {
9349 REPORT_DISSECTOR_BUG("Field '%s' (%s) has 'display' value %s but it can only be used with FT_UINT24, not %s",
9350 hfinfo->name, hfinfo->abbrev,
9351 tmp_str, ftype_name(hfinfo->type));
9353 if (hfinfo->strings != NULL) {
9354 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s (%s) but has a strings value",
9355 hfinfo->name, hfinfo->abbrev,
9356 ftype_name(hfinfo->type), tmp_str);
9358 if (hfinfo->bitmask != 0) {
9359 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s (%s) but has a bitmask",
9360 hfinfo->name, hfinfo->abbrev,
9361 ftype_name(hfinfo->type), tmp_str);
9363 wmem_free(NULL, tmp_str);
9364 break;
9367 /* Require integral types (other than frame number,
9368 * which is always displayed in decimal) to have a
9369 * number base.
9371 * If the display value is BASE_NONE and there is a
9372 * strings conversion then the dissector writer is
9373 * telling us that the field's numerical value is
9374 * meaningless; we'll avoid showing the value to the
9375 * user.
9377 switch (FIELD_DISPLAY(hfinfo->display)) {
9378 case BASE_DEC:
9379 case BASE_HEX:
9380 case BASE_OCT:
9381 case BASE_DEC_HEX:
9382 case BASE_HEX_DEC:
9383 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
9384 break;
9385 case BASE_NONE:
9386 if (hfinfo->strings == NULL) {
9387 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an integral value (%s)"
9388 " but is being displayed as BASE_NONE but"
9389 " without a strings conversion",
9390 hfinfo->name, hfinfo->abbrev,
9391 ftype_name(hfinfo->type));
9393 if (hfinfo->display & BASE_SPECIAL_VALS) {
9394 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an integral value (%s)"
9395 " that is being displayed as BASE_NONE but"
9396 " with BASE_SPECIAL_VALS",
9397 hfinfo->name, hfinfo->abbrev,
9398 ftype_name(hfinfo->type));
9400 break;
9402 default:
9403 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
9404 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an integral value (%s)"
9405 " but is being displayed as %s",
9406 hfinfo->name, hfinfo->abbrev,
9407 ftype_name(hfinfo->type), tmp_str);
9408 //wmem_free(NULL, tmp_str);
9410 break;
9411 case FT_BYTES:
9412 case FT_UINT_BYTES:
9413 /* Require bytes to have a "display type" that could
9414 * add a character between displayed bytes.
9416 switch (FIELD_DISPLAY(hfinfo->display)) {
9417 case BASE_NONE:
9418 case SEP_DOT:
9419 case SEP_DASH:
9420 case SEP_COLON:
9421 case SEP_SPACE:
9422 break;
9423 default:
9424 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
9425 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an byte array but is being displayed as %s instead of BASE_NONE, SEP_DOT, SEP_DASH, SEP_COLON, or SEP_SPACE",
9426 hfinfo->name, hfinfo->abbrev, tmp_str);
9427 //wmem_free(NULL, tmp_str);
9429 if (hfinfo->bitmask != 0)
9430 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9431 hfinfo->name, hfinfo->abbrev,
9432 ftype_name(hfinfo->type));
9433 //allowed to support string if its a protocol (for pinos)
9434 if ((hfinfo->strings != NULL) && (!(hfinfo->display & BASE_PROTOCOL_INFO)))
9435 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a strings value",
9436 hfinfo->name, hfinfo->abbrev,
9437 ftype_name(hfinfo->type));
9438 break;
9440 case FT_PROTOCOL:
9441 case FT_FRAMENUM:
9442 if (hfinfo->display != BASE_NONE) {
9443 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
9444 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE",
9445 hfinfo->name, hfinfo->abbrev,
9446 ftype_name(hfinfo->type), tmp_str);
9447 //wmem_free(NULL, tmp_str);
9449 if (hfinfo->bitmask != 0)
9450 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9451 hfinfo->name, hfinfo->abbrev,
9452 ftype_name(hfinfo->type));
9453 break;
9455 case FT_BOOLEAN:
9456 break;
9458 case FT_ABSOLUTE_TIME:
9459 if (!FIELD_DISPLAY_IS_ABSOLUTE_TIME(hfinfo->display)) {
9460 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
9461 REPORT_DISSECTOR_BUG("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time",
9462 hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type), tmp_str);
9463 //wmem_free(NULL, tmp_str);
9465 if (hfinfo->bitmask != 0)
9466 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9467 hfinfo->name, hfinfo->abbrev,
9468 ftype_name(hfinfo->type));
9469 break;
9471 case FT_STRING:
9472 case FT_STRINGZ:
9473 case FT_UINT_STRING:
9474 case FT_STRINGZPAD:
9475 case FT_STRINGZTRUNC:
9476 switch (FIELD_DISPLAY(hfinfo->display)) {
9477 case BASE_NONE:
9478 case BASE_STR_WSP:
9479 break;
9481 default:
9482 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
9483 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an string value (%s)"
9484 " but is being displayed as %s",
9485 hfinfo->name, hfinfo->abbrev,
9486 ftype_name(hfinfo->type), tmp_str);
9487 //wmem_free(NULL, tmp_str);
9490 if (hfinfo->bitmask != 0)
9491 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9492 hfinfo->name, hfinfo->abbrev,
9493 ftype_name(hfinfo->type));
9494 if (hfinfo->strings != NULL)
9495 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a strings value",
9496 hfinfo->name, hfinfo->abbrev,
9497 ftype_name(hfinfo->type));
9498 break;
9500 case FT_IPv4:
9501 switch (hfinfo->display) {
9502 case BASE_NONE:
9503 case BASE_NETMASK:
9504 break;
9506 default:
9507 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
9508 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an IPv4 value (%s)"
9509 " but is being displayed as %s",
9510 hfinfo->name, hfinfo->abbrev,
9511 ftype_name(hfinfo->type), tmp_str);
9512 //wmem_free(NULL, tmp_str);
9513 break;
9515 break;
9516 case FT_FLOAT:
9517 case FT_DOUBLE:
9518 switch (FIELD_DISPLAY(hfinfo->display)) {
9519 case BASE_NONE:
9520 case BASE_DEC:
9521 case BASE_HEX:
9522 case BASE_EXP:
9523 case BASE_CUSTOM:
9524 break;
9525 default:
9526 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
9527 REPORT_DISSECTOR_BUG("Field '%s' (%s) is a float value (%s)"
9528 " but is being displayed as %s",
9529 hfinfo->name, hfinfo->abbrev,
9530 ftype_name(hfinfo->type), tmp_str);
9531 //wmem_free(NULL, tmp_str);
9533 if (hfinfo->bitmask != 0)
9534 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9535 hfinfo->name, hfinfo->abbrev,
9536 ftype_name(hfinfo->type));
9537 if (FIELD_DISPLAY(hfinfo->display) != BASE_CUSTOM && (hfinfo->strings != NULL) && !(hfinfo->display & BASE_UNIT_STRING))
9538 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a strings value",
9539 hfinfo->name, hfinfo->abbrev,
9540 ftype_name(hfinfo->type));
9541 break;
9542 default:
9543 if (hfinfo->display != BASE_NONE) {
9544 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
9545 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE",
9546 hfinfo->name, hfinfo->abbrev,
9547 ftype_name(hfinfo->type),
9548 tmp_str);
9549 //wmem_free(NULL, tmp_str);
9551 if (hfinfo->bitmask != 0)
9552 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9553 hfinfo->name, hfinfo->abbrev,
9554 ftype_name(hfinfo->type));
9555 if (hfinfo->strings != NULL)
9556 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a strings value",
9557 hfinfo->name, hfinfo->abbrev,
9558 ftype_name(hfinfo->type));
9559 break;
9563 #ifdef ENABLE_CHECK_FILTER
9564 static enum ftenum
9565 _ftype_common(enum ftenum type)
9567 switch (type) {
9568 case FT_INT8:
9569 case FT_INT16:
9570 case FT_INT24:
9571 case FT_INT32:
9572 return FT_INT32;
9574 case FT_CHAR:
9575 case FT_UINT8:
9576 case FT_UINT16:
9577 case FT_UINT24:
9578 case FT_UINT32:
9579 case FT_IPXNET:
9580 case FT_FRAMENUM:
9581 return FT_UINT32;
9583 case FT_UINT64:
9584 case FT_EUI64:
9585 return FT_UINT64;
9587 case FT_STRING:
9588 case FT_STRINGZ:
9589 case FT_UINT_STRING:
9590 return FT_STRING;
9592 case FT_FLOAT:
9593 case FT_DOUBLE:
9594 return FT_DOUBLE;
9596 case FT_BYTES:
9597 case FT_UINT_BYTES:
9598 case FT_ETHER:
9599 case FT_OID:
9600 return FT_BYTES;
9602 case FT_ABSOLUTE_TIME:
9603 case FT_RELATIVE_TIME:
9604 return FT_ABSOLUTE_TIME;
9606 default:
9607 return type;
9610 #endif
9612 static void
9613 register_type_length_mismatch(void)
9615 static ei_register_info ei[] = {
9616 { &ei_type_length_mismatch_error, { "_ws.type_length.mismatch", PI_MALFORMED, PI_ERROR, "Trying to fetch X with length Y", EXPFILL }},
9617 { &ei_type_length_mismatch_warn, { "_ws.type_length.mismatch", PI_MALFORMED, PI_WARN, "Trying to fetch X with length Y", EXPFILL }},
9620 expert_module_t* expert_type_length_mismatch;
9622 proto_type_length_mismatch = proto_register_protocol("Type Length Mismatch", "Type length mismatch", "_ws.type_length");
9624 expert_type_length_mismatch = expert_register_protocol(proto_type_length_mismatch);
9625 expert_register_field_array(expert_type_length_mismatch, ei, array_length(ei));
9627 /* "Type Length Mismatch" isn't really a protocol, it's an error indication;
9628 disabling them makes no sense. */
9629 proto_set_cant_toggle(proto_type_length_mismatch);
9632 static void
9633 register_byte_array_string_decodinws_error(void)
9635 static ei_register_info ei[] = {
9636 { &ei_byte_array_string_decoding_failed_error,
9637 { "_ws.byte_array_string.decoding_error.failed", PI_MALFORMED, PI_ERROR,
9638 "Failed to decode byte array from string", EXPFILL
9643 expert_module_t* expert_byte_array_string_decoding_error;
9645 proto_byte_array_string_decoding_error =
9646 proto_register_protocol("Byte Array-String Decoding Error",
9647 "Byte Array-string decoding error",
9648 "_ws.byte_array_string.decoding_error");
9650 expert_byte_array_string_decoding_error =
9651 expert_register_protocol(proto_byte_array_string_decoding_error);
9652 expert_register_field_array(expert_byte_array_string_decoding_error, ei, array_length(ei));
9654 /* "Byte Array-String Decoding Error" isn't really a protocol, it's an error indication;
9655 disabling them makes no sense. */
9656 proto_set_cant_toggle(proto_byte_array_string_decoding_error);
9659 static void
9660 register_date_time_string_decodinws_error(void)
9662 static ei_register_info ei[] = {
9663 { &ei_date_time_string_decoding_failed_error,
9664 { "_ws.date_time_string.decoding_error.failed", PI_MALFORMED, PI_ERROR,
9665 "Failed to decode date and time from string", EXPFILL
9670 expert_module_t* expert_date_time_string_decoding_error;
9672 proto_date_time_string_decoding_error =
9673 proto_register_protocol("Date and Time-String Decoding Error",
9674 "Date and Time-string decoding error",
9675 "_ws.date_time_string.decoding_error");
9677 expert_date_time_string_decoding_error =
9678 expert_register_protocol(proto_date_time_string_decoding_error);
9679 expert_register_field_array(expert_date_time_string_decoding_error, ei, array_length(ei));
9681 /* "Date and Time-String Decoding Error" isn't really a protocol, it's an error indication;
9682 disabling them makes no sense. */
9683 proto_set_cant_toggle(proto_date_time_string_decoding_error);
9686 static void
9687 register_string_errors(void)
9689 static ei_register_info ei[] = {
9690 { &ei_string_trailing_characters,
9691 { "_ws.string.trailing_stray_characters", PI_UNDECODED, PI_WARN, "Trailing stray characters", EXPFILL }
9695 expert_module_t* expert_string_errors;
9697 proto_string_errors = proto_register_protocol("String Errors", "String errors", "_ws.string");
9699 expert_string_errors = expert_register_protocol(proto_string_errors);
9700 expert_register_field_array(expert_string_errors, ei, array_length(ei));
9702 /* "String Errors" isn't really a protocol, it's an error indication;
9703 disabling them makes no sense. */
9704 proto_set_cant_toggle(proto_string_errors);
9707 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM (300000+PRE_ALLOC_EXPERT_FIELDS_MEM)
9708 static int
9709 proto_register_field_init(header_field_info *hfinfo, const int parent)
9712 tmp_fld_check_assert(hfinfo);
9714 hfinfo->parent = parent;
9715 hfinfo->same_name_next = NULL;
9716 hfinfo->same_name_prev_id = -1;
9718 /* if we always add and never delete, then id == len - 1 is correct */
9719 if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
9720 if (!gpa_hfinfo.hfi) {
9721 gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
9722 gpa_hfinfo.hfi = (header_field_info **)g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
9723 /* The entry with index 0 is not used. */
9724 gpa_hfinfo.hfi[0] = NULL;
9725 gpa_hfinfo.len = 1;
9726 } else {
9727 gpa_hfinfo.allocated_len += 1000;
9728 gpa_hfinfo.hfi = (header_field_info **)g_realloc(gpa_hfinfo.hfi,
9729 sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
9730 /*ws_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
9733 gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
9734 gpa_hfinfo.len++;
9735 hfinfo->id = gpa_hfinfo.len - 1;
9737 /* if we have real names, enter this field in the name tree */
9738 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
9740 header_field_info *same_name_next_hfinfo;
9741 unsigned char c;
9743 /* Check that the filter name (abbreviation) is legal;
9744 * it must contain only alphanumerics, '-', "_", and ".". */
9745 c = proto_check_field_name(hfinfo->abbrev);
9746 if (c) {
9747 if (c == '.') {
9748 REPORT_DISSECTOR_BUG("Invalid leading, duplicated or trailing '.' found in filter name '%s'", hfinfo->abbrev);
9749 } else if (g_ascii_isprint(c)) {
9750 REPORT_DISSECTOR_BUG("Invalid character '%c' in filter name '%s'", c, hfinfo->abbrev);
9751 } else {
9752 REPORT_DISSECTOR_BUG("Invalid byte \\%03o in filter name '%s'", c, hfinfo->abbrev);
9756 /* We allow multiple hfinfo's to be registered under the same
9757 * abbreviation. This was done for X.25, as, depending
9758 * on whether it's modulo-8 or modulo-128 operation,
9759 * some bitfield fields may be in different bits of
9760 * a byte, and we want to be able to refer to that field
9761 * with one name regardless of whether the packets
9762 * are modulo-8 or modulo-128 packets. */
9764 same_name_hfinfo = NULL;
9766 g_hash_table_insert(gpa_name_map, (void *) (hfinfo->abbrev), hfinfo);
9767 /* GLIB 2.x - if it is already present
9768 * the previous hfinfo with the same name is saved
9769 * to same_name_hfinfo by value destroy callback */
9770 if (same_name_hfinfo) {
9771 /* There's already a field with this name.
9772 * Put the current field *before* that field
9773 * in the list of fields with this name, Thus,
9774 * we end up with an effectively
9775 * doubly-linked-list of same-named hfinfo's,
9776 * with the head of the list (stored in the
9777 * hash) being the last seen hfinfo.
9779 same_name_next_hfinfo =
9780 same_name_hfinfo->same_name_next;
9782 hfinfo->same_name_next = same_name_next_hfinfo;
9783 if (same_name_next_hfinfo)
9784 same_name_next_hfinfo->same_name_prev_id = hfinfo->id;
9786 same_name_hfinfo->same_name_next = hfinfo;
9787 hfinfo->same_name_prev_id = same_name_hfinfo->id;
9788 #ifdef ENABLE_CHECK_FILTER
9789 while (same_name_hfinfo) {
9790 if (_ftype_common(hfinfo->type) != _ftype_common(same_name_hfinfo->type))
9791 ws_warning("'%s' exists multiple times with incompatible types: %s and %s", hfinfo->abbrev, ftype_name(hfinfo->type), ftype_name(same_name_hfinfo->type));
9792 same_name_hfinfo = same_name_hfinfo->same_name_next;
9794 #endif
9798 return hfinfo->id;
9801 void
9802 proto_register_subtree_array(int * const *indices, const int num_indices)
9804 int i;
9805 int *const *ptr = indices;
9808 * If we've already allocated the array of tree types, expand
9809 * it; this lets plugins such as mate add tree types after
9810 * the initial startup. (If we haven't already allocated it,
9811 * we don't allocate it; on the first pass, we just assign
9812 * ett values and keep track of how many we've assigned, and
9813 * when we're finished registering all dissectors we allocate
9814 * the array, so that we do only one allocation rather than
9815 * wasting CPU time and memory by growing the array for each
9816 * dissector that registers ett values.)
9818 if (tree_is_expanded != NULL) {
9819 tree_is_expanded = (uint32_t *)g_realloc(tree_is_expanded, (1+((num_tree_types + num_indices)/32)) * sizeof(uint32_t));
9821 /* set new items to 0 */
9822 /* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of uint32_t to 0) */
9823 for (i = num_tree_types; i < num_tree_types + num_indices; i++)
9824 tree_is_expanded[i >> 5] &= ~(1U << (i & 31));
9828 * Assign "num_indices" subtree numbers starting at "num_tree_types",
9829 * returning the indices through the pointers in the array whose
9830 * first element is pointed to by "indices", and update
9831 * "num_tree_types" appropriately.
9833 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
9834 if (**ptr != -1 && **ptr != 0) {
9835 REPORT_DISSECTOR_BUG("register_subtree_array: subtree item type (ett_...) not -1 or 0 !"
9836 " This is a development error:"
9837 " Either the subtree item type has already been assigned or"
9838 " was not initialized to -1 or 0.");
9840 **ptr = num_tree_types;
9844 static void
9845 mark_truncated(char *label_str, size_t name_pos, const size_t size, size_t *value_pos)
9847 static const char trunc_str[] = " [" UTF8_HORIZONTAL_ELLIPSIS "]";
9848 const size_t trunc_len = sizeof(trunc_str)-1;
9849 char *last_char;
9851 /* ..... field_name: dataaaaaaaaaaaaa
9853 * ^^^^^ name_pos
9855 * ..... field_name […]: dataaaaaaaaaaaaa
9857 * name_pos==0 means that we have only data or only a field_name
9860 if (name_pos < size - trunc_len) {
9861 memmove(label_str + name_pos + trunc_len, label_str + name_pos, size - name_pos - trunc_len);
9862 memcpy(label_str + name_pos, trunc_str, trunc_len);
9864 /* in general, label_str is UTF-8
9865 we can truncate it only at the beginning of a new character
9866 we go backwards from the byte right after our buffer and
9867 find the next starting byte of a UTF-8 character, this is
9868 where we cut
9869 there's no need to use g_utf8_find_prev_char(), the search
9870 will always succeed since we copied trunc_str into the
9871 buffer */
9872 /* g_utf8_prev_char does not deference the memory address
9873 * passed in (until after decrementing it, so it is perfectly
9874 * legal to pass in a pointer one past the last element.
9876 last_char = g_utf8_prev_char(label_str + size);
9877 *last_char = '\0';
9879 if (value_pos && *value_pos > 0) {
9880 if (name_pos == 0) {
9881 *value_pos += trunc_len;
9882 } else {
9883 /* Move one back to include trunc_str in the value. */
9884 *value_pos -= 1;
9887 } else if (name_pos < size)
9888 (void) g_strlcpy(label_str + name_pos, trunc_str, size - name_pos);
9891 static void
9892 label_mark_truncated(char *label_str, size_t name_pos, size_t *value_pos)
9894 mark_truncated(label_str, name_pos, ITEM_LABEL_LENGTH, value_pos);
9897 static size_t
9898 label_fill(char *label_str, size_t pos, const header_field_info *hfinfo, const char *text, size_t *value_pos)
9900 size_t name_pos;
9902 /* "%s: %s", hfinfo->name, text */
9903 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
9904 if (!(hfinfo->display & BASE_NO_DISPLAY_VALUE)) {
9905 pos = label_concat(label_str, pos, ": ");
9906 if (value_pos) {
9907 *value_pos = pos;
9909 pos = ws_label_strcpy(label_str, ITEM_LABEL_LENGTH, pos, text ? text : "(null)", label_strcat_flags(hfinfo));
9912 if (pos >= ITEM_LABEL_LENGTH) {
9913 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
9914 label_mark_truncated(label_str, name_pos, value_pos);
9917 return pos;
9920 static size_t
9921 label_fill_descr(char *label_str, size_t pos, const header_field_info *hfinfo, const char *text, const char *descr, size_t *value_pos)
9923 size_t name_pos;
9925 /* "%s: %s (%s)", hfinfo->name, text, descr */
9926 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
9927 if (!(hfinfo->display & BASE_NO_DISPLAY_VALUE)) {
9928 pos = label_concat(label_str, pos, ": ");
9929 if (value_pos) {
9930 *value_pos = pos;
9932 if (hfinfo->display & BASE_UNIT_STRING) {
9933 pos = label_concat(label_str, pos, descr ? descr : "(null)");
9934 pos = label_concat(label_str, pos, text ? text : "(null)");
9935 } else {
9936 pos = label_concat(label_str, pos, text ? text : "(null)");
9937 pos = label_concat(label_str, pos, " (");
9938 pos = label_concat(label_str, pos, descr ? descr : "(null)");
9939 pos = label_concat(label_str, pos, ")");
9943 if (pos >= ITEM_LABEL_LENGTH) {
9944 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
9945 label_mark_truncated(label_str, name_pos, value_pos);
9948 return pos;
9951 void
9952 proto_item_fill_label(const field_info *fi, char *label_str, size_t *value_pos)
9954 const header_field_info *hfinfo;
9955 const char *str;
9956 const uint8_t *bytes;
9957 uint32_t integer;
9958 uint64_t integer64;
9959 const ipv4_addr_and_mask *ipv4;
9960 const ipv6_addr_and_prefix *ipv6;
9961 const e_guid_t *guid;
9962 char *name;
9963 address addr;
9964 char *addr_str;
9965 char *tmp;
9967 if (!label_str) {
9968 ws_warning("NULL label_str passed to proto_item_fill_label.");
9969 return;
9972 label_str[0]= '\0';
9974 if (!fi) {
9975 return;
9978 hfinfo = fi->hfinfo;
9980 switch (hfinfo->type) {
9981 case FT_NONE:
9982 case FT_PROTOCOL:
9983 (void) g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
9984 if (value_pos) {
9985 *value_pos = strlen(hfinfo->name);
9987 break;
9989 case FT_BOOLEAN:
9990 fill_label_boolean(fi, label_str, value_pos);
9991 break;
9993 case FT_BYTES:
9994 case FT_UINT_BYTES:
9995 tmp = format_bytes_hfinfo(NULL, hfinfo,
9996 fvalue_get_bytes_data(fi->value),
9997 (unsigned)fvalue_length2(fi->value));
9998 label_fill(label_str, 0, hfinfo, tmp, value_pos);
9999 wmem_free(NULL, tmp);
10000 break;
10002 case FT_CHAR:
10003 if (hfinfo->bitmask) {
10004 fill_label_bitfield_char(fi, label_str, value_pos);
10005 } else {
10006 fill_label_char(fi, label_str, value_pos);
10008 break;
10010 /* Four types of integers to take care of:
10011 * Bitfield, with val_string
10012 * Bitfield, w/o val_string
10013 * Non-bitfield, with val_string
10014 * Non-bitfield, w/o val_string
10016 case FT_UINT8:
10017 case FT_UINT16:
10018 case FT_UINT24:
10019 case FT_UINT32:
10020 if (hfinfo->bitmask) {
10021 fill_label_bitfield(fi, label_str, value_pos, false);
10022 } else {
10023 fill_label_number(fi, label_str, value_pos, false);
10025 break;
10027 case FT_FRAMENUM:
10028 fill_label_number(fi, label_str, value_pos, false);
10029 break;
10031 case FT_UINT40:
10032 case FT_UINT48:
10033 case FT_UINT56:
10034 case FT_UINT64:
10035 if (hfinfo->bitmask) {
10036 fill_label_bitfield64(fi, label_str, value_pos, false);
10037 } else {
10038 fill_label_number64(fi, label_str, value_pos, false);
10040 break;
10042 case FT_INT8:
10043 case FT_INT16:
10044 case FT_INT24:
10045 case FT_INT32:
10046 if (hfinfo->bitmask) {
10047 fill_label_bitfield(fi, label_str, value_pos, true);
10048 } else {
10049 fill_label_number(fi, label_str, value_pos, true);
10051 break;
10053 case FT_INT40:
10054 case FT_INT48:
10055 case FT_INT56:
10056 case FT_INT64:
10057 if (hfinfo->bitmask) {
10058 fill_label_bitfield64(fi, label_str, value_pos, true);
10059 } else {
10060 fill_label_number64(fi, label_str, value_pos, true);
10062 break;
10064 case FT_FLOAT:
10065 case FT_DOUBLE:
10066 fill_label_float(fi, label_str, value_pos);
10067 break;
10069 case FT_ABSOLUTE_TIME:
10071 int flags = ABS_TIME_TO_STR_SHOW_ZONE;
10072 if (prefs.display_abs_time_ascii < ABS_TIME_ASCII_TREE) {
10073 flags |= ABS_TIME_TO_STR_ISO8601;
10075 tmp = abs_time_to_str_ex(NULL, fvalue_get_time(fi->value), hfinfo->display, flags);
10076 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10077 wmem_free(NULL, tmp);
10078 break;
10080 case FT_RELATIVE_TIME:
10081 tmp = rel_time_to_str(NULL, fvalue_get_time(fi->value));
10082 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10083 wmem_free(NULL, tmp);
10084 break;
10086 case FT_IPXNET:
10087 integer = fvalue_get_uinteger(fi->value);
10088 tmp = get_ipxnet_name(NULL, integer);
10089 addr_str = wmem_strdup_printf(NULL, "0x%08X", integer);
10090 label_fill_descr(label_str, 0, hfinfo, tmp, addr_str, value_pos);
10091 wmem_free(NULL, tmp);
10092 wmem_free(NULL, addr_str);
10093 break;
10095 case FT_VINES:
10096 addr.type = AT_VINES;
10097 addr.len = VINES_ADDR_LEN;
10098 addr.data = fvalue_get_bytes_data(fi->value);
10100 addr_str = (char*)address_to_str(NULL, &addr);
10101 label_fill(label_str, 0, hfinfo, addr_str, value_pos);
10102 wmem_free(NULL, addr_str);
10103 break;
10105 case FT_ETHER:
10106 bytes = fvalue_get_bytes_data(fi->value);
10108 addr.type = AT_ETHER;
10109 addr.len = 6;
10110 addr.data = bytes;
10112 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
10113 label_fill(label_str, 0, hfinfo, addr_str, value_pos);
10114 wmem_free(NULL, addr_str);
10115 break;
10117 case FT_IPv4:
10118 ipv4 = fvalue_get_ipv4(fi->value);
10119 set_address_ipv4(&addr, ipv4);
10121 if (hfinfo->display == BASE_NETMASK) {
10122 addr_str = (char*)address_to_str(NULL, &addr);
10123 } else {
10124 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
10126 label_fill(label_str, 0, hfinfo, addr_str, value_pos);
10127 wmem_free(NULL, addr_str);
10128 free_address(&addr);
10129 break;
10131 case FT_IPv6:
10132 ipv6 = fvalue_get_ipv6(fi->value);
10133 set_address_ipv6(&addr, ipv6);
10135 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
10136 label_fill(label_str, 0, hfinfo, addr_str, value_pos);
10137 wmem_free(NULL, addr_str);
10138 free_address(&addr);
10139 break;
10141 case FT_FCWWN:
10142 bytes = fvalue_get_bytes_data(fi->value);
10143 addr.type = AT_FCWWN;
10144 addr.len = FCWWN_ADDR_LEN;
10145 addr.data = bytes;
10147 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
10148 label_fill(label_str, 0, hfinfo, addr_str, value_pos);
10149 wmem_free(NULL, addr_str);
10150 break;
10152 case FT_GUID:
10153 guid = fvalue_get_guid(fi->value);
10154 tmp = guid_to_str(NULL, guid);
10155 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10156 wmem_free(NULL, tmp);
10157 break;
10159 case FT_OID:
10160 bytes = fvalue_get_bytes_data(fi->value);
10161 name = oid_resolved_from_encoded(NULL, bytes, (int)fvalue_length2(fi->value));
10162 tmp = oid_encoded2string(NULL, bytes, (unsigned)fvalue_length2(fi->value));
10163 if (name) {
10164 label_fill_descr(label_str, 0, hfinfo, tmp, name, value_pos);
10165 wmem_free(NULL, name);
10166 } else {
10167 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10169 wmem_free(NULL, tmp);
10170 break;
10172 case FT_REL_OID:
10173 bytes = fvalue_get_bytes_data(fi->value);
10174 name = rel_oid_resolved_from_encoded(NULL, bytes, (int)fvalue_length2(fi->value));
10175 tmp = rel_oid_encoded2string(NULL, bytes, (unsigned)fvalue_length2(fi->value));
10176 if (name) {
10177 label_fill_descr(label_str, 0, hfinfo, tmp, name, value_pos);
10178 wmem_free(NULL, name);
10179 } else {
10180 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10182 wmem_free(NULL, tmp);
10183 break;
10185 case FT_SYSTEM_ID:
10186 bytes = fvalue_get_bytes_data(fi->value);
10187 tmp = print_system_id(NULL, bytes, (int)fvalue_length2(fi->value));
10188 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10189 wmem_free(NULL, tmp);
10190 break;
10192 case FT_EUI64:
10193 integer64 = fvalue_get_uinteger64(fi->value);
10194 addr_str = eui64_to_str(NULL, integer64);
10195 tmp = (char*)eui64_to_display(NULL, integer64);
10196 label_fill_descr(label_str, 0, hfinfo, tmp, addr_str, value_pos);
10197 wmem_free(NULL, tmp);
10198 wmem_free(NULL, addr_str);
10199 break;
10200 case FT_STRING:
10201 case FT_STRINGZ:
10202 case FT_UINT_STRING:
10203 case FT_STRINGZPAD:
10204 case FT_STRINGZTRUNC:
10205 case FT_AX25:
10206 str = fvalue_get_string(fi->value);
10207 label_fill(label_str, 0, hfinfo, str, value_pos);
10208 break;
10210 case FT_IEEE_11073_SFLOAT:
10211 case FT_IEEE_11073_FLOAT:
10212 tmp = fvalue_to_string_repr(NULL, fi->value, FTREPR_DISPLAY, hfinfo->display);
10213 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10214 wmem_free(NULL, tmp);
10215 break;
10217 default:
10218 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_item_fill_label()",
10219 hfinfo->abbrev,
10220 hfinfo->type,
10221 ftype_name(hfinfo->type));
10222 break;
10226 static void
10227 fill_label_boolean(const field_info *fi, char *label_str, size_t *value_pos)
10229 char *p;
10230 int bitfield_byte_length = 0, bitwidth;
10231 uint64_t unshifted_value;
10232 uint64_t value;
10234 const header_field_info *hfinfo = fi->hfinfo;
10236 value = fvalue_get_uinteger64(fi->value);
10237 if (hfinfo->bitmask) {
10238 /* Figure out the bit width */
10239 bitwidth = hfinfo_container_bitwidth(hfinfo);
10241 /* Un-shift bits */
10242 unshifted_value = value;
10243 unshifted_value <<= hfinfo_bitshift(hfinfo);
10245 /* Create the bitfield first */
10246 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
10247 bitfield_byte_length = (int) (p - label_str);
10250 /* Fill in the textual info */
10251 label_fill(label_str, bitfield_byte_length, hfinfo, tfs_get_string(!!value, hfinfo->strings), value_pos);
10254 static const char *
10255 hf_try_val_to_str(uint32_t value, const header_field_info *hfinfo)
10257 if (hfinfo->display & BASE_RANGE_STRING)
10258 return try_rval_to_str(value, (const range_string *) hfinfo->strings);
10260 if (hfinfo->display & BASE_EXT_STRING) {
10261 if (hfinfo->display & BASE_VAL64_STRING)
10262 return try_val64_to_str_ext(value, (val64_string_ext *) hfinfo->strings);
10263 else
10264 return try_val_to_str_ext(value, (value_string_ext *) hfinfo->strings);
10267 if (hfinfo->display & BASE_VAL64_STRING)
10268 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
10270 if (hfinfo->display & BASE_UNIT_STRING)
10271 return unit_name_string_get_value(value, (const struct unit_name_string*) hfinfo->strings);
10273 return try_val_to_str(value, (const value_string *) hfinfo->strings);
10276 static const char *
10277 hf_try_val64_to_str(uint64_t value, const header_field_info *hfinfo)
10279 if (hfinfo->display & BASE_VAL64_STRING) {
10280 if (hfinfo->display & BASE_EXT_STRING)
10281 return try_val64_to_str_ext(value, (val64_string_ext *) hfinfo->strings);
10282 else
10283 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
10286 if (hfinfo->display & BASE_RANGE_STRING)
10287 return try_rval64_to_str(value, (const range_string *) hfinfo->strings);
10289 if (hfinfo->display & BASE_UNIT_STRING)
10290 return unit_name_string_get_value64(value, (const struct unit_name_string*) hfinfo->strings);
10292 /* If this is reached somebody registered a 64-bit field with a 32-bit
10293 * value-string, which isn't right. */
10294 REPORT_DISSECTOR_BUG("field %s is a 64-bit field with a 32-bit value_string",
10295 hfinfo->abbrev);
10297 /* This is necessary to squelch MSVC errors; is there
10298 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
10299 never returns? */
10300 return NULL;
10303 static const char *
10304 hf_try_double_val_to_str(double value, const header_field_info *hfinfo)
10306 if (hfinfo->display & BASE_UNIT_STRING)
10307 return unit_name_string_get_double(value, (const struct unit_name_string*)hfinfo->strings);
10309 REPORT_DISSECTOR_BUG("field %s (FT_DOUBLE) has no base_unit_string", hfinfo->abbrev);
10311 /* This is necessary to squelch MSVC errors; is there
10312 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
10313 never returns? */
10314 return NULL;
10317 static const char *
10318 hf_try_val_to_str_const(uint32_t value, const header_field_info *hfinfo, const char *unknown_str)
10320 const char *str = hf_try_val_to_str(value, hfinfo);
10322 return (str) ? str : unknown_str;
10325 static const char *
10326 hf_try_val64_to_str_const(uint64_t value, const header_field_info *hfinfo, const char *unknown_str)
10328 const char *str = hf_try_val64_to_str(value, hfinfo);
10330 return (str) ? str : unknown_str;
10333 /* Fills data for bitfield chars with val_strings */
10334 static void
10335 fill_label_bitfield_char(const field_info *fi, char *label_str, size_t *value_pos)
10337 char *p;
10338 int bitfield_byte_length, bitwidth;
10339 uint32_t unshifted_value;
10340 uint32_t value;
10342 char buf[32];
10343 const char *out;
10345 const header_field_info *hfinfo = fi->hfinfo;
10347 /* Figure out the bit width */
10348 bitwidth = hfinfo_container_bitwidth(hfinfo);
10350 /* Un-shift bits */
10351 value = fvalue_get_uinteger(fi->value);
10353 unshifted_value = value;
10354 if (hfinfo->bitmask) {
10355 unshifted_value <<= hfinfo_bitshift(hfinfo);
10358 /* Create the bitfield first */
10359 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
10360 bitfield_byte_length = (int) (p - label_str);
10362 /* Fill in the textual info using stored (shifted) value */
10363 if (hfinfo->display == BASE_CUSTOM) {
10364 char tmp[ITEM_LABEL_LENGTH];
10365 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
10367 DISSECTOR_ASSERT(fmtfunc);
10368 fmtfunc(tmp, value);
10369 label_fill(label_str, bitfield_byte_length, hfinfo, tmp, value_pos);
10371 else if (hfinfo->strings) {
10372 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
10374 out = hfinfo_char_vals_format(hfinfo, buf, value);
10375 if (out == NULL) /* BASE_NONE so don't put integer in descr */
10376 label_fill(label_str, bitfield_byte_length, hfinfo, val_str, value_pos);
10377 else
10378 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out, value_pos);
10380 else {
10381 out = hfinfo_char_value_format(hfinfo, buf, value);
10383 label_fill(label_str, bitfield_byte_length, hfinfo, out, value_pos);
10387 /* Fills data for bitfield ints with val_strings */
10388 static void
10389 fill_label_bitfield(const field_info *fi, char *label_str, size_t *value_pos, bool is_signed)
10391 char *p;
10392 int bitfield_byte_length, bitwidth;
10393 uint32_t value, unshifted_value;
10394 char buf[NUMBER_LABEL_LENGTH];
10395 const char *out;
10397 const header_field_info *hfinfo = fi->hfinfo;
10399 /* Figure out the bit width */
10400 if (fi->flags & FI_VARINT)
10401 bitwidth = fi->length*8;
10402 else
10403 bitwidth = hfinfo_container_bitwidth(hfinfo);
10405 /* Un-shift bits */
10406 if (is_signed)
10407 value = fvalue_get_sinteger(fi->value);
10408 else
10409 value = fvalue_get_uinteger(fi->value);
10411 unshifted_value = value;
10412 if (hfinfo->bitmask) {
10413 unshifted_value <<= hfinfo_bitshift(hfinfo);
10416 /* Create the bitfield first */
10417 if (fi->flags & FI_VARINT)
10418 p = decode_bitfield_varint_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
10419 else
10420 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
10421 bitfield_byte_length = (int) (p - label_str);
10423 /* Fill in the textual info using stored (shifted) value */
10424 if (hfinfo->display == BASE_CUSTOM) {
10425 char tmp[ITEM_LABEL_LENGTH];
10426 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
10428 DISSECTOR_ASSERT(fmtfunc);
10429 fmtfunc(tmp, value);
10430 label_fill(label_str, bitfield_byte_length, hfinfo, tmp, value_pos);
10432 else if (hfinfo->strings) {
10433 const char *val_str = hf_try_val_to_str(value, hfinfo);
10435 out = hfinfo_number_vals_format(hfinfo, buf, value);
10436 if (hfinfo->display & BASE_SPECIAL_VALS) {
10438 * Unique values only display value_string string
10439 * if there is a match. Otherwise it's just a number
10441 if (val_str) {
10442 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out, value_pos);
10443 } else {
10444 label_fill(label_str, bitfield_byte_length, hfinfo, out, value_pos);
10446 } else {
10447 if (val_str == NULL)
10448 val_str = "Unknown";
10450 if (out == NULL) /* BASE_NONE so don't put integer in descr */
10451 label_fill(label_str, bitfield_byte_length, hfinfo, val_str, value_pos);
10452 else
10453 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out, value_pos);
10456 else {
10457 out = hfinfo_number_value_format(hfinfo, buf, value);
10459 label_fill(label_str, bitfield_byte_length, hfinfo, out, value_pos);
10463 static void
10464 fill_label_bitfield64(const field_info *fi, char *label_str, size_t *value_pos, bool is_signed)
10466 char *p;
10467 int bitfield_byte_length, bitwidth;
10468 uint64_t value, unshifted_value;
10469 char buf[NUMBER_LABEL_LENGTH];
10470 const char *out;
10472 const header_field_info *hfinfo = fi->hfinfo;
10474 /* Figure out the bit width */
10475 if (fi->flags & FI_VARINT)
10476 bitwidth = fi->length*8;
10477 else
10478 bitwidth = hfinfo_container_bitwidth(hfinfo);
10480 /* Un-shift bits */
10481 if (is_signed)
10482 value = fvalue_get_sinteger64(fi->value);
10483 else
10484 value = fvalue_get_uinteger64(fi->value);
10486 unshifted_value = value;
10487 if (hfinfo->bitmask) {
10488 unshifted_value <<= hfinfo_bitshift(hfinfo);
10491 /* Create the bitfield first */
10492 if (fi->flags & FI_VARINT)
10493 p = decode_bitfield_varint_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
10494 else
10495 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
10496 bitfield_byte_length = (int) (p - label_str);
10498 /* Fill in the textual info using stored (shifted) value */
10499 if (hfinfo->display == BASE_CUSTOM) {
10500 char tmp[ITEM_LABEL_LENGTH];
10501 const custom_fmt_func_64_t fmtfunc64 = (const custom_fmt_func_64_t)hfinfo->strings;
10503 DISSECTOR_ASSERT(fmtfunc64);
10504 fmtfunc64(tmp, value);
10505 label_fill(label_str, bitfield_byte_length, hfinfo, tmp, value_pos);
10507 else if (hfinfo->strings) {
10508 const char *val_str = hf_try_val64_to_str(value, hfinfo);
10510 out = hfinfo_number_vals_format64(hfinfo, buf, value);
10511 if (hfinfo->display & BASE_SPECIAL_VALS) {
10513 * Unique values only display value_string string
10514 * if there is a match. Otherwise it's just a number
10516 if (val_str) {
10517 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out, value_pos);
10518 } else {
10519 label_fill(label_str, bitfield_byte_length, hfinfo, out, value_pos);
10521 } else {
10522 if (val_str == NULL)
10523 val_str = "Unknown";
10525 if (out == NULL) /* BASE_NONE so don't put integer in descr */
10526 label_fill(label_str, bitfield_byte_length, hfinfo, val_str, value_pos);
10527 else
10528 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out, value_pos);
10531 else {
10532 out = hfinfo_number_value_format64(hfinfo, buf, value);
10534 label_fill(label_str, bitfield_byte_length, hfinfo, out, value_pos);
10538 static void
10539 fill_label_char(const field_info *fi, char *label_str, size_t *value_pos)
10541 const header_field_info *hfinfo = fi->hfinfo;
10542 uint32_t value;
10544 char buf[32];
10545 const char *out;
10547 value = fvalue_get_uinteger(fi->value);
10549 /* Fill in the textual info */
10550 if (hfinfo->display == BASE_CUSTOM) {
10551 char tmp[ITEM_LABEL_LENGTH];
10552 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
10554 DISSECTOR_ASSERT(fmtfunc);
10555 fmtfunc(tmp, value);
10556 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10558 else if (hfinfo->strings) {
10559 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
10561 out = hfinfo_char_vals_format(hfinfo, buf, value);
10562 label_fill_descr(label_str, 0, hfinfo, val_str, out, value_pos);
10564 else {
10565 out = hfinfo_char_value_format(hfinfo, buf, value);
10567 label_fill(label_str, 0, hfinfo, out, value_pos);
10571 static void
10572 fill_label_number(const field_info *fi, char *label_str, size_t *value_pos, bool is_signed)
10574 const header_field_info *hfinfo = fi->hfinfo;
10575 uint32_t value;
10577 char buf[NUMBER_LABEL_LENGTH];
10578 const char *out;
10580 if (is_signed)
10581 value = fvalue_get_sinteger(fi->value);
10582 else
10583 value = fvalue_get_uinteger(fi->value);
10585 /* Fill in the textual info */
10586 if (hfinfo->display == BASE_CUSTOM) {
10587 char tmp[ITEM_LABEL_LENGTH];
10588 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
10590 DISSECTOR_ASSERT(fmtfunc);
10591 fmtfunc(tmp, value);
10592 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10594 else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) {
10596 * It makes no sense to have a value-string table for a
10597 * frame-number field - they're just integers giving
10598 * the ordinal frame number.
10600 const char *val_str = hf_try_val_to_str(value, hfinfo);
10602 out = hfinfo_number_vals_format(hfinfo, buf, value);
10603 if (hfinfo->display & BASE_SPECIAL_VALS) {
10605 * Unique values only display value_string string
10606 * if there is a match. Otherwise it's just a number
10608 if (val_str) {
10609 label_fill_descr(label_str, 0, hfinfo, val_str, out, value_pos);
10610 } else {
10611 label_fill(label_str, 0, hfinfo, out, value_pos);
10613 } else {
10614 if (val_str == NULL)
10615 val_str = "Unknown";
10617 if (out == NULL) /* BASE_NONE so don't put integer in descr */
10618 label_fill(label_str, 0, hfinfo, val_str, value_pos);
10619 else
10620 label_fill_descr(label_str, 0, hfinfo, val_str, out, value_pos);
10623 else if (IS_BASE_PORT(hfinfo->display)) {
10624 char tmp[ITEM_LABEL_LENGTH];
10626 port_with_resolution_to_str_buf(tmp, sizeof(tmp),
10627 display_to_port_type((field_display_e)hfinfo->display), value);
10628 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10630 else {
10631 out = hfinfo_number_value_format(hfinfo, buf, value);
10633 label_fill(label_str, 0, hfinfo, out, value_pos);
10637 static void
10638 fill_label_number64(const field_info *fi, char *label_str, size_t *value_pos, bool is_signed)
10640 const header_field_info *hfinfo = fi->hfinfo;
10641 uint64_t value;
10643 char buf[NUMBER_LABEL_LENGTH];
10644 const char *out;
10646 if (is_signed)
10647 value = fvalue_get_sinteger64(fi->value);
10648 else
10649 value = fvalue_get_uinteger64(fi->value);
10651 /* Fill in the textual info */
10652 if (hfinfo->display == BASE_CUSTOM) {
10653 char tmp[ITEM_LABEL_LENGTH];
10654 const custom_fmt_func_64_t fmtfunc64 = (const custom_fmt_func_64_t)hfinfo->strings;
10656 DISSECTOR_ASSERT(fmtfunc64);
10657 fmtfunc64(tmp, value);
10658 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10660 else if (hfinfo->strings) {
10661 const char *val_str = hf_try_val64_to_str(value, hfinfo);
10663 out = hfinfo_number_vals_format64(hfinfo, buf, value);
10664 if (hfinfo->display & BASE_SPECIAL_VALS) {
10666 * Unique values only display value_string string
10667 * if there is a match. Otherwise it's just a number
10669 if (val_str) {
10670 label_fill_descr(label_str, 0, hfinfo, val_str, out, value_pos);
10671 } else {
10672 label_fill(label_str, 0, hfinfo, out, value_pos);
10674 } else {
10675 if (val_str == NULL)
10676 val_str = "Unknown";
10678 if (out == NULL) /* BASE_NONE so don't put integer in descr */
10679 label_fill(label_str, 0, hfinfo, val_str, value_pos);
10680 else
10681 label_fill_descr(label_str, 0, hfinfo, val_str, out, value_pos);
10684 else {
10685 out = hfinfo_number_value_format64(hfinfo, buf, value);
10687 label_fill(label_str, 0, hfinfo, out, value_pos);
10691 static size_t
10692 fill_display_label_float(const field_info *fi, char *label_str)
10694 int display;
10695 int digits;
10696 int n;
10697 double value;
10699 display = FIELD_DISPLAY(fi->hfinfo->display);
10700 value = fvalue_get_floating(fi->value);
10702 if (display == BASE_CUSTOM) {
10703 const custom_fmt_func_double_t fmtfunc = (const custom_fmt_func_double_t)fi->hfinfo->strings;
10704 DISSECTOR_ASSERT(fmtfunc);
10705 fmtfunc(label_str, value);
10706 return strlen(label_str);
10709 switch (display) {
10710 case BASE_NONE:
10711 if (fi->hfinfo->type == FT_FLOAT)
10712 digits = FLT_DIG;
10713 else
10714 digits = DBL_DIG;
10716 n = snprintf(label_str, ITEM_LABEL_LENGTH, "%.*g", digits, value);
10717 break;
10718 case BASE_DEC:
10719 n = snprintf(label_str, ITEM_LABEL_LENGTH, "%f", value);
10720 break;
10721 case BASE_HEX:
10722 n = snprintf(label_str, ITEM_LABEL_LENGTH, "%a", value);
10723 break;
10724 case BASE_EXP:
10725 n = snprintf(label_str, ITEM_LABEL_LENGTH, "%e", value);
10726 break;
10727 default:
10728 ws_assert_not_reached();
10730 if (n < 0) {
10731 return 0; /* error */
10733 if ((fi->hfinfo->strings) && (fi->hfinfo->display & BASE_UNIT_STRING)) {
10734 const char *hf_str_val;
10735 hf_str_val = hf_try_double_val_to_str(value, fi->hfinfo);
10736 n += protoo_strlcpy(label_str + n, hf_str_val, ITEM_LABEL_LENGTH - n);
10738 if (n > ITEM_LABEL_LENGTH) {
10739 ws_warning("label length too small");
10740 return strlen(label_str);
10743 return n;
10746 void
10747 fill_label_float(const field_info *fi, char *label_str, size_t *value_pos)
10749 char tmp[ITEM_LABEL_LENGTH];
10751 fill_display_label_float(fi, tmp);
10752 label_fill(label_str, 0, fi->hfinfo, tmp, value_pos);
10756 hfinfo_bitshift(const header_field_info *hfinfo)
10758 return ws_ctz(hfinfo->bitmask);
10762 static int
10763 hfinfo_bitoffset(const header_field_info *hfinfo)
10765 if (!hfinfo->bitmask) {
10766 return 0;
10769 /* ilog2 = first set bit, counting 0 as the last bit; we want 0
10770 * as the first bit */
10771 return hfinfo_container_bitwidth(hfinfo) - 1 - ws_ilog2(hfinfo->bitmask);
10774 static int
10775 hfinfo_mask_bitwidth(const header_field_info *hfinfo)
10777 if (!hfinfo->bitmask) {
10778 return 0;
10781 /* ilog2 = first set bit, ctz = last set bit */
10782 return ws_ilog2(hfinfo->bitmask) - ws_ctz(hfinfo->bitmask) + 1;
10785 static int
10786 hfinfo_type_bitwidth(enum ftenum type)
10788 int bitwidth = 0;
10790 switch (type) {
10791 case FT_CHAR:
10792 case FT_UINT8:
10793 case FT_INT8:
10794 bitwidth = 8;
10795 break;
10796 case FT_UINT16:
10797 case FT_INT16:
10798 bitwidth = 16;
10799 break;
10800 case FT_UINT24:
10801 case FT_INT24:
10802 bitwidth = 24;
10803 break;
10804 case FT_UINT32:
10805 case FT_INT32:
10806 bitwidth = 32;
10807 break;
10808 case FT_UINT40:
10809 case FT_INT40:
10810 bitwidth = 40;
10811 break;
10812 case FT_UINT48:
10813 case FT_INT48:
10814 bitwidth = 48;
10815 break;
10816 case FT_UINT56:
10817 case FT_INT56:
10818 bitwidth = 56;
10819 break;
10820 case FT_UINT64:
10821 case FT_INT64:
10822 bitwidth = 64;
10823 break;
10824 default:
10825 DISSECTOR_ASSERT_NOT_REACHED();
10828 return bitwidth;
10832 static int
10833 hfinfo_container_bitwidth(const header_field_info *hfinfo)
10835 if (!hfinfo->bitmask) {
10836 return 0;
10839 if (hfinfo->type == FT_BOOLEAN) {
10840 return hfinfo->display; /* hacky? :) */
10843 return hfinfo_type_bitwidth(hfinfo->type);
10846 static int
10847 hfinfo_hex_digits(const header_field_info *hfinfo)
10849 int bitwidth;
10851 /* If we have a bitmask, hfinfo->type is the width of the container, so not
10852 * appropriate to determine the number of hex digits for the field.
10853 * So instead, we compute it from the bitmask.
10855 if (hfinfo->bitmask != 0) {
10856 bitwidth = hfinfo_mask_bitwidth(hfinfo);
10857 } else {
10858 bitwidth = hfinfo_type_bitwidth(hfinfo->type);
10861 /* Divide by 4, rounding up, to get number of hex digits. */
10862 return (bitwidth + 3) / 4;
10865 const char *
10866 hfinfo_char_value_format_display(int display, char buf[7], uint32_t value)
10868 char *ptr = &buf[6];
10869 static const char hex_digits[16] =
10870 { '0', '1', '2', '3', '4', '5', '6', '7',
10871 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
10873 *ptr = '\0';
10874 *(--ptr) = '\'';
10875 /* Properly format value */
10876 if (g_ascii_isprint(value)) {
10878 * Printable, so just show the character, and, if it needs
10879 * to be escaped, escape it.
10881 *(--ptr) = value;
10882 if (value == '\\' || value == '\'')
10883 *(--ptr) = '\\';
10884 } else {
10886 * Non-printable; show it as an escape sequence.
10888 switch (value) {
10890 case '\0':
10892 * Show a NUL with only one digit.
10894 *(--ptr) = '0';
10895 break;
10897 case '\a':
10898 *(--ptr) = 'a';
10899 break;
10901 case '\b':
10902 *(--ptr) = 'b';
10903 break;
10905 case '\f':
10906 *(--ptr) = 'f';
10907 break;
10909 case '\n':
10910 *(--ptr) = 'n';
10911 break;
10913 case '\r':
10914 *(--ptr) = 'r';
10915 break;
10917 case '\t':
10918 *(--ptr) = 't';
10919 break;
10921 case '\v':
10922 *(--ptr) = 'v';
10923 break;
10925 default:
10926 switch (FIELD_DISPLAY(display)) {
10928 case BASE_OCT:
10929 *(--ptr) = (value & 0x7) + '0';
10930 value >>= 3;
10931 *(--ptr) = (value & 0x7) + '0';
10932 value >>= 3;
10933 *(--ptr) = (value & 0x7) + '0';
10934 break;
10936 case BASE_HEX:
10937 *(--ptr) = hex_digits[value & 0x0F];
10938 value >>= 4;
10939 *(--ptr) = hex_digits[value & 0x0F];
10940 *(--ptr) = 'x';
10941 break;
10943 default:
10944 REPORT_DISSECTOR_BUG("Invalid base: %d", FIELD_DISPLAY(display));
10947 *(--ptr) = '\\';
10949 *(--ptr) = '\'';
10950 return ptr;
10953 static const char *
10954 hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[NUMBER_LABEL_LENGTH], uint32_t value)
10956 char *ptr = &buf[NUMBER_LABEL_LENGTH-1];
10957 bool isint = FT_IS_INT(hfinfo->type);
10959 *ptr = '\0';
10960 /* Properly format value */
10961 switch (FIELD_DISPLAY(display)) {
10962 case BASE_DEC:
10963 return isint ? int_to_str_back(ptr, (int32_t) value) : uint_to_str_back(ptr, value);
10965 case BASE_DEC_HEX:
10966 *(--ptr) = ')';
10967 ptr = hex_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
10968 *(--ptr) = '(';
10969 *(--ptr) = ' ';
10970 ptr = isint ? int_to_str_back(ptr, (int32_t) value) : uint_to_str_back(ptr, value);
10971 return ptr;
10973 case BASE_OCT:
10974 return oct_to_str_back(ptr, value);
10976 case BASE_HEX:
10977 return hex_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
10979 case BASE_HEX_DEC:
10980 *(--ptr) = ')';
10981 ptr = isint ? int_to_str_back(ptr, (int32_t) value) : uint_to_str_back(ptr, value);
10982 *(--ptr) = '(';
10983 *(--ptr) = ' ';
10984 ptr = hex_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
10985 return ptr;
10987 case BASE_PT_UDP:
10988 case BASE_PT_TCP:
10989 case BASE_PT_DCCP:
10990 case BASE_PT_SCTP:
10991 port_with_resolution_to_str_buf(buf, NUMBER_LABEL_LENGTH,
10992 display_to_port_type((field_display_e)display), value);
10993 return buf;
10994 case BASE_OUI:
10996 uint8_t p_oui[3];
10997 const char *manuf_name;
10999 p_oui[0] = value >> 16 & 0xFF;
11000 p_oui[1] = value >> 8 & 0xFF;
11001 p_oui[2] = value & 0xFF;
11003 /* Attempt an OUI lookup. */
11004 manuf_name = uint_get_manuf_name_if_known(value);
11005 if (manuf_name == NULL) {
11006 /* Could not find an OUI. */
11007 snprintf(buf, NUMBER_LABEL_LENGTH, "%02x:%02x:%02x", p_oui[0], p_oui[1], p_oui[2]);
11009 else {
11010 /* Found an address string. */
11011 snprintf(buf, NUMBER_LABEL_LENGTH, "%02x:%02x:%02x (%s)", p_oui[0], p_oui[1], p_oui[2], manuf_name);
11013 return buf;
11016 default:
11017 REPORT_DISSECTOR_BUG("Invalid base: %d", FIELD_DISPLAY(display));
11019 return ptr;
11022 static const char *
11023 hfinfo_number_value_format_display64(const header_field_info *hfinfo, int display, char buf[NUMBER_LABEL_LENGTH], uint64_t value)
11025 char *ptr = &buf[NUMBER_LABEL_LENGTH-1];
11026 bool isint = FT_IS_INT(hfinfo->type);
11028 *ptr = '\0';
11029 /* Properly format value */
11030 switch (FIELD_DISPLAY(display)) {
11031 case BASE_DEC:
11032 return isint ? int64_to_str_back(ptr, (int64_t) value) : uint64_to_str_back(ptr, value);
11034 case BASE_DEC_HEX:
11035 *(--ptr) = ')';
11036 ptr = hex64_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
11037 *(--ptr) = '(';
11038 *(--ptr) = ' ';
11039 ptr = isint ? int64_to_str_back(ptr, (int64_t) value) : uint64_to_str_back(ptr, value);
11040 return ptr;
11042 case BASE_OCT:
11043 return oct64_to_str_back(ptr, value);
11045 case BASE_HEX:
11046 return hex64_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
11048 case BASE_HEX_DEC:
11049 *(--ptr) = ')';
11050 ptr = isint ? int64_to_str_back(ptr, (int64_t) value) : uint64_to_str_back(ptr, value);
11051 *(--ptr) = '(';
11052 *(--ptr) = ' ';
11053 ptr = hex64_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
11054 return ptr;
11056 default:
11057 REPORT_DISSECTOR_BUG("Invalid base: %d", FIELD_DISPLAY(display));
11060 return ptr;
11063 static const char *
11064 hfinfo_number_value_format(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint32_t value)
11066 int display = hfinfo->display;
11068 if (hfinfo->type == FT_FRAMENUM) {
11070 * Frame numbers are always displayed in decimal.
11072 display = BASE_DEC;
11075 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
11078 static const char *
11079 hfinfo_number_value_format64(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint64_t value)
11081 int display = hfinfo->display;
11083 if (hfinfo->type == FT_FRAMENUM) {
11085 * Frame numbers are always displayed in decimal.
11087 display = BASE_DEC;
11090 return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
11093 static const char *
11094 hfinfo_char_value_format(const header_field_info *hfinfo, char buf[32], uint32_t value)
11096 /* Get the underlying BASE_ value */
11097 int display = FIELD_DISPLAY(hfinfo->display);
11099 return hfinfo_char_value_format_display(display, buf, value);
11102 static const char *
11103 hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint32_t value)
11105 /* Get the underlying BASE_ value */
11106 int display = FIELD_DISPLAY(hfinfo->display);
11108 if (hfinfo->type == FT_FRAMENUM) {
11110 * Frame numbers are always displayed in decimal.
11112 display = BASE_DEC;
11115 if (IS_BASE_PORT(display)) {
11116 display = BASE_DEC;
11117 } else if (display == BASE_OUI) {
11118 display = BASE_HEX;
11121 switch (display) {
11122 case BASE_NONE:
11123 /* case BASE_DEC: */
11124 case BASE_DEC_HEX:
11125 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
11126 case BASE_CUSTOM:
11127 display = BASE_DEC;
11128 break;
11130 /* case BASE_HEX: */
11131 case BASE_HEX_DEC:
11132 display = BASE_HEX;
11133 break;
11136 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
11139 static const char *
11140 hfinfo_numeric_value_format64(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint64_t value)
11142 /* Get the underlying BASE_ value */
11143 int display = FIELD_DISPLAY(hfinfo->display);
11145 if (hfinfo->type == FT_FRAMENUM) {
11147 * Frame numbers are always displayed in decimal.
11149 display = BASE_DEC;
11152 switch (display) {
11153 case BASE_NONE:
11154 /* case BASE_DEC: */
11155 case BASE_DEC_HEX:
11156 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
11157 case BASE_CUSTOM:
11158 display = BASE_DEC;
11159 break;
11161 /* case BASE_HEX: */
11162 case BASE_HEX_DEC:
11163 display = BASE_HEX;
11164 break;
11167 return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
11170 static const char *
11171 hfinfo_char_vals_format(const header_field_info *hfinfo, char buf[32], uint32_t value)
11173 /* Get the underlying BASE_ value */
11174 int display = FIELD_DISPLAY(hfinfo->display);
11176 return hfinfo_char_value_format_display(display, buf, value);
11179 static const char *
11180 hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint32_t value)
11182 /* Get the underlying BASE_ value */
11183 int display = FIELD_DISPLAY(hfinfo->display);
11185 if (display == BASE_NONE)
11186 return NULL;
11188 if (display == BASE_DEC_HEX)
11189 display = BASE_DEC;
11190 if (display == BASE_HEX_DEC)
11191 display = BASE_HEX;
11193 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
11196 static const char *
11197 hfinfo_number_vals_format64(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint64_t value)
11199 /* Get the underlying BASE_ value */
11200 int display = FIELD_DISPLAY(hfinfo->display);
11202 if (display == BASE_NONE)
11203 return NULL;
11205 if (display == BASE_DEC_HEX)
11206 display = BASE_DEC;
11207 if (display == BASE_HEX_DEC)
11208 display = BASE_HEX;
11210 return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
11213 const char *
11214 proto_registrar_get_name(const int n)
11216 header_field_info *hfinfo;
11218 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
11219 return hfinfo->name;
11222 const char *
11223 proto_registrar_get_abbrev(const int n)
11225 header_field_info *hfinfo;
11227 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
11228 return hfinfo->abbrev;
11231 enum ftenum
11232 proto_registrar_get_ftype(const int n)
11234 header_field_info *hfinfo;
11236 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
11237 return hfinfo->type;
11241 proto_registrar_get_parent(const int n)
11243 header_field_info *hfinfo;
11245 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
11246 return hfinfo->parent;
11249 bool
11250 proto_registrar_is_protocol(const int n)
11252 header_field_info *hfinfo;
11254 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
11255 return (((hfinfo->id != hf_text_only) && (hfinfo->parent == -1)) ? true : false);
11258 /* Returns length of field in packet (not necessarily the length
11259 * in our internal representation, as in the case of IPv4).
11260 * 0 means undeterminable at time of registration
11261 * -1 means the field is not registered. */
11263 proto_registrar_get_length(const int n)
11265 header_field_info *hfinfo;
11267 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
11268 return ftype_wire_size(hfinfo->type);
11271 /* Looks for a protocol or a field in a proto_tree. Returns true if
11272 * it exists anywhere, or false if it exists nowhere. */
11273 bool
11274 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
11276 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
11278 if (g_ptr_array_len(ptrs) > 0) {
11279 return true;
11281 else {
11282 return false;
11286 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
11287 * This only works if the hfindex was "primed" before the dissection
11288 * took place, as we just pass back the already-created GPtrArray*.
11289 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
11290 * handles that. */
11291 GPtrArray *
11292 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
11294 if (!tree)
11295 return NULL;
11297 if (PTREE_DATA(tree)->interesting_hfids != NULL)
11298 return (GPtrArray *)g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
11299 GINT_TO_POINTER(id));
11300 else
11301 return NULL;
11304 bool
11305 proto_tracking_interesting_fields(const proto_tree *tree)
11307 GHashTable *interesting_hfids;
11309 if (!tree)
11310 return false;
11312 interesting_hfids = PTREE_DATA(tree)->interesting_hfids;
11314 return (interesting_hfids != NULL) && g_hash_table_size(interesting_hfids);
11317 /* Helper struct for proto_find_info() and proto_all_finfos() */
11318 typedef struct {
11319 GPtrArray *array;
11320 int id;
11321 } ffdata_t;
11323 /* Helper function for proto_find_info() */
11324 static bool
11325 find_finfo(proto_node *node, void * data)
11327 field_info *fi = PNODE_FINFO(node);
11328 if (fi && fi->hfinfo) {
11329 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
11330 g_ptr_array_add(((ffdata_t*)data)->array, fi);
11334 /* Don't stop traversing. */
11335 return false;
11338 /* Helper function for proto_find_first_info() */
11339 static bool
11340 find_first_finfo(proto_node *node, void *data)
11342 field_info *fi = PNODE_FINFO(node);
11343 if (fi && fi->hfinfo) {
11344 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
11345 g_ptr_array_add(((ffdata_t*)data)->array, fi);
11347 /* Stop traversing. */
11348 return true;
11352 /* Continue traversing. */
11353 return false;
11356 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
11357 * This works on any proto_tree, primed or unprimed, but actually searches
11358 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
11359 * The caller does need to free the returned GPtrArray with
11360 * g_ptr_array_free(<array>, true).
11362 GPtrArray *
11363 proto_find_finfo(proto_tree *tree, const int id)
11365 ffdata_t ffdata;
11367 ffdata.array = g_ptr_array_new();
11368 ffdata.id = id;
11370 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
11372 return ffdata.array;
11375 /* Return GPtrArray* of first field_info pointers for the searched hfindex that appear in a tree.
11376 * This works on any proto_tree, primed or unprimed, but actually searches
11377 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
11378 * The caller does need to free the returned GPtrArray with
11379 * g_ptr_array_free(<array>, true).
11381 GPtrArray *
11382 proto_find_first_finfo(proto_tree *tree, const int id)
11384 ffdata_t ffdata;
11386 ffdata.array = g_ptr_array_new();
11387 ffdata.id = id;
11389 proto_tree_traverse_pre_order(tree, find_first_finfo, &ffdata);
11391 return ffdata.array;
11394 /* Helper function for proto_all_finfos() */
11395 static bool
11396 every_finfo(proto_node *node, void * data)
11398 field_info *fi = PNODE_FINFO(node);
11399 if (fi && fi->hfinfo) {
11400 g_ptr_array_add(((ffdata_t*)data)->array, fi);
11403 /* Don't stop traversing. */
11404 return false;
11407 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree.
11408 * The caller does need to free the returned GPtrArray with
11409 * g_ptr_array_free(<array>, true).
11411 GPtrArray *
11412 proto_all_finfos(proto_tree *tree)
11414 ffdata_t ffdata;
11416 /* Pre allocate enough space to hold all fields in most cases */
11417 ffdata.array = g_ptr_array_sized_new(512);
11418 ffdata.id = 0;
11420 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
11422 return ffdata.array;
11426 typedef struct {
11427 unsigned offset;
11428 field_info *finfo;
11429 tvbuff_t *tvb;
11430 } offset_search_t;
11432 static bool
11433 check_for_offset(proto_node *node, void * data)
11435 field_info *fi = PNODE_FINFO(node);
11436 offset_search_t *offsearch = (offset_search_t *)data;
11438 /* !fi == the top most container node which holds nothing */
11439 if (fi && !proto_item_is_hidden(node) && !proto_item_is_generated(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
11440 if (offsearch->offset >= (unsigned) fi->start &&
11441 offsearch->offset < (unsigned) (fi->start + fi->length)) {
11443 offsearch->finfo = fi;
11444 return false; /* keep traversing */
11447 return false; /* keep traversing */
11450 /* Search a proto_tree backwards (from leaves to root) looking for the field
11451 * whose start/length occupies 'offset' */
11452 /* XXX - I couldn't find an easy way to search backwards, so I search
11453 * forwards, w/o stopping. Therefore, the last finfo I find will the be
11454 * the one I want to return to the user. This algorithm is inefficient
11455 * and could be re-done, but I'd have to handle all the children and
11456 * siblings of each node myself. When I have more time I'll do that.
11457 * (yeah right) */
11458 field_info *
11459 proto_find_field_from_offset(proto_tree *tree, unsigned offset, tvbuff_t *tvb)
11461 offset_search_t offsearch;
11463 offsearch.offset = offset;
11464 offsearch.finfo = NULL;
11465 offsearch.tvb = tvb;
11467 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
11469 return offsearch.finfo;
11472 typedef struct {
11473 int length;
11474 char *buf;
11475 } decoded_data_t;
11477 static bool
11478 check_for_undecoded(proto_node *node, void * data)
11480 field_info *fi = PNODE_FINFO(node);
11481 decoded_data_t* decoded = (decoded_data_t*)data;
11482 int i;
11483 unsigned byte;
11484 unsigned bit;
11486 if (fi && fi->hfinfo->type != FT_PROTOCOL) {
11487 for (i = fi->start; i < fi->start + fi->length && i < decoded->length; i++) {
11488 byte = i / 8;
11489 bit = i % 8;
11490 decoded->buf[byte] |= (1 << bit);
11494 return false;
11497 char*
11498 proto_find_undecoded_data(proto_tree *tree, unsigned length)
11500 decoded_data_t decoded;
11501 decoded.length = length;
11502 decoded.buf = (char*)wmem_alloc0(PNODE_POOL(tree), length / 8 + 1);
11504 proto_tree_traverse_pre_order(tree, check_for_undecoded, &decoded);
11505 return decoded.buf;
11508 /* Dumps the protocols in the registration database to stdout. An independent
11509 * program can take this output and format it into nice tables or HTML or
11510 * whatever.
11512 * There is one record per line. The fields are tab-delimited.
11514 * Field 1 = protocol name
11515 * Field 2 = protocol short name
11516 * Field 3 = protocol filter name
11517 * Field 4 = protocol enabled
11518 * Field 5 = protocol enabled by default
11519 * Field 6 = protocol can toggle
11521 void
11522 proto_registrar_dump_protocols(void)
11524 protocol_t *protocol;
11525 int i;
11526 void *cookie = NULL;
11529 i = proto_get_first_protocol(&cookie);
11530 while (i != -1) {
11531 protocol = find_protocol_by_id(i);
11532 printf("%s\t%s\t%s\t%c\t%c\t%c\n",
11533 protocol->name,
11534 protocol->short_name,
11535 protocol->filter_name,
11536 (proto_is_protocol_enabled_by_default(protocol) ? 'T' : 'F'),
11537 (proto_is_protocol_enabled(protocol) ? 'T' : 'F'),
11538 (proto_can_toggle_protocol(protocol->proto_id) ? 'T' : 'F'));
11539 i = proto_get_next_protocol(&cookie);
11543 /* Dumps the value_strings, extended value string headers, range_strings
11544 * or true/false strings for fields that have them.
11545 * There is one record per line. Fields are tab-delimited.
11546 * There are four types of records: Value String, Extended Value String Header,
11547 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
11548 * the type of record.
11550 * Note that a record will be generated only if the value_string,... is referenced
11551 * in a registered hfinfo entry.
11554 * Value Strings
11555 * -------------
11556 * Field 1 = 'V'
11557 * Field 2 = Field abbreviation to which this value string corresponds
11558 * Field 3 = Integer value
11559 * Field 4 = String
11561 * Extended Value String Headers
11562 * -----------------------------
11563 * Field 1 = 'E'
11564 * Field 2 = Field abbreviation to which this extended value string header corresponds
11565 * Field 3 = Extended Value String "Name"
11566 * Field 4 = Number of entries in the associated value_string array
11567 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
11569 * Range Strings
11570 * -------------
11571 * Field 1 = 'R'
11572 * Field 2 = Field abbreviation to which this range string corresponds
11573 * Field 3 = Integer value: lower bound
11574 * Field 4 = Integer value: upper bound
11575 * Field 5 = String
11577 * True/False Strings
11578 * ------------------
11579 * Field 1 = 'T'
11580 * Field 2 = Field abbreviation to which this true/false string corresponds
11581 * Field 3 = True String
11582 * Field 4 = False String
11584 void
11585 proto_registrar_dump_values(void)
11587 header_field_info *hfinfo;
11588 int i, len, vi;
11589 const value_string *vals;
11590 const val64_string *vals64;
11591 const range_string *range;
11592 const true_false_string *tfs;
11593 const unit_name_string *units;
11595 len = gpa_hfinfo.len;
11596 for (i = 0; i < len ; i++) {
11597 if (gpa_hfinfo.hfi[i] == NULL)
11598 continue; /* This is a deregistered protocol or field */
11600 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
11602 if (hfinfo->id == hf_text_only) {
11603 continue;
11606 /* ignore protocols */
11607 if (proto_registrar_is_protocol(i)) {
11608 continue;
11610 /* process header fields */
11611 #if 0 /* XXX: We apparently allow fields with the same name but with differing "strings" content */
11613 * If this field isn't at the head of the list of
11614 * fields with this name, skip this field - all
11615 * fields with the same name are really just versions
11616 * of the same field stored in different bits, and
11617 * should have the same type/radix/value list, and
11618 * just differ in their bit masks. (If a field isn't
11619 * a bitfield, but can be, say, 1 or 2 bytes long,
11620 * it can just be made FT_UINT16, meaning the
11621 * *maximum* length is 2 bytes, and be used
11622 * for all lengths.)
11624 if (hfinfo->same_name_prev_id != -1)
11625 continue;
11626 #endif
11627 vals = NULL;
11628 vals64 = NULL;
11629 range = NULL;
11630 tfs = NULL;
11631 units = NULL;
11633 if (hfinfo->strings != NULL) {
11634 if (FIELD_DISPLAY(hfinfo->display) != BASE_CUSTOM &&
11635 (hfinfo->type == FT_CHAR ||
11636 hfinfo->type == FT_UINT8 ||
11637 hfinfo->type == FT_UINT16 ||
11638 hfinfo->type == FT_UINT24 ||
11639 hfinfo->type == FT_UINT32 ||
11640 hfinfo->type == FT_UINT40 ||
11641 hfinfo->type == FT_UINT48 ||
11642 hfinfo->type == FT_UINT56 ||
11643 hfinfo->type == FT_UINT64 ||
11644 hfinfo->type == FT_INT8 ||
11645 hfinfo->type == FT_INT16 ||
11646 hfinfo->type == FT_INT24 ||
11647 hfinfo->type == FT_INT32 ||
11648 hfinfo->type == FT_INT40 ||
11649 hfinfo->type == FT_INT48 ||
11650 hfinfo->type == FT_INT56 ||
11651 hfinfo->type == FT_INT64 ||
11652 hfinfo->type == FT_FLOAT ||
11653 hfinfo->type == FT_DOUBLE)) {
11655 if (hfinfo->display & BASE_RANGE_STRING) {
11656 range = (const range_string *)hfinfo->strings;
11657 } else if (hfinfo->display & BASE_EXT_STRING) {
11658 if (hfinfo->display & BASE_VAL64_STRING) {
11659 vals64 = VAL64_STRING_EXT_VS_P((const val64_string_ext *)hfinfo->strings);
11660 } else {
11661 vals = VALUE_STRING_EXT_VS_P((const value_string_ext *)hfinfo->strings);
11663 } else if (hfinfo->display & BASE_VAL64_STRING) {
11664 vals64 = (const val64_string *)hfinfo->strings;
11665 } else if (hfinfo->display & BASE_UNIT_STRING) {
11666 units = (const unit_name_string *)hfinfo->strings;
11667 } else {
11668 vals = (const value_string *)hfinfo->strings;
11671 else if (hfinfo->type == FT_BOOLEAN) {
11672 tfs = (const struct true_false_string *)hfinfo->strings;
11676 /* Print value strings? */
11677 if (vals) {
11678 if (hfinfo->display & BASE_EXT_STRING) {
11679 if (hfinfo->display & BASE_VAL64_STRING) {
11680 val64_string_ext *vse_p = (val64_string_ext *)hfinfo->strings;
11681 if (!val64_string_ext_validate(vse_p)) {
11682 ws_warning("Invalid val64_string_ext ptr for: %s", hfinfo->abbrev);
11683 continue;
11685 try_val64_to_str_ext(0, vse_p); /* "prime" the extended val64_string */
11686 printf("E\t%s\t%u\t%s\t%s\n",
11687 hfinfo->abbrev,
11688 VAL64_STRING_EXT_VS_NUM_ENTRIES(vse_p),
11689 VAL64_STRING_EXT_VS_NAME(vse_p),
11690 val64_string_ext_match_type_str(vse_p));
11691 } else {
11692 value_string_ext *vse_p = (value_string_ext *)hfinfo->strings;
11693 if (!value_string_ext_validate(vse_p)) {
11694 ws_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
11695 continue;
11697 try_val_to_str_ext(0, vse_p); /* "prime" the extended value_string */
11698 printf("E\t%s\t%u\t%s\t%s\n",
11699 hfinfo->abbrev,
11700 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
11701 VALUE_STRING_EXT_VS_NAME(vse_p),
11702 value_string_ext_match_type_str(vse_p));
11705 vi = 0;
11706 while (vals[vi].strptr) {
11707 /* Print in the proper base */
11708 if (hfinfo->type == FT_CHAR) {
11709 if (g_ascii_isprint(vals[vi].value)) {
11710 printf("V\t%s\t'%c'\t%s\n",
11711 hfinfo->abbrev,
11712 vals[vi].value,
11713 vals[vi].strptr);
11714 } else {
11715 if (hfinfo->display == BASE_HEX) {
11716 printf("V\t%s\t'\\x%02x'\t%s\n",
11717 hfinfo->abbrev,
11718 vals[vi].value,
11719 vals[vi].strptr);
11721 else {
11722 printf("V\t%s\t'\\%03o'\t%s\n",
11723 hfinfo->abbrev,
11724 vals[vi].value,
11725 vals[vi].strptr);
11728 } else {
11729 if (hfinfo->display == BASE_HEX) {
11730 printf("V\t%s\t0x%x\t%s\n",
11731 hfinfo->abbrev,
11732 vals[vi].value,
11733 vals[vi].strptr);
11735 else {
11736 printf("V\t%s\t%u\t%s\n",
11737 hfinfo->abbrev,
11738 vals[vi].value,
11739 vals[vi].strptr);
11742 vi++;
11745 else if (vals64) {
11746 vi = 0;
11747 while (vals64[vi].strptr) {
11748 printf("V64\t%s\t%" PRIu64 "\t%s\n",
11749 hfinfo->abbrev,
11750 vals64[vi].value,
11751 vals64[vi].strptr);
11752 vi++;
11756 /* print range strings? */
11757 else if (range) {
11758 vi = 0;
11759 while (range[vi].strptr) {
11760 /* Print in the proper base */
11761 if (FIELD_DISPLAY(hfinfo->display) == BASE_HEX) {
11762 printf("R\t%s\t0x%"PRIx64"\t0x%"PRIx64"\t%s\n",
11763 hfinfo->abbrev,
11764 range[vi].value_min,
11765 range[vi].value_max,
11766 range[vi].strptr);
11768 else {
11769 printf("R\t%s\t%"PRIu64"\t%"PRIu64"\t%s\n",
11770 hfinfo->abbrev,
11771 range[vi].value_min,
11772 range[vi].value_max,
11773 range[vi].strptr);
11775 vi++;
11779 /* Print true/false strings? */
11780 else if (tfs) {
11781 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
11782 tfs->true_string, tfs->false_string);
11784 /* Print unit strings? */
11785 else if (units) {
11786 printf("U\t%s\t%s\t%s\n", hfinfo->abbrev,
11787 units->singular, units->plural ? units->plural : "(no plural)");
11792 /* Prints the number of registered fields.
11793 * Useful for determining an appropriate value for
11794 * PROTO_PRE_ALLOC_HF_FIELDS_MEM.
11796 * Returns false if PROTO_PRE_ALLOC_HF_FIELDS_MEM is larger than or equal to
11797 * the number of fields, true otherwise.
11799 bool
11800 proto_registrar_dump_fieldcount(void)
11802 uint32_t i;
11803 header_field_info *hfinfo;
11804 uint32_t deregistered_count = 0;
11805 uint32_t same_name_count = 0;
11806 uint32_t protocol_count = 0;
11808 for (i = 0; i < gpa_hfinfo.len; i++) {
11809 if (gpa_hfinfo.hfi[i] == NULL) {
11810 deregistered_count++;
11811 continue; /* This is a deregistered protocol or header field */
11814 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
11816 if (proto_registrar_is_protocol(i))
11817 protocol_count++;
11819 if (hfinfo->same_name_prev_id != -1)
11820 same_name_count++;
11823 printf("There are %u header fields registered, of which:\n"
11824 "\t%u are deregistered\n"
11825 "\t%u are protocols\n"
11826 "\t%u have the same name as another field\n\n",
11827 gpa_hfinfo.len, deregistered_count, protocol_count,
11828 same_name_count);
11830 printf("%d fields were pre-allocated.\n%s", PROTO_PRE_ALLOC_HF_FIELDS_MEM,
11831 (gpa_hfinfo.allocated_len > PROTO_PRE_ALLOC_HF_FIELDS_MEM) ?
11832 "* * Please increase PROTO_PRE_ALLOC_HF_FIELDS_MEM (in epan/proto.c)! * *\n\n" :
11833 "\n");
11835 printf("The header field table consumes %u KiB of memory.\n",
11836 (unsigned int)(gpa_hfinfo.allocated_len * sizeof(header_field_info *) / 1024));
11837 printf("The fields themselves consume %u KiB of memory.\n",
11838 (unsigned int)(gpa_hfinfo.len * sizeof(header_field_info) / 1024));
11840 return (gpa_hfinfo.allocated_len > PROTO_PRE_ALLOC_HF_FIELDS_MEM);
11843 static void
11844 elastic_add_base_mapping(json_dumper *dumper)
11846 json_dumper_set_member_name(dumper, "settings");
11847 json_dumper_begin_object(dumper);
11848 json_dumper_set_member_name(dumper, "index.mapping.total_fields.limit");
11849 json_dumper_value_anyf(dumper, "%d", 1000000);
11850 json_dumper_end_object(dumper);
11853 static char*
11854 ws_type_to_elastic(unsigned type _U_)
11856 switch(type) {
11857 case FT_UINT16:
11858 case FT_INT16:
11859 case FT_INT32:
11860 case FT_UINT24:
11861 case FT_INT24:
11862 return "integer";
11863 case FT_INT8:
11864 case FT_UINT8:
11865 return "short";
11866 case FT_FRAMENUM:
11867 case FT_UINT32:
11868 case FT_UINT40:
11869 case FT_UINT48:
11870 case FT_UINT56:
11871 case FT_UINT64: // Actually it's not handled by 'long' elastic type.
11872 case FT_INT48:
11873 case FT_INT64:
11874 return "long";
11875 case FT_FLOAT:
11876 case FT_DOUBLE:
11877 return "float";
11878 case FT_IPv6:
11879 case FT_IPv4:
11880 return "ip";
11881 case FT_ABSOLUTE_TIME:
11882 case FT_RELATIVE_TIME:
11883 return "date";
11884 case FT_BYTES:
11885 case FT_UINT_BYTES:
11886 return "byte";
11887 case FT_BOOLEAN:
11888 return "boolean";
11889 default:
11890 return NULL;
11894 static char*
11895 dot_to_underscore(char* str)
11897 unsigned i;
11898 for (i = 0; i < strlen(str); i++) {
11899 if (str[i] == '.')
11900 str[i] = '_';
11902 return str;
11905 /* Dumps a mapping file for ElasticSearch
11907 void
11908 proto_registrar_dump_elastic(const char* filter)
11910 header_field_info *hfinfo;
11911 header_field_info *parent_hfinfo;
11912 unsigned i;
11913 bool open_object = true;
11914 const char* prev_proto = NULL;
11915 char* str;
11916 char** protos = NULL;
11917 char* proto;
11918 bool found;
11919 unsigned j;
11920 char* type;
11921 char* prev_item = NULL;
11923 /* We have filtering protocols. Extract them. */
11924 if (filter) {
11925 protos = g_strsplit(filter, ",", -1);
11929 * To help tracking down the json tree, objects have been appended with a comment:
11930 * n.label -> where n is the indentation level and label the name of the object
11933 json_dumper dumper = {
11934 .output_file = stdout,
11935 .flags = JSON_DUMPER_FLAGS_PRETTY_PRINT,
11937 json_dumper_begin_object(&dumper); // 1.root
11938 elastic_add_base_mapping(&dumper);
11940 json_dumper_set_member_name(&dumper, "mappings");
11941 json_dumper_begin_object(&dumper); // 2.mappings
11942 json_dumper_set_member_name(&dumper, "dynamic");
11943 json_dumper_value_anyf(&dumper, "false");
11945 json_dumper_set_member_name(&dumper, "properties");
11946 json_dumper_begin_object(&dumper); // 3.properties
11947 json_dumper_set_member_name(&dumper, "timestamp");
11948 json_dumper_begin_object(&dumper); // 4.timestamp
11949 json_dumper_set_member_name(&dumper, "type");
11950 json_dumper_value_string(&dumper, "date");
11951 json_dumper_end_object(&dumper); // 4.timestamp
11953 json_dumper_set_member_name(&dumper, "layers");
11954 json_dumper_begin_object(&dumper); // 4.layers
11955 json_dumper_set_member_name(&dumper, "properties");
11956 json_dumper_begin_object(&dumper); // 5.properties
11958 for (i = 0; i < gpa_hfinfo.len; i++) {
11959 if (gpa_hfinfo.hfi[i] == NULL)
11960 continue; /* This is a deregistered protocol or header field */
11962 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
11965 * Skip the pseudo-field for "proto_tree_add_text()" since
11966 * we don't want it in the list of filterable protocols.
11968 if (hfinfo->id == hf_text_only)
11969 continue;
11971 if (!proto_registrar_is_protocol(i)) {
11972 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
11975 * Skip the field if filter protocols have been set and this one's
11976 * parent is not listed.
11978 if (protos) {
11979 found = false;
11980 j = 0;
11981 proto = protos[0];
11982 while(proto) {
11983 if (!g_strcmp0(proto, parent_hfinfo->abbrev)) {
11984 found = true;
11985 break;
11987 j++;
11988 proto = protos[j];
11990 if (!found)
11991 continue;
11994 if (prev_proto && g_strcmp0(parent_hfinfo->abbrev, prev_proto)) {
11995 json_dumper_end_object(&dumper); // 7.properties
11996 json_dumper_end_object(&dumper); // 8.parent_hfinfo->abbrev
11997 open_object = true;
12000 prev_proto = parent_hfinfo->abbrev;
12002 if (open_object) {
12003 json_dumper_set_member_name(&dumper, parent_hfinfo->abbrev);
12004 json_dumper_begin_object(&dumper); // 6.parent_hfinfo->abbrev
12005 json_dumper_set_member_name(&dumper, "properties");
12006 json_dumper_begin_object(&dumper); // 7.properties
12007 open_object = false;
12009 /* Skip the fields that would map into string. This is the default in elasticsearch. */
12010 type = ws_type_to_elastic(hfinfo->type);
12011 /* when type is NULL, we have the default mapping: string */
12012 if (type) {
12013 str = ws_strdup_printf("%s_%s", prev_proto, hfinfo->abbrev);
12014 dot_to_underscore(str);
12015 if (g_strcmp0(prev_item, str)) {
12016 json_dumper_set_member_name(&dumper, str);
12017 json_dumper_begin_object(&dumper); // 8.hfinfo->abbrev
12018 json_dumper_set_member_name(&dumper, "type");
12019 json_dumper_value_string(&dumper, type);
12020 json_dumper_end_object(&dumper); // 8.hfinfo->abbrev
12022 g_free(prev_item);
12023 prev_item = str;
12027 g_free(prev_item);
12029 if (prev_proto) {
12030 json_dumper_end_object(&dumper); // 7.properties
12031 json_dumper_end_object(&dumper); // 6.parent_hfinfo->abbrev
12034 json_dumper_end_object(&dumper); // 5.properties
12035 json_dumper_end_object(&dumper); // 4.layers
12036 json_dumper_end_object(&dumper); // 3.properties
12037 json_dumper_end_object(&dumper); // 2.mappings
12038 json_dumper_end_object(&dumper); // 1.root
12039 bool ret = json_dumper_finish(&dumper);
12040 DISSECTOR_ASSERT(ret);
12042 g_strfreev(protos);
12045 /* Dumps the contents of the registration database to stdout. An independent
12046 * program can take this output and format it into nice tables or HTML or
12047 * whatever.
12049 * There is one record per line. Each record is either a protocol or a header
12050 * field, differentiated by the first field. The fields are tab-delimited.
12052 * Protocols
12053 * ---------
12054 * Field 1 = 'P'
12055 * Field 2 = descriptive protocol name
12056 * Field 3 = protocol abbreviation
12058 * Header Fields
12059 * -------------
12060 * Field 1 = 'F'
12061 * Field 2 = descriptive field name
12062 * Field 3 = field abbreviation
12063 * Field 4 = type ( textual representation of the ftenum type )
12064 * Field 5 = parent protocol abbreviation
12065 * Field 6 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
12066 * Field 7 = bitmask: format: hex: 0x....
12067 * Field 8 = blurb describing field
12069 void
12070 proto_registrar_dump_fields(void)
12072 header_field_info *hfinfo, *parent_hfinfo;
12073 int i, len;
12074 const char *enum_name;
12075 const char *base_name;
12076 const char *blurb;
12077 char width[5];
12079 len = gpa_hfinfo.len;
12080 for (i = 0; i < len ; i++) {
12081 if (gpa_hfinfo.hfi[i] == NULL)
12082 continue; /* This is a deregistered protocol or header field */
12084 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
12087 * Skip the pseudo-field for "proto_tree_add_text()" since
12088 * we don't want it in the list of filterable fields.
12090 if (hfinfo->id == hf_text_only)
12091 continue;
12093 /* format for protocols */
12094 if (proto_registrar_is_protocol(i)) {
12095 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
12097 /* format for header fields */
12098 else {
12100 * If this field isn't at the head of the list of
12101 * fields with this name, skip this field - all
12102 * fields with the same name are really just versions
12103 * of the same field stored in different bits, and
12104 * should have the same type/radix/value list, and
12105 * just differ in their bit masks. (If a field isn't
12106 * a bitfield, but can be, say, 1 or 2 bytes long,
12107 * it can just be made FT_UINT16, meaning the
12108 * *maximum* length is 2 bytes, and be used
12109 * for all lengths.)
12111 if (hfinfo->same_name_prev_id != -1)
12112 continue;
12114 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
12116 enum_name = ftype_name(hfinfo->type);
12117 base_name = "";
12119 if (hfinfo->type == FT_CHAR ||
12120 hfinfo->type == FT_UINT8 ||
12121 hfinfo->type == FT_UINT16 ||
12122 hfinfo->type == FT_UINT24 ||
12123 hfinfo->type == FT_UINT32 ||
12124 hfinfo->type == FT_UINT40 ||
12125 hfinfo->type == FT_UINT48 ||
12126 hfinfo->type == FT_UINT56 ||
12127 hfinfo->type == FT_UINT64 ||
12128 hfinfo->type == FT_INT8 ||
12129 hfinfo->type == FT_INT16 ||
12130 hfinfo->type == FT_INT24 ||
12131 hfinfo->type == FT_INT32 ||
12132 hfinfo->type == FT_INT40 ||
12133 hfinfo->type == FT_INT48 ||
12134 hfinfo->type == FT_INT56 ||
12135 hfinfo->type == FT_INT64) {
12137 switch (FIELD_DISPLAY(hfinfo->display)) {
12138 case BASE_NONE:
12139 case BASE_DEC:
12140 case BASE_HEX:
12141 case BASE_OCT:
12142 case BASE_DEC_HEX:
12143 case BASE_HEX_DEC:
12144 case BASE_CUSTOM:
12145 case BASE_PT_UDP:
12146 case BASE_PT_TCP:
12147 case BASE_PT_DCCP:
12148 case BASE_PT_SCTP:
12149 case BASE_OUI:
12150 base_name = val_to_str_const(FIELD_DISPLAY(hfinfo->display), hf_display, "????");
12151 break;
12152 default:
12153 base_name = "????";
12154 break;
12156 } else if (hfinfo->type == FT_BOOLEAN) {
12157 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
12158 snprintf(width, sizeof(width), "%d", hfinfo->display);
12159 base_name = width;
12162 blurb = hfinfo->blurb;
12163 if (blurb == NULL)
12164 blurb = "";
12165 else if (strlen(blurb) == 0)
12166 blurb = "\"\"";
12168 printf("F\t%s\t%s\t%s\t%s\t%s\t0x%" PRIx64 "\t%s\n",
12169 hfinfo->name, hfinfo->abbrev, enum_name,
12170 parent_hfinfo->abbrev, base_name,
12171 hfinfo->bitmask, blurb);
12176 /* Dumps all abbreviated field and protocol completions of the given string to
12177 * stdout. An independent program may use this for command-line tab completion
12178 * of fields.
12180 bool
12181 proto_registrar_dump_field_completions(const char *prefix)
12183 header_field_info *hfinfo;
12184 int i, len;
12185 size_t prefix_len;
12186 bool matched = false;
12188 prefix_len = strlen(prefix);
12189 len = gpa_hfinfo.len;
12190 for (i = 0; i < len ; i++) {
12191 if (gpa_hfinfo.hfi[i] == NULL)
12192 continue; /* This is a deregistered protocol or header field */
12194 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
12197 * Skip the pseudo-field for "proto_tree_add_text()" since
12198 * we don't want it in the list of filterable fields.
12200 if (hfinfo->id == hf_text_only)
12201 continue;
12203 /* format for protocols */
12204 if (proto_registrar_is_protocol(i)) {
12205 if(0 == strncmp(hfinfo->abbrev, prefix, prefix_len)) {
12206 matched = true;
12207 printf("%s\t%s\n", hfinfo->abbrev, hfinfo->name);
12210 /* format for header fields */
12211 else {
12213 * If this field isn't at the head of the list of
12214 * fields with this name, skip this field - all
12215 * fields with the same name are really just versions
12216 * of the same field stored in different bits, and
12217 * should have the same type/radix/value list, and
12218 * just differ in their bit masks. (If a field isn't
12219 * a bitfield, but can be, say, 1 or 2 bytes long,
12220 * it can just be made FT_UINT16, meaning the
12221 * *maximum* length is 2 bytes, and be used
12222 * for all lengths.)
12224 if (hfinfo->same_name_prev_id != -1)
12225 continue;
12227 if(0 == strncmp(hfinfo->abbrev, prefix, prefix_len)) {
12228 matched = true;
12229 printf("%s\t%s\n", hfinfo->abbrev, hfinfo->name);
12233 return matched;
12236 /* Dumps field types and descriptive names to stdout. An independent
12237 * program can take this output and format it into nice tables or HTML or
12238 * whatever.
12240 * There is one record per line. The fields are tab-delimited.
12242 * Field 1 = field type name, e.g. FT_UINT8
12243 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
12245 void
12246 proto_registrar_dump_ftypes(void)
12248 int fte;
12250 for (fte = 0; fte < FT_NUM_TYPES; fte++) {
12251 printf("%s\t%s\n", ftype_name((ftenum_t)fte), ftype_pretty_name((ftenum_t)fte));
12255 /* This function indicates whether it's possible to construct a
12256 * "match selected" display filter string for the specified field,
12257 * returns an indication of whether it's possible, and, if it's
12258 * possible and "filter" is non-null, constructs the filter and
12259 * sets "*filter" to point to it.
12260 * You do not need to [g_]free() this string since it will be automatically
12261 * freed once the next packet is dissected.
12263 static bool
12264 construct_match_selected_string(const field_info *finfo, epan_dissect_t *edt,
12265 char **filter)
12267 const header_field_info *hfinfo;
12268 char *ptr;
12269 int buf_len;
12270 int i;
12271 int start, length, length_remaining;
12272 uint8_t c;
12274 if (!finfo)
12275 return false;
12277 hfinfo = finfo->hfinfo;
12278 DISSECTOR_ASSERT(hfinfo);
12280 /* If we have BASE_NONE and strings (a non-NULL FIELDCONVERT),
12281 * then "the numeric value ... is not used when preparing
12282 * filters for the field in question." If it's any other
12283 * base, we'll generate the filter normally (which will
12284 * be numeric, even though the human-readable string does
12285 * work for filtering.)
12287 * XXX - It might be nice to use fvalue_to_string_repr() in
12288 * "proto_item_fill_label()" as well, although, there, you'd
12289 * have to deal with the base *and* with resolved values for
12290 * addresses.
12292 * Perhaps in addition to taking the repr type (DISPLAY
12293 * or DFILTER) and the display (base), fvalue_to_string_repr()
12294 * should have the the "strings" values in the header_field_info
12295 * structure for the field as a parameter, so it can have
12296 * if the field is Boolean or an enumerated integer type,
12297 * the tables used to generate human-readable values.
12299 if (hfinfo->strings && FIELD_DISPLAY(hfinfo->display) == BASE_NONE) {
12300 const char *str = NULL;
12302 switch (hfinfo->type) {
12304 case FT_INT8:
12305 case FT_INT16:
12306 case FT_INT24:
12307 case FT_INT32:
12308 str = hf_try_val_to_str(fvalue_get_sinteger(finfo->value), hfinfo);
12309 break;
12311 case FT_CHAR:
12312 case FT_UINT8:
12313 case FT_UINT16:
12314 case FT_UINT24:
12315 case FT_UINT32:
12316 str = hf_try_val_to_str(fvalue_get_uinteger(finfo->value), hfinfo);
12317 break;
12319 default:
12320 break;
12323 if (str != NULL && filter != NULL) {
12324 *filter = wmem_strdup_printf(NULL, "%s == \"%s\"", hfinfo->abbrev, str);
12325 return true;
12329 switch (hfinfo->type) {
12331 case FT_PROTOCOL:
12332 if (filter != NULL)
12333 *filter = wmem_strdup(NULL, finfo->hfinfo->abbrev);
12334 break;
12336 case FT_NONE:
12338 * If the length is 0, just match the name of the
12339 * field.
12341 * (Also check for negative values, just in case,
12342 * as we'll cast it to an unsigned value later.)
12344 length = finfo->length;
12345 if (length == 0) {
12346 if (filter != NULL)
12347 *filter = wmem_strdup(NULL, finfo->hfinfo->abbrev);
12348 break;
12350 if (length < 0)
12351 return false;
12354 * This doesn't have a value, so we'd match
12355 * on the raw bytes at this address.
12357 * Should we be allowed to access to the raw bytes?
12358 * If "edt" is NULL, the answer is "no".
12360 if (edt == NULL)
12361 return false;
12364 * Is this field part of the raw frame tvbuff?
12365 * If not, we can't use "frame[N:M]" to match
12366 * it.
12368 * XXX - should this be frame-relative, or
12369 * protocol-relative?
12371 * XXX - does this fallback for non-registered
12372 * fields even make sense?
12374 if (finfo->ds_tvb != edt->tvb)
12375 return false; /* you lose */
12378 * Don't go past the end of that tvbuff.
12380 length_remaining = tvb_captured_length_remaining(finfo->ds_tvb, finfo->start);
12381 if (length > length_remaining)
12382 length = length_remaining;
12383 if (length <= 0)
12384 return false;
12386 if (filter != NULL) {
12387 start = finfo->start;
12388 buf_len = 32 + length * 3;
12389 *filter = (char *)wmem_alloc0(NULL, buf_len);
12390 ptr = *filter;
12392 ptr += snprintf(ptr, buf_len-(ptr-*filter),
12393 "frame[%d:%d] == ", finfo->start, length);
12394 for (i=0; i<length; i++) {
12395 c = tvb_get_uint8(finfo->ds_tvb, start);
12396 start++;
12397 if (i == 0 ) {
12398 ptr += snprintf(ptr, buf_len-(ptr-*filter), "%02x", c);
12400 else {
12401 ptr += snprintf(ptr, buf_len-(ptr-*filter), ":%02x", c);
12405 break;
12407 /* By default, use the fvalue's "to_string_repr" method. */
12408 default:
12409 if (filter != NULL) {
12410 char *str = fvalue_to_string_repr(NULL, finfo->value, FTREPR_DFILTER, finfo->hfinfo->display);
12411 *filter = wmem_strdup_printf(NULL, "%s == %s", hfinfo->abbrev, str);
12412 wmem_free(NULL, str);
12414 break;
12417 return true;
12421 * Returns true if we can do a "match selected" on the field, false
12422 * otherwise.
12424 bool
12425 proto_can_match_selected(const field_info *finfo, epan_dissect_t *edt)
12427 return construct_match_selected_string(finfo, edt, NULL);
12430 /* This function attempts to construct a "match selected" display filter
12431 * string for the specified field; if it can do so, it returns a pointer
12432 * to the string, otherwise it returns NULL.
12434 * The string is wmem allocated and must be freed with "wmem_free(NULL, ...)".
12436 char *
12437 proto_construct_match_selected_string(const field_info *finfo, epan_dissect_t *edt)
12439 char *filter = NULL;
12441 if (!construct_match_selected_string(finfo, edt, &filter))
12443 wmem_free(NULL, filter);
12444 return NULL;
12446 return filter;
12449 /* This function is common code for all proto_tree_add_bitmask... functions.
12452 static bool
12453 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
12454 const int len, const int ett, int * const *fields,
12455 const int flags, bool first,
12456 bool use_parent_tree,
12457 proto_tree* tree, uint64_t value)
12459 uint64_t available_bits = UINT64_MAX;
12460 uint64_t bitmask = 0;
12461 uint64_t tmpval;
12462 header_field_info *hf;
12463 uint32_t integer32;
12464 int bit_offset;
12465 int no_of_bits;
12467 if (!*fields)
12468 REPORT_DISSECTOR_BUG("Illegal call of proto_item_add_bitmask_tree without fields");
12470 if (len < 0 || len > 8)
12471 REPORT_DISSECTOR_BUG("Invalid len: %d", len);
12473 * packet-frame.c uses len=0 since the value is taken from the packet
12474 * metadata, not the packet bytes. In that case, assume that all bits
12475 * in the provided value are valid.
12477 if (len > 0) {
12478 available_bits >>= (8 - (unsigned)len)*8;
12481 if (use_parent_tree == false)
12482 tree = proto_item_add_subtree(item, ett);
12484 while (*fields) {
12485 uint64_t present_bits;
12486 PROTO_REGISTRAR_GET_NTH(**fields,hf);
12487 DISSECTOR_ASSERT_HINT(hf->bitmask != 0, hf->abbrev);
12489 bitmask |= hf->bitmask;
12491 /* Skip fields that aren't fully present */
12492 present_bits = available_bits & hf->bitmask;
12493 if (present_bits != hf->bitmask) {
12494 fields++;
12495 continue;
12498 switch (hf->type) {
12499 case FT_CHAR:
12500 case FT_UINT8:
12501 case FT_UINT16:
12502 case FT_UINT24:
12503 case FT_UINT32:
12504 proto_tree_add_uint(tree, **fields, tvb, offset, len, (uint32_t)value);
12505 break;
12507 case FT_INT8:
12508 case FT_INT16:
12509 case FT_INT24:
12510 case FT_INT32:
12511 proto_tree_add_int(tree, **fields, tvb, offset, len, (int32_t)value);
12512 break;
12514 case FT_UINT40:
12515 case FT_UINT48:
12516 case FT_UINT56:
12517 case FT_UINT64:
12518 proto_tree_add_uint64(tree, **fields, tvb, offset, len, value);
12519 break;
12521 case FT_INT40:
12522 case FT_INT48:
12523 case FT_INT56:
12524 case FT_INT64:
12525 proto_tree_add_int64(tree, **fields, tvb, offset, len, (int64_t)value);
12526 break;
12528 case FT_BOOLEAN:
12529 proto_tree_add_boolean(tree, **fields, tvb, offset, len, value);
12530 break;
12532 default:
12533 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_item_add_bitmask_tree()",
12534 hf->abbrev,
12535 hf->type,
12536 ftype_name(hf->type));
12537 break;
12539 if (flags & BMT_NO_APPEND) {
12540 fields++;
12541 continue;
12543 tmpval = (value & hf->bitmask) >> hfinfo_bitshift(hf);
12545 /* XXX: README.developer and the comments have always defined
12546 * BMT_NO_INT as "only boolean flags are added to the title /
12547 * don't add non-boolean (integral) fields", but the
12548 * implementation has always added BASE_CUSTOM and fields with
12549 * value_strings, though not fields with unit_strings.
12550 * Possibly this is because some dissectors use a FT_UINT8
12551 * with a value_string for fields that should be a FT_BOOLEAN.
12553 switch (hf->type) {
12554 case FT_CHAR:
12555 if (hf->display == BASE_CUSTOM) {
12556 char lbl[ITEM_LABEL_LENGTH];
12557 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
12559 DISSECTOR_ASSERT(fmtfunc);
12560 fmtfunc(lbl, (uint32_t) tmpval);
12561 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12562 hf->name, lbl);
12563 first = false;
12565 else if (hf->strings) {
12566 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12567 hf->name, hf_try_val_to_str_const((uint32_t) tmpval, hf, "Unknown"));
12568 first = false;
12570 else if (!(flags & BMT_NO_INT)) {
12571 char buf[32];
12572 const char *out;
12574 if (!first) {
12575 proto_item_append_text(item, ", ");
12578 out = hfinfo_char_value_format(hf, buf, (uint32_t) tmpval);
12579 proto_item_append_text(item, "%s: %s", hf->name, out);
12580 first = false;
12583 break;
12585 case FT_UINT8:
12586 case FT_UINT16:
12587 case FT_UINT24:
12588 case FT_UINT32:
12589 if (hf->display == BASE_CUSTOM) {
12590 char lbl[ITEM_LABEL_LENGTH];
12591 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
12593 DISSECTOR_ASSERT(fmtfunc);
12594 fmtfunc(lbl, (uint32_t) tmpval);
12595 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12596 hf->name, lbl);
12597 first = false;
12599 else if ((hf->strings) &&(!(hf->display & (BASE_UNIT_STRING|BASE_SPECIAL_VALS)))) {
12600 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12601 hf->name, hf_try_val_to_str_const((uint32_t) tmpval, hf, "Unknown"));
12602 first = false;
12604 else if (!(flags & BMT_NO_INT)) {
12605 char buf[NUMBER_LABEL_LENGTH];
12606 const char *out = NULL;
12608 if (!first) {
12609 proto_item_append_text(item, ", ");
12612 if (hf->strings && hf->display & BASE_SPECIAL_VALS) {
12613 out = hf_try_val_to_str((uint32_t) tmpval, hf);
12615 if (out == NULL) {
12616 out = hfinfo_number_value_format(hf, buf, (uint32_t) tmpval);
12618 proto_item_append_text(item, "%s: %s", hf->name, out);
12619 if (hf->strings && hf->display & BASE_UNIT_STRING) {
12620 proto_item_append_text(item, "%s", unit_name_string_get_value((uint32_t) tmpval, (const unit_name_string*)hf->strings));
12622 first = false;
12625 break;
12627 case FT_INT8:
12628 case FT_INT16:
12629 case FT_INT24:
12630 case FT_INT32:
12631 integer32 = (uint32_t) tmpval;
12632 if (hf->bitmask) {
12633 no_of_bits = ws_count_ones(hf->bitmask);
12634 integer32 = ws_sign_ext32(integer32, no_of_bits);
12636 if (hf->display == BASE_CUSTOM) {
12637 char lbl[ITEM_LABEL_LENGTH];
12638 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
12640 DISSECTOR_ASSERT(fmtfunc);
12641 fmtfunc(lbl, (int32_t) integer32);
12642 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12643 hf->name, lbl);
12644 first = false;
12646 else if ((hf->strings) &&(!(hf->display & (BASE_UNIT_STRING|BASE_SPECIAL_VALS)))) {
12647 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12648 hf->name, hf_try_val_to_str_const((int32_t) integer32, hf, "Unknown"));
12649 first = false;
12651 else if (!(flags & BMT_NO_INT)) {
12652 char buf[NUMBER_LABEL_LENGTH];
12653 const char *out = NULL;
12655 if (!first) {
12656 proto_item_append_text(item, ", ");
12659 if (hf->strings && hf->display & BASE_SPECIAL_VALS) {
12660 out = hf_try_val_to_str((int32_t) integer32, hf);
12662 if (out == NULL) {
12663 out = hfinfo_number_value_format(hf, buf, (int32_t) integer32);
12665 proto_item_append_text(item, "%s: %s", hf->name, out);
12666 if (hf->display & BASE_UNIT_STRING) {
12667 proto_item_append_text(item, "%s", unit_name_string_get_value((uint32_t) tmpval, (const unit_name_string*)hf->strings));
12669 first = false;
12672 break;
12674 case FT_UINT40:
12675 case FT_UINT48:
12676 case FT_UINT56:
12677 case FT_UINT64:
12678 if (hf->display == BASE_CUSTOM) {
12679 char lbl[ITEM_LABEL_LENGTH];
12680 const custom_fmt_func_64_t fmtfunc = (const custom_fmt_func_64_t)hf->strings;
12682 DISSECTOR_ASSERT(fmtfunc);
12683 fmtfunc(lbl, tmpval);
12684 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12685 hf->name, lbl);
12686 first = false;
12688 else if ((hf->strings) &&(!(hf->display & (BASE_UNIT_STRING|BASE_SPECIAL_VALS)))) {
12689 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12690 hf->name, hf_try_val64_to_str_const(tmpval, hf, "Unknown"));
12691 first = false;
12693 else if (!(flags & BMT_NO_INT)) {
12694 char buf[NUMBER_LABEL_LENGTH];
12695 const char *out = NULL;
12697 if (!first) {
12698 proto_item_append_text(item, ", ");
12701 if (hf->strings && hf->display & BASE_SPECIAL_VALS) {
12702 out = hf_try_val64_to_str(tmpval, hf);
12704 if (out == NULL) {
12705 out = hfinfo_number_value_format64(hf, buf, tmpval);
12707 proto_item_append_text(item, "%s: %s", hf->name, out);
12708 if (hf->strings && hf->display & BASE_UNIT_STRING) {
12709 proto_item_append_text(item, "%s", unit_name_string_get_value64(tmpval, (const unit_name_string*)hf->strings));
12711 first = false;
12714 break;
12716 case FT_INT40:
12717 case FT_INT48:
12718 case FT_INT56:
12719 case FT_INT64:
12720 if (hf->bitmask) {
12721 no_of_bits = ws_count_ones(hf->bitmask);
12722 tmpval = ws_sign_ext64(tmpval, no_of_bits);
12724 if (hf->display == BASE_CUSTOM) {
12725 char lbl[ITEM_LABEL_LENGTH];
12726 const custom_fmt_func_64_t fmtfunc = (const custom_fmt_func_64_t)hf->strings;
12728 DISSECTOR_ASSERT(fmtfunc);
12729 fmtfunc(lbl, (int64_t) tmpval);
12730 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12731 hf->name, lbl);
12732 first = false;
12734 else if ((hf->strings) &&(!(hf->display & (BASE_UNIT_STRING|BASE_SPECIAL_VALS)))) {
12735 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12736 hf->name, hf_try_val64_to_str_const((int64_t) tmpval, hf, "Unknown"));
12737 first = false;
12739 else if (!(flags & BMT_NO_INT)) {
12740 char buf[NUMBER_LABEL_LENGTH];
12741 const char *out = NULL;
12743 if (!first) {
12744 proto_item_append_text(item, ", ");
12747 if (hf->strings && hf->display & BASE_SPECIAL_VALS) {
12748 out = hf_try_val64_to_str((int64_t) tmpval, hf);
12750 if (out == NULL) {
12751 out = hfinfo_number_value_format64(hf, buf, (int64_t) tmpval);
12753 proto_item_append_text(item, "%s: %s", hf->name, out);
12754 if (hf->strings && hf->display & BASE_UNIT_STRING) {
12755 proto_item_append_text(item, "%s", unit_name_string_get_value64(tmpval, (const unit_name_string*)hf->strings));
12757 first = false;
12760 break;
12762 case FT_BOOLEAN:
12763 if (hf->strings && !(flags & BMT_NO_TFS)) {
12764 /* If we have true/false strings, emit full - otherwise messages
12765 might look weird */
12766 const struct true_false_string *tfs =
12767 (const struct true_false_string *)hf->strings;
12769 if (tmpval) {
12770 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12771 hf->name, tfs->true_string);
12772 first = false;
12773 } else if (!(flags & BMT_NO_FALSE)) {
12774 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12775 hf->name, tfs->false_string);
12776 first = false;
12778 } else if (hf->bitmask & value) {
12779 /* If the flag is set, show the name */
12780 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
12781 first = false;
12783 break;
12784 default:
12785 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_item_add_bitmask_tree()",
12786 hf->abbrev,
12787 hf->type,
12788 ftype_name(hf->type));
12789 break;
12792 fields++;
12795 /* XXX: We don't pass the hfi into this function. Perhaps we should,
12796 * but then again most dissectors don't set the bitmask field for
12797 * the higher level bitmask hfi, so calculate the bitmask from the
12798 * fields present. */
12799 if (item) {
12800 bit_offset = len*8 - 1 - ws_ilog2(bitmask);
12801 no_of_bits = ws_ilog2(bitmask) - ws_ctz(bitmask) + 1;
12802 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
12803 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
12805 return first;
12808 /* This function will dissect a sequence of bytes that describe a
12809 * bitmask and supply the value of that sequence through a pointer.
12810 * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
12811 * to be dissected.
12812 * This field will form an expansion under which the individual fields of the
12813 * bitmask is dissected and displayed.
12814 * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
12816 * fields is an array of pointers to int that lists all the fields of the
12817 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
12818 * or another integer of the same type/size as hf_hdr with a mask specified.
12819 * This array is terminated by a NULL entry.
12821 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
12822 * FT_integer fields that have a value_string attached will have the
12823 * matched string displayed on the expansion line.
12825 proto_item *
12826 proto_tree_add_bitmask_ret_uint64(proto_tree *parent_tree, tvbuff_t *tvb,
12827 const unsigned offset, const int hf_hdr,
12828 const int ett, int * const *fields,
12829 const unsigned encoding, uint64_t *retval)
12831 return proto_tree_add_bitmask_with_flags_ret_uint64(parent_tree, tvb, offset, hf_hdr, ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS, retval);
12834 /* This function will dissect a sequence of bytes that describe a
12835 * bitmask.
12836 * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
12837 * to be dissected.
12838 * This field will form an expansion under which the individual fields of the
12839 * bitmask is dissected and displayed.
12840 * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
12842 * fields is an array of pointers to int that lists all the fields of the
12843 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
12844 * or another integer of the same type/size as hf_hdr with a mask specified.
12845 * This array is terminated by a NULL entry.
12847 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
12848 * FT_integer fields that have a value_string attached will have the
12849 * matched string displayed on the expansion line.
12851 proto_item *
12852 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
12853 const unsigned offset, const int hf_hdr,
12854 const int ett, int * const *fields,
12855 const unsigned encoding)
12857 return proto_tree_add_bitmask_with_flags(parent_tree, tvb, offset, hf_hdr, ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS);
12860 /* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
12861 * what data is appended to the header.
12863 proto_item *
12864 proto_tree_add_bitmask_with_flags_ret_uint64(proto_tree *parent_tree, tvbuff_t *tvb, const unsigned offset,
12865 const int hf_hdr, const int ett, int * const *fields, const unsigned encoding, const int flags,
12866 uint64_t *retval)
12868 proto_item *item = NULL;
12869 header_field_info *hf;
12870 int len;
12871 uint64_t value;
12873 PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
12874 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
12875 len = ftype_wire_size(hf->type);
12876 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
12878 if (parent_tree) {
12879 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
12880 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
12881 flags, false, false, NULL, value);
12884 *retval = value;
12885 if (hf->bitmask) {
12886 /* Mask out irrelevant portions */
12887 *retval &= hf->bitmask;
12888 /* Shift bits */
12889 *retval >>= hfinfo_bitshift(hf);
12892 return item;
12895 /* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
12896 * what data is appended to the header.
12898 proto_item *
12899 proto_tree_add_bitmask_with_flags(proto_tree *parent_tree, tvbuff_t *tvb, const unsigned offset,
12900 const int hf_hdr, const int ett, int * const *fields, const unsigned encoding, const int flags)
12902 proto_item *item = NULL;
12903 header_field_info *hf;
12904 int len;
12905 uint64_t value;
12907 PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
12908 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
12910 if (parent_tree) {
12911 len = ftype_wire_size(hf->type);
12912 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
12913 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
12914 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
12915 flags, false, false, NULL, value);
12918 return item;
12921 /* Similar to proto_tree_add_bitmask(), but with a passed in value (presumably because it
12922 can't be retrieved directly from tvb) */
12923 proto_item *
12924 proto_tree_add_bitmask_value(proto_tree *parent_tree, tvbuff_t *tvb, const unsigned offset,
12925 const int hf_hdr, const int ett, int * const *fields, const uint64_t value)
12927 return proto_tree_add_bitmask_value_with_flags(parent_tree, tvb, offset,
12928 hf_hdr, ett, fields, value, BMT_NO_INT|BMT_NO_TFS);
12931 /* Similar to proto_tree_add_bitmask_value(), but with control of flag values */
12932 WS_DLL_PUBLIC proto_item *
12933 proto_tree_add_bitmask_value_with_flags(proto_tree *parent_tree, tvbuff_t *tvb, const unsigned offset,
12934 const int hf_hdr, const int ett, int * const *fields, const uint64_t value, const int flags)
12936 proto_item *item = NULL;
12937 header_field_info *hf;
12938 int len;
12940 PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
12941 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
12942 /* the proto_tree_add_uint/_uint64() calls below
12943 will fail if tvb==NULL and len!=0 */
12944 len = tvb ? ftype_wire_size(hf->type) : 0;
12946 if (parent_tree) {
12947 if (len <= 4)
12948 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len, (uint32_t)value);
12949 else
12950 item = proto_tree_add_uint64(parent_tree, hf_hdr, tvb, offset, len, value);
12952 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
12953 flags, false, false, NULL, value);
12956 return item;
12959 /* Similar to proto_tree_add_bitmask(), but with no "header" item to group all of the fields */
12960 void
12961 proto_tree_add_bitmask_list(proto_tree *tree, tvbuff_t *tvb, const unsigned offset,
12962 const int len, int * const *fields, const unsigned encoding)
12964 uint64_t value;
12966 if (tree) {
12967 value = get_uint64_value(tree, tvb, offset, len, encoding);
12968 proto_item_add_bitmask_tree(NULL, tvb, offset, len, -1, fields,
12969 BMT_NO_APPEND, false, true, tree, value);
12973 WS_DLL_PUBLIC void
12974 proto_tree_add_bitmask_list_ret_uint64(proto_tree *tree, tvbuff_t *tvb, const unsigned offset,
12975 const int len, int * const *fields, const unsigned encoding, uint64_t *retval)
12977 uint64_t value;
12979 value = get_uint64_value(tree, tvb, offset, len, encoding);
12980 if (tree) {
12981 proto_item_add_bitmask_tree(NULL, tvb, offset, len, -1, fields,
12982 BMT_NO_APPEND, false, true, tree, value);
12984 if (retval) {
12985 *retval = value;
12989 WS_DLL_PUBLIC void
12990 proto_tree_add_bitmask_list_value(proto_tree *tree, tvbuff_t *tvb, const unsigned offset,
12991 const int len, int * const *fields, const uint64_t value)
12993 if (tree) {
12994 proto_item_add_bitmask_tree(NULL, tvb, offset, len, -1, fields,
12995 BMT_NO_APPEND, false, true, tree, value);
13000 /* The same as proto_tree_add_bitmask(), but using a caller-supplied length.
13001 * This is intended to support bitmask fields whose lengths can vary, perhaps
13002 * as the underlying standard evolves over time.
13003 * With this API there is the possibility of being called to display more or
13004 * less data than the dissector was coded to support.
13005 * In such cases, it is assumed that bitmasks are extended on the MSb end.
13006 * Thus when presented with "too much" or "too little" data, MSbits will be
13007 * ignored or MSfields sacrificed.
13009 * Only fields for which all defined bits are available are displayed.
13011 proto_item *
13012 proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb,
13013 const unsigned offset, const unsigned len, const int hf_hdr,
13014 const int ett, int * const *fields, struct expert_field* exp,
13015 const unsigned encoding)
13017 proto_item *item = NULL;
13018 header_field_info *hf;
13019 unsigned decodable_len;
13020 unsigned decodable_offset;
13021 uint32_t decodable_value;
13022 uint64_t value;
13024 PROTO_REGISTRAR_GET_NTH(hf_hdr, hf);
13025 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
13027 decodable_offset = offset;
13028 decodable_len = MIN(len, (unsigned) ftype_wire_size(hf->type));
13030 /* If we are ftype_wire_size-limited,
13031 * make sure we decode as many LSBs as possible.
13033 if (encoding == ENC_BIG_ENDIAN) {
13034 decodable_offset += (len - decodable_len);
13037 if (parent_tree) {
13038 decodable_value = get_uint_value(parent_tree, tvb, decodable_offset,
13039 decodable_len, encoding);
13041 /* The root item covers all the bytes even if we can't decode them all */
13042 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len,
13043 decodable_value);
13046 if (decodable_len < len) {
13047 /* Dissector likely requires updating for new protocol revision */
13048 expert_add_info_format(NULL, item, exp,
13049 "Only least-significant %d of %d bytes decoded",
13050 decodable_len, len);
13053 if (item) {
13054 value = get_uint64_value(parent_tree, tvb, decodable_offset, decodable_len, encoding);
13055 proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len,
13056 ett, fields, BMT_NO_INT|BMT_NO_TFS, false, false, NULL, value);
13059 return item;
13062 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
13063 proto_item *
13064 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
13065 const unsigned offset, const unsigned len,
13066 const char *name, const char *fallback,
13067 const int ett, int * const *fields,
13068 const unsigned encoding, const int flags)
13070 proto_item *item = NULL;
13071 uint64_t value;
13073 if (parent_tree) {
13074 item = proto_tree_add_text_internal(parent_tree, tvb, offset, len, "%s", name ? name : "");
13075 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
13076 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
13077 flags, true, false, NULL, value) && fallback) {
13078 /* Still at first item - append 'fallback' text if any */
13079 proto_item_append_text(item, "%s", fallback);
13083 return item;
13086 proto_item *
13087 proto_tree_add_bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
13088 const unsigned bit_offset, const int no_of_bits,
13089 const unsigned encoding)
13091 header_field_info *hfinfo;
13092 int octet_length;
13093 int octet_offset;
13095 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
13097 if (no_of_bits < 0) {
13098 THROW(ReportedBoundsError);
13100 octet_length = (no_of_bits + 7) >> 3;
13101 octet_offset = bit_offset >> 3;
13102 test_length(hfinfo, tvb, octet_offset, octet_length, encoding);
13104 /* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
13105 * but only after doing a bunch more work (which we can, in the common
13106 * case, shortcut here).
13108 CHECK_FOR_NULL_TREE(tree);
13109 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
13111 return proto_tree_add_bits_ret_val(tree, hfindex, tvb, bit_offset, no_of_bits, NULL, encoding);
13115 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
13116 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
13117 * Offset should be given in bits from the start of the tvb.
13120 static proto_item *
13121 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
13122 const unsigned bit_offset, const int no_of_bits,
13123 uint64_t *return_value, const unsigned encoding)
13125 int offset;
13126 unsigned length;
13127 uint8_t tot_no_bits;
13128 char *bf_str;
13129 char lbl_str[ITEM_LABEL_LENGTH];
13130 uint64_t value = 0;
13131 uint8_t *bytes = NULL;
13132 size_t bytes_length = 0;
13134 proto_item *pi;
13135 header_field_info *hf_field;
13137 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
13138 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
13140 if (hf_field->bitmask != 0) {
13141 REPORT_DISSECTOR_BUG("Incompatible use of proto_tree_add_bits_ret_val"
13142 " with field '%s' (%s) with bitmask != 0",
13143 hf_field->abbrev, hf_field->name);
13146 if (no_of_bits < 0) {
13147 THROW(ReportedBoundsError);
13148 } else if (no_of_bits == 0) {
13149 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_ret_val() has a bit width of 0",
13150 hf_field->abbrev);
13153 /* Byte align offset */
13154 offset = bit_offset>>3;
13157 * Calculate the number of octets used to hold the bits
13159 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
13160 length = (tot_no_bits + 7) >> 3;
13162 if (no_of_bits < 65) {
13163 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
13164 } else if (hf_field->type != FT_BYTES) {
13165 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_ret_val() has a bit width of %u > 65",
13166 hf_field->abbrev, no_of_bits);
13167 return NULL;
13170 /* Sign extend for signed types */
13171 switch (hf_field->type) {
13172 case FT_INT8:
13173 case FT_INT16:
13174 case FT_INT24:
13175 case FT_INT32:
13176 case FT_INT40:
13177 case FT_INT48:
13178 case FT_INT56:
13179 case FT_INT64:
13180 value = ws_sign_ext64(value, no_of_bits);
13181 break;
13183 default:
13184 break;
13187 if (return_value) {
13188 *return_value = value;
13191 /* Coast clear. Try and fake it */
13192 CHECK_FOR_NULL_TREE(tree);
13193 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13195 bf_str = decode_bits_in_field(PNODE_POOL(tree), bit_offset, no_of_bits, value, encoding);
13197 switch (hf_field->type) {
13198 case FT_BOOLEAN:
13199 /* Boolean field */
13200 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, value,
13201 "%s = %s: %s",
13202 bf_str, hf_field->name, tfs_get_string(!!value, hf_field->strings));
13203 break;
13205 case FT_CHAR:
13206 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (uint32_t)value);
13207 fill_label_char(PITEM_FINFO(pi), lbl_str, NULL);
13208 break;
13210 case FT_UINT8:
13211 case FT_UINT16:
13212 case FT_UINT24:
13213 case FT_UINT32:
13214 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (uint32_t)value);
13215 fill_label_number(PITEM_FINFO(pi), lbl_str, NULL, false);
13216 break;
13218 case FT_INT8:
13219 case FT_INT16:
13220 case FT_INT24:
13221 case FT_INT32:
13222 pi = proto_tree_add_int(tree, hfindex, tvb, offset, length, (int32_t)value);
13223 fill_label_number(PITEM_FINFO(pi), lbl_str, NULL, true);
13224 break;
13226 case FT_UINT40:
13227 case FT_UINT48:
13228 case FT_UINT56:
13229 case FT_UINT64:
13230 pi = proto_tree_add_uint64(tree, hfindex, tvb, offset, length, value);
13231 fill_label_number64(PITEM_FINFO(pi), lbl_str, NULL, false);
13232 break;
13234 case FT_INT40:
13235 case FT_INT48:
13236 case FT_INT56:
13237 case FT_INT64:
13238 pi = proto_tree_add_int64(tree, hfindex, tvb, offset, length, (int64_t)value);
13239 fill_label_number64(PITEM_FINFO(pi), lbl_str, NULL, true);
13240 break;
13242 case FT_BYTES:
13243 bytes = tvb_get_bits_array(PNODE_POOL(tree), tvb, bit_offset, no_of_bits, &bytes_length, encoding);
13244 pi = proto_tree_add_bytes_with_length(tree, hfindex, tvb, offset, length, bytes, (int) bytes_length);
13245 proto_item_fill_label(PITEM_FINFO(pi), lbl_str, NULL);
13246 proto_item_set_text(pi, "%s", lbl_str);
13247 return pi;
13249 /* TODO: should handle FT_UINT_BYTES ? */
13251 default:
13252 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_tree_add_bits_ret_val()",
13253 hf_field->abbrev,
13254 hf_field->type,
13255 ftype_name(hf_field->type));
13256 return NULL;
13259 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
13260 return pi;
13263 proto_item *
13264 proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
13265 const unsigned bit_offset, const crumb_spec_t *crumb_spec,
13266 uint64_t *return_value)
13268 proto_item *pi;
13269 int no_of_bits;
13270 int octet_offset;
13271 unsigned mask_initial_bit_offset;
13272 unsigned mask_greatest_bit_offset;
13273 unsigned octet_length;
13274 uint8_t i;
13275 char bf_str[256];
13276 char lbl_str[ITEM_LABEL_LENGTH];
13277 uint64_t value;
13278 uint64_t composite_bitmask;
13279 uint64_t composite_bitmap;
13281 header_field_info *hf_field;
13283 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
13284 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
13286 if (hf_field->bitmask != 0) {
13287 REPORT_DISSECTOR_BUG("Incompatible use of proto_tree_add_split_bits_item_ret_val"
13288 " with field '%s' (%s) with bitmask != 0",
13289 hf_field->abbrev, hf_field->name);
13292 mask_initial_bit_offset = bit_offset % 8;
13294 no_of_bits = 0;
13295 value = 0;
13296 i = 0;
13297 mask_greatest_bit_offset = 0;
13298 composite_bitmask = 0;
13299 composite_bitmap = 0;
13301 while (crumb_spec[i].crumb_bit_length != 0) {
13302 uint64_t crumb_mask, crumb_value;
13303 uint8_t crumb_end_bit_offset;
13305 crumb_value = tvb_get_bits64(tvb,
13306 bit_offset + crumb_spec[i].crumb_bit_offset,
13307 crumb_spec[i].crumb_bit_length,
13308 ENC_BIG_ENDIAN);
13309 value += crumb_value;
13310 no_of_bits += crumb_spec[i].crumb_bit_length;
13311 DISSECTOR_ASSERT_HINT(no_of_bits <= 64, "a value larger than 64 bits cannot be represented");
13313 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
13314 octet containing the initial offset.
13315 If the mask is beyond 32 bits, then give up on bit map display.
13316 This could be improved in future, probably showing a table
13317 of 32 or 64 bits per row */
13318 if (mask_greatest_bit_offset < 32) {
13319 crumb_end_bit_offset = mask_initial_bit_offset
13320 + crumb_spec[i].crumb_bit_offset
13321 + crumb_spec[i].crumb_bit_length;
13322 crumb_mask = (UINT64_C(1) << crumb_spec[i].crumb_bit_length) - 1;
13324 if (crumb_end_bit_offset > mask_greatest_bit_offset) {
13325 mask_greatest_bit_offset = crumb_end_bit_offset;
13327 /* Currently the bitmap of the crumbs are only shown if
13328 * smaller than 32 bits. Do not bother calculating the
13329 * mask if it is larger than that. */
13330 if (crumb_end_bit_offset <= 32) {
13331 composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset));
13332 composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset));
13335 /* Shift left for the next segment */
13336 value <<= crumb_spec[++i].crumb_bit_length;
13339 /* Sign extend for signed types */
13340 switch (hf_field->type) {
13341 case FT_INT8:
13342 case FT_INT16:
13343 case FT_INT24:
13344 case FT_INT32:
13345 case FT_INT40:
13346 case FT_INT48:
13347 case FT_INT56:
13348 case FT_INT64:
13349 value = ws_sign_ext64(value, no_of_bits);
13350 break;
13351 default:
13352 break;
13355 if (return_value) {
13356 *return_value = value;
13359 /* Coast clear. Try and fake it */
13360 CHECK_FOR_NULL_TREE(tree);
13361 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13363 /* initialise the format string */
13364 bf_str[0] = '\0';
13366 octet_offset = bit_offset >> 3;
13368 /* Round up mask length to nearest octet */
13369 octet_length = ((mask_greatest_bit_offset + 7) >> 3);
13370 mask_greatest_bit_offset = octet_length << 3;
13372 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
13373 It would be a useful enhancement to eliminate this restriction. */
13374 if (mask_greatest_bit_offset > 0 && mask_greatest_bit_offset <= 32) {
13375 other_decode_bitfield_value(bf_str,
13376 (uint32_t)(composite_bitmap >> (64 - mask_greatest_bit_offset)),
13377 (uint32_t)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
13378 mask_greatest_bit_offset);
13379 } else {
13380 /* If the bitmask is too large, try to describe its contents. */
13381 snprintf(bf_str, sizeof(bf_str), "%d bits", no_of_bits);
13384 switch (hf_field->type) {
13385 case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
13386 /* Boolean field */
13387 return proto_tree_add_boolean_format(tree, hfindex,
13388 tvb, octet_offset, octet_length, value,
13389 "%s = %s: %s",
13390 bf_str, hf_field->name, tfs_get_string(!!value, hf_field->strings));
13391 break;
13393 case FT_CHAR:
13394 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (uint32_t)value);
13395 fill_label_char(PITEM_FINFO(pi), lbl_str, NULL);
13396 break;
13398 case FT_UINT8:
13399 case FT_UINT16:
13400 case FT_UINT24:
13401 case FT_UINT32:
13402 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (uint32_t)value);
13403 fill_label_number(PITEM_FINFO(pi), lbl_str, NULL, false);
13404 break;
13406 case FT_INT8:
13407 case FT_INT16:
13408 case FT_INT24:
13409 case FT_INT32:
13410 pi = proto_tree_add_int(tree, hfindex, tvb, octet_offset, octet_length, (int32_t)value);
13411 fill_label_number(PITEM_FINFO(pi), lbl_str, NULL, true);
13412 break;
13414 case FT_UINT40:
13415 case FT_UINT48:
13416 case FT_UINT56:
13417 case FT_UINT64:
13418 pi = proto_tree_add_uint64(tree, hfindex, tvb, octet_offset, octet_length, value);
13419 fill_label_number64(PITEM_FINFO(pi), lbl_str, NULL, false);
13420 break;
13422 case FT_INT40:
13423 case FT_INT48:
13424 case FT_INT56:
13425 case FT_INT64:
13426 pi = proto_tree_add_int64(tree, hfindex, tvb, octet_offset, octet_length, (int64_t)value);
13427 fill_label_number64(PITEM_FINFO(pi), lbl_str, NULL, true);
13428 break;
13430 default:
13431 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_tree_add_split_bits_item_ret_val()",
13432 hf_field->abbrev,
13433 hf_field->type,
13434 ftype_name(hf_field->type));
13435 return NULL;
13437 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
13438 return pi;
13441 void
13442 proto_tree_add_split_bits_crumb(proto_tree *tree, const int hfindex, tvbuff_t *tvb, const unsigned bit_offset,
13443 const crumb_spec_t *crumb_spec, uint16_t crumb_index)
13445 header_field_info *hfinfo;
13446 int start = bit_offset >> 3;
13447 int length = ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1;
13449 /* We have to duplicate this length check from proto_tree_add_text_internal in order to check for a null tree
13450 * so that we can use the tree's memory scope in calculating the string */
13451 if (length == -1) {
13452 tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
13453 } else {
13454 tvb_ensure_bytes_exist(tvb, start, length);
13456 if (!tree) return;
13458 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
13459 proto_tree_add_text_internal(tree, tvb, start, length,
13460 "%s crumb %d of %s (decoded above)",
13461 decode_bits_in_field(PNODE_POOL(tree), bit_offset, crumb_spec[crumb_index].crumb_bit_length,
13462 tvb_get_bits(tvb,
13463 bit_offset,
13464 crumb_spec[crumb_index].crumb_bit_length,
13465 ENC_BIG_ENDIAN),
13466 ENC_BIG_ENDIAN),
13467 crumb_index,
13468 hfinfo->name);
13471 proto_item *
13472 proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
13473 const unsigned bit_offset, const int no_of_bits,
13474 uint64_t *return_value, const unsigned encoding)
13476 proto_item *item;
13478 if ((item = _proto_tree_add_bits_ret_val(tree, hfindex, tvb,
13479 bit_offset, no_of_bits,
13480 return_value, encoding))) {
13481 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
13482 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
13484 return item;
13487 static proto_item *
13488 _proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
13489 tvbuff_t *tvb, const unsigned bit_offset,
13490 const int no_of_bits, void *value_ptr,
13491 const unsigned encoding, char *value_str)
13493 int offset;
13494 unsigned length;
13495 uint8_t tot_no_bits;
13496 char *str;
13497 uint64_t value = 0;
13498 header_field_info *hf_field;
13500 /* We do not have to return a value, try to fake it as soon as possible */
13501 CHECK_FOR_NULL_TREE(tree);
13502 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13504 if (hf_field->bitmask != 0) {
13505 REPORT_DISSECTOR_BUG("Incompatible use of proto_tree_add_bits_format_value"
13506 " with field '%s' (%s) with bitmask != 0",
13507 hf_field->abbrev, hf_field->name);
13510 if (no_of_bits < 0) {
13511 THROW(ReportedBoundsError);
13512 } else if (no_of_bits == 0) {
13513 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_format_value() has a bit width of 0",
13514 hf_field->abbrev);
13517 /* Byte align offset */
13518 offset = bit_offset>>3;
13521 * Calculate the number of octets used to hold the bits
13523 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
13524 length = tot_no_bits>>3;
13525 /* If we are using part of the next octet, increase length by 1 */
13526 if (tot_no_bits & 0x07)
13527 length++;
13529 if (no_of_bits < 65) {
13530 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
13531 } else {
13532 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_format_value() has a bit width of %u > 65",
13533 hf_field->abbrev, no_of_bits);
13534 return NULL;
13537 str = decode_bits_in_field(PNODE_POOL(tree), bit_offset, no_of_bits, value, encoding);
13539 (void) g_strlcat(str, " = ", 256+64);
13540 (void) g_strlcat(str, hf_field->name, 256+64);
13543 * This function does not receive an actual value but a dimensionless pointer to that value.
13544 * For this reason, the type of the header field is examined in order to determine
13545 * what kind of value we should read from this address.
13546 * The caller of this function must make sure that for the specific header field type the address of
13547 * a compatible value is provided.
13549 switch (hf_field->type) {
13550 case FT_BOOLEAN:
13551 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, *(uint64_t *)value_ptr,
13552 "%s: %s", str, value_str);
13553 break;
13555 case FT_CHAR:
13556 case FT_UINT8:
13557 case FT_UINT16:
13558 case FT_UINT24:
13559 case FT_UINT32:
13560 return proto_tree_add_uint_format(tree, hfindex, tvb, offset, length, *(uint32_t *)value_ptr,
13561 "%s: %s", str, value_str);
13562 break;
13564 case FT_UINT40:
13565 case FT_UINT48:
13566 case FT_UINT56:
13567 case FT_UINT64:
13568 return proto_tree_add_uint64_format(tree, hfindex, tvb, offset, length, *(uint64_t *)value_ptr,
13569 "%s: %s", str, value_str);
13570 break;
13572 case FT_INT8:
13573 case FT_INT16:
13574 case FT_INT24:
13575 case FT_INT32:
13576 return proto_tree_add_int_format(tree, hfindex, tvb, offset, length, *(int32_t *)value_ptr,
13577 "%s: %s", str, value_str);
13578 break;
13580 case FT_INT40:
13581 case FT_INT48:
13582 case FT_INT56:
13583 case FT_INT64:
13584 return proto_tree_add_int64_format(tree, hfindex, tvb, offset, length, *(int64_t *)value_ptr,
13585 "%s: %s", str, value_str);
13586 break;
13588 case FT_FLOAT:
13589 return proto_tree_add_float_format(tree, hfindex, tvb, offset, length, *(float *)value_ptr,
13590 "%s: %s", str, value_str);
13591 break;
13593 default:
13594 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_tree_add_bits_format_value()",
13595 hf_field->abbrev,
13596 hf_field->type,
13597 ftype_name(hf_field->type));
13598 return NULL;
13602 static proto_item *
13603 proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
13604 tvbuff_t *tvb, const unsigned bit_offset,
13605 const int no_of_bits, void *value_ptr,
13606 const unsigned encoding, char *value_str)
13608 proto_item *item;
13610 if ((item = _proto_tree_add_bits_format_value(tree, hfindex,
13611 tvb, bit_offset, no_of_bits,
13612 value_ptr, encoding, value_str))) {
13613 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
13614 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
13616 return item;
13619 #define CREATE_VALUE_STRING(tree,dst,format,ap) \
13620 va_start(ap, format); \
13621 dst = wmem_strdup_vprintf(PNODE_POOL(tree), format, ap); \
13622 va_end(ap);
13624 proto_item *
13625 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hfindex,
13626 tvbuff_t *tvb, const unsigned bit_offset,
13627 const int no_of_bits, uint32_t value,
13628 const unsigned encoding,
13629 const char *format, ...)
13631 va_list ap;
13632 char *dst;
13633 header_field_info *hf_field;
13635 CHECK_FOR_NULL_TREE(tree);
13637 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13639 switch (hf_field->type) {
13640 case FT_UINT8:
13641 case FT_UINT16:
13642 case FT_UINT24:
13643 case FT_UINT32:
13644 break;
13646 default:
13647 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
13648 hf_field->abbrev);
13649 return NULL;
13652 CREATE_VALUE_STRING(tree, dst, format, ap);
13654 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
13657 proto_item *
13658 proto_tree_add_uint64_bits_format_value(proto_tree *tree, const int hfindex,
13659 tvbuff_t *tvb, const unsigned bit_offset,
13660 const int no_of_bits, uint64_t value,
13661 const unsigned encoding,
13662 const char *format, ...)
13664 va_list ap;
13665 char *dst;
13666 header_field_info *hf_field;
13668 CHECK_FOR_NULL_TREE(tree);
13670 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13672 switch (hf_field->type) {
13673 case FT_UINT40:
13674 case FT_UINT48:
13675 case FT_UINT56:
13676 case FT_UINT64:
13677 break;
13679 default:
13680 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, or FT_UINT64",
13681 hf_field->abbrev);
13682 return NULL;
13685 CREATE_VALUE_STRING(tree, dst, format, ap);
13687 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
13690 proto_item *
13691 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hfindex,
13692 tvbuff_t *tvb, const unsigned bit_offset,
13693 const int no_of_bits, float value,
13694 const unsigned encoding,
13695 const char *format, ...)
13697 va_list ap;
13698 char *dst;
13699 header_field_info *hf_field;
13701 CHECK_FOR_NULL_TREE(tree);
13703 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13705 DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_FLOAT);
13707 CREATE_VALUE_STRING(tree, dst, format, ap);
13709 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
13712 proto_item *
13713 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hfindex,
13714 tvbuff_t *tvb, const unsigned bit_offset,
13715 const int no_of_bits, int32_t value,
13716 const unsigned encoding,
13717 const char *format, ...)
13719 va_list ap;
13720 char *dst;
13721 header_field_info *hf_field;
13723 CHECK_FOR_NULL_TREE(tree);
13725 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13727 switch (hf_field->type) {
13728 case FT_INT8:
13729 case FT_INT16:
13730 case FT_INT24:
13731 case FT_INT32:
13732 break;
13734 default:
13735 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
13736 hf_field->abbrev);
13737 return NULL;
13740 CREATE_VALUE_STRING(tree, dst, format, ap);
13742 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
13745 proto_item *
13746 proto_tree_add_int64_bits_format_value(proto_tree *tree, const int hfindex,
13747 tvbuff_t *tvb, const unsigned bit_offset,
13748 const int no_of_bits, int64_t value,
13749 const unsigned encoding,
13750 const char *format, ...)
13752 va_list ap;
13753 char *dst;
13754 header_field_info *hf_field;
13756 CHECK_FOR_NULL_TREE(tree);
13758 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13760 switch (hf_field->type) {
13761 case FT_INT40:
13762 case FT_INT48:
13763 case FT_INT56:
13764 case FT_INT64:
13765 break;
13767 default:
13768 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
13769 hf_field->abbrev);
13770 return NULL;
13773 CREATE_VALUE_STRING(tree, dst, format, ap);
13775 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
13778 proto_item *
13779 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hfindex,
13780 tvbuff_t *tvb, const unsigned bit_offset,
13781 const int no_of_bits, uint64_t value,
13782 const unsigned encoding,
13783 const char *format, ...)
13785 va_list ap;
13786 char *dst;
13787 header_field_info *hf_field;
13789 CHECK_FOR_NULL_TREE(tree);
13791 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13793 DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_BOOLEAN);
13795 CREATE_VALUE_STRING(tree, dst, format, ap);
13797 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
13800 proto_item *
13801 proto_tree_add_ts_23_038_7bits_packed_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
13802 const unsigned bit_offset, const int no_of_chars)
13804 proto_item *pi;
13805 header_field_info *hfinfo;
13806 int byte_length;
13807 int byte_offset;
13808 char *string;
13810 CHECK_FOR_NULL_TREE(tree);
13812 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
13814 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_STRING);
13816 byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3;
13817 byte_offset = bit_offset >> 3;
13819 string = tvb_get_ts_23_038_7bits_string_packed(PNODE_POOL(tree), tvb, bit_offset, no_of_chars);
13821 pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length);
13822 DISSECTOR_ASSERT(byte_length >= 0);
13823 proto_tree_set_string(PNODE_FINFO(pi), string);
13825 return pi;
13828 proto_item *
13829 proto_tree_add_ascii_7bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
13830 const unsigned bit_offset, const int no_of_chars)
13832 proto_item *pi;
13833 header_field_info *hfinfo;
13834 int byte_length;
13835 int byte_offset;
13836 char *string;
13838 CHECK_FOR_NULL_TREE(tree);
13840 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
13842 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_STRING);
13844 byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3;
13845 byte_offset = bit_offset >> 3;
13847 string = tvb_get_ascii_7bits_string(PNODE_POOL(tree), tvb, bit_offset, no_of_chars);
13849 pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length);
13850 DISSECTOR_ASSERT(byte_length >= 0);
13851 proto_tree_set_string(PNODE_FINFO(pi), string);
13853 return pi;
13856 const value_string proto_checksum_vals[] = {
13857 { PROTO_CHECKSUM_E_BAD, "Bad" },
13858 { PROTO_CHECKSUM_E_GOOD, "Good" },
13859 { PROTO_CHECKSUM_E_UNVERIFIED, "Unverified" },
13860 { PROTO_CHECKSUM_E_NOT_PRESENT, "Not present" },
13861 { PROTO_CHECKSUM_E_ILLEGAL, "Illegal" },
13863 { 0, NULL }
13866 proto_item *
13867 proto_tree_add_checksum(proto_tree *tree, tvbuff_t *tvb, const unsigned offset,
13868 const int hf_checksum, const int hf_checksum_status, struct expert_field* bad_checksum_expert,
13869 packet_info *pinfo, uint32_t computed_checksum, const unsigned encoding, const unsigned flags)
13871 header_field_info *hfinfo;
13872 uint32_t checksum;
13873 uint32_t len;
13874 proto_item* ti = NULL;
13875 proto_item* ti2;
13876 bool incorrect_checksum = true;
13878 PROTO_REGISTRAR_GET_NTH(hf_checksum, hfinfo);
13880 switch (hfinfo->type) {
13881 case FT_UINT8:
13882 len = 1;
13883 break;
13884 case FT_UINT16:
13885 len = 2;
13886 break;
13887 case FT_UINT24:
13888 len = 3;
13889 break;
13890 case FT_UINT32:
13891 len = 4;
13892 break;
13893 default:
13894 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
13895 hfinfo->abbrev);
13898 if (flags & PROTO_CHECKSUM_NOT_PRESENT) {
13899 ti = proto_tree_add_uint_format_value(tree, hf_checksum, tvb, offset, len, 0, "[missing]");
13900 proto_item_set_generated(ti);
13901 if (hf_checksum_status != -1) {
13902 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, len, PROTO_CHECKSUM_E_NOT_PRESENT);
13903 proto_item_set_generated(ti2);
13905 return ti;
13908 if (flags & PROTO_CHECKSUM_GENERATED) {
13909 ti = proto_tree_add_uint(tree, hf_checksum, tvb, offset, len, computed_checksum);
13910 proto_item_set_generated(ti);
13911 } else {
13912 ti = proto_tree_add_item_ret_uint(tree, hf_checksum, tvb, offset, len, encoding, &checksum);
13913 if (flags & PROTO_CHECKSUM_VERIFY) {
13914 if (flags & (PROTO_CHECKSUM_IN_CKSUM|PROTO_CHECKSUM_ZERO)) {
13915 if (computed_checksum == 0) {
13916 proto_item_append_text(ti, " [correct]");
13917 if (hf_checksum_status != -1) {
13918 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
13919 proto_item_set_generated(ti2);
13921 incorrect_checksum = false;
13922 } else if (flags & PROTO_CHECKSUM_IN_CKSUM) {
13923 computed_checksum = in_cksum_shouldbe(checksum, computed_checksum);
13925 } else {
13926 if (checksum == computed_checksum) {
13927 proto_item_append_text(ti, " [correct]");
13928 if (hf_checksum_status != -1) {
13929 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
13930 proto_item_set_generated(ti2);
13932 incorrect_checksum = false;
13936 if (incorrect_checksum) {
13937 if (hf_checksum_status != -1) {
13938 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_BAD);
13939 proto_item_set_generated(ti2);
13941 if (flags & PROTO_CHECKSUM_ZERO) {
13942 proto_item_append_text(ti, " [incorrect]");
13943 if (bad_checksum_expert != NULL)
13944 expert_add_info_format(pinfo, ti, bad_checksum_expert, "%s", expert_get_summary(bad_checksum_expert));
13945 } else {
13946 proto_item_append_text(ti, " incorrect, should be 0x%0*x", len*2, computed_checksum);
13947 if (bad_checksum_expert != NULL)
13948 expert_add_info_format(pinfo, ti, bad_checksum_expert, "%s [should be 0x%0*x]", expert_get_summary(bad_checksum_expert), len * 2, computed_checksum);
13951 } else {
13952 if (hf_checksum_status != -1) {
13953 proto_item_append_text(ti, " [unverified]");
13954 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_UNVERIFIED);
13955 proto_item_set_generated(ti2);
13960 return ti;
13963 proto_item *
13964 proto_tree_add_checksum_bytes(proto_tree *tree, tvbuff_t *tvb, const unsigned offset,
13965 const int hf_checksum, const int hf_checksum_status, struct expert_field* bad_checksum_expert,
13966 packet_info *pinfo, const uint8_t *computed_checksum, size_t checksum_len, const unsigned flags)
13968 header_field_info *hfinfo;
13969 uint8_t *checksum = NULL;
13970 proto_item* ti = NULL;
13971 proto_item* ti2;
13972 bool incorrect_checksum = true;
13974 PROTO_REGISTRAR_GET_NTH(hf_checksum, hfinfo);
13976 if (hfinfo->type != FT_BYTES) {
13977 REPORT_DISSECTOR_BUG("field %s is not of type FT_BYTES",
13978 hfinfo->abbrev);
13981 if (flags & PROTO_CHECKSUM_NOT_PRESENT) {
13982 ti = proto_tree_add_bytes_format_value(tree, hf_checksum, tvb, offset, (int)checksum_len, 0, "[missing]");
13983 proto_item_set_generated(ti);
13984 if (hf_checksum_status != -1) {
13985 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, (int)checksum_len, PROTO_CHECKSUM_E_NOT_PRESENT);
13986 proto_item_set_generated(ti2);
13988 return ti;
13991 if (flags & PROTO_CHECKSUM_GENERATED) {
13992 ti = proto_tree_add_bytes(tree, hf_checksum, tvb, offset, (int)checksum_len, computed_checksum);
13993 proto_item_set_generated(ti);
13994 } else {
13995 checksum = (uint8_t*)wmem_alloc0_array(wmem_packet_scope(), uint8_t, checksum_len);
13996 tvb_memcpy(tvb, checksum, offset, checksum_len);
13997 ti = proto_tree_add_bytes(tree, hf_checksum, tvb, offset, (int)checksum_len, checksum);
13998 if (flags & PROTO_CHECKSUM_VERIFY) {
13999 if (flags & (PROTO_CHECKSUM_IN_CKSUM|PROTO_CHECKSUM_ZERO)) {
14000 if (computed_checksum == 0) {
14001 proto_item_append_text(ti, " [correct]");
14002 if (hf_checksum_status != -1) {
14003 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
14004 proto_item_set_generated(ti2);
14006 incorrect_checksum = false;
14008 } else {
14009 if (memcmp(computed_checksum, checksum, checksum_len) == 0) {
14010 proto_item_append_text(ti, " [correct]");
14011 if (hf_checksum_status != -1) {
14012 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
14013 proto_item_set_generated(ti2);
14015 incorrect_checksum = false;
14019 if (incorrect_checksum) {
14020 if (hf_checksum_status != -1) {
14021 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_BAD);
14022 proto_item_set_generated(ti2);
14024 if (flags & PROTO_CHECKSUM_ZERO) {
14025 proto_item_append_text(ti, " [incorrect]");
14026 if (bad_checksum_expert != NULL)
14027 expert_add_info_format(pinfo, ti, bad_checksum_expert, "%s", expert_get_summary(bad_checksum_expert));
14028 } else {
14029 size_t computed_checksum_str_len = (2 * checksum_len * sizeof(char)) + 1;
14030 char *computed_checksum_str = (char*)wmem_alloc0_array(wmem_packet_scope(), char, computed_checksum_str_len);
14031 for (size_t counter = 0; counter < checksum_len; ++counter) {
14032 snprintf(
14033 /* On ecah iteration inserts two characters */
14034 (char*)&computed_checksum_str[counter << 1],
14035 computed_checksum_str_len - (counter << 1),
14036 "%02x",
14037 computed_checksum[counter]);
14039 proto_item_append_text(ti, " incorrect, should be 0x%s", computed_checksum_str);
14040 if (bad_checksum_expert != NULL)
14041 expert_add_info_format(pinfo, ti, bad_checksum_expert, "%s [should be 0x%s]", expert_get_summary(bad_checksum_expert), computed_checksum_str);
14044 } else {
14045 if (hf_checksum_status != -1) {
14046 proto_item_append_text(ti, " [unverified]");
14047 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_UNVERIFIED);
14048 proto_item_set_generated(ti2);
14053 return ti;
14056 unsigned char
14057 proto_check_field_name(const char *field_name)
14059 return module_check_valid_name(field_name, false);
14062 unsigned char
14063 proto_check_field_name_lower(const char *field_name)
14065 return module_check_valid_name(field_name, true);
14068 bool
14069 tree_expanded(int tree_type)
14071 if (tree_type <= 0) {
14072 return false;
14074 ws_assert(tree_type >= 0 && tree_type < num_tree_types);
14075 return tree_is_expanded[tree_type >> 5] & (1U << (tree_type & 31));
14078 void
14079 tree_expanded_set(int tree_type, bool value)
14081 ws_assert(tree_type >= 0 && tree_type < num_tree_types);
14083 if (value)
14084 tree_is_expanded[tree_type >> 5] |= (1U << (tree_type & 31));
14085 else
14086 tree_is_expanded[tree_type >> 5] &= ~(1U << (tree_type & 31));
14090 * Editor modelines - https://www.wireshark.org/tools/modelines.html
14092 * Local variables:
14093 * c-basic-offset: 8
14094 * tab-width: 8
14095 * indent-tabs-mode: t
14096 * End:
14098 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
14099 * :indentSize=8:tabSize=8:noTabs=false: