regen pidl all: rm epan/dissectors/pidl/*-stamp; pushd epan/dissectors/pidl/ && make...
[wireshark-sm.git] / epan / proto.c
blobabae72971cd5c589f677388248180066fafcc290
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 visible \
129 because that means we can change its length or repr, and we \
130 don't want to do so with calls intended for this faked new \
131 item, so this item needs a new (hidden) child node. \
132 We fake FT_PROTOCOL unless some clients have requested us \
133 not to do so. \
134 */ \
135 PTREE_DATA(tree)->count++; \
136 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
137 if (PTREE_DATA(tree)->count > prefs.gui_max_tree_items) { \
138 free_block; \
139 if (wireshark_abort_on_too_many_items) \
140 ws_error("Adding %s would put more than %d items in the tree -- possible infinite loop (max number of items can be increased in advanced preferences)", \
141 hfinfo->abbrev, prefs.gui_max_tree_items); \
142 /* Let the exception handler add items to the tree */ \
143 PTREE_DATA(tree)->count = 0; \
144 THROW_MESSAGE(DissectorError, \
145 wmem_strdup_printf(PNODE_POOL(tree), \
146 "Adding %s would put more than %d items in the tree -- possible infinite loop (max number of items can be increased in advanced preferences)", \
147 hfinfo->abbrev, prefs.gui_max_tree_items)); \
149 if (!(PTREE_DATA(tree)->visible)) { \
150 if (PROTO_ITEM_IS_HIDDEN(tree)) { \
151 if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
152 && (hfinfo->ref_type != HF_REF_TYPE_PRINT) \
153 && (hfinfo->type != FT_PROTOCOL || \
154 PTREE_DATA(tree)->fake_protocols)) { \
155 free_block; \
156 /* return fake node with no field info */\
157 return proto_tree_add_fake_node(tree, hfinfo); \
162 /** See inlined comments.
163 @param tree the tree to append this item to
164 @param hfindex field index
165 @param hfinfo header_field
166 @return the header field matching 'hfinfo' */
167 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
168 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, ((void)0))
171 /** See inlined comments.
172 @param pi the created protocol item we're about to return */
173 #define TRY_TO_FAKE_THIS_REPR(pi) \
174 ws_assert(pi); \
175 if (!PITEM_FINFO(pi)) \
176 return pi; \
177 if (!(PTREE_DATA(pi)->visible) && \
178 PROTO_ITEM_IS_HIDDEN(pi)) { \
179 /* If the tree (GUI) or item isn't visible it's pointless for \
180 * us to generate the protocol item's string representation */ \
181 return pi; \
183 /* Same as above but returning void */
184 #define TRY_TO_FAKE_THIS_REPR_VOID(pi) \
185 if (!pi || !PITEM_FINFO(pi)) \
186 return; \
187 if (!(PTREE_DATA(pi)->visible) && \
188 PROTO_ITEM_IS_HIDDEN(pi)) { \
189 /* If the tree (GUI) or item isn't visible it's pointless for \
190 * us to generate the protocol item's string representation */ \
191 return; \
193 /* Similar to above, but allows a NULL tree */
194 #define TRY_TO_FAKE_THIS_REPR_NESTED(pi) \
195 if ((pi == NULL) || (PITEM_FINFO(pi) == NULL) || (!(PTREE_DATA(pi)->visible) && \
196 PROTO_ITEM_IS_HIDDEN(pi))) { \
197 /* If the tree (GUI) or item isn't visible it's pointless for \
198 * us to generate the protocol item's string representation */ \
199 return pi; \
202 #ifdef ENABLE_CHECK_FILTER
203 #define CHECK_HF_VALUE(type, spec, start_values) \
205 const type *current; \
206 int n, m; \
207 current = start_values; \
208 for (n=0; current; n++, current++) { \
209 /* Drop out if we reached the end. */ \
210 if ((current->value == 0) && (current->strptr == NULL)) { \
211 break; \
213 /* Check value against all previous */ \
214 for (m=0; m < n; m++) { \
215 /* There are lots of duplicates with the same string, \
216 so only report if different... */ \
217 if ((start_values[m].value == current->value) && \
218 (strcmp(start_values[m].strptr, current->strptr) != 0)) { \
219 ws_warning("Field '%s' (%s) has a conflicting entry in its" \
220 " value_string: %" spec " is at indices %u (%s) and %u (%s)", \
221 hfinfo->name, hfinfo->abbrev, \
222 current->value, m, start_values[m].strptr, n, current->strptr); \
227 #endif
229 /* The longest NUMBER-like field label we have is for BASE_OUI, which
230 * can have up to 64 bytes for the manufacturer name if resolved plus
231 * 11 bytes for the "XX:XX:XX ()" part = 75 octets.
233 #define NUMBER_LABEL_LENGTH 80
235 static const char *hf_try_val_to_str(uint32_t value, const header_field_info *hfinfo);
236 static const char *hf_try_val64_to_str(uint64_t value, const header_field_info *hfinfo);
237 static const char *hf_try_val_to_str_const(uint32_t value, const header_field_info *hfinfo, const char *unknown_str);
238 static const char *hf_try_val64_to_str_const(uint64_t value, const header_field_info *hfinfo, const char *unknown_str);
239 static int hfinfo_bitoffset(const header_field_info *hfinfo);
240 static int hfinfo_mask_bitwidth(const header_field_info *hfinfo);
241 static int hfinfo_container_bitwidth(const header_field_info *hfinfo);
243 #define label_concat(dst, pos, src) \
244 ws_label_strcpy(dst, ITEM_LABEL_LENGTH, pos, src, 0)
246 static void mark_truncated(char *label_str, size_t name_pos, const size_t size, size_t *value_pos);
247 static void label_mark_truncated(char *label_str, size_t name_pos, size_t *value_pos);
248 #define LABEL_MARK_TRUNCATED_START(label_str, value_pos) label_mark_truncated(label_str, 0, value_pos)
250 static void fill_label_boolean(const field_info *fi, char *label_str, size_t *value_pos);
251 static void fill_label_bitfield_char(const field_info *fi, char *label_str, size_t *value_pos);
252 static void fill_label_bitfield(const field_info *fi, char *label_str, size_t *value_pos, bool is_signed);
253 static void fill_label_bitfield64(const field_info *fi, char *label_str, size_t *value_pos, bool is_signed);
254 static void fill_label_char(const field_info *fi, char *label_str, size_t *value_pos);
255 static void fill_label_number(const field_info *fi, char *label_str, size_t *value_pos, bool is_signed);
256 static void fill_label_number64(const field_info *fi, char *label_str, size_t *value_pos, bool is_signed);
258 static size_t fill_display_label_float(const field_info *fi, char *label_str);
259 static void fill_label_float(const field_info *fi, char *label_str, size_t *value_pos);
261 static const char *hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[NUMBER_LABEL_LENGTH], uint32_t value);
262 static const char *hfinfo_number_value_format_display64(const header_field_info *hfinfo, int display, char buf[NUMBER_LABEL_LENGTH], uint64_t value);
263 static const char *hfinfo_char_vals_format(const header_field_info *hfinfo, char buf[32], uint32_t value);
264 static const char *hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint32_t value);
265 static const char *hfinfo_number_vals_format64(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint64_t value);
266 static const char *hfinfo_number_value_format(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint32_t value);
267 static const char *hfinfo_number_value_format64(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint64_t value);
268 static const char *hfinfo_char_value_format(const header_field_info *hfinfo, char buf[32], uint32_t value);
269 static const char *hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint32_t value);
270 static const char *hfinfo_numeric_value_format64(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint64_t value);
272 static void proto_cleanup_base(void);
274 static proto_item *
275 proto_tree_add_node(proto_tree *tree, field_info *fi);
277 static proto_item *
278 proto_tree_add_fake_node(proto_tree *tree, const header_field_info *hfinfo);
280 static void
281 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const int start, int *length,
282 int *item_length, const unsigned encoding);
284 static int
285 get_full_length(header_field_info *hfinfo, tvbuff_t *tvb, const int start,
286 int length, unsigned item_length, const int encoding);
288 static field_info *
289 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
290 const int start, const int item_length);
292 static proto_item *
293 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
294 int start, int *length);
296 static void
297 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
298 static void
299 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
301 static void
302 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb, const char* field_data, int length);
303 static void
304 proto_tree_set_bytes(field_info *fi, const uint8_t* start_ptr, int length);
305 static void
306 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, int offset, int length);
307 static void
308 proto_tree_set_bytes_gbytearray(field_info *fi, const GByteArray *value);
309 static void
310 proto_tree_set_time(field_info *fi, const nstime_t *value_ptr);
311 static void
312 proto_tree_set_string(field_info *fi, const char* value);
313 static void
314 proto_tree_set_ax25(field_info *fi, const uint8_t* value);
315 static void
316 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, int start);
317 static void
318 proto_tree_set_vines(field_info *fi, const uint8_t* value);
319 static void
320 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, int start);
321 static void
322 proto_tree_set_ether(field_info *fi, const uint8_t* value);
323 static void
324 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, int start);
325 static void
326 proto_tree_set_ipxnet(field_info *fi, uint32_t value);
327 static void
328 proto_tree_set_ipv4(field_info *fi, ws_in4_addr value);
329 static void
330 proto_tree_set_ipv6(field_info *fi, const ws_in6_addr* value);
331 static void
332 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, int start, int length);
333 static void
334 proto_tree_set_fcwwn_tvb(field_info *fi, tvbuff_t *tvb, int start, int length);
335 static void
336 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
337 static void
338 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, int start, const unsigned encoding);
339 static void
340 proto_tree_set_oid(field_info *fi, const uint8_t* value_ptr, int length);
341 static void
342 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, int start, int length);
343 static void
344 proto_tree_set_system_id(field_info *fi, const uint8_t* value_ptr, int length);
345 static void
346 proto_tree_set_system_id_tvb(field_info *fi, tvbuff_t *tvb, int start, int length);
347 static void
348 proto_tree_set_boolean(field_info *fi, uint64_t value);
349 static void
350 proto_tree_set_float(field_info *fi, float value);
351 static void
352 proto_tree_set_double(field_info *fi, double value);
353 static void
354 proto_tree_set_uint(field_info *fi, uint32_t value);
355 static void
356 proto_tree_set_int(field_info *fi, int32_t value);
357 static void
358 proto_tree_set_uint64(field_info *fi, uint64_t value);
359 static void
360 proto_tree_set_int64(field_info *fi, int64_t value);
361 static void
362 proto_tree_set_eui64(field_info *fi, const uint64_t value);
363 static void
364 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, int start, const unsigned encoding);
366 /* Handle type length mismatch (now filterable) expert info */
367 static int proto_type_length_mismatch;
368 static expert_field ei_type_length_mismatch_error;
369 static expert_field ei_type_length_mismatch_warn;
370 static void register_type_length_mismatch(void);
372 /* Handle byte array string decoding errors with expert info */
373 static int proto_byte_array_string_decoding_error;
374 static expert_field ei_byte_array_string_decoding_failed_error;
375 static void register_byte_array_string_decodinws_error(void);
377 /* Handle date and time string decoding errors with expert info */
378 static int proto_date_time_string_decoding_error;
379 static expert_field ei_date_time_string_decoding_failed_error;
380 static void register_date_time_string_decodinws_error(void);
382 /* Handle string errors expert info */
383 static int proto_string_errors;
384 static expert_field ei_string_trailing_characters;
385 static void register_string_errors(void);
387 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
389 /* special-case header field used within proto.c */
390 static header_field_info hfi_text_only =
391 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
392 int hf_text_only;
394 /* Structure for information about a protocol */
395 struct _protocol {
396 const char *name; /* long description */
397 const char *short_name; /* short description */
398 const char *filter_name; /* name of this protocol in filters */
399 GPtrArray *fields; /* fields for this protocol */
400 int proto_id; /* field ID for this protocol */
401 bool is_enabled; /* true if protocol is enabled */
402 bool enabled_by_default; /* true if protocol is enabled by default */
403 bool can_toggle; /* true if is_enabled can be changed */
404 int parent_proto_id; /* Used to identify "pino"s (Protocol In Name Only).
405 For dissectors that need a protocol name so they
406 can be added to a dissector table, but use the
407 parent_proto_id for things like enable/disable */
408 GList *heur_list; /* Heuristic dissectors associated with this protocol */
411 /* List of all protocols */
412 static GList *protocols;
414 /* Structure stored for deregistered g_slice */
415 struct g_slice_data {
416 size_t block_size;
417 void *mem_block;
420 /* Deregistered fields */
421 static GPtrArray *deregistered_fields;
422 static GPtrArray *deregistered_data;
423 static GPtrArray *deregistered_slice;
425 /* indexed by prefix, contains initializers */
426 static GHashTable* prefixes;
428 /* Contains information about a field when a dissector calls
429 * proto_tree_add_item. */
430 #define FIELD_INFO_NEW(pool, fi) fi = wmem_new(pool, field_info)
431 #define FIELD_INFO_FREE(pool, fi) wmem_free(pool, fi)
433 /* Contains the space for proto_nodes. */
434 #define PROTO_NODE_INIT(node) \
435 node->first_child = NULL; \
436 node->last_child = NULL; \
437 node->next = NULL;
439 #define PROTO_NODE_FREE(pool, node) \
440 wmem_free(pool, node)
442 /* String space for protocol and field items for the GUI */
443 #define ITEM_LABEL_NEW(pool, il) \
444 il = wmem_new(pool, item_label_t); \
445 il->value_pos = 0; \
446 il->value_len = 0;
447 #define ITEM_LABEL_FREE(pool, il) \
448 wmem_free(pool, il);
450 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
451 if((hfindex == 0 || (unsigned)hfindex > gpa_hfinfo.len) && wireshark_abort_on_dissector_bug) \
452 ws_error("Unregistered hf! index=%d", hfindex); \
453 DISSECTOR_ASSERT_HINT(hfindex > 0 && (unsigned)hfindex < gpa_hfinfo.len, "Unregistered hf!"); \
454 DISSECTOR_ASSERT_HINT(gpa_hfinfo.hfi[hfindex] != NULL, "Unregistered hf!"); \
455 hfinfo = gpa_hfinfo.hfi[hfindex];
457 /* List which stores protocols and fields that have been registered */
458 typedef struct _gpa_hfinfo_t {
459 uint32_t len;
460 uint32_t allocated_len;
461 header_field_info **hfi;
462 } gpa_hfinfo_t;
464 static gpa_hfinfo_t gpa_hfinfo;
466 /* Hash table of abbreviations and IDs */
467 static GHashTable *gpa_name_map;
468 static header_field_info *same_name_hfinfo;
470 /* Hash table protocol aliases. const char * -> const char * */
471 static GHashTable *gpa_protocol_aliases;
474 * We're called repeatedly with the same field name when sorting a column.
475 * Cache our last gpa_name_map hit for faster lookups.
477 static char *last_field_name;
478 static header_field_info *last_hfinfo;
480 static void save_same_name_hfinfo(void *data)
482 same_name_hfinfo = (header_field_info*)data;
485 /* Points to the first element of an array of bits, indexed by
486 a subtree item type; that array element is true if subtrees of
487 an item of that type are to be expanded. */
488 static uint32_t *tree_is_expanded;
490 /* Number of elements in that array. The entry with index 0 is not used. */
491 int num_tree_types = 1;
493 /* Name hashtables for fast detection of duplicate names */
494 static GHashTable* proto_names;
495 static GHashTable* proto_short_names;
496 static GHashTable* proto_filter_names;
498 static const char *reserved_filter_names[] = {
499 /* Display filter keywords. */
500 "eq",
501 "ne",
502 "all_eq",
503 "any_eq",
504 "all_ne",
505 "any_ne",
506 "gt",
507 "ge",
508 "lt",
509 "le",
510 "bitand",
511 "bitwise_and",
512 "contains",
513 "matches",
514 "not",
515 "and",
516 "or",
517 "xor",
518 "in",
519 "any",
520 "all",
521 "true",
522 "false",
523 "nan",
524 "inf",
525 "infinity",
526 NULL
529 static GHashTable *proto_reserved_filter_names;
531 static int
532 proto_compare_name(const void *p1_arg, const void *p2_arg)
534 const protocol_t *p1 = (const protocol_t *)p1_arg;
535 const protocol_t *p2 = (const protocol_t *)p2_arg;
537 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
540 static GSList *dissector_plugins;
542 #ifdef HAVE_PLUGINS
543 void
544 proto_register_plugin(const proto_plugin *plug)
546 dissector_plugins = g_slist_prepend(dissector_plugins, (proto_plugin *)plug);
548 #else /* HAVE_PLUGINS */
549 void
550 proto_register_plugin(const proto_plugin *plug _U_)
552 ws_warning("proto_register_plugin: built without support for binary plugins");
554 #endif /* HAVE_PLUGINS */
556 static void
557 call_plugin_register_protoinfo(void *data, void *user_data _U_)
559 proto_plugin *plug = (proto_plugin *)data;
561 if (plug->register_protoinfo) {
562 plug->register_protoinfo();
566 static void
567 call_plugin_register_handoff(void *data, void *user_data _U_)
569 proto_plugin *plug = (proto_plugin *)data;
571 if (plug->register_handoff) {
572 plug->register_handoff();
576 /* initialize data structures and register protocols and fields */
577 void
578 proto_init(GSList *register_all_plugin_protocols_list,
579 GSList *register_all_plugin_handoffs_list,
580 register_cb cb,
581 void *client_data)
583 proto_cleanup_base();
585 proto_names = g_hash_table_new(g_str_hash, g_str_equal);
586 proto_short_names = g_hash_table_new(g_str_hash, g_str_equal);
587 proto_filter_names = g_hash_table_new(g_str_hash, g_str_equal);
589 proto_reserved_filter_names = g_hash_table_new(g_str_hash, g_str_equal);
590 for (const char **ptr = reserved_filter_names; *ptr != NULL; ptr++) {
591 /* GHashTable has no key destructor so the cast is safe. */
592 g_hash_table_add(proto_reserved_filter_names, *(char **)ptr);
595 gpa_hfinfo.len = 0;
596 gpa_hfinfo.allocated_len = 0;
597 gpa_hfinfo.hfi = NULL;
598 gpa_name_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, save_same_name_hfinfo);
599 gpa_protocol_aliases = g_hash_table_new(g_str_hash, g_str_equal);
600 deregistered_fields = g_ptr_array_new();
601 deregistered_data = g_ptr_array_new();
602 deregistered_slice = g_ptr_array_new();
604 /* Initialize the ftype subsystem */
605 ftypes_initialize();
607 /* Initialize the address type subsystem */
608 address_types_initialize();
610 /* Register one special-case FT_TEXT_ONLY field for use when
611 converting wireshark to new-style proto_tree. These fields
612 are merely strings on the GUI tree; they are not filterable */
613 hf_text_only = proto_register_field_init(&hfi_text_only, -1);
615 /* Register the pseudo-protocols used for exceptions. */
616 register_show_exception();
617 register_type_length_mismatch();
618 register_byte_array_string_decodinws_error();
619 register_date_time_string_decodinws_error();
620 register_string_errors();
621 ftypes_register_pseudofields();
622 col_register_protocol();
624 /* Have each built-in dissector register its protocols, fields,
625 dissector tables, and dissectors to be called through a
626 handle, and do whatever one-time initialization it needs to
627 do. */
628 register_all_protocols(cb, client_data);
630 /* Now call the registration routines for all epan plugins. */
631 for (GSList *l = register_all_plugin_protocols_list; l != NULL; l = l->next) {
632 ((void (*)(register_cb, void *))l->data)(cb, client_data);
635 /* Now call the registration routines for all dissector plugins. */
636 if (cb)
637 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
638 g_slist_foreach(dissector_plugins, call_plugin_register_protoinfo, NULL);
640 /* Now call the "handoff registration" routines of all built-in
641 dissectors; those routines register the dissector in other
642 dissectors' handoff tables, and fetch any dissector handles
643 they need. */
644 register_all_protocol_handoffs(cb, client_data);
646 /* Now do the same with epan plugins. */
647 for (GSList *l = register_all_plugin_handoffs_list; l != NULL; l = l->next) {
648 ((void (*)(register_cb, void *))l->data)(cb, client_data);
651 /* Now do the same with dissector plugins. */
652 if (cb)
653 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
654 g_slist_foreach(dissector_plugins, call_plugin_register_handoff, NULL);
656 /* sort the protocols by protocol name */
657 protocols = g_list_sort(protocols, proto_compare_name);
659 /* sort the dissector handles in dissector tables (for -G reports
660 * and -d error messages. The GUI sorts the handles itself.) */
661 packet_all_tables_sort_handles();
663 /* We've assigned all the subtree type values; allocate the array
664 for them, and zero it out. */
665 tree_is_expanded = g_new0(uint32_t, (num_tree_types/32)+1);
668 static void
669 proto_cleanup_base(void)
671 protocol_t *protocol;
672 header_field_info *hfinfo;
674 /* Free the abbrev/ID hash table */
675 if (gpa_name_map) {
676 g_hash_table_destroy(gpa_name_map);
677 gpa_name_map = NULL;
679 if (gpa_protocol_aliases) {
680 g_hash_table_destroy(gpa_protocol_aliases);
681 gpa_protocol_aliases = NULL;
683 g_free(last_field_name);
684 last_field_name = NULL;
686 while (protocols) {
687 protocol = (protocol_t *)protocols->data;
688 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
689 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
691 g_slice_free(header_field_info, hfinfo);
692 if (protocol->parent_proto_id != -1) {
693 // pino protocol
694 DISSECTOR_ASSERT(protocol->fields == NULL); //helpers should not have any registered fields
695 DISSECTOR_ASSERT(protocol->heur_list == NULL); //helpers should not have a heuristic list
696 } else {
697 if (protocol->fields) {
698 g_ptr_array_free(protocol->fields, true);
700 g_list_free(protocol->heur_list);
702 protocols = g_list_remove(protocols, protocol);
703 g_free(protocol);
706 if (proto_names) {
707 g_hash_table_destroy(proto_names);
708 proto_names = NULL;
711 if (proto_short_names) {
712 g_hash_table_destroy(proto_short_names);
713 proto_short_names = NULL;
716 if (proto_filter_names) {
717 g_hash_table_destroy(proto_filter_names);
718 proto_filter_names = NULL;
721 if (proto_reserved_filter_names) {
722 g_hash_table_destroy(proto_reserved_filter_names);
723 proto_reserved_filter_names = NULL;
726 if (gpa_hfinfo.allocated_len) {
727 gpa_hfinfo.len = 0;
728 gpa_hfinfo.allocated_len = 0;
729 g_free(gpa_hfinfo.hfi);
730 gpa_hfinfo.hfi = NULL;
733 if (deregistered_fields) {
734 g_ptr_array_free(deregistered_fields, true);
735 deregistered_fields = NULL;
738 if (deregistered_data) {
739 g_ptr_array_free(deregistered_data, true);
740 deregistered_data = NULL;
743 if (deregistered_slice) {
744 g_ptr_array_free(deregistered_slice, true);
745 deregistered_slice = NULL;
748 g_free(tree_is_expanded);
749 tree_is_expanded = NULL;
751 if (prefixes)
752 g_hash_table_destroy(prefixes);
755 void
756 proto_cleanup(void)
758 proto_free_deregistered_fields();
759 proto_cleanup_base();
761 g_slist_free(dissector_plugins);
762 dissector_plugins = NULL;
765 static bool
766 // NOLINTNEXTLINE(misc-no-recursion)
767 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
768 void *data)
770 proto_node *pnode = tree;
771 proto_node *child;
772 proto_node *current;
774 if (func(pnode, data))
775 return true;
777 child = pnode->first_child;
778 while (child != NULL) {
780 * The routine we call might modify the child, e.g. by
781 * freeing it, so we get the child's successor before
782 * calling that routine.
784 current = child;
785 child = current->next;
786 // We recurse here, but we're limited by prefs.gui_max_tree_depth
787 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
788 return true;
791 return false;
794 void
795 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
796 void *data)
798 proto_node *node = tree;
799 proto_node *current;
801 if (!node)
802 return;
804 node = node->first_child;
805 while (node != NULL) {
806 current = node;
807 node = current->next;
808 func((proto_tree *)current, data);
812 static void
813 free_GPtrArray_value(void *key, void *value, void *user_data _U_)
815 GPtrArray *ptrs = (GPtrArray *)value;
816 int hfid = GPOINTER_TO_UINT(key);
817 header_field_info *hfinfo;
819 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
820 if (hfinfo->ref_type != HF_REF_TYPE_NONE) {
821 /* when a field is referenced by a filter this also
822 affects the refcount for the parent protocol so we need
823 to adjust the refcount for the parent as well
825 if (hfinfo->parent != -1) {
826 header_field_info *parent_hfinfo;
827 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
828 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
830 hfinfo->ref_type = HF_REF_TYPE_NONE;
833 g_ptr_array_free(ptrs, true);
836 static void
837 proto_tree_free_node(proto_node *node, void *data _U_)
839 field_info *finfo = PNODE_FINFO(node);
841 proto_tree_children_foreach(node, proto_tree_free_node, NULL);
843 if (finfo) {
844 fvalue_free(finfo->value);
845 finfo->value = NULL;
849 void
850 proto_tree_reset(proto_tree *tree)
852 tree_data_t *tree_data = PTREE_DATA(tree);
854 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
856 /* free tree data */
857 if (tree_data->interesting_hfids) {
858 /* Free all the GPtrArray's in the interesting_hfids hash. */
859 g_hash_table_foreach(tree_data->interesting_hfids,
860 free_GPtrArray_value, NULL);
862 /* And then remove all values. */
863 g_hash_table_remove_all(tree_data->interesting_hfids);
866 /* Reset track of the number of children */
867 tree_data->count = 0;
869 /* Reset our loop checks */
870 tree_data->max_start = 0;
871 tree_data->start_idle_count = 0;
873 PROTO_NODE_INIT(tree);
876 /* frees the resources that the dissection a proto_tree uses */
877 void
878 proto_tree_free(proto_tree *tree)
880 tree_data_t *tree_data = PTREE_DATA(tree);
882 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
884 /* free tree data */
885 if (tree_data->interesting_hfids) {
886 /* Free all the GPtrArray's in the interesting_hfids hash. */
887 g_hash_table_foreach(tree_data->interesting_hfids,
888 free_GPtrArray_value, NULL);
890 /* And then destroy the hash. */
891 g_hash_table_destroy(tree_data->interesting_hfids);
894 g_slice_free(tree_data_t, tree_data);
896 g_slice_free(proto_tree, tree);
899 /* Is the parsing being done for a visible proto_tree or an invisible one?
900 * By setting this correctly, the proto_tree creation is sped up by not
901 * having to call vsnprintf and copy strings around.
903 bool
904 proto_tree_set_visible(proto_tree *tree, bool visible)
906 bool old_visible = PTREE_DATA(tree)->visible;
908 PTREE_DATA(tree)->visible = visible;
910 return old_visible;
913 void
914 proto_tree_set_fake_protocols(proto_tree *tree, bool fake_protocols)
916 if (tree)
917 PTREE_DATA(tree)->fake_protocols = fake_protocols;
920 /* Assume dissector set only its protocol fields.
921 This function is called by dissectors and allows the speeding up of filtering
922 in wireshark; if this function returns false it is safe to reset tree to NULL
923 and thus skip calling most of the expensive proto_tree_add_...()
924 functions.
925 If the tree is visible we implicitly assume the field is referenced.
927 bool
928 proto_field_is_referenced(proto_tree *tree, int proto_id)
930 register header_field_info *hfinfo;
933 if (!tree)
934 return false;
936 if (PTREE_DATA(tree)->visible)
937 return true;
939 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
940 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
941 return true;
943 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
944 return true;
946 return false;
950 /* Finds a record in the hfinfo array by id. */
951 header_field_info *
952 proto_registrar_get_nth(unsigned hfindex)
954 register header_field_info *hfinfo;
956 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
957 return hfinfo;
961 /* Prefix initialization
962 * this allows for a dissector to register a display filter name prefix
963 * so that it can delay the initialization of the hf array as long as
964 * possible.
967 /* compute a hash for the part before the dot of a display filter */
968 static unsigned
969 prefix_hash (const void *key) {
970 /* end the string at the dot and compute its hash */
971 char* copy = g_strdup((const char *)key);
972 char* c = copy;
973 unsigned tmp;
975 for (; *c; c++) {
976 if (*c == '.') {
977 *c = 0;
978 break;
982 tmp = g_str_hash(copy);
983 g_free(copy);
984 return tmp;
987 /* are both strings equal up to the end or the dot? */
988 static gboolean
989 prefix_equal (const void *ap, const void *bp) {
990 const char* a = (const char *)ap;
991 const char* b = (const char *)bp;
993 do {
994 char ac = *a++;
995 char bc = *b++;
997 if ( (ac == '.' || ac == '\0') && (bc == '.' || bc == '\0') ) return TRUE;
999 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
1000 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
1002 if (ac != bc) return FALSE;
1003 } while (1);
1005 return FALSE;
1008 /* Register a new prefix for "delayed" initialization of field arrays */
1009 void
1010 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
1011 if (! prefixes ) {
1012 prefixes = g_hash_table_new(prefix_hash, prefix_equal);
1015 g_hash_table_insert(prefixes, (void *)prefix, (void *)pi);
1018 /* helper to call all prefix initializers */
1019 static gboolean
1020 initialize_prefix(void *k, void *v, void *u _U_) {
1021 ((prefix_initializer_t)v)((const char *)k);
1022 return TRUE;
1025 /** Initialize every remaining uninitialized prefix. */
1026 void
1027 proto_initialize_all_prefixes(void) {
1028 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
1031 /* Finds a record in the hfinfo array by name.
1032 * If it fails to find it in the already registered fields,
1033 * it tries to find and call an initializer in the prefixes
1034 * table and if so it looks again.
1037 header_field_info *
1038 proto_registrar_get_byname(const char *field_name)
1040 header_field_info *hfinfo;
1041 prefix_initializer_t pi;
1043 if (!field_name)
1044 return NULL;
1046 if (g_strcmp0(field_name, last_field_name) == 0) {
1047 return last_hfinfo;
1050 hfinfo = (header_field_info *)g_hash_table_lookup(gpa_name_map, field_name);
1052 if (hfinfo) {
1053 g_free(last_field_name);
1054 last_field_name = g_strdup(field_name);
1055 last_hfinfo = hfinfo;
1056 return hfinfo;
1059 if (!prefixes)
1060 return NULL;
1062 if ((pi = (prefix_initializer_t)g_hash_table_lookup(prefixes, field_name) ) != NULL) {
1063 pi(field_name);
1064 g_hash_table_remove(prefixes, field_name);
1065 } else {
1066 return NULL;
1069 hfinfo = (header_field_info *)g_hash_table_lookup(gpa_name_map, field_name);
1071 if (hfinfo) {
1072 g_free(last_field_name);
1073 last_field_name = g_strdup(field_name);
1074 last_hfinfo = hfinfo;
1076 return hfinfo;
1079 header_field_info*
1080 proto_registrar_get_byalias(const char *alias_name)
1082 if (!alias_name) {
1083 return NULL;
1086 /* Find our aliased protocol. */
1087 char *an_copy = g_strdup(alias_name);
1088 char *dot = strchr(an_copy, '.');
1089 if (dot) {
1090 *dot = '\0';
1092 const char *proto_pfx = (const char *) g_hash_table_lookup(gpa_protocol_aliases, an_copy);
1093 if (!proto_pfx) {
1094 g_free(an_copy);
1095 return NULL;
1098 /* Construct our aliased field and look it up. */
1099 GString *filter_name = g_string_new(proto_pfx);
1100 if (dot) {
1101 g_string_append_printf(filter_name, ".%s", dot+1);
1103 header_field_info *hfinfo = proto_registrar_get_byname(filter_name->str);
1104 g_free(an_copy);
1105 g_string_free(filter_name, TRUE);
1107 return hfinfo;
1111 proto_registrar_get_id_byname(const char *field_name)
1113 header_field_info *hfinfo;
1115 hfinfo = proto_registrar_get_byname(field_name);
1117 if (!hfinfo)
1118 return -1;
1120 return hfinfo->id;
1123 static int
1124 label_strcat_flags(const header_field_info *hfinfo)
1126 if (FIELD_DISPLAY(hfinfo->display) & BASE_STR_WSP)
1127 return FORMAT_LABEL_REPLACE_SPACE;
1129 return 0;
1132 static char *
1133 format_bytes_hfinfo_maxlen(wmem_allocator_t *scope, const header_field_info *hfinfo,
1134 const uint8_t *bytes, unsigned length, size_t max_str_len)
1136 char *str = NULL;
1137 const uint8_t *p;
1138 bool is_printable;
1140 if (bytes) {
1141 if (hfinfo->display & BASE_SHOW_UTF_8_PRINTABLE) {
1143 * If all bytes are valid and printable UTF-8, show the
1144 * bytes as a string - in quotes to indicate that it's
1145 * a string.
1147 if (isprint_utf8_string(bytes, length)) {
1148 str = wmem_strdup_printf(scope, "\"%.*s\"",
1149 (int)length, bytes);
1150 return str;
1152 } else if (hfinfo->display & BASE_SHOW_ASCII_PRINTABLE) {
1154 * Check whether all bytes are printable.
1156 is_printable = true;
1157 for (p = bytes; p < bytes+length; p++) {
1158 if (!g_ascii_isprint(*p)) {
1159 /* Not printable. */
1160 is_printable = false;
1161 break;
1166 * If all bytes are printable ASCII, show the bytes
1167 * as a string - in quotes to indicate that it's
1168 * a string.
1170 if (is_printable) {
1171 str = wmem_strdup_printf(scope, "\"%.*s\"",
1172 (int)length, bytes);
1173 return str;
1178 * Either it's not printable ASCII, or we don't care whether
1179 * it's printable ASCII; show it as hex bytes.
1181 switch (FIELD_DISPLAY(hfinfo->display)) {
1182 case SEP_DOT:
1183 str = bytes_to_str_punct_maxlen(scope, bytes, length, '.', max_str_len/3);
1184 break;
1185 case SEP_DASH:
1186 str = bytes_to_str_punct_maxlen(scope, bytes, length, '-', max_str_len/3);
1187 break;
1188 case SEP_COLON:
1189 str = bytes_to_str_punct_maxlen(scope, bytes, length, ':', max_str_len/3);
1190 break;
1191 case SEP_SPACE:
1192 str = bytes_to_str_punct_maxlen(scope, bytes, length, ' ', max_str_len/3);
1193 break;
1194 case BASE_NONE:
1195 default:
1196 if (prefs.display_byte_fields_with_spaces) {
1197 str = bytes_to_str_punct_maxlen(scope, bytes, length, ' ', max_str_len/3);
1198 } else {
1199 str = bytes_to_str_maxlen(scope, bytes, length, max_str_len/2);
1201 break;
1204 else {
1205 if (hfinfo->display & BASE_ALLOW_ZERO) {
1206 str = wmem_strdup(scope, "<none>");
1207 } else {
1208 str = wmem_strdup(scope, "<MISSING>");
1211 return str;
1214 static char *
1215 format_bytes_hfinfo(wmem_allocator_t *scope, const header_field_info *hfinfo,
1216 const uint8_t *bytes, unsigned length)
1218 return format_bytes_hfinfo_maxlen(scope, hfinfo, bytes, length, ITEM_LABEL_LENGTH);
1221 static void
1222 ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
1224 subtree_lvl *pushed_tree;
1226 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
1227 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
1229 pushed_tree = (subtree_lvl *)wmem_realloc(ptvc->scope, (void *)ptvc->pushed_tree, sizeof(subtree_lvl) * ptvc->pushed_tree_max);
1230 DISSECTOR_ASSERT(pushed_tree != NULL);
1231 ptvc->pushed_tree = pushed_tree;
1234 static void
1235 ptvcursor_free_subtree_levels(ptvcursor_t *ptvc)
1237 ptvc->pushed_tree = NULL;
1238 ptvc->pushed_tree_max = 0;
1239 DISSECTOR_ASSERT(ptvc->pushed_tree_index == 0);
1240 ptvc->pushed_tree_index = 0;
1243 /* Allocates an initializes a ptvcursor_t with 3 variables:
1244 * proto_tree, tvbuff, and offset. */
1245 ptvcursor_t *
1246 ptvcursor_new(wmem_allocator_t *scope, proto_tree *tree, tvbuff_t *tvb, int offset)
1248 ptvcursor_t *ptvc;
1250 ptvc = wmem_new(scope, ptvcursor_t);
1251 ptvc->scope = scope;
1252 ptvc->tree = tree;
1253 ptvc->tvb = tvb;
1254 ptvc->offset = offset;
1255 ptvc->pushed_tree = NULL;
1256 ptvc->pushed_tree_max = 0;
1257 ptvc->pushed_tree_index = 0;
1258 return ptvc;
1262 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
1263 void
1264 ptvcursor_free(ptvcursor_t *ptvc)
1266 ptvcursor_free_subtree_levels(ptvc);
1267 /*g_free(ptvc);*/
1270 /* Returns tvbuff. */
1271 tvbuff_t *
1272 ptvcursor_tvbuff(ptvcursor_t *ptvc)
1274 return ptvc->tvb;
1277 /* Returns current offset. */
1279 ptvcursor_current_offset(ptvcursor_t *ptvc)
1281 return ptvc->offset;
1284 proto_tree *
1285 ptvcursor_tree(ptvcursor_t *ptvc)
1287 if (!ptvc)
1288 return NULL;
1290 return ptvc->tree;
1293 void
1294 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
1296 ptvc->tree = tree;
1299 /* creates a subtree, sets it as the working tree and pushes the old working tree */
1300 proto_tree *
1301 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, int ett_subtree)
1303 subtree_lvl *subtree;
1304 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
1305 ptvcursor_new_subtree_levels(ptvc);
1307 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
1308 subtree->tree = ptvc->tree;
1309 subtree->it= NULL;
1310 ptvc->pushed_tree_index++;
1311 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
1314 /* pops a subtree */
1315 void
1316 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
1318 subtree_lvl *subtree;
1320 if (ptvc->pushed_tree_index <= 0)
1321 return;
1323 ptvc->pushed_tree_index--;
1324 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
1325 if (subtree->it != NULL)
1326 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
1328 ptvc->tree = subtree->tree;
1331 /* saves the current tvb offset and the item in the current subtree level */
1332 static void
1333 ptvcursor_subtree_set_item(ptvcursor_t *ptvc, proto_item *it)
1335 subtree_lvl *subtree;
1337 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
1339 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index - 1;
1340 subtree->it = it;
1341 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
1344 /* Creates a subtree and adds it to the cursor as the working tree but does not
1345 * save the old working tree */
1346 proto_tree *
1347 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, int ett_subtree)
1349 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
1350 return ptvc->tree;
1353 static proto_tree *
1354 ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, int ett_subtree, int length)
1356 ptvcursor_push_subtree(ptvc, it, ett_subtree);
1357 if (length == SUBTREE_UNDEFINED_LENGTH)
1358 ptvcursor_subtree_set_item(ptvc, it);
1359 return ptvcursor_tree(ptvc);
1362 /* Add an item to the tree and create a subtree
1363 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1364 * In this case, when the subtree will be closed, the parent item length will
1365 * be equal to the advancement of the cursor since the creation of the subtree.
1367 proto_tree *
1368 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, int length,
1369 const unsigned encoding, int ett_subtree)
1371 proto_item *it;
1373 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
1374 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
1377 static proto_item *
1378 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, int start, int length);
1380 /* Add a text node to the tree and create a subtree
1381 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1382 * In this case, when the subtree will be closed, the item length will be equal
1383 * to the advancement of the cursor since the creation of the subtree.
1385 proto_tree *
1386 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, int length,
1387 int ett_subtree, const char *format, ...)
1389 proto_item *pi;
1390 va_list ap;
1391 header_field_info *hfinfo;
1392 proto_tree *tree;
1394 tree = ptvcursor_tree(ptvc);
1396 CHECK_FOR_NULL_TREE(tree);
1398 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1400 pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
1401 ptvcursor_current_offset(ptvc), length);
1403 TRY_TO_FAKE_THIS_REPR(pi);
1405 va_start(ap, format);
1406 proto_tree_set_representation(pi, format, ap);
1407 va_end(ap);
1409 return ptvcursor_add_subtree_item(ptvc, pi, ett_subtree, length);
1412 /* Add a text-only node, leaving it to our caller to fill the text in */
1413 static proto_item *
1414 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, int start, int length)
1416 proto_item *pi;
1418 if (tree == NULL)
1419 return NULL;
1421 pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length);
1423 return pi;
1426 /* (INTERNAL USE ONLY) Add a text-only node to the proto_tree */
1427 proto_item *
1428 proto_tree_add_text_internal(proto_tree *tree, tvbuff_t *tvb, int start, int length,
1429 const char *format, ...)
1431 proto_item *pi;
1432 va_list ap;
1433 header_field_info *hfinfo;
1435 if (length == -1) {
1436 length = tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
1437 } else {
1438 tvb_ensure_bytes_exist(tvb, start, length);
1441 CHECK_FOR_NULL_TREE(tree);
1443 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1445 pi = proto_tree_add_text_node(tree, tvb, start, length);
1447 TRY_TO_FAKE_THIS_REPR(pi);
1449 va_start(ap, format);
1450 proto_tree_set_representation(pi, format, ap);
1451 va_end(ap);
1453 return pi;
1456 /* (INTERNAL USE ONLY) Add a text-only node to the proto_tree (va_list version) */
1457 proto_item *
1458 proto_tree_add_text_valist_internal(proto_tree *tree, tvbuff_t *tvb, int start,
1459 int length, const char *format, va_list ap)
1461 proto_item *pi;
1462 header_field_info *hfinfo;
1464 /* proto_tree_add_text_node calls proto_tree_add_pi() with the
1465 * FT_NONE hf_text_only, which calls get_hfi_length, which adjusts
1466 * the length to be what's in the tvbuff if length is -1, and the
1467 * minimum of length and what's in the tvbuff if not.
1470 CHECK_FOR_NULL_TREE(tree);
1472 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1474 pi = proto_tree_add_text_node(tree, tvb, start, length);
1476 TRY_TO_FAKE_THIS_REPR(pi);
1478 proto_tree_set_representation(pi, format, ap);
1480 return pi;
1483 /* Add a text-only node that creates a subtree underneath.
1485 proto_tree *
1486 proto_tree_add_subtree(proto_tree *tree, tvbuff_t *tvb, int start, int length, int idx, proto_item **tree_item, const char *text)
1488 return proto_tree_add_subtree_format(tree, tvb, start, length, idx, tree_item, "%s", text);
1491 /* Add a text-only node that creates a subtree underneath.
1493 proto_tree *
1494 proto_tree_add_subtree_format(proto_tree *tree, tvbuff_t *tvb, int start, int length, int idx, proto_item **tree_item, const char *format, ...)
1496 proto_tree *pt;
1497 proto_item *pi;
1498 va_list ap;
1500 va_start(ap, format);
1501 pi = proto_tree_add_text_valist_internal(tree, tvb, start, length, format, ap);
1502 va_end(ap);
1504 if (tree_item != NULL)
1505 *tree_item = pi;
1507 pt = proto_item_add_subtree(pi, idx);
1509 return pt;
1512 /* Add a text-only node for debugging purposes. The caller doesn't need
1513 * to worry about tvbuff, start, or length. Debug message gets sent to
1514 * STDOUT, too */
1515 proto_item *
1516 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1518 proto_item *pi;
1519 va_list ap;
1521 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1523 if (pi) {
1524 va_start(ap, format);
1525 proto_tree_set_representation(pi, format, ap);
1526 va_end(ap);
1528 va_start(ap, format);
1529 vprintf(format, ap);
1530 va_end(ap);
1531 printf("\n");
1533 return pi;
1536 proto_item *
1537 proto_tree_add_format_text(proto_tree *tree, tvbuff_t *tvb, int start, int length)
1539 proto_item *pi;
1540 header_field_info *hfinfo;
1542 CHECK_FOR_NULL_TREE(tree);
1544 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1546 pi = proto_tree_add_text_node(tree, tvb, start, length);
1548 TRY_TO_FAKE_THIS_REPR(pi);
1550 proto_item_set_text(pi, "%s", tvb_format_text(tree->tree_data->pinfo->pool, tvb, start, length));
1552 return pi;
1555 proto_item *
1556 proto_tree_add_format_wsp_text(proto_tree *tree, tvbuff_t *tvb, int start, int length)
1558 proto_item *pi;
1559 header_field_info *hfinfo;
1560 char *str;
1562 CHECK_FOR_NULL_TREE(tree);
1564 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1566 pi = proto_tree_add_text_node(tree, tvb, start, length);
1568 TRY_TO_FAKE_THIS_REPR(pi);
1570 str = tvb_format_text_wsp(NULL, tvb, start, length);
1571 proto_item_set_text(pi, "%s", str);
1572 wmem_free(NULL, str);
1574 return pi;
1577 void proto_report_dissector_bug(const char *format, ...)
1579 va_list args;
1581 if (wireshark_abort_on_dissector_bug) {
1583 * Try to have the error message show up in the crash
1584 * information.
1586 va_start(args, format);
1587 ws_vadd_crash_info(format, args);
1588 va_end(args);
1591 * Print the error message.
1593 va_start(args, format);
1594 vfprintf(stderr, format, args);
1595 va_end(args);
1596 putc('\n', stderr);
1599 * And crash.
1601 abort();
1602 } else {
1603 va_start(args, format);
1604 VTHROW_FORMATTED(DissectorError, format, args);
1605 va_end(args);
1609 /* We could probably get away with changing is_error to a minimum length value. */
1610 static void
1611 report_type_length_mismatch(proto_tree *tree, const char *descr, int length, bool is_error)
1613 if (is_error) {
1614 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_error, "Trying to fetch %s with length %d", descr, length);
1615 } else {
1616 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_warn, "Trying to fetch %s with length %d", descr, length);
1619 if (is_error) {
1620 THROW(ReportedBoundsError);
1624 static uint32_t
1625 get_uint_value(proto_tree *tree, tvbuff_t *tvb, int offset, int length, const unsigned encoding)
1627 uint32_t value;
1628 bool length_error;
1630 switch (length) {
1632 case 1:
1633 value = tvb_get_uint8(tvb, offset);
1634 if (encoding & ENC_ZIGBEE) {
1635 if (value == 0xFF) { /* Invalid Zigbee length, set to 0 */
1636 value = 0;
1639 break;
1641 case 2:
1642 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1643 : tvb_get_ntohs(tvb, offset);
1644 if (encoding & ENC_ZIGBEE) {
1645 if (value == 0xFFFF) { /* Invalid Zigbee length, set to 0 */
1646 value = 0;
1649 break;
1651 case 3:
1652 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1653 : tvb_get_ntoh24(tvb, offset);
1654 break;
1656 case 4:
1657 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1658 : tvb_get_ntohl(tvb, offset);
1659 break;
1661 default:
1662 if (length < 1) {
1663 length_error = true;
1664 value = 0;
1665 } else {
1666 length_error = false;
1667 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1668 : tvb_get_ntohl(tvb, offset);
1670 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1671 break;
1673 return value;
1676 static inline uint64_t
1677 get_uint64_value(proto_tree *tree, tvbuff_t *tvb, int offset, unsigned length, const unsigned encoding)
1679 uint64_t value;
1681 value = tvb_get_uint64_with_length(tvb, offset, length, encoding);
1683 if (length < 1 || length > 8) {
1684 report_type_length_mismatch(tree, "an unsigned integer", length, (length < 1));
1687 return value;
1690 static int32_t
1691 get_int_value(proto_tree *tree, tvbuff_t *tvb, int offset, int length, const unsigned encoding)
1693 int32_t value;
1694 bool length_error;
1696 switch (length) {
1698 case 1:
1699 value = tvb_get_int8(tvb, offset);
1700 break;
1702 case 2:
1703 value = encoding ? tvb_get_letohis(tvb, offset)
1704 : tvb_get_ntohis(tvb, offset);
1705 break;
1707 case 3:
1708 value = encoding ? tvb_get_letohi24(tvb, offset)
1709 : tvb_get_ntohi24(tvb, offset);
1710 break;
1712 case 4:
1713 value = encoding ? tvb_get_letohil(tvb, offset)
1714 : tvb_get_ntohil(tvb, offset);
1715 break;
1717 default:
1718 if (length < 1) {
1719 length_error = true;
1720 value = 0;
1721 } else {
1722 length_error = false;
1723 value = encoding ? tvb_get_letohil(tvb, offset)
1724 : tvb_get_ntohil(tvb, offset);
1726 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1727 break;
1729 return value;
1732 /* Note: this returns an unsigned int64, but with the appropriate bit(s) set to
1733 * be cast-able as a int64_t. This is weird, but what the code has always done.
1735 static inline uint64_t
1736 get_int64_value(proto_tree *tree, tvbuff_t *tvb, int start, unsigned length, const unsigned encoding)
1738 uint64_t value = get_uint64_value(tree, tvb, start, length, encoding);
1740 switch (length) {
1741 case 7:
1742 value = ws_sign_ext64(value, 56);
1743 break;
1744 case 6:
1745 value = ws_sign_ext64(value, 48);
1746 break;
1747 case 5:
1748 value = ws_sign_ext64(value, 40);
1749 break;
1750 case 4:
1751 value = ws_sign_ext64(value, 32);
1752 break;
1753 case 3:
1754 value = ws_sign_ext64(value, 24);
1755 break;
1756 case 2:
1757 value = ws_sign_ext64(value, 16);
1758 break;
1759 case 1:
1760 value = ws_sign_ext64(value, 8);
1761 break;
1764 return value;
1767 /* For FT_STRING */
1768 static inline const uint8_t *
1769 get_string_value(wmem_allocator_t *scope, tvbuff_t *tvb, int start,
1770 int length, int *ret_length, const unsigned encoding)
1772 if (length == -1) {
1773 length = tvb_ensure_captured_length_remaining(tvb, start);
1775 *ret_length = length;
1776 return tvb_get_string_enc(scope, tvb, start, length, encoding);
1779 /* For FT_STRINGZ */
1780 static inline const uint8_t *
1781 get_stringz_value(wmem_allocator_t *scope, proto_tree *tree, tvbuff_t *tvb,
1782 int start, int length, int *ret_length, const unsigned encoding)
1784 const uint8_t *value;
1786 if (length < -1) {
1787 report_type_length_mismatch(tree, "a string", length, true);
1789 if (length == -1) {
1790 /* This can throw an exception */
1791 value = tvb_get_stringz_enc(scope, tvb, start, &length, encoding);
1792 } else {
1793 /* In this case, length signifies the length of the string.
1795 * This could either be a null-padded string, which doesn't
1796 * necessarily have a '\0' at the end, or a null-terminated
1797 * string, with a trailing '\0'. (Yes, there are cases
1798 * where you have a string that's both counted and null-
1799 * terminated.)
1801 * In the first case, we must allocate a buffer of length
1802 * "length+1", to make room for a trailing '\0'.
1804 * In the second case, we don't assume that there is a
1805 * trailing '\0' there, as the packet might be malformed.
1806 * (XXX - should we throw an exception if there's no
1807 * trailing '\0'?) Therefore, we allocate a buffer of
1808 * length "length+1", and put in a trailing '\0', just to
1809 * be safe.
1811 * (XXX - this would change if we made string values counted
1812 * rather than null-terminated.)
1814 value = tvb_get_string_enc(scope, tvb, start, length, encoding);
1816 *ret_length = length;
1817 return value;
1820 /* For FT_UINT_STRING */
1821 static inline const uint8_t *
1822 get_uint_string_value(wmem_allocator_t *scope, proto_tree *tree,
1823 tvbuff_t *tvb, int start, int length, int *ret_length,
1824 const unsigned encoding)
1826 uint32_t n;
1827 const uint8_t *value;
1829 /* I believe it's ok if this is called with a NULL tree */
1830 n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1831 value = tvb_get_string_enc(scope, tvb, start + length, n, encoding);
1832 length += n;
1833 *ret_length = length;
1834 return value;
1837 /* For FT_STRINGZPAD */
1838 static inline const uint8_t *
1839 get_stringzpad_value(wmem_allocator_t *scope, tvbuff_t *tvb, int start,
1840 int length, int *ret_length, const unsigned encoding)
1843 * XXX - currently, string values are null-
1844 * terminated, so a "zero-padded" string
1845 * isn't special. If we represent string
1846 * values as something that includes a counted
1847 * array of bytes, we'll need to strip the
1848 * trailing NULs.
1850 if (length == -1) {
1851 length = tvb_ensure_captured_length_remaining(tvb, start);
1853 *ret_length = length;
1854 return tvb_get_string_enc(scope, tvb, start, length, encoding);
1857 /* For FT_STRINGZTRUNC */
1858 static inline const uint8_t *
1859 get_stringztrunc_value(wmem_allocator_t *scope, tvbuff_t *tvb, int start,
1860 int length, int *ret_length, const unsigned encoding)
1863 * XXX - currently, string values are null-
1864 * terminated, so a "zero-truncated" string
1865 * isn't special. If we represent string
1866 * values as something that includes a counted
1867 * array of bytes, we'll need to strip everything
1868 * starting with the terminating NUL.
1870 if (length == -1) {
1871 length = tvb_ensure_captured_length_remaining(tvb, start);
1873 *ret_length = length;
1874 return tvb_get_string_enc(scope, tvb, start, length, encoding);
1878 * Deltas between the epochs for various non-UN*X time stamp formats and
1879 * the January 1, 1970, 00:00:00 (proleptic?) UTC epoch for the UN*X time
1880 * stamp format.
1884 * NTP Era 0: the epoch is January 1, 1900, 00:00:00 (proleptic?) UTC.
1885 * XXX - if it's OK if this is unsigned, can we just use
1886 * EPOCH_DELTA_1900_01_01_00_00_00_UTC?
1888 #define NTP_TIMEDIFF1900TO1970SEC INT64_C(2208988800)
1891 * NTP Era 1: the epoch is February 7, 2036, 06:28:16 UTC.
1893 #define NTP_TIMEDIFF1970TO2036SEC INT64_C(2085978496)
1895 /* this can be called when there is no tree, so tree may be null */
1896 static void
1897 get_time_value(proto_tree *tree, tvbuff_t *tvb, const int start,
1898 const int length, const unsigned encoding, nstime_t *time_stamp,
1899 const bool is_relative)
1901 uint32_t tmpsecs;
1902 uint64_t tmp64secs;
1903 uint64_t todusecs;
1905 switch (encoding) {
1907 case ENC_TIME_SECS_NSECS|ENC_BIG_ENDIAN:
1909 * If the length is 16, 8-byte seconds, followed
1910 * by 8-byte fractional time in nanoseconds,
1911 * both big-endian.
1913 * If the length is 12, 8-byte seconds, followed
1914 * by 4-byte fractional time in nanoseconds,
1915 * both big-endian.
1917 * If the length is 8, 4-byte seconds, followed
1918 * by 4-byte fractional time in nanoseconds,
1919 * both big-endian.
1921 * For absolute times, the seconds are seconds
1922 * since the UN*X epoch.
1924 if (length == 16) {
1925 time_stamp->secs = (time_t)tvb_get_ntoh64(tvb, start);
1926 time_stamp->nsecs = (uint32_t)tvb_get_ntoh64(tvb, start+8);
1927 } else if (length == 12) {
1928 time_stamp->secs = (time_t)tvb_get_ntoh64(tvb, start);
1929 time_stamp->nsecs = tvb_get_ntohl(tvb, start+8);
1930 } else if (length == 8) {
1931 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
1932 time_stamp->nsecs = tvb_get_ntohl(tvb, start+4);
1933 } else if (length == 4) {
1935 * Backwards compatibility.
1936 * ENC_TIME_SECS_NSECS is 0; using
1937 * ENC_BIG_ENDIAN by itself with a 4-byte
1938 * time-in-seconds value was done in the
1939 * past.
1941 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
1942 time_stamp->nsecs = 0;
1943 } else {
1944 time_stamp->secs = 0;
1945 time_stamp->nsecs = 0;
1946 report_type_length_mismatch(tree, "a timespec", length, (length < 4));
1948 break;
1950 case ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN:
1952 * If the length is 16, 8-byte seconds, followed
1953 * by 8-byte fractional time in nanoseconds,
1954 * both little-endian.
1956 * If the length is 12, 8-byte seconds, followed
1957 * by 4-byte fractional time in nanoseconds,
1958 * both little-endian.
1960 * If the length is 8, 4-byte seconds, followed
1961 * by 4-byte fractional time in nanoseconds,
1962 * both little-endian.
1964 * For absolute times, the seconds are seconds
1965 * since the UN*X epoch.
1967 if (length == 16) {
1968 time_stamp->secs = (time_t)tvb_get_letoh64(tvb, start);
1969 time_stamp->nsecs = (uint32_t)tvb_get_letoh64(tvb, start+8);
1970 } else if (length == 12) {
1971 time_stamp->secs = (time_t)tvb_get_letoh64(tvb, start);
1972 time_stamp->nsecs = tvb_get_letohl(tvb, start+8);
1973 } else if (length == 8) {
1974 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
1975 time_stamp->nsecs = tvb_get_letohl(tvb, start+4);
1976 } else if (length == 4) {
1978 * Backwards compatibility.
1979 * ENC_TIME_SECS_NSECS is 0; using
1980 * ENC_LITTLE_ENDIAN by itself with a 4-byte
1981 * time-in-seconds value was done in the
1982 * past.
1984 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
1985 time_stamp->nsecs = 0;
1986 } else {
1987 time_stamp->secs = 0;
1988 time_stamp->nsecs = 0;
1989 report_type_length_mismatch(tree, "a timespec", length, (length < 4));
1991 break;
1993 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1995 * NTP time stamp, big-endian.
1996 * Only supported for absolute times.
1998 DISSECTOR_ASSERT(!is_relative);
2000 /* We need a temporary variable here so the unsigned math
2001 * works correctly (for years > 2036 according to RFC 2030
2002 * chapter 3).
2004 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2005 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2006 * If bit 0 is not set, the time is in the range 2036-2104 and
2007 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2009 tmpsecs = tvb_get_ntohl(tvb, start);
2010 if ((tmpsecs & 0x80000000) != 0)
2011 time_stamp->secs = (time_t)((int64_t)tmpsecs - NTP_TIMEDIFF1900TO1970SEC);
2012 else
2013 time_stamp->secs = (time_t)((int64_t)tmpsecs + NTP_TIMEDIFF1970TO2036SEC);
2015 if (length == 8) {
2016 tmp64secs = tvb_get_ntoh64(tvb, start);
2017 if (tmp64secs == 0) {
2018 //This is "NULL" time
2019 time_stamp->secs = 0;
2020 time_stamp->nsecs = 0;
2021 } else {
2023 * Convert 1/2^32s of a second to
2024 * nanoseconds.
2026 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
2028 } else if (length == 4) {
2030 * Backwards compatibility.
2032 if (tmpsecs == 0) {
2033 //This is "NULL" time
2034 time_stamp->secs = 0;
2036 time_stamp->nsecs = 0;
2037 } else {
2038 time_stamp->secs = 0;
2039 time_stamp->nsecs = 0;
2040 report_type_length_mismatch(tree, "an NTP time stamp", length, (length < 4));
2042 break;
2044 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
2046 * NTP time stamp, little-endian.
2047 * Only supported for absolute times.
2049 * NTP doesn't use this, because it's an Internet format
2050 * and hence big-endian. Any implementation must decide
2051 * whether the NTP timestamp is a 64-bit unsigned fixed
2052 * point number (RFC 1305, RFC 4330) or a 64-bit struct
2053 * with a 32-bit unsigned seconds field followed by a
2054 * 32-bit fraction field (cf. RFC 5905, which obsoletes
2055 * the previous two).
2057 * XXX: We do the latter, but no dissector uses this format.
2058 * OTOH, ERF timestamps do the former, so perhaps we
2059 * should switch the interpretation so that packet-erf.c
2060 * could use this directly?
2062 DISSECTOR_ASSERT(!is_relative);
2064 /* We need a temporary variable here so the unsigned math
2065 * works correctly (for years > 2036 according to RFC 2030
2066 * chapter 3).
2068 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2069 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2070 * If bit 0 is not set, the time is in the range 2036-2104 and
2071 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2073 tmpsecs = tvb_get_letohl(tvb, start);
2074 if ((tmpsecs & 0x80000000) != 0)
2075 time_stamp->secs = (time_t)((int64_t)tmpsecs - NTP_TIMEDIFF1900TO1970SEC);
2076 else
2077 time_stamp->secs = (time_t)((int64_t)tmpsecs + NTP_TIMEDIFF1970TO2036SEC);
2079 if (length == 8) {
2080 tmp64secs = tvb_get_letoh64(tvb, start);
2081 if (tmp64secs == 0) {
2082 //This is "NULL" time
2083 time_stamp->secs = 0;
2084 time_stamp->nsecs = 0;
2085 } else {
2087 * Convert 1/2^32s of a second to
2088 * nanoseconds.
2090 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
2092 } else if (length == 4) {
2094 * Backwards compatibility.
2096 if (tmpsecs == 0) {
2097 //This is "NULL" time
2098 time_stamp->secs = 0;
2100 time_stamp->nsecs = 0;
2101 } else {
2102 time_stamp->secs = 0;
2103 time_stamp->nsecs = 0;
2104 report_type_length_mismatch(tree, "an NTP time stamp", length, (length < 4));
2106 break;
2108 case ENC_TIME_TOD|ENC_BIG_ENDIAN:
2110 * S/3x0 and z/Architecture TOD clock time stamp,
2111 * big-endian. The epoch is January 1, 1900,
2112 * 00:00:00 (proleptic?) UTC.
2114 * Only supported for absolute times.
2116 DISSECTOR_ASSERT(!is_relative);
2117 DISSECTOR_ASSERT(length == 8);
2119 if (length == 8) {
2120 todusecs = tvb_get_ntoh64(tvb, start) >> 12;
2121 time_stamp->secs = (time_t)((todusecs / 1000000) - EPOCH_DELTA_1900_01_01_00_00_00_UTC);
2122 time_stamp->nsecs = (int)((todusecs % 1000000) * 1000);
2123 } else {
2124 time_stamp->secs = 0;
2125 time_stamp->nsecs = 0;
2126 report_type_length_mismatch(tree, "a TOD clock time stamp", length, (length < 4));
2128 break;
2130 case ENC_TIME_TOD|ENC_LITTLE_ENDIAN:
2132 * S/3x0 and z/Architecture TOD clock time stamp,
2133 * little-endian. The epoch is January 1, 1900,
2134 * 00:00:00 (proleptic?) UTC.
2136 * Only supported for absolute times.
2138 DISSECTOR_ASSERT(!is_relative);
2140 if (length == 8) {
2141 todusecs = tvb_get_letoh64(tvb, start) >> 12 ;
2142 time_stamp->secs = (time_t)((todusecs / 1000000) - EPOCH_DELTA_1900_01_01_00_00_00_UTC);
2143 time_stamp->nsecs = (int)((todusecs % 1000000) * 1000);
2144 } else {
2145 time_stamp->secs = 0;
2146 time_stamp->nsecs = 0;
2147 report_type_length_mismatch(tree, "a TOD clock time stamp", length, (length < 4));
2149 break;
2151 case ENC_TIME_RTPS|ENC_BIG_ENDIAN:
2153 * Time stamp using the same seconds/fraction format
2154 * as NTP, but with the origin of the time stamp being
2155 * the UNIX epoch rather than the NTP epoch; big-
2156 * endian.
2158 * Only supported for absolute times.
2160 DISSECTOR_ASSERT(!is_relative);
2162 if (length == 8) {
2163 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
2165 * Convert 1/2^32s of a second to nanoseconds.
2167 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
2168 } else {
2169 time_stamp->secs = 0;
2170 time_stamp->nsecs = 0;
2171 report_type_length_mismatch(tree, "an RTPS time stamp", length, (length < 4));
2173 break;
2175 case ENC_TIME_RTPS|ENC_LITTLE_ENDIAN:
2177 * Time stamp using the same seconds/fraction format
2178 * as NTP, but with the origin of the time stamp being
2179 * the UNIX epoch rather than the NTP epoch; little-
2180 * endian.
2182 * Only supported for absolute times.
2184 * The RTPS specification explicitly supports Little
2185 * Endian encoding. In one place, it states that its
2186 * Time_t representation "is the one defined by ...
2187 * RFC 1305", but in another explicitly defines it as
2188 * a struct consisting of an 32 bit unsigned seconds
2189 * field and a 32 bit unsigned fraction field, not a 64
2190 * bit fixed point, so we do that here.
2191 * https://www.omg.org/spec/DDSI-RTPS/2.5/PDF
2193 DISSECTOR_ASSERT(!is_relative);
2195 if (length == 8) {
2196 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
2198 * Convert 1/2^32s of a second to nanoseconds.
2200 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
2201 } else {
2202 time_stamp->secs = 0;
2203 time_stamp->nsecs = 0;
2204 report_type_length_mismatch(tree, "an RTPS time stamp", length, (length < 4));
2206 break;
2208 case ENC_TIME_MIP6 | ENC_BIG_ENDIAN:
2210 * MIP6 time stamp, big-endian.
2211 * A 64-bit unsigned integer field containing a timestamp. The
2212 * value indicates the number of seconds since January 1, 1970,
2213 * 00:00 UTC, by using a fixed point format. In this format, the
2214 * integer number of seconds is contained in the first 48 bits of
2215 * the field, and the remaining 16 bits indicate the number of
2216 * 1/65536 fractions of a second.
2218 * Only supported for absolute times.
2220 DISSECTOR_ASSERT(!is_relative);
2222 if (length == 8) {
2223 /* We need a temporary variable here so the casting and fractions
2224 * of a second work correctly.
2226 tmp64secs = tvb_get_ntoh48(tvb, start);
2227 tmpsecs = tvb_get_ntohs(tvb, start + 6);
2228 tmpsecs <<= 16;
2230 if ((tmp64secs == 0) && (tmpsecs == 0)) {
2231 //This is "NULL" time
2232 time_stamp->secs = 0;
2233 time_stamp->nsecs = 0;
2234 } else {
2235 time_stamp->secs = (time_t)tmp64secs;
2236 time_stamp->nsecs = (int)((tmpsecs / 4294967296.0) * 1000000000);
2238 } else {
2239 time_stamp->secs = 0;
2240 time_stamp->nsecs = 0;
2241 report_type_length_mismatch(tree, "an NTP time stamp", length, (length != 8));
2243 break;
2245 case ENC_TIME_SECS_USECS|ENC_BIG_ENDIAN:
2247 * If the length is 16, 8-byte seconds, followed
2248 * by 8-byte fractional time in microseconds,
2249 * both big-endian.
2251 * If the length is 12, 8-byte seconds, followed
2252 * by 4-byte fractional time in microseconds,
2253 * both big-endian.
2255 * If the length is 8, 4-byte seconds, followed
2256 * by 4-byte fractional time in microseconds,
2257 * both big-endian.
2259 * For absolute times, the seconds are seconds
2260 * since the UN*X epoch.
2262 if (length == 16) {
2263 time_stamp->secs = (time_t)tvb_get_ntoh64(tvb, start);
2264 time_stamp->nsecs = (uint32_t)tvb_get_ntoh64(tvb, start+8)*1000;
2265 } else if (length == 12) {
2266 time_stamp->secs = (time_t)tvb_get_ntoh64(tvb, start);
2267 time_stamp->nsecs = tvb_get_ntohl(tvb, start+8)*1000;
2268 } else if (length == 8) {
2269 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
2270 time_stamp->nsecs = tvb_get_ntohl(tvb, start+4)*1000;
2271 } else {
2272 time_stamp->secs = 0;
2273 time_stamp->nsecs = 0;
2274 report_type_length_mismatch(tree, "a timeval", length, (length < 4));
2276 break;
2278 case ENC_TIME_SECS_USECS|ENC_LITTLE_ENDIAN:
2280 * If the length is 16, 8-byte seconds, followed
2281 * by 8-byte fractional time in microseconds,
2282 * both little-endian.
2284 * If the length is 12, 8-byte seconds, followed
2285 * by 4-byte fractional time in microseconds,
2286 * both little-endian.
2288 * If the length is 8, 4-byte seconds, followed
2289 * by 4-byte fractional time in microseconds,
2290 * both little-endian.
2292 * For absolute times, the seconds are seconds
2293 * since the UN*X epoch.
2295 if (length == 16) {
2296 time_stamp->secs = (time_t)tvb_get_letoh64(tvb, start);
2297 time_stamp->nsecs = (uint32_t)tvb_get_letoh64(tvb, start+8)*1000;
2298 } else if (length == 12) {
2299 time_stamp->secs = (time_t)tvb_get_letoh64(tvb, start);
2300 time_stamp->nsecs = tvb_get_letohl(tvb, start+8)*1000;
2301 } else if (length == 8) {
2302 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
2303 time_stamp->nsecs = tvb_get_letohl(tvb, start+4)*1000;
2304 } else {
2305 time_stamp->secs = 0;
2306 time_stamp->nsecs = 0;
2307 report_type_length_mismatch(tree, "a timeval", length, (length < 4));
2309 break;
2311 case ENC_TIME_SECS|ENC_BIG_ENDIAN:
2312 case ENC_TIME_SECS|ENC_LITTLE_ENDIAN:
2314 * Seconds, 1 to 8 bytes.
2315 * For absolute times, it's seconds since the
2316 * UN*X epoch.
2318 if (length >= 1 && length <= 8) {
2319 time_stamp->secs = (time_t)get_uint64_value(tree, tvb, start, length, encoding);
2320 time_stamp->nsecs = 0;
2321 } else {
2322 time_stamp->secs = 0;
2323 time_stamp->nsecs = 0;
2324 report_type_length_mismatch(tree, "a time-in-seconds time stamp", length, (length < 4));
2326 break;
2328 case ENC_TIME_MSECS|ENC_BIG_ENDIAN:
2329 case ENC_TIME_MSECS|ENC_LITTLE_ENDIAN:
2331 * Milliseconds, 1 to 8 bytes.
2332 * For absolute times, it's milliseconds since the
2333 * UN*X epoch.
2335 if (length >= 1 && length <= 8) {
2336 uint64_t msecs;
2338 msecs = get_uint64_value(tree, tvb, start, length, encoding);
2339 time_stamp->secs = (time_t)(msecs / 1000);
2340 time_stamp->nsecs = (int)(msecs % 1000)*1000000;
2341 } else {
2342 time_stamp->secs = 0;
2343 time_stamp->nsecs = 0;
2344 report_type_length_mismatch(tree, "a time-in-milliseconds time stamp", length, (length < 4));
2346 break;
2348 case ENC_TIME_USECS|ENC_BIG_ENDIAN:
2349 case ENC_TIME_USECS|ENC_LITTLE_ENDIAN:
2351 * Microseconds, 1 to 8 bytes.
2352 * For absolute times, it's microseconds since the
2353 * UN*X epoch.
2355 if (length >= 1 && length <= 8) {
2356 uint64_t usecs;
2358 usecs = get_uint64_value(tree, tvb, start, length, encoding);
2359 time_stamp->secs = (time_t)(usecs / 1000000);
2360 time_stamp->nsecs = (int)(usecs % 1000000)*1000;
2361 } else {
2362 time_stamp->secs = 0;
2363 time_stamp->nsecs = 0;
2364 report_type_length_mismatch(tree, "a time-in-microseconds time stamp", length, (length < 4));
2366 break;
2368 case ENC_TIME_NSECS|ENC_BIG_ENDIAN:
2369 case ENC_TIME_NSECS|ENC_LITTLE_ENDIAN:
2371 * nanoseconds, 1 to 8 bytes.
2372 * For absolute times, it's nanoseconds since the
2373 * UN*X epoch.
2376 if (length >= 1 && length <= 8) {
2377 uint64_t nsecs;
2379 nsecs = get_uint64_value(tree, tvb, start, length, encoding);
2380 time_stamp->secs = (time_t)(nsecs / 1000000000);
2381 time_stamp->nsecs = (int)(nsecs % 1000000000);
2382 } else {
2383 time_stamp->secs = 0;
2384 time_stamp->nsecs = 0;
2385 report_type_length_mismatch(tree, "a time-in-nanoseconds time stamp", length, (length < 4));
2387 break;
2389 case ENC_TIME_RFC_3971|ENC_BIG_ENDIAN:
2391 * 1/64ths of a second since the UN*X epoch,
2392 * big-endian.
2394 * Only supported for absolute times.
2396 DISSECTOR_ASSERT(!is_relative);
2398 if (length == 8) {
2400 * The upper 48 bits are seconds since the
2401 * UN*X epoch.
2403 time_stamp->secs = (time_t)tvb_get_ntoh48(tvb, start);
2405 * The lower 16 bits are 1/2^16s of a second;
2406 * convert them to nanoseconds.
2408 * XXX - this may give the impression of higher
2409 * precision than you actually get.
2411 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohs(tvb, start+6)/65536.0));
2412 } else {
2413 time_stamp->secs = 0;
2414 time_stamp->nsecs = 0;
2415 report_type_length_mismatch(tree, "an RFC 3971-style time stamp", length, (length < 4));
2417 break;
2419 case ENC_TIME_RFC_3971|ENC_LITTLE_ENDIAN:
2421 * 1/64ths of a second since the UN*X epoch,
2422 * little-endian.
2424 * Only supported for absolute times.
2426 DISSECTOR_ASSERT(!is_relative);
2428 if (length == 8) {
2430 * XXX - this is assuming that, if anybody
2431 * were ever to use this format - RFC 3971
2432 * doesn't, because that's an Internet
2433 * protocol, and those use network byte
2434 * order, i.e. big-endian - they'd treat it
2435 * as a 64-bit count of 1/2^16s of a second,
2436 * putting the upper 48 bits at the end.
2438 * The lower 48 bits are seconds since the
2439 * UN*X epoch.
2441 time_stamp->secs = (time_t)tvb_get_letoh48(tvb, start+2);
2443 * The upper 16 bits are 1/2^16s of a second;
2444 * convert them to nanoseconds.
2446 * XXX - this may give the impression of higher
2447 * precision than you actually get.
2449 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohs(tvb, start)/65536.0));
2450 } else {
2451 time_stamp->secs = 0;
2452 time_stamp->nsecs = 0;
2453 report_type_length_mismatch(tree, "an RFC 3971-style time stamp", length, (length < 4));
2455 break;
2457 case ENC_TIME_SECS_NTP|ENC_BIG_ENDIAN:
2459 * NTP time stamp, with 1-second resolution (i.e.,
2460 * seconds since the NTP epoch), big-endian.
2461 * Only supported for absolute times.
2463 DISSECTOR_ASSERT(!is_relative);
2465 if (length == 4) {
2467 * We need a temporary variable here so the unsigned math
2468 * works correctly (for years > 2036 according to RFC 2030
2469 * chapter 3).
2471 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2472 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2473 * If bit 0 is not set, the time is in the range 2036-2104 and
2474 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2476 tmpsecs = tvb_get_ntohl(tvb, start);
2477 if ((tmpsecs & 0x80000000) != 0)
2478 time_stamp->secs = (time_t)((int64_t)tmpsecs - NTP_TIMEDIFF1900TO1970SEC);
2479 else
2480 time_stamp->secs = (time_t)((int64_t)tmpsecs + NTP_TIMEDIFF1970TO2036SEC);
2481 time_stamp->nsecs = 0;
2482 } else {
2483 time_stamp->secs = 0;
2484 time_stamp->nsecs = 0;
2485 report_type_length_mismatch(tree, "an NTP seconds-only time stamp", length, (length < 4));
2487 break;
2489 case ENC_TIME_SECS_NTP|ENC_LITTLE_ENDIAN:
2491 * NTP time stamp, with 1-second resolution (i.e.,
2492 * seconds since the NTP epoch), little-endian.
2493 * Only supported for absolute times.
2495 DISSECTOR_ASSERT(!is_relative);
2498 * We need a temporary variable here so the unsigned math
2499 * works correctly (for years > 2036 according to RFC 2030
2500 * chapter 3).
2502 * If bit 0 is set, the UTC time is in the range 1968-2036 and
2503 * UTC time is reckoned from 0h 0m 0s UTC on 1 January 1900.
2504 * If bit 0 is not set, the time is in the range 2036-2104 and
2505 * UTC time is reckoned from 6h 28m 16s UTC on 7 February 2036.
2507 if (length == 4) {
2508 tmpsecs = tvb_get_letohl(tvb, start);
2509 if ((tmpsecs & 0x80000000) != 0)
2510 time_stamp->secs = (time_t)((int64_t)tmpsecs - NTP_TIMEDIFF1900TO1970SEC);
2511 else
2512 time_stamp->secs = (time_t)((int64_t)tmpsecs + NTP_TIMEDIFF1970TO2036SEC);
2513 time_stamp->nsecs = 0;
2514 } else {
2515 time_stamp->secs = 0;
2516 time_stamp->nsecs = 0;
2517 report_type_length_mismatch(tree, "an NTP seconds-only time stamp", length, (length < 4));
2519 break;
2521 case ENC_TIME_MSEC_NTP | ENC_BIG_ENDIAN:
2523 * Milliseconds, 6 to 8 bytes.
2524 * For absolute times, it's milliseconds since the
2525 * NTP epoch.
2527 * ETSI TS 129.274 8.119 defines this as:
2528 * "a 48 bit unsigned integer in network order format
2529 * ...encoded as the number of milliseconds since
2530 * 00:00:00 January 1, 1900 00:00 UTC, i.e. as the
2531 * rounded value of 1000 x the value of the 64-bit
2532 * timestamp (Seconds + (Fraction / (1<<32))) defined
2533 * in clause 6 of IETF RFC 5905."
2535 * Taken literally, the part after "i.e." would
2536 * mean that the value rolls over before reaching
2537 * 2^32 * 1000 = 4294967296000 = 0x3e800000000
2538 * when the 64 bit timestamp rolls over, and we have
2539 * to pick an NTP Era equivalence class to support
2540 * (such as 1968-01-20 to 2104-02-06).
2542 * OTOH, the extra room might be used to store Era
2543 * information instead, in which case times until
2544 * 10819-08-03 can be represented with 6 bytes without
2545 * ambiguity. We handle both implementations, and assume
2546 * that times before 1968-01-20 are not represented.
2548 * Only 6 bytes or more makes sense as an absolute
2549 * time. 5 bytes or fewer could express a span of
2550 * less than 35 years, either 1900-1934 or 2036-2070.
2552 if (length >= 6 && length <= 8) {
2553 uint64_t msecs;
2555 msecs = get_uint64_value(tree, tvb, start, length, encoding);
2556 tmp64secs = (msecs / 1000);
2558 * Assume that times in the first half of NTP
2559 * Era 0 really represent times in the NTP
2560 * Era 1.
2562 if (tmp64secs >= 0x80000000)
2563 time_stamp->secs = (time_t)((int64_t)tmp64secs - NTP_TIMEDIFF1900TO1970SEC);
2564 else
2565 time_stamp->secs = (time_t)((int64_t)tmp64secs + NTP_TIMEDIFF1970TO2036SEC);
2566 time_stamp->nsecs = (int)(msecs % 1000)*1000000;
2568 else {
2569 time_stamp->secs = 0;
2570 time_stamp->nsecs = 0;
2571 report_type_length_mismatch(tree, "a time-in-milliseconds NTP time stamp", length, (length < 6));
2573 break;
2575 case ENC_TIME_MP4_FILE_SECS|ENC_BIG_ENDIAN:
2577 * MP4 file time stamps, big-endian.
2578 * Only supported for absolute times.
2580 DISSECTOR_ASSERT(!is_relative);
2582 if (length == 8) {
2583 tmp64secs = tvb_get_ntoh64(tvb, start);
2584 time_stamp->secs = (time_t)(int64_t)(tmp64secs - EPOCH_DELTA_1904_01_01_00_00_00_UTC);
2585 time_stamp->nsecs = 0;
2586 } else if (length == 4) {
2587 tmpsecs = tvb_get_ntohl(tvb, start);
2588 time_stamp->secs = (time_t)(int32_t)(tmpsecs - EPOCH_DELTA_1904_01_01_00_00_00_UTC);
2589 time_stamp->nsecs = 0;
2590 } else {
2591 time_stamp->secs = 0;
2592 time_stamp->nsecs = 0;
2593 report_type_length_mismatch(tree, "an MP4 time stamp", length, (length < 4));
2595 break;
2597 case ENC_TIME_ZBEE_ZCL | ENC_BIG_ENDIAN:
2599 * Zigbee ZCL time stamps, big-endian.
2600 * Only supported for absolute times.
2602 DISSECTOR_ASSERT(!is_relative);
2604 if (length == 8) {
2605 tmp64secs = tvb_get_ntoh64(tvb, start);
2606 time_stamp->secs = (time_t)(int64_t)(tmp64secs - EPOCH_DELTA_2000_01_01_00_00_00_UTC);
2607 time_stamp->nsecs = 0;
2608 } else if (length == 4) {
2609 tmpsecs = tvb_get_ntohl(tvb, start);
2610 time_stamp->secs = (time_t)(int32_t)(tmpsecs - EPOCH_DELTA_2000_01_01_00_00_00_UTC);
2611 time_stamp->nsecs = 0;
2612 } else {
2613 time_stamp->secs = 0;
2614 time_stamp->nsecs = 0;
2615 report_type_length_mismatch(tree, "a Zigbee ZCL time stamp", length, (length < 4));
2617 break;
2619 case ENC_TIME_ZBEE_ZCL | ENC_LITTLE_ENDIAN:
2621 * Zigbee ZCL time stamps, little-endian.
2622 * Only supported for absolute times.
2624 DISSECTOR_ASSERT(!is_relative);
2626 if (length == 8) {
2627 tmp64secs = tvb_get_letoh64(tvb, start);
2628 time_stamp->secs = (time_t)(int64_t)(tmp64secs - EPOCH_DELTA_2000_01_01_00_00_00_UTC);
2629 time_stamp->nsecs = 0;
2630 } else if (length == 4) {
2631 tmpsecs = tvb_get_letohl(tvb, start);
2632 time_stamp->secs = (time_t)(int32_t)(tmpsecs - EPOCH_DELTA_2000_01_01_00_00_00_UTC);
2633 time_stamp->nsecs = 0;
2634 } else {
2635 time_stamp->secs = 0;
2636 time_stamp->nsecs = 0;
2637 report_type_length_mismatch(tree, "a Zigbee ZCL time stamp", length, (length < 4));
2639 break;
2641 default:
2642 DISSECTOR_ASSERT_NOT_REACHED();
2643 break;
2647 static void
2648 tree_data_add_maybe_interesting_field(tree_data_t *tree_data, field_info *fi)
2650 const header_field_info *hfinfo = fi->hfinfo;
2652 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT || hfinfo->ref_type == HF_REF_TYPE_PRINT) {
2653 GPtrArray *ptrs = NULL;
2655 if (tree_data->interesting_hfids == NULL) {
2656 /* Initialize the hash because we now know that it is needed */
2657 tree_data->interesting_hfids =
2658 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
2659 } else if (g_hash_table_size(tree_data->interesting_hfids)) {
2660 ptrs = (GPtrArray *)g_hash_table_lookup(tree_data->interesting_hfids,
2661 GINT_TO_POINTER(hfinfo->id));
2664 if (!ptrs) {
2665 /* First element triggers the creation of pointer array */
2666 ptrs = g_ptr_array_new();
2667 g_hash_table_insert(tree_data->interesting_hfids,
2668 GINT_TO_POINTER(hfinfo->id), ptrs);
2671 g_ptr_array_add(ptrs, fi);
2677 * Validates that field length bytes are available starting from
2678 * start (pos/neg). Throws an exception if they aren't.
2680 static void
2681 test_length(header_field_info *hfinfo, tvbuff_t *tvb,
2682 int start, int length, const unsigned encoding)
2684 int size = length;
2686 if (!tvb)
2687 return;
2689 if ((hfinfo->type == FT_STRINGZ) ||
2690 ((encoding & ENC_VARINT_MASK) &&
2691 (FT_IS_UINT(hfinfo->type) || FT_IS_INT(hfinfo->type)))) {
2692 /* If we're fetching until the end of the TVB, only validate
2693 * that the offset is within range.
2695 if (length == -1)
2696 size = 0;
2699 tvb_ensure_bytes_exist(tvb, start, size);
2702 static void
2703 detect_trailing_stray_characters(unsigned encoding, const char *string, int length, proto_item *pi)
2705 bool found_stray_character = false;
2707 if (!string)
2708 return;
2710 switch (encoding & ENC_CHARENCODING_MASK) {
2711 case ENC_ASCII:
2712 case ENC_UTF_8:
2713 for (int i = (int)strlen(string); i < length; i++) {
2714 if (string[i] != '\0') {
2715 found_stray_character = true;
2716 break;
2719 break;
2721 default:
2722 break;
2725 if (found_stray_character) {
2726 expert_add_info(NULL, pi, &ei_string_trailing_characters);
2730 static void
2731 free_fvalue_cb(void *data)
2733 fvalue_t *fv = (fvalue_t*)data;
2734 fvalue_free(fv);
2737 /* Add an item to a proto_tree, using the text label registered to that item;
2738 the item is extracted from the tvbuff handed to it. */
2739 static proto_item *
2740 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
2741 tvbuff_t *tvb, int start, int length,
2742 unsigned encoding)
2744 proto_item *pi;
2745 uint32_t value, n;
2746 uint64_t value64;
2747 ws_in4_addr ipv4_value;
2748 float floatval;
2749 double doubleval;
2750 const char *stringval = NULL;
2751 nstime_t time_stamp;
2752 bool length_error;
2754 /* Ensure that the newly created fvalue_t is freed if we throw an
2755 * exception before adding it to the tree. (gcc creates clobbering
2756 * when it optimizes the equivalent TRY..EXCEPT implementation.)
2757 * XXX: Move the new_field_info() call inside here?
2759 CLEANUP_PUSH(free_fvalue_cb, new_fi->value);
2761 switch (new_fi->hfinfo->type) {
2762 case FT_NONE:
2763 /* no value to set for FT_NONE */
2764 break;
2766 case FT_PROTOCOL:
2767 proto_tree_set_protocol_tvb(new_fi, tvb, new_fi->hfinfo->name, length);
2768 break;
2770 case FT_BYTES:
2771 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
2772 break;
2774 case FT_UINT_BYTES:
2775 n = get_uint_value(tree, tvb, start, length, encoding);
2776 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
2778 /* Instead of calling proto_item_set_len(), since we don't yet
2779 * have a proto_item, we set the field_info's length ourselves. */
2780 new_fi->length = n + length;
2781 break;
2783 case FT_BOOLEAN:
2785 * Map all non-zero values to little-endian for
2786 * backwards compatibility.
2788 if (encoding)
2789 encoding = ENC_LITTLE_ENDIAN;
2790 proto_tree_set_boolean(new_fi,
2791 get_uint64_value(tree, tvb, start, length, encoding));
2792 break;
2794 case FT_CHAR:
2795 /* XXX - make these just FT_UINT? */
2796 case FT_UINT8:
2797 case FT_UINT16:
2798 case FT_UINT24:
2799 case FT_UINT32:
2800 if (encoding & ENC_VARINT_MASK) {
2801 new_fi->length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value64, encoding);
2802 value = (uint32_t)value64;
2803 if (!(encoding & ENC_VARINT_QUIC)) {
2804 new_fi->flags |= FI_VARINT;
2807 else {
2809 * Map all non-zero values to little-endian for
2810 * backwards compatibility.
2812 if (encoding)
2813 encoding = ENC_LITTLE_ENDIAN;
2815 value = get_uint_value(tree, tvb, start, length, encoding);
2817 proto_tree_set_uint(new_fi, value);
2818 break;
2820 case FT_UINT40:
2821 case FT_UINT48:
2822 case FT_UINT56:
2823 case FT_UINT64:
2824 if (encoding & ENC_VARINT_MASK) {
2825 new_fi->length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value64, encoding);
2826 if (!(encoding & ENC_VARINT_QUIC)) {
2827 new_fi->flags |= FI_VARINT;
2830 else {
2832 * Map all other non-zero values to little-endian for
2833 * backwards compatibility.
2835 if (encoding)
2836 encoding = ENC_LITTLE_ENDIAN;
2838 value64 = get_uint64_value(tree, tvb, start, length, encoding);
2840 proto_tree_set_uint64(new_fi, value64);
2841 break;
2843 /* XXX - make these just FT_INT? */
2844 case FT_INT8:
2845 case FT_INT16:
2846 case FT_INT24:
2847 case FT_INT32:
2849 * Map all non-zero values to little-endian for
2850 * backwards compatibility.
2852 if (encoding)
2853 encoding = ENC_LITTLE_ENDIAN;
2854 proto_tree_set_int(new_fi,
2855 get_int_value(tree, tvb, start, length, encoding));
2856 break;
2858 case FT_INT40:
2859 case FT_INT48:
2860 case FT_INT56:
2861 case FT_INT64:
2863 * Map all non-zero values to little-endian for
2864 * backwards compatibility.
2866 if (encoding)
2867 encoding = ENC_LITTLE_ENDIAN;
2868 proto_tree_set_int64(new_fi,
2869 get_int64_value(tree, tvb, start, length, encoding));
2870 break;
2872 case FT_IPv4:
2874 * Map all non-zero values to little-endian for
2875 * backwards compatibility.
2877 if (encoding)
2878 encoding = ENC_LITTLE_ENDIAN;
2879 if (length != FT_IPv4_LEN) {
2880 length_error = length < FT_IPv4_LEN ? true : false;
2881 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
2883 ipv4_value = tvb_get_ipv4(tvb, start);
2885 * NOTE: to support code written when
2886 * proto_tree_add_item() took a bool as its
2887 * last argument, with false meaning "big-endian"
2888 * and true meaning "little-endian", we treat any
2889 * non-zero value of "encoding" as meaning
2890 * "little-endian".
2892 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(ipv4_value) : ipv4_value);
2893 break;
2895 case FT_IPXNET:
2896 if (length != FT_IPXNET_LEN) {
2897 length_error = length < FT_IPXNET_LEN ? true : false;
2898 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
2900 proto_tree_set_ipxnet(new_fi,
2901 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, ENC_BIG_ENDIAN));
2902 break;
2904 case FT_IPv6:
2905 if (length != FT_IPv6_LEN) {
2906 length_error = length < FT_IPv6_LEN ? true : false;
2907 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
2909 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
2910 break;
2912 case FT_FCWWN:
2913 if (length != FT_FCWWN_LEN) {
2914 length_error = length < FT_FCWWN_LEN ? true : false;
2915 report_type_length_mismatch(tree, "an FCWWN address", length, length_error);
2917 proto_tree_set_fcwwn_tvb(new_fi, tvb, start, length);
2918 break;
2920 case FT_AX25:
2921 if (length != 7) {
2922 length_error = length < 7 ? true : false;
2923 report_type_length_mismatch(tree, "an AX.25 address", length, length_error);
2925 proto_tree_set_ax25_tvb(new_fi, tvb, start);
2926 break;
2928 case FT_VINES:
2929 if (length != VINES_ADDR_LEN) {
2930 length_error = length < VINES_ADDR_LEN ? true : false;
2931 report_type_length_mismatch(tree, "a Vines address", length, length_error);
2933 proto_tree_set_vines_tvb(new_fi, tvb, start);
2934 break;
2936 case FT_ETHER:
2937 if (length != FT_ETHER_LEN) {
2938 length_error = length < FT_ETHER_LEN ? true : false;
2939 report_type_length_mismatch(tree, "a MAC address", length, length_error);
2941 proto_tree_set_ether_tvb(new_fi, tvb, start);
2942 break;
2944 case FT_EUI64:
2946 * Map all non-zero values to little-endian for
2947 * backwards compatibility.
2949 if (encoding)
2950 encoding = ENC_LITTLE_ENDIAN;
2951 if (length != FT_EUI64_LEN) {
2952 length_error = length < FT_EUI64_LEN ? true : false;
2953 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
2955 proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
2956 break;
2957 case FT_GUID:
2959 * Map all non-zero values to little-endian for
2960 * backwards compatibility.
2962 if (encoding)
2963 encoding = ENC_LITTLE_ENDIAN;
2964 if (length != FT_GUID_LEN) {
2965 length_error = length < FT_GUID_LEN ? true : false;
2966 report_type_length_mismatch(tree, "a GUID", length, length_error);
2968 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
2969 break;
2971 case FT_OID:
2972 case FT_REL_OID:
2973 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
2974 break;
2976 case FT_SYSTEM_ID:
2977 proto_tree_set_system_id_tvb(new_fi, tvb, start, length);
2978 break;
2980 case FT_FLOAT:
2982 * NOTE: to support code written when
2983 * proto_tree_add_item() took a bool as its
2984 * last argument, with false meaning "big-endian"
2985 * and true meaning "little-endian", we treat any
2986 * non-zero value of "encoding" as meaning
2987 * "little-endian".
2989 * At some point in the future, we might
2990 * support non-IEEE-binary floating-point
2991 * formats in the encoding as well
2992 * (IEEE decimal, System/3x0, VAX).
2994 if (encoding)
2995 encoding = ENC_LITTLE_ENDIAN;
2996 if (length != 4) {
2997 length_error = length < 4 ? true : false;
2998 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
3000 if (encoding)
3001 floatval = tvb_get_letohieee_float(tvb, start);
3002 else
3003 floatval = tvb_get_ntohieee_float(tvb, start);
3004 proto_tree_set_float(new_fi, floatval);
3005 break;
3007 case FT_DOUBLE:
3009 * NOTE: to support code written when
3010 * proto_tree_add_item() took a bool as its
3011 * last argument, with false meaning "big-endian"
3012 * and true meaning "little-endian", we treat any
3013 * non-zero value of "encoding" as meaning
3014 * "little-endian".
3016 * At some point in the future, we might
3017 * support non-IEEE-binary floating-point
3018 * formats in the encoding as well
3019 * (IEEE decimal, System/3x0, VAX).
3021 if (encoding == true)
3022 encoding = ENC_LITTLE_ENDIAN;
3023 if (length != 8) {
3024 length_error = length < 8 ? true : false;
3025 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
3027 if (encoding)
3028 doubleval = tvb_get_letohieee_double(tvb, start);
3029 else
3030 doubleval = tvb_get_ntohieee_double(tvb, start);
3031 proto_tree_set_double(new_fi, doubleval);
3032 break;
3034 case FT_STRING:
3035 stringval = get_string_value(PNODE_POOL(tree),
3036 tvb, start, length, &length, encoding);
3037 proto_tree_set_string(new_fi, stringval);
3039 /* Instead of calling proto_item_set_len(), since we
3040 * don't yet have a proto_item, we set the
3041 * field_info's length ourselves.
3043 * XXX - our caller can't use that length to
3044 * advance an offset unless they arrange that
3045 * there always be a protocol tree into which
3046 * we're putting this item.
3048 new_fi->length = length;
3049 break;
3051 case FT_STRINGZ:
3052 stringval = get_stringz_value(PNODE_POOL(tree),
3053 tree, tvb, start, length, &length, encoding);
3054 proto_tree_set_string(new_fi, stringval);
3056 /* Instead of calling proto_item_set_len(),
3057 * since we don't yet have a proto_item, we
3058 * set the field_info's length ourselves.
3060 * XXX - our caller can't use that length to
3061 * advance an offset unless they arrange that
3062 * there always be a protocol tree into which
3063 * we're putting this item.
3065 new_fi->length = length;
3066 break;
3068 case FT_UINT_STRING:
3070 * NOTE: to support code written when
3071 * proto_tree_add_item() took a bool as its
3072 * last argument, with false meaning "big-endian"
3073 * and true meaning "little-endian", if the
3074 * encoding value is true, treat that as
3075 * ASCII with a little-endian length.
3077 * This won't work for code that passes
3078 * arbitrary non-zero values; that code
3079 * will need to be fixed.
3081 if (encoding == true)
3082 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
3083 stringval = get_uint_string_value(PNODE_POOL(tree),
3084 tree, tvb, start, length, &length, encoding);
3085 proto_tree_set_string(new_fi, stringval);
3087 /* Instead of calling proto_item_set_len(), since we
3088 * don't yet have a proto_item, we set the
3089 * field_info's length ourselves.
3091 * XXX - our caller can't use that length to
3092 * advance an offset unless they arrange that
3093 * there always be a protocol tree into which
3094 * we're putting this item.
3096 new_fi->length = length;
3097 break;
3099 case FT_STRINGZPAD:
3100 stringval = get_stringzpad_value(PNODE_POOL(tree),
3101 tvb, start, length, &length, encoding);
3102 proto_tree_set_string(new_fi, stringval);
3104 /* Instead of calling proto_item_set_len(), since we
3105 * don't yet have a proto_item, we set the
3106 * field_info's length ourselves.
3108 * XXX - our caller can't use that length to
3109 * advance an offset unless they arrange that
3110 * there always be a protocol tree into which
3111 * we're putting this item.
3113 new_fi->length = length;
3114 break;
3116 case FT_STRINGZTRUNC:
3117 stringval = get_stringztrunc_value(PNODE_POOL(tree),
3118 tvb, start, length, &length, encoding);
3119 proto_tree_set_string(new_fi, stringval);
3121 /* Instead of calling proto_item_set_len(), since we
3122 * don't yet have a proto_item, we set the
3123 * field_info's length ourselves.
3125 * XXX - our caller can't use that length to
3126 * advance an offset unless they arrange that
3127 * there always be a protocol tree into which
3128 * we're putting this item.
3130 new_fi->length = length;
3131 break;
3133 case FT_ABSOLUTE_TIME:
3135 * Absolute times can be in any of a number of
3136 * formats, and they can be big-endian or
3137 * little-endian.
3139 * Historically FT_TIMEs were only timespecs;
3140 * the only question was whether they were stored
3141 * in big- or little-endian format.
3143 * For backwards compatibility, we interpret an
3144 * encoding of 1 as meaning "little-endian timespec",
3145 * so that passing true is interpreted as that.
3147 if (encoding == true)
3148 encoding = ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN;
3150 get_time_value(tree, tvb, start, length, encoding, &time_stamp, false);
3152 proto_tree_set_time(new_fi, &time_stamp);
3153 break;
3155 case FT_RELATIVE_TIME:
3157 * Relative times can be in any of a number of
3158 * formats, and they can be big-endian or
3159 * little-endian.
3161 * Historically FT_TIMEs were only timespecs;
3162 * the only question was whether they were stored
3163 * in big- or little-endian format.
3165 * For backwards compatibility, we interpret an
3166 * encoding of 1 as meaning "little-endian timespec",
3167 * so that passing true is interpreted as that.
3169 if (encoding == true)
3170 encoding = ENC_TIME_SECS_NSECS|ENC_LITTLE_ENDIAN;
3172 get_time_value(tree, tvb, start, length, encoding, &time_stamp, true);
3174 proto_tree_set_time(new_fi, &time_stamp);
3175 break;
3176 case FT_IEEE_11073_SFLOAT:
3177 if (encoding)
3178 encoding = ENC_LITTLE_ENDIAN;
3179 if (length != 2) {
3180 length_error = length < 2 ? true : false;
3181 report_type_length_mismatch(tree, "a IEEE 11073 SFLOAT", length, length_error);
3184 fvalue_set_uinteger(new_fi->value, tvb_get_uint16(tvb, start, encoding));
3186 break;
3187 case FT_IEEE_11073_FLOAT:
3188 if (encoding)
3189 encoding = ENC_LITTLE_ENDIAN;
3190 if (length != 4) {
3191 length_error = length < 4 ? true : false;
3192 report_type_length_mismatch(tree, "a IEEE 11073 FLOAT", length, length_error);
3195 break;
3196 default:
3197 REPORT_DISSECTOR_BUG("field %s is of unknown type %d (%s)",
3198 new_fi->hfinfo->abbrev,
3199 new_fi->hfinfo->type,
3200 ftype_name(new_fi->hfinfo->type));
3201 break;
3203 FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
3205 /* Don't add new node to proto_tree until now so that any exceptions
3206 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
3207 /* XXX. wouldn't be better to add this item to tree, with some special
3208 * flag (FI_EXCEPTION?) to know which item caused exception? For
3209 * strings and bytes, we would have to set new_fi->value to something
3210 * non-NULL, or otherwise ensure that proto_item_fill_display_label
3211 * could handle NULL values. */
3212 CLEANUP_POP
3213 pi = proto_tree_add_node(tree, new_fi);
3215 switch (new_fi->hfinfo->type) {
3217 case FT_STRING:
3218 /* XXX: trailing stray character detection should be done
3219 * _before_ conversion to UTF-8, because conversion can change
3220 * the length, or else get_string_length should return a value
3221 * for the "length in bytes of the string after conversion
3222 * including internal nulls." (Noting that we do, for other
3223 * reasons, still need the "length in bytes in the field",
3224 * especially for FT_STRINGZ.)
3226 * This is true even for ASCII and UTF-8, because
3227 * substituting REPLACEMENT CHARACTERS for illegal characters
3228 * can also do so (and for UTF-8 possibly even make the
3229 * string _shorter_).
3231 detect_trailing_stray_characters(encoding, stringval, length, pi);
3232 break;
3234 default:
3235 break;
3238 return pi;
3241 proto_item *
3242 proto_tree_add_item_ret_int(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3243 const int start, int length,
3244 const unsigned encoding, int32_t *retval)
3246 header_field_info *hfinfo;
3247 field_info *new_fi;
3248 int32_t value;
3250 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3252 switch (hfinfo->type) {
3253 case FT_INT8:
3254 case FT_INT16:
3255 case FT_INT24:
3256 case FT_INT32:
3257 break;
3258 case FT_INT64:
3259 REPORT_DISSECTOR_BUG("64-bit signed integer field %s used with proto_tree_add_item_ret_int()",
3260 hfinfo->abbrev);
3261 default:
3262 REPORT_DISSECTOR_BUG("Non-signed-integer field %s used with proto_tree_add_item_ret_int()",
3263 hfinfo->abbrev);
3266 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length,
3268 if(retval)
3270 *retval = 0;
3272 } );
3274 if (encoding & ENC_STRING) {
3275 REPORT_DISSECTOR_BUG("wrong encoding");
3277 /* I believe it's ok if this is called with a NULL tree */
3278 value = get_int_value(tree, tvb, start, length, encoding);
3280 if (retval) {
3281 int no_of_bits;
3282 *retval = value;
3283 if (hfinfo->bitmask) {
3284 /* Mask out irrelevant portions */
3285 *retval &= (uint32_t)(hfinfo->bitmask);
3286 /* Shift bits */
3287 *retval >>= hfinfo_bitshift(hfinfo);
3289 no_of_bits = ws_count_ones(hfinfo->bitmask);
3290 *retval = ws_sign_ext32(*retval, no_of_bits);
3293 CHECK_FOR_NULL_TREE(tree);
3295 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3297 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3299 proto_tree_set_int(new_fi, value);
3301 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3303 return proto_tree_add_node(tree, new_fi);
3306 proto_item *
3307 proto_tree_add_item_ret_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3308 const int start, int length,
3309 const unsigned encoding, uint32_t *retval)
3311 header_field_info *hfinfo;
3312 field_info *new_fi;
3313 uint32_t value;
3315 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3317 switch (hfinfo->type) {
3318 case FT_CHAR:
3319 case FT_UINT8:
3320 case FT_UINT16:
3321 case FT_UINT24:
3322 case FT_UINT32:
3323 break;
3324 default:
3325 REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
3326 hfinfo->abbrev);
3329 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length,
3331 if(retval)
3333 *retval = 0;
3335 } );
3337 if (encoding & ENC_STRING) {
3338 REPORT_DISSECTOR_BUG("wrong encoding");
3340 /* I believe it's ok if this is called with a NULL tree */
3341 /* XXX - modify if we ever support EBCDIC FT_CHAR */
3342 if (encoding & ENC_VARINT_MASK) {
3343 uint64_t temp64;
3344 tvb_get_varint(tvb, start, length, &temp64, encoding);
3345 value = (uint32_t)temp64;
3346 } else {
3347 value = get_uint_value(tree, tvb, start, length, encoding);
3350 if (retval) {
3351 *retval = value;
3352 if (hfinfo->bitmask) {
3353 /* Mask out irrelevant portions */
3354 *retval &= (uint32_t)(hfinfo->bitmask);
3355 /* Shift bits */
3356 *retval >>= hfinfo_bitshift(hfinfo);
3360 CHECK_FOR_NULL_TREE(tree);
3362 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3364 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3366 proto_tree_set_uint(new_fi, value);
3368 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3369 if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG|ENC_VARINT_SDNV)) {
3370 new_fi->flags |= FI_VARINT;
3372 return proto_tree_add_node(tree, new_fi);
3375 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3376 * and returns proto_item* and uint value retreived*/
3377 proto_item *
3378 ptvcursor_add_ret_uint(ptvcursor_t *ptvc, int hfindex, int length,
3379 const unsigned encoding, uint32_t *retval)
3381 field_info *new_fi;
3382 header_field_info *hfinfo;
3383 int item_length;
3384 int offset;
3385 uint32_t value;
3387 offset = ptvc->offset;
3388 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3390 switch (hfinfo->type) {
3391 case FT_CHAR:
3392 case FT_UINT8:
3393 case FT_UINT16:
3394 case FT_UINT24:
3395 case FT_UINT32:
3396 break;
3397 default:
3398 REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
3399 hfinfo->abbrev);
3402 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
3403 test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);
3405 /* I believe it's ok if this is called with a NULL tree */
3406 /* XXX - modify if we ever support EBCDIC FT_CHAR */
3407 value = get_uint_value(ptvc->tree, ptvc->tvb, offset, item_length, encoding);
3409 if (retval) {
3410 *retval = value;
3411 if (hfinfo->bitmask) {
3412 /* Mask out irrelevant portions */
3413 *retval &= (uint32_t)(hfinfo->bitmask);
3414 /* Shift bits */
3415 *retval >>= hfinfo_bitshift(hfinfo);
3419 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
3420 item_length, encoding);
3422 CHECK_FOR_NULL_TREE(ptvc->tree);
3424 /* Coast clear. Try and fake it */
3425 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
3427 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
3429 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
3430 offset, length, encoding);
3433 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3434 * and returns proto_item* and int value retreived*/
3435 proto_item *
3436 ptvcursor_add_ret_int(ptvcursor_t *ptvc, int hfindex, int length,
3437 const unsigned encoding, int32_t *retval)
3439 field_info *new_fi;
3440 header_field_info *hfinfo;
3441 int item_length;
3442 int offset;
3443 uint32_t value;
3445 offset = ptvc->offset;
3446 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3448 switch (hfinfo->type) {
3449 case FT_INT8:
3450 case FT_INT16:
3451 case FT_INT24:
3452 case FT_INT32:
3453 break;
3454 default:
3455 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
3456 hfinfo->abbrev);
3459 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
3460 test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);
3462 /* I believe it's ok if this is called with a NULL tree */
3463 /* XXX - modify if we ever support EBCDIC FT_CHAR */
3464 value = get_int_value(ptvc->tree, ptvc->tvb, offset, item_length, encoding);
3466 if (retval) {
3467 int no_of_bits;
3468 *retval = value;
3469 if (hfinfo->bitmask) {
3470 /* Mask out irrelevant portions */
3471 *retval &= (uint32_t)(hfinfo->bitmask);
3472 /* Shift bits */
3473 *retval >>= hfinfo_bitshift(hfinfo);
3475 no_of_bits = ws_count_ones(hfinfo->bitmask);
3476 *retval = ws_sign_ext32(*retval, no_of_bits);
3479 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
3480 item_length, encoding);
3482 CHECK_FOR_NULL_TREE(ptvc->tree);
3484 /* Coast clear. Try and fake it */
3485 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
3487 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
3489 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
3490 offset, length, encoding);
3493 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3494 * and returns proto_item* and string value retreived */
3495 proto_item*
3496 ptvcursor_add_ret_string(ptvcursor_t* ptvc, int hf, int length, const unsigned encoding, wmem_allocator_t *scope, const uint8_t **retval)
3498 header_field_info *hfinfo;
3499 field_info *new_fi;
3500 const uint8_t *value;
3501 int item_length;
3502 int offset;
3504 offset = ptvc->offset;
3506 PROTO_REGISTRAR_GET_NTH(hf, hfinfo);
3508 switch (hfinfo->type) {
3509 case FT_STRING:
3510 value = get_string_value(scope, ptvc->tvb, offset, length, &item_length, encoding);
3511 break;
3512 case FT_STRINGZ:
3513 value = get_stringz_value(scope, ptvc->tree, ptvc->tvb, offset, length, &item_length, encoding);
3514 break;
3515 case FT_UINT_STRING:
3516 value = get_uint_string_value(scope, ptvc->tree, ptvc->tvb, offset, length, &item_length, encoding);
3517 break;
3518 case FT_STRINGZPAD:
3519 value = get_stringzpad_value(scope, ptvc->tvb, offset, length, &item_length, encoding);
3520 break;
3521 case FT_STRINGZTRUNC:
3522 value = get_stringztrunc_value(scope, ptvc->tvb, offset, length, &item_length, encoding);
3523 break;
3524 default:
3525 REPORT_DISSECTOR_BUG("field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, FT_STRINGZPAD, or FT_STRINGZTRUNC",
3526 hfinfo->abbrev);
3529 if (retval)
3530 *retval = value;
3532 ptvc->offset += item_length;
3534 CHECK_FOR_NULL_TREE(ptvc->tree);
3536 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfinfo->id, hfinfo);
3538 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
3540 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
3541 offset, length, encoding);
3544 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3545 * and returns proto_item* and boolean value retreived */
3546 proto_item*
3547 ptvcursor_add_ret_boolean(ptvcursor_t* ptvc, int hfindex, int length, const unsigned encoding, bool *retval)
3549 header_field_info *hfinfo;
3550 field_info *new_fi;
3551 int item_length;
3552 int offset;
3553 uint64_t value, bitval;
3555 offset = ptvc->offset;
3556 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3558 if (hfinfo->type != FT_BOOLEAN) {
3559 REPORT_DISSECTOR_BUG("field %s is not of type FT_BOOLEAN",
3560 hfinfo->abbrev);
3563 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length,
3565 if(retval)
3567 *retval = false;
3569 } );
3571 if (encoding & ENC_STRING) {
3572 REPORT_DISSECTOR_BUG("wrong encoding");
3575 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
3576 test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);
3578 /* I believe it's ok if this is called with a NULL tree */
3579 value = get_uint64_value(ptvc->tree, ptvc->tvb, offset, length, encoding);
3581 if (retval) {
3582 bitval = value;
3583 if (hfinfo->bitmask) {
3584 /* Mask out irrelevant portions */
3585 bitval &= hfinfo->bitmask;
3587 *retval = (bitval != 0);
3590 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
3591 item_length, encoding);
3593 CHECK_FOR_NULL_TREE(ptvc->tree);
3595 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfinfo->id, hfinfo);
3597 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
3599 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
3600 offset, length, encoding);
3603 proto_item *
3604 proto_tree_add_item_ret_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3605 const int start, int length, const unsigned encoding, uint64_t *retval)
3607 header_field_info *hfinfo;
3608 field_info *new_fi;
3609 uint64_t value;
3611 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3613 switch (hfinfo->type) {
3614 case FT_UINT40:
3615 case FT_UINT48:
3616 case FT_UINT56:
3617 case FT_UINT64:
3618 break;
3619 default:
3620 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, or FT_UINT64",
3621 hfinfo->abbrev);
3624 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length,
3626 if(retval)
3628 *retval = 0;
3630 } );
3632 if (encoding & ENC_STRING) {
3633 REPORT_DISSECTOR_BUG("wrong encoding");
3635 /* I believe it's ok if this is called with a NULL tree */
3636 if (encoding & ENC_VARINT_MASK) {
3637 tvb_get_varint(tvb, start, length, &value, encoding);
3638 } else {
3639 value = get_uint64_value(tree, tvb, start, length, encoding);
3642 if (retval) {
3643 *retval = value;
3644 if (hfinfo->bitmask) {
3645 /* Mask out irrelevant portions */
3646 *retval &= hfinfo->bitmask;
3647 /* Shift bits */
3648 *retval >>= hfinfo_bitshift(hfinfo);
3652 CHECK_FOR_NULL_TREE(tree);
3654 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3656 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3658 proto_tree_set_uint64(new_fi, value);
3660 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3661 if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG|ENC_VARINT_SDNV)) {
3662 new_fi->flags |= FI_VARINT;
3665 return proto_tree_add_node(tree, new_fi);
3668 proto_item *
3669 proto_tree_add_item_ret_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3670 const int start, int length, const unsigned encoding, int64_t *retval)
3672 header_field_info *hfinfo;
3673 field_info *new_fi;
3674 int64_t value;
3676 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3678 switch (hfinfo->type) {
3679 case FT_INT40:
3680 case FT_INT48:
3681 case FT_INT56:
3682 case FT_INT64:
3683 break;
3684 default:
3685 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
3686 hfinfo->abbrev);
3689 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length,
3691 if(retval)
3693 *retval = 0;
3695 } );
3697 if (encoding & ENC_STRING) {
3698 REPORT_DISSECTOR_BUG("wrong encoding");
3700 /* I believe it's ok if this is called with a NULL tree */
3701 if (encoding & ENC_VARINT_MASK) {
3702 tvb_get_varint(tvb, start, length, &value, encoding);
3704 else {
3705 value = get_int64_value(tree, tvb, start, length, encoding);
3708 if (retval) {
3709 *retval = value;
3712 CHECK_FOR_NULL_TREE(tree);
3714 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3716 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3718 proto_tree_set_int64(new_fi, value);
3720 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3721 if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG|ENC_VARINT_SDNV)) {
3722 new_fi->flags |= FI_VARINT;
3725 return proto_tree_add_node(tree, new_fi);
3728 proto_item *
3729 proto_tree_add_item_ret_varint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3730 const int start, int length, const unsigned encoding, uint64_t *retval, int *lenretval)
3732 header_field_info *hfinfo;
3733 field_info *new_fi;
3734 uint64_t value;
3736 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3738 if ((!FT_IS_INT(hfinfo->type)) && (!FT_IS_UINT(hfinfo->type))) {
3739 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT or FT_INT",
3740 hfinfo->abbrev);
3743 /* length validation for native number encoding caught by get_uint64_value() */
3744 /* length has to be -1 or > 0 regardless of encoding */
3745 if (length == 0)
3746 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_varint",
3747 length);
3749 if (encoding & ENC_STRING) {
3750 REPORT_DISSECTOR_BUG("wrong encoding");
3753 length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value, encoding);
3755 if (retval) {
3756 *retval = value;
3757 if (hfinfo->bitmask) {
3758 /* Mask out irrelevant portions */
3759 *retval &= hfinfo->bitmask;
3760 /* Shift bits */
3761 *retval >>= hfinfo_bitshift(hfinfo);
3765 if (lenretval) {
3766 *lenretval = length;
3769 CHECK_FOR_NULL_TREE(tree);
3771 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3773 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3775 proto_tree_set_uint64(new_fi, value);
3777 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3778 if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG|ENC_VARINT_SDNV)) {
3779 new_fi->flags |= FI_VARINT;
3782 return proto_tree_add_node(tree, new_fi);
3786 proto_item *
3787 proto_tree_add_item_ret_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3788 const int start, int length,
3789 const unsigned encoding, bool *retval)
3791 header_field_info *hfinfo;
3792 field_info *new_fi;
3793 uint64_t value, bitval;
3795 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3797 if (hfinfo->type != FT_BOOLEAN) {
3798 REPORT_DISSECTOR_BUG("field %s is not of type FT_BOOLEAN",
3799 hfinfo->abbrev);
3802 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length,
3804 if(retval)
3806 *retval = false;
3808 } );
3810 if (encoding & ENC_STRING) {
3811 REPORT_DISSECTOR_BUG("wrong encoding");
3813 /* I believe it's ok if this is called with a NULL tree */
3814 value = get_uint64_value(tree, tvb, start, length, encoding);
3816 if (retval) {
3817 bitval = value;
3818 if (hfinfo->bitmask) {
3819 /* Mask out irrelevant portions */
3820 bitval &= hfinfo->bitmask;
3822 *retval = (bitval != 0);
3825 CHECK_FOR_NULL_TREE(tree);
3827 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3829 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3831 proto_tree_set_boolean(new_fi, value);
3833 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3835 return proto_tree_add_node(tree, new_fi);
3838 proto_item *
3839 proto_tree_add_item_ret_float(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3840 const int start, int length,
3841 const unsigned encoding, float *retval)
3843 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3844 field_info *new_fi;
3845 float value;
3847 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3849 if (hfinfo->type != FT_FLOAT) {
3850 REPORT_DISSECTOR_BUG("field %s is not of type FT_FLOAT", hfinfo->abbrev);
3853 if (length != 4) {
3854 report_type_length_mismatch(tree, "a single-precision floating point number", length, true);
3857 /* treat any nonzero encoding as little endian for backwards compatibility */
3858 value = encoding ? tvb_get_letohieee_float(tvb, start) : tvb_get_ntohieee_float(tvb, start);
3859 if (retval) {
3860 *retval = value;
3863 CHECK_FOR_NULL_TREE(tree);
3865 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3867 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3868 if (encoding) {
3869 new_fi->flags |= FI_LITTLE_ENDIAN;
3872 proto_tree_set_float(new_fi, value);
3874 return proto_tree_add_node(tree, new_fi);
3877 proto_item *
3878 proto_tree_add_item_ret_double(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3879 const int start, int length,
3880 const unsigned encoding, double *retval)
3882 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3883 field_info *new_fi;
3884 double value;
3886 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3888 if (hfinfo->type != FT_DOUBLE) {
3889 REPORT_DISSECTOR_BUG("field %s is not of type FT_DOUBLE", hfinfo->abbrev);
3892 if (length != 8) {
3893 report_type_length_mismatch(tree, "a double-precision floating point number", length, true);
3896 /* treat any nonzero encoding as little endian for backwards compatibility */
3897 value = encoding ? tvb_get_letohieee_double(tvb, start) : tvb_get_ntohieee_double(tvb, start);
3898 if (retval) {
3899 *retval = value;
3902 CHECK_FOR_NULL_TREE(tree);
3904 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3906 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3907 if (encoding) {
3908 new_fi->flags |= FI_LITTLE_ENDIAN;
3911 proto_tree_set_double(new_fi, value);
3913 return proto_tree_add_node(tree, new_fi);
3916 proto_item *
3917 proto_tree_add_item_ret_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3918 const int start, int length,
3919 const unsigned encoding, ws_in4_addr *retval)
3921 header_field_info *hfinfo;
3922 field_info *new_fi;
3923 ws_in4_addr value;
3925 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3927 switch (hfinfo->type) {
3928 case FT_IPv4:
3929 break;
3930 default:
3931 REPORT_DISSECTOR_BUG("field %s is not of type FT_IPv4",
3932 hfinfo->abbrev);
3935 if (length != FT_IPv4_LEN)
3936 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_ipv4",
3937 length);
3939 if (encoding & (ENC_STRING | ENC_VARINT_MASK)) {
3940 REPORT_DISSECTOR_BUG("wrong encoding");
3944 * NOTE: to support code written when proto_tree_add_item() took
3945 * a bool as its last argument, with false meaning "big-endian"
3946 * and true meaning "little-endian", we treat any non-zero value
3947 * of "encoding" as meaning "little-endian".
3949 value = tvb_get_ipv4(tvb, start);
3950 if (encoding)
3951 value = GUINT32_SWAP_LE_BE(value);
3953 if (retval) {
3954 *retval = value;
3957 CHECK_FOR_NULL_TREE(tree);
3959 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3961 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3963 proto_tree_set_ipv4(new_fi, value);
3965 new_fi->flags |= encoding ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3966 return proto_tree_add_node(tree, new_fi);
3969 proto_item *
3970 proto_tree_add_item_ret_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3971 const int start, int length,
3972 const unsigned encoding, ws_in6_addr *addr)
3974 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3975 field_info *new_fi;
3977 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3979 switch (hfinfo->type) {
3980 case FT_IPv6:
3981 break;
3982 default:
3983 REPORT_DISSECTOR_BUG("field %s is not of type FT_IPv6",
3984 hfinfo->abbrev);
3987 if (length != FT_IPv6_LEN)
3988 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_ipv6",
3989 length);
3991 if (encoding) {
3992 REPORT_DISSECTOR_BUG("Encodings not yet implemented for proto_tree_add_item_ret_ipv6");
3995 tvb_get_ipv6(tvb, start, addr);
3997 CHECK_FOR_NULL_TREE(tree);
3999 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
4001 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
4003 proto_tree_set_ipv6(new_fi, addr);
4005 return proto_tree_add_node(tree, new_fi);
4008 proto_item *
4009 proto_tree_add_item_ret_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4010 const int start, int length, const unsigned encoding, uint8_t *retval) {
4012 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
4013 field_info *new_fi;
4015 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
4017 switch (hfinfo->type) {
4018 case FT_ETHER:
4019 break;
4020 default:
4021 REPORT_DISSECTOR_BUG("field %s is not of type FT_ETHER",
4022 hfinfo->abbrev);
4025 if (length != FT_ETHER_LEN)
4026 REPORT_DISSECTOR_BUG("Invalid length %d passed to proto_tree_add_item_ret_ether",
4027 length);
4029 if (encoding) {
4030 REPORT_DISSECTOR_BUG("Encodings not yet implemented for proto_tree_add_item_ret_ether");
4033 tvb_memcpy(tvb, retval, start, length);
4035 CHECK_FOR_NULL_TREE(tree);
4037 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
4039 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
4041 proto_tree_set_ether(new_fi, retval);
4043 return proto_tree_add_node(tree, new_fi);
4047 proto_item *
4048 proto_tree_add_item_ret_string_and_length(proto_tree *tree, int hfindex,
4049 tvbuff_t *tvb,
4050 const int start, int length,
4051 const unsigned encoding,
4052 wmem_allocator_t *scope,
4053 const uint8_t **retval,
4054 int *lenretval)
4056 proto_item *pi;
4057 header_field_info *hfinfo;
4058 field_info *new_fi;
4059 const uint8_t *value;
4061 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4063 switch (hfinfo->type) {
4064 case FT_STRING:
4065 value = get_string_value(scope, tvb, start, length, lenretval, encoding);
4066 break;
4067 case FT_STRINGZ:
4068 value = get_stringz_value(scope, tree, tvb, start, length, lenretval, encoding);
4069 break;
4070 case FT_UINT_STRING:
4071 value = get_uint_string_value(scope, tree, tvb, start, length, lenretval, encoding);
4072 break;
4073 case FT_STRINGZPAD:
4074 value = get_stringzpad_value(scope, tvb, start, length, lenretval, encoding);
4075 break;
4076 case FT_STRINGZTRUNC:
4077 value = get_stringztrunc_value(scope, tvb, start, length, lenretval, encoding);
4078 break;
4079 default:
4080 REPORT_DISSECTOR_BUG("field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, FT_STRINGZPAD, or FT_STRINGZTRUNC",
4081 hfinfo->abbrev);
4084 if (retval)
4085 *retval = value;
4087 CHECK_FOR_NULL_TREE(tree);
4089 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
4091 new_fi = new_field_info(tree, hfinfo, tvb, start, *lenretval);
4093 proto_tree_set_string(new_fi, value);
4095 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
4097 pi = proto_tree_add_node(tree, new_fi);
4099 switch (hfinfo->type) {
4101 case FT_STRINGZ:
4102 case FT_STRINGZPAD:
4103 case FT_STRINGZTRUNC:
4104 case FT_UINT_STRING:
4105 break;
4107 case FT_STRING:
4108 detect_trailing_stray_characters(encoding, value, length, pi);
4109 break;
4111 default:
4112 ws_assert_not_reached();
4115 return pi;
4118 proto_item *
4119 proto_tree_add_item_ret_string(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4120 const int start, int length,
4121 const unsigned encoding, wmem_allocator_t *scope,
4122 const uint8_t **retval)
4124 return proto_tree_add_item_ret_string_and_length(tree, hfindex,
4125 tvb, start, length, encoding, scope, retval, &length);
4128 proto_item *
4129 proto_tree_add_item_ret_display_string_and_length(proto_tree *tree, int hfindex,
4130 tvbuff_t *tvb,
4131 const int start, int length,
4132 const unsigned encoding,
4133 wmem_allocator_t *scope,
4134 char **retval,
4135 int *lenretval)
4137 proto_item *pi;
4138 header_field_info *hfinfo;
4139 field_info *new_fi;
4140 const uint8_t *value;
4141 uint32_t n = 0;
4143 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4145 switch (hfinfo->type) {
4146 case FT_STRING:
4147 value = get_string_value(scope, tvb, start, length, lenretval, encoding);
4148 *retval = wmem_alloc(scope, ITEM_LABEL_LENGTH);
4149 ws_label_strcpy(*retval, ITEM_LABEL_LENGTH, 0, value, label_strcat_flags(hfinfo));
4150 break;
4151 case FT_STRINGZ:
4152 value = get_stringz_value(scope, tree, tvb, start, length, lenretval, encoding);
4153 *retval = wmem_alloc(scope, ITEM_LABEL_LENGTH);
4154 ws_label_strcpy(*retval, ITEM_LABEL_LENGTH, 0, value, label_strcat_flags(hfinfo));
4155 break;
4156 case FT_UINT_STRING:
4157 value = get_uint_string_value(scope, tree, tvb, start, length, lenretval, encoding);
4158 *retval = wmem_alloc(scope, ITEM_LABEL_LENGTH);
4159 ws_label_strcpy(*retval, ITEM_LABEL_LENGTH, 0, value, label_strcat_flags(hfinfo));
4160 break;
4161 case FT_STRINGZPAD:
4162 value = get_stringzpad_value(scope, tvb, start, length, lenretval, encoding);
4163 *retval = wmem_alloc(scope, ITEM_LABEL_LENGTH);
4164 ws_label_strcpy(*retval, ITEM_LABEL_LENGTH, 0, value, label_strcat_flags(hfinfo));
4165 break;
4166 case FT_STRINGZTRUNC:
4167 value = get_stringztrunc_value(scope, tvb, start, length, lenretval, encoding);
4168 *retval = wmem_alloc(scope, ITEM_LABEL_LENGTH);
4169 ws_label_strcpy(*retval, ITEM_LABEL_LENGTH, 0, value, label_strcat_flags(hfinfo));
4170 break;
4171 case FT_BYTES:
4172 tvb_ensure_bytes_exist(tvb, start, length);
4173 value = tvb_get_ptr(tvb, start, length);
4174 *retval = format_bytes_hfinfo(scope, hfinfo, value, length);
4175 *lenretval = length;
4176 break;
4177 case FT_UINT_BYTES:
4178 n = get_uint_value(tree, tvb, start, length, encoding);
4179 tvb_ensure_bytes_exist(tvb, start + length, n);
4180 value = tvb_get_ptr(tvb, start + length, n);
4181 *retval = format_bytes_hfinfo(scope, hfinfo, value, n);
4182 *lenretval = length + n;
4183 break;
4184 default:
4185 REPORT_DISSECTOR_BUG("field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, FT_STRINGZPAD, FT_STRINGZTRUNC, FT_BYTES, or FT_UINT_BYTES",
4186 hfinfo->abbrev);
4189 CHECK_FOR_NULL_TREE(tree);
4191 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
4193 new_fi = new_field_info(tree, hfinfo, tvb, start, *lenretval);
4195 switch (hfinfo->type) {
4197 case FT_STRING:
4198 case FT_STRINGZ:
4199 case FT_UINT_STRING:
4200 case FT_STRINGZPAD:
4201 case FT_STRINGZTRUNC:
4202 proto_tree_set_string(new_fi, value);
4203 break;
4205 case FT_BYTES:
4206 proto_tree_set_bytes(new_fi, value, length);
4207 break;
4209 case FT_UINT_BYTES:
4210 proto_tree_set_bytes(new_fi, value, n);
4211 break;
4213 default:
4214 ws_assert_not_reached();
4217 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
4219 pi = proto_tree_add_node(tree, new_fi);
4221 switch (hfinfo->type) {
4223 case FT_STRINGZ:
4224 case FT_STRINGZPAD:
4225 case FT_STRINGZTRUNC:
4226 case FT_UINT_STRING:
4227 break;
4229 case FT_STRING:
4230 detect_trailing_stray_characters(encoding, value, length, pi);
4231 break;
4233 case FT_BYTES:
4234 case FT_UINT_BYTES:
4235 break;
4237 default:
4238 ws_assert_not_reached();
4241 return pi;
4244 proto_item *
4245 proto_tree_add_item_ret_display_string(proto_tree *tree, int hfindex,
4246 tvbuff_t *tvb,
4247 const int start, int length,
4248 const unsigned encoding,
4249 wmem_allocator_t *scope,
4250 char **retval)
4252 return proto_tree_add_item_ret_display_string_and_length(tree, hfindex,
4253 tvb, start, length, encoding, scope, retval, &length);
4256 proto_item *
4257 proto_tree_add_item_ret_time_string(proto_tree *tree, int hfindex,
4258 tvbuff_t *tvb,
4259 const int start, int length, const unsigned encoding,
4260 wmem_allocator_t *scope, char **retval)
4262 header_field_info *hfinfo;
4263 field_info *new_fi;
4264 nstime_t time_stamp;
4265 int flags;
4267 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4269 switch (hfinfo->type) {
4270 case FT_ABSOLUTE_TIME:
4271 get_time_value(tree, tvb, start, length, encoding, &time_stamp, false);
4272 flags = ABS_TIME_TO_STR_SHOW_ZONE;
4273 if (prefs.display_abs_time_ascii < ABS_TIME_ASCII_TREE) {
4274 flags |= ABS_TIME_TO_STR_ISO8601;
4276 *retval = abs_time_to_str_ex(scope, &time_stamp, hfinfo->display, flags);
4277 break;
4278 case FT_RELATIVE_TIME:
4279 get_time_value(tree, tvb, start, length, encoding, &time_stamp, true);
4280 *retval = rel_time_to_secs_str(scope, &time_stamp);
4281 break;
4282 default:
4283 REPORT_DISSECTOR_BUG("field %s is not of type FT_ABSOLUTE_TIME or FT_RELATIVE_TIME",
4284 hfinfo->abbrev);
4287 CHECK_FOR_NULL_TREE(tree);
4289 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
4291 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
4293 switch (hfinfo->type) {
4295 case FT_ABSOLUTE_TIME:
4296 case FT_RELATIVE_TIME:
4297 proto_tree_set_time(new_fi, &time_stamp);
4298 break;
4299 default:
4300 ws_assert_not_reached();
4303 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
4305 return proto_tree_add_node(tree, new_fi);
4308 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
4309 and returns proto_item* */
4310 proto_item *
4311 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, int length,
4312 const unsigned encoding)
4314 field_info *new_fi;
4315 header_field_info *hfinfo;
4316 int item_length;
4317 int offset;
4319 offset = ptvc->offset;
4320 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4321 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
4322 test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);
4324 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
4325 item_length, encoding);
4327 CHECK_FOR_NULL_TREE(ptvc->tree);
4329 /* Coast clear. Try and fake it */
4330 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
4332 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
4334 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
4335 offset, length, encoding);
4338 /* Add an item to a proto_tree, using the text label registered to that item;
4339 the item is extracted from the tvbuff handed to it. */
4340 proto_item *
4341 proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
4342 const int start, int length, const unsigned encoding)
4344 field_info *new_fi;
4345 int item_length;
4347 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
4349 get_hfi_length(hfinfo, tvb, start, &length, &item_length, encoding);
4350 test_length(hfinfo, tvb, start, item_length, encoding);
4352 CHECK_FOR_NULL_TREE(tree);
4354 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
4356 new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
4358 return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
4361 proto_item *
4362 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4363 const int start, int length, const unsigned encoding)
4365 register header_field_info *hfinfo;
4367 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4368 return proto_tree_add_item_new(tree, hfinfo, tvb, start, length, encoding);
4371 /* Add an item to a proto_tree, using the text label registered to that item;
4372 the item is extracted from the tvbuff handed to it.
4374 Return the length of the item through the pointer. */
4375 proto_item *
4376 proto_tree_add_item_new_ret_length(proto_tree *tree, header_field_info *hfinfo,
4377 tvbuff_t *tvb, const int start,
4378 int length, const unsigned encoding,
4379 int *lenretval)
4381 field_info *new_fi;
4382 int item_length;
4383 proto_item *item;
4385 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
4387 get_hfi_length(hfinfo, tvb, start, &length, &item_length, encoding);
4388 test_length(hfinfo, tvb, start, item_length, encoding);
4390 if (!tree) {
4392 * We need to get the correct item length here.
4393 * That's normally done by proto_tree_new_item(),
4394 * but we won't be calling it.
4396 *lenretval = get_full_length(hfinfo, tvb, start, length,
4397 item_length, encoding);
4398 return NULL;
4401 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfinfo->id, hfinfo, {
4403 * Even if the tree item is not referenced (and thus faked),
4404 * the caller must still be informed of the actual length.
4406 *lenretval = get_full_length(hfinfo, tvb, start, length,
4407 item_length, encoding);
4410 new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
4412 item = proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
4413 *lenretval = new_fi->length;
4414 return item;
4417 proto_item *
4418 proto_tree_add_item_ret_length(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4419 const int start, int length,
4420 const unsigned encoding, int *lenretval)
4422 register header_field_info *hfinfo;
4424 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4425 return proto_tree_add_item_new_ret_length(tree, hfinfo, tvb, start, length, encoding, lenretval);
4428 /* which FT_ types can use proto_tree_add_bytes_item() */
4429 static inline bool
4430 validate_proto_tree_add_bytes_ftype(const enum ftenum type)
4432 return (type == FT_BYTES ||
4433 type == FT_UINT_BYTES ||
4434 type == FT_OID ||
4435 type == FT_REL_OID ||
4436 type == FT_SYSTEM_ID );
4439 /* Note: this does no validation that the byte array of an FT_OID or
4440 FT_REL_OID is actually valid; and neither does proto_tree_add_item(),
4441 so I think it's ok to continue not validating it?
4443 proto_item *
4444 proto_tree_add_bytes_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4445 const int start, int length, const unsigned encoding,
4446 GByteArray *retval, int *endoff, int *err)
4448 field_info *new_fi;
4449 GByteArray *bytes = retval;
4450 GByteArray *created_bytes = NULL;
4451 bool failed = false;
4452 uint32_t n = 0;
4453 header_field_info *hfinfo;
4454 bool generate = (bytes || tree) ? true : false;
4456 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4458 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
4460 DISSECTOR_ASSERT_HINT(validate_proto_tree_add_bytes_ftype(hfinfo->type),
4461 "Called proto_tree_add_bytes_item but not a bytes-based FT_XXX type");
4463 CHECK_FOR_ZERO_OR_MINUS_LENGTH(length);
4465 if (encoding & ENC_STR_NUM) {
4466 REPORT_DISSECTOR_BUG("Decoding number strings for byte arrays is not supported");
4469 if (generate && (encoding & ENC_STR_HEX)) {
4470 if (hfinfo->type == FT_UINT_BYTES) {
4471 /* can't decode FT_UINT_BYTES from strings */
4472 REPORT_DISSECTOR_BUG("proto_tree_add_bytes_item called for "
4473 "FT_UINT_BYTES type, but as ENC_STR_HEX");
4476 unsigned hex_encoding = encoding;
4477 if (!(encoding & ENC_SEP_MASK)) {
4478 /* If none of the separator values are used,
4479 * assume no separator (the common case). */
4480 hex_encoding |= ENC_SEP_NONE;
4481 #if 0
4482 REPORT_DISSECTOR_BUG("proto_tree_add_bytes_item called "
4483 "with ENC_STR_HEX but no ENC_SEP_XXX value");
4484 #endif
4487 if (!bytes) {
4488 /* caller doesn't care about return value, but we need it to
4489 call tvb_get_string_bytes() and set the tree later */
4490 bytes = created_bytes = g_byte_array_new();
4494 * bytes might be NULL after this, but can't add expert
4495 * error until later; if it's NULL, just note that
4496 * it failed.
4498 bytes = tvb_get_string_bytes(tvb, start, length, hex_encoding, bytes, endoff);
4499 if (bytes == NULL)
4500 failed = true;
4502 else if (generate) {
4503 tvb_ensure_bytes_exist(tvb, start, length);
4505 if (hfinfo->type == FT_UINT_BYTES) {
4506 n = length; /* n is now the "header" length */
4507 length = get_uint_value(tree, tvb, start, n, encoding);
4508 /* length is now the value's length; only store the value in the array */
4509 tvb_ensure_bytes_exist(tvb, start + n, length);
4510 if (!bytes) {
4511 /* caller doesn't care about return value, but
4512 * we may need it to set the tree later */
4513 bytes = created_bytes = g_byte_array_new();
4515 g_byte_array_append(bytes, tvb_get_ptr(tvb, start + n, length), length);
4517 else if (length > 0) {
4518 if (!bytes) {
4519 /* caller doesn't care about return value, but
4520 * we may need it to set the tree later */
4521 bytes = created_bytes = g_byte_array_new();
4523 g_byte_array_append(bytes, tvb_get_ptr(tvb, start, length), length);
4526 if (endoff)
4527 *endoff = start + n + length;
4530 if (err)
4531 *err = failed ? EINVAL : 0;
4533 CHECK_FOR_NULL_TREE_AND_FREE(tree,
4535 if (created_bytes)
4536 g_byte_array_free(created_bytes, true);
4537 created_bytes = NULL;
4538 bytes = NULL;
4539 } );
4541 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfinfo->id, hfinfo,
4543 if (created_bytes)
4544 g_byte_array_free(created_bytes, true);
4545 created_bytes = NULL;
4546 bytes = NULL;
4547 } );
4549 /* n will be zero except when it's a FT_UINT_BYTES */
4550 new_fi = new_field_info(tree, hfinfo, tvb, start, n + length);
4552 if (encoding & ENC_STRING) {
4553 if (failed)
4554 expert_add_info(NULL, tree, &ei_byte_array_string_decoding_failed_error);
4556 if (bytes)
4557 proto_tree_set_bytes_gbytearray(new_fi, bytes);
4558 else
4559 proto_tree_set_bytes(new_fi, NULL, 0);
4561 if (created_bytes)
4562 g_byte_array_free(created_bytes, true);
4564 else {
4565 /* n will be zero except when it's a FT_UINT_BYTES */
4566 proto_tree_set_bytes_tvb(new_fi, tvb, start + n, length);
4568 /* XXX: If we have a non-NULL tree but NULL retval, we don't
4569 * use the byte array created above in this case.
4571 if (created_bytes)
4572 g_byte_array_free(created_bytes, true);
4574 FI_SET_FLAG(new_fi,
4575 (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
4578 return proto_tree_add_node(tree, new_fi);
4582 proto_item *
4583 proto_tree_add_time_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4584 const int start, int length, const unsigned encoding,
4585 nstime_t *retval, int *endoff, int *err)
4587 field_info *new_fi;
4588 nstime_t time_stamp;
4589 int saved_err = 0;
4590 header_field_info *hfinfo;
4592 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4594 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
4596 CHECK_FOR_ZERO_OR_MINUS_LENGTH_AND_CLEANUP(length,
4598 if(retval)
4600 nstime_set_zero(retval);
4602 } );
4604 nstime_set_zero(&time_stamp);
4606 if (encoding & ENC_STR_TIME_MASK) {
4607 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_ABSOLUTE_TIME);
4608 /* The only string format that could be a relative time is
4609 * ENC_ISO_8601_TIME, and that is treated as an absolute time
4610 * relative to "now" currently.
4612 if (!tvb_get_string_time(tvb, start, length, encoding, &time_stamp, endoff))
4613 saved_err = EINVAL;
4615 else {
4616 DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo);
4617 const bool is_relative = (hfinfo->type == FT_RELATIVE_TIME) ? true : false;
4619 tvb_ensure_bytes_exist(tvb, start, length);
4620 get_time_value(tree, tvb, start, length, encoding, &time_stamp, is_relative);
4621 if (endoff) *endoff = start + length;
4624 if (err) *err = saved_err;
4626 if (retval) {
4627 retval->secs = time_stamp.secs;
4628 retval->nsecs = time_stamp.nsecs;
4631 CHECK_FOR_NULL_TREE(tree);
4633 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
4635 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
4637 proto_tree_set_time(new_fi, &time_stamp);
4639 if (encoding & ENC_STRING) {
4640 if (saved_err)
4641 expert_add_info(NULL, tree, &ei_date_time_string_decoding_failed_error);
4643 else {
4644 FI_SET_FLAG(new_fi,
4645 (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
4648 return proto_tree_add_node(tree, new_fi);
4651 /* Add a FT_NONE to a proto_tree */
4652 proto_item *
4653 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
4654 const int start, int length, const char *format,
4655 ...)
4657 proto_item *pi;
4658 va_list ap;
4659 header_field_info *hfinfo;
4661 CHECK_FOR_NULL_TREE(tree);
4663 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4665 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_NONE);
4667 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4669 TRY_TO_FAKE_THIS_REPR(pi);
4671 va_start(ap, format);
4672 proto_tree_set_representation(pi, format, ap);
4673 va_end(ap);
4675 /* no value to set for FT_NONE */
4676 return pi;
4679 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
4680 * offset, and returns proto_item* */
4681 proto_item *
4682 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, int length,
4683 const unsigned encoding)
4685 proto_item *item;
4687 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
4688 length, encoding);
4690 return item;
4693 /* Advance the ptvcursor's offset within its tvbuff without
4694 * adding anything to the proto_tree. */
4695 void
4696 ptvcursor_advance(ptvcursor_t* ptvc, int length)
4698 ptvc->offset += length;
4702 static void
4703 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb, const char* field_data, int length)
4705 fvalue_set_protocol(fi->value, tvb, field_data, length);
4708 /* Add a FT_PROTOCOL to a proto_tree */
4709 proto_item *
4710 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4711 int start, int length, const char *format, ...)
4713 proto_item *pi;
4714 tvbuff_t *protocol_tvb;
4715 va_list ap;
4716 header_field_info *hfinfo;
4717 char* protocol_rep;
4719 CHECK_FOR_NULL_TREE(tree);
4721 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4723 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_PROTOCOL);
4726 * This can throw an exception, so do it before we allocate anything.
4728 protocol_tvb = (start == 0 ? tvb : tvb_new_subset_length(tvb, start, length));
4730 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4732 va_start(ap, format);
4733 protocol_rep = ws_strdup_vprintf(format, ap);
4734 proto_tree_set_protocol_tvb(PNODE_FINFO(pi), protocol_tvb, protocol_rep, length);
4735 g_free(protocol_rep);
4736 va_end(ap);
4738 TRY_TO_FAKE_THIS_REPR(pi);
4740 va_start(ap, format);
4741 proto_tree_set_representation(pi, format, ap);
4742 va_end(ap);
4744 return pi;
4747 /* Add a FT_BYTES to a proto_tree */
4748 proto_item *
4749 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
4750 int length, const uint8_t *start_ptr)
4752 proto_item *pi;
4753 header_field_info *hfinfo;
4754 int item_length;
4756 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4757 get_hfi_length(hfinfo, tvb, start, &length, &item_length, ENC_NA);
4758 test_length(hfinfo, tvb, start, item_length, ENC_NA);
4760 CHECK_FOR_NULL_TREE(tree);
4762 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4764 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BYTES);
4766 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4767 proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, length);
4769 return pi;
4772 /* Add a FT_BYTES to a proto_tree */
4773 proto_item *
4774 proto_tree_add_bytes_with_length(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
4775 int tvbuff_length, const uint8_t *start_ptr, int ptr_length)
4777 proto_item *pi;
4778 header_field_info *hfinfo;
4779 int item_length;
4781 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
4782 get_hfi_length(hfinfo, tvb, start, &tvbuff_length, &item_length, ENC_NA);
4783 test_length(hfinfo, tvb, start, item_length, ENC_NA);
4785 CHECK_FOR_NULL_TREE(tree);
4787 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4789 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BYTES);
4791 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &tvbuff_length);
4792 proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, ptr_length);
4794 return pi;
4797 proto_item *
4798 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4799 int start, int length,
4800 const uint8_t *start_ptr,
4801 const char *format, ...)
4803 proto_item *pi;
4804 va_list ap;
4806 if (start_ptr == NULL)
4807 start_ptr = tvb_get_ptr(tvb, start, length);
4809 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
4811 TRY_TO_FAKE_THIS_REPR_NESTED(pi);
4813 va_start(ap, format);
4814 proto_tree_set_representation_value(pi, format, ap);
4815 va_end(ap);
4817 return pi;
4820 proto_item *
4821 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4822 int start, int length, const uint8_t *start_ptr,
4823 const char *format, ...)
4825 proto_item *pi;
4826 va_list ap;
4828 if (start_ptr == NULL)
4829 start_ptr = tvb_get_ptr(tvb, start, length);
4831 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
4833 TRY_TO_FAKE_THIS_REPR_NESTED(pi);
4835 va_start(ap, format);
4836 proto_tree_set_representation(pi, format, ap);
4837 va_end(ap);
4839 return pi;
4842 static void
4843 proto_tree_set_bytes(field_info *fi, const uint8_t* start_ptr, int length)
4845 DISSECTOR_ASSERT(length >= 0);
4846 DISSECTOR_ASSERT(start_ptr != NULL || length == 0);
4848 fvalue_set_bytes_data(fi->value, start_ptr, length);
4852 static void
4853 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, int offset, int length)
4855 tvb_ensure_bytes_exist(tvb, offset, length);
4856 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
4859 static void
4860 proto_tree_set_bytes_gbytearray(field_info *fi, const GByteArray *value)
4862 GByteArray *bytes;
4864 DISSECTOR_ASSERT(value != NULL);
4866 bytes = byte_array_dup(value);
4868 fvalue_set_byte_array(fi->value, bytes);
4871 /* Add a FT_*TIME to a proto_tree */
4872 proto_item *
4873 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
4874 int length, const nstime_t *value_ptr)
4876 proto_item *pi;
4877 header_field_info *hfinfo;
4879 CHECK_FOR_NULL_TREE(tree);
4881 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4883 DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo);
4885 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4886 proto_tree_set_time(PNODE_FINFO(pi), value_ptr);
4888 return pi;
4891 proto_item *
4892 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4893 int start, int length, nstime_t *value_ptr,
4894 const char *format, ...)
4896 proto_item *pi;
4897 va_list ap;
4899 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
4900 if (pi != tree) {
4901 va_start(ap, format);
4902 proto_tree_set_representation_value(pi, format, ap);
4903 va_end(ap);
4906 return pi;
4909 proto_item *
4910 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4911 int start, int length, nstime_t *value_ptr,
4912 const char *format, ...)
4914 proto_item *pi;
4915 va_list ap;
4917 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
4918 if (pi != tree) {
4919 TRY_TO_FAKE_THIS_REPR(pi);
4921 va_start(ap, format);
4922 proto_tree_set_representation(pi, format, ap);
4923 va_end(ap);
4926 return pi;
4929 /* Set the FT_*TIME value */
4930 static void
4931 proto_tree_set_time(field_info *fi, const nstime_t *value_ptr)
4933 DISSECTOR_ASSERT(value_ptr != NULL);
4935 fvalue_set_time(fi->value, value_ptr);
4938 /* Add a FT_IPXNET to a proto_tree */
4939 proto_item *
4940 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
4941 int length, uint32_t value)
4943 proto_item *pi;
4944 header_field_info *hfinfo;
4946 CHECK_FOR_NULL_TREE(tree);
4948 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4950 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPXNET);
4952 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4953 proto_tree_set_ipxnet(PNODE_FINFO(pi), value);
4955 return pi;
4958 proto_item *
4959 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4960 int start, int length, uint32_t value,
4961 const char *format, ...)
4963 proto_item *pi;
4964 va_list ap;
4966 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
4967 if (pi != tree) {
4968 va_start(ap, format);
4969 proto_tree_set_representation_value(pi, format, ap);
4970 va_end(ap);
4973 return pi;
4976 proto_item *
4977 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4978 int start, int length, uint32_t value,
4979 const char *format, ...)
4981 proto_item *pi;
4982 va_list ap;
4984 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
4985 if (pi != tree) {
4986 TRY_TO_FAKE_THIS_REPR(pi);
4988 va_start(ap, format);
4989 proto_tree_set_representation(pi, format, ap);
4990 va_end(ap);
4993 return pi;
4996 /* Set the FT_IPXNET value */
4997 static void
4998 proto_tree_set_ipxnet(field_info *fi, uint32_t value)
5000 fvalue_set_uinteger(fi->value, value);
5003 /* Add a FT_IPv4 to a proto_tree */
5004 proto_item *
5005 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5006 int length, ws_in4_addr value)
5008 proto_item *pi;
5009 header_field_info *hfinfo;
5011 CHECK_FOR_NULL_TREE(tree);
5013 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5015 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPv4);
5017 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5018 proto_tree_set_ipv4(PNODE_FINFO(pi), value);
5020 return pi;
5023 proto_item *
5024 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5025 int start, int length, ws_in4_addr value,
5026 const char *format, ...)
5028 proto_item *pi;
5029 va_list ap;
5031 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
5032 if (pi != tree) {
5033 va_start(ap, format);
5034 proto_tree_set_representation_value(pi, format, ap);
5035 va_end(ap);
5038 return pi;
5041 proto_item *
5042 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5043 int start, int length, ws_in4_addr value,
5044 const char *format, ...)
5046 proto_item *pi;
5047 va_list ap;
5049 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
5050 if (pi != tree) {
5051 TRY_TO_FAKE_THIS_REPR(pi);
5053 va_start(ap, format);
5054 proto_tree_set_representation(pi, format, ap);
5055 va_end(ap);
5058 return pi;
5061 /* Set the FT_IPv4 value */
5062 static void
5063 proto_tree_set_ipv4(field_info *fi, ws_in4_addr value)
5065 ipv4_addr_and_mask ipv4;
5066 ws_ipv4_addr_and_mask_init(&ipv4, value, 32);
5067 fvalue_set_ipv4(fi->value, &ipv4);
5070 /* Add a FT_IPv6 to a proto_tree */
5071 proto_item *
5072 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5073 int length, const ws_in6_addr *value)
5075 proto_item *pi;
5076 header_field_info *hfinfo;
5078 CHECK_FOR_NULL_TREE(tree);
5080 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5082 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPv6);
5084 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5085 proto_tree_set_ipv6(PNODE_FINFO(pi), value);
5087 return pi;
5090 proto_item *
5091 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5092 int start, int length,
5093 const ws_in6_addr *value_ptr,
5094 const char *format, ...)
5096 proto_item *pi;
5097 va_list ap;
5099 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
5100 if (pi != tree) {
5101 va_start(ap, format);
5102 proto_tree_set_representation_value(pi, format, ap);
5103 va_end(ap);
5106 return pi;
5109 proto_item *
5110 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5111 int start, int length,
5112 const ws_in6_addr *value_ptr,
5113 const char *format, ...)
5115 proto_item *pi;
5116 va_list ap;
5118 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
5119 if (pi != tree) {
5120 TRY_TO_FAKE_THIS_REPR(pi);
5122 va_start(ap, format);
5123 proto_tree_set_representation(pi, format, ap);
5124 va_end(ap);
5127 return pi;
5130 /* Set the FT_IPv6 value */
5131 static void
5132 proto_tree_set_ipv6(field_info *fi, const ws_in6_addr *value)
5134 DISSECTOR_ASSERT(value != NULL);
5135 ipv6_addr_and_prefix ipv6;
5136 ipv6.addr = *value;
5137 ipv6.prefix = 128;
5138 fvalue_set_ipv6(fi->value, &ipv6);
5141 static void
5142 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, int start, int length)
5144 proto_tree_set_ipv6(fi, (const ws_in6_addr *)tvb_get_ptr(tvb, start, length));
5147 /* Set the FT_FCWWN value */
5148 static void
5149 proto_tree_set_fcwwn(field_info *fi, const uint8_t* value_ptr)
5151 DISSECTOR_ASSERT(value_ptr != NULL);
5152 fvalue_set_fcwwn(fi->value, value_ptr);
5155 static void
5156 proto_tree_set_fcwwn_tvb(field_info *fi, tvbuff_t *tvb, int start, int length)
5158 proto_tree_set_fcwwn(fi, tvb_get_ptr(tvb, start, length));
5161 /* Add a FT_GUID to a proto_tree */
5162 proto_item *
5163 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5164 int length, const e_guid_t *value_ptr)
5166 proto_item *pi;
5167 header_field_info *hfinfo;
5169 CHECK_FOR_NULL_TREE(tree);
5171 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5173 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_GUID);
5175 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5176 proto_tree_set_guid(PNODE_FINFO(pi), value_ptr);
5178 return pi;
5181 proto_item *
5182 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5183 int start, int length,
5184 const e_guid_t *value_ptr,
5185 const char *format, ...)
5187 proto_item *pi;
5188 va_list ap;
5190 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
5191 if (pi != tree) {
5192 va_start(ap, format);
5193 proto_tree_set_representation_value(pi, format, ap);
5194 va_end(ap);
5197 return pi;
5200 proto_item *
5201 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5202 int start, int length, const e_guid_t *value_ptr,
5203 const char *format, ...)
5205 proto_item *pi;
5206 va_list ap;
5208 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
5209 if (pi != tree) {
5210 TRY_TO_FAKE_THIS_REPR(pi);
5212 va_start(ap, format);
5213 proto_tree_set_representation(pi, format, ap);
5214 va_end(ap);
5217 return pi;
5220 /* Set the FT_GUID value */
5221 static void
5222 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
5224 DISSECTOR_ASSERT(value_ptr != NULL);
5225 fvalue_set_guid(fi->value, value_ptr);
5228 static void
5229 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, int start,
5230 const unsigned encoding)
5232 e_guid_t guid;
5234 tvb_get_guid(tvb, start, &guid, encoding);
5235 proto_tree_set_guid(fi, &guid);
5238 /* Add a FT_OID to a proto_tree */
5239 proto_item *
5240 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5241 int length, const uint8_t* value_ptr)
5243 proto_item *pi;
5244 header_field_info *hfinfo;
5246 CHECK_FOR_NULL_TREE(tree);
5248 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5250 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_OID);
5252 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5253 proto_tree_set_oid(PNODE_FINFO(pi), value_ptr, length);
5255 return pi;
5258 proto_item *
5259 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5260 int start, int length,
5261 const uint8_t* value_ptr,
5262 const char *format, ...)
5264 proto_item *pi;
5265 va_list ap;
5267 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
5268 if (pi != tree) {
5269 va_start(ap, format);
5270 proto_tree_set_representation_value(pi, format, ap);
5271 va_end(ap);
5274 return pi;
5277 proto_item *
5278 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5279 int start, int length, const uint8_t* value_ptr,
5280 const char *format, ...)
5282 proto_item *pi;
5283 va_list ap;
5285 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
5286 if (pi != tree) {
5287 TRY_TO_FAKE_THIS_REPR(pi);
5289 va_start(ap, format);
5290 proto_tree_set_representation(pi, format, ap);
5291 va_end(ap);
5294 return pi;
5297 /* Set the FT_OID value */
5298 static void
5299 proto_tree_set_oid(field_info *fi, const uint8_t* value_ptr, int length)
5301 GByteArray *bytes;
5303 DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
5305 bytes = g_byte_array_new();
5306 if (length > 0) {
5307 g_byte_array_append(bytes, value_ptr, length);
5309 fvalue_set_byte_array(fi->value, bytes);
5312 static void
5313 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, int start, int length)
5315 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
5318 /* Set the FT_SYSTEM_ID value */
5319 static void
5320 proto_tree_set_system_id(field_info *fi, const uint8_t* value_ptr, int length)
5322 GByteArray *bytes;
5324 DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
5326 bytes = g_byte_array_new();
5327 if (length > 0) {
5328 g_byte_array_append(bytes, value_ptr, length);
5330 fvalue_set_byte_array(fi->value, bytes);
5333 static void
5334 proto_tree_set_system_id_tvb(field_info *fi, tvbuff_t *tvb, int start, int length)
5336 proto_tree_set_system_id(fi, tvb_get_ptr(tvb, start, length), length);
5339 /* Add a FT_STRING, FT_STRINGZ, FT_STRINGZPAD, or FT_STRINGZTRUNC to a
5340 * proto_tree. Creates own copy of string, and frees it when the proto_tree
5341 * is destroyed. */
5342 proto_item *
5343 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5344 int length, const char* value)
5346 proto_item *pi;
5347 header_field_info *hfinfo;
5348 int item_length;
5350 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
5351 get_hfi_length(hfinfo, tvb, start, &length, &item_length, ENC_NA);
5353 * Special case - if the length is 0, skip the test, so that
5354 * we can have an empty string right after the end of the
5355 * packet. (This handles URL-encoded forms where the last field
5356 * has no value so the form ends right after the =.)
5358 if (item_length != 0)
5359 test_length(hfinfo, tvb, start, item_length, ENC_NA);
5361 CHECK_FOR_NULL_TREE(tree);
5363 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5365 DISSECTOR_ASSERT_FIELD_TYPE_IS_STRING(hfinfo);
5367 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5368 DISSECTOR_ASSERT(length >= 0);
5370 WS_UTF_8_CHECK(value, -1);
5371 proto_tree_set_string(PNODE_FINFO(pi), value);
5373 return pi;
5376 proto_item *
5377 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5378 int start, int length, const char* value,
5379 const char *format,
5380 ...)
5382 proto_item *pi;
5383 va_list ap;
5385 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
5386 if (pi != tree) {
5387 va_start(ap, format);
5388 proto_tree_set_representation_value(pi, format, ap);
5389 va_end(ap);
5392 return pi;
5395 proto_item *
5396 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5397 int start, int length, const char* value,
5398 const char *format, ...)
5400 proto_item *pi;
5401 va_list ap;
5403 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
5404 if (pi != tree) {
5405 TRY_TO_FAKE_THIS_REPR(pi);
5407 va_start(ap, format);
5408 proto_tree_set_representation(pi, format, ap);
5409 va_end(ap);
5412 return pi;
5415 /* Set the FT_STRING value */
5416 static void
5417 proto_tree_set_string(field_info *fi, const char* value)
5419 if (value) {
5420 fvalue_set_string(fi->value, value);
5421 } else {
5423 * XXX - why is a null value for a string field
5424 * considered valid?
5426 fvalue_set_string(fi->value, "[ Null ]");
5430 /* Set the FT_AX25 value */
5431 static void
5432 proto_tree_set_ax25(field_info *fi, const uint8_t* value)
5434 fvalue_set_ax25(fi->value, value);
5437 static void
5438 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, int start)
5440 proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
5443 /* Set the FT_VINES value */
5444 static void
5445 proto_tree_set_vines(field_info *fi, const uint8_t* value)
5447 fvalue_set_vines(fi->value, value);
5450 static void
5451 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, int start)
5453 proto_tree_set_vines(fi, tvb_get_ptr(tvb, start, FT_VINES_ADDR_LEN));
5456 /* Add a FT_ETHER to a proto_tree */
5457 proto_item *
5458 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5459 int length, const uint8_t* value)
5461 proto_item *pi;
5462 header_field_info *hfinfo;
5464 CHECK_FOR_NULL_TREE(tree);
5466 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5468 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_ETHER);
5470 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5471 proto_tree_set_ether(PNODE_FINFO(pi), value);
5473 return pi;
5476 proto_item *
5477 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5478 int start, int length, const uint8_t* value,
5479 const char *format, ...)
5481 proto_item *pi;
5482 va_list ap;
5484 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
5485 if (pi != tree) {
5486 va_start(ap, format);
5487 proto_tree_set_representation_value(pi, format, ap);
5488 va_end(ap);
5491 return pi;
5494 proto_item *
5495 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5496 int start, int length, const uint8_t* value,
5497 const char *format, ...)
5499 proto_item *pi;
5500 va_list ap;
5502 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
5503 if (pi != tree) {
5504 TRY_TO_FAKE_THIS_REPR(pi);
5506 va_start(ap, format);
5507 proto_tree_set_representation(pi, format, ap);
5508 va_end(ap);
5511 return pi;
5514 /* Set the FT_ETHER value */
5515 static void
5516 proto_tree_set_ether(field_info *fi, const uint8_t* value)
5518 fvalue_set_ether(fi->value, value);
5521 static void
5522 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, int start)
5524 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
5527 /* Add a FT_BOOLEAN to a proto_tree */
5528 proto_item *
5529 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5530 int length, uint64_t value)
5532 proto_item *pi;
5533 header_field_info *hfinfo;
5535 CHECK_FOR_NULL_TREE(tree);
5537 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5539 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BOOLEAN);
5541 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5542 proto_tree_set_boolean(PNODE_FINFO(pi), value);
5544 return pi;
5547 proto_item *
5548 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
5549 tvbuff_t *tvb, int start, int length,
5550 uint64_t value, const char *format, ...)
5552 proto_item *pi;
5553 va_list ap;
5555 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
5556 if (pi != tree) {
5557 va_start(ap, format);
5558 proto_tree_set_representation_value(pi, format, ap);
5559 va_end(ap);
5562 return pi;
5565 proto_item *
5566 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5567 int start, int length, uint64_t value,
5568 const char *format, ...)
5570 proto_item *pi;
5571 va_list ap;
5573 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
5574 if (pi != tree) {
5575 TRY_TO_FAKE_THIS_REPR(pi);
5577 va_start(ap, format);
5578 proto_tree_set_representation(pi, format, ap);
5579 va_end(ap);
5582 return pi;
5585 /* Set the FT_BOOLEAN value */
5586 static void
5587 proto_tree_set_boolean(field_info *fi, uint64_t value)
5589 proto_tree_set_uint64(fi, value);
5592 /* Generate, into "buf", a string showing the bits of a bitfield.
5593 Return a pointer to the character after that string. */
5594 static char *
5595 other_decode_bitfield_value(char *buf, const uint64_t val, const uint64_t mask, const int width)
5597 int i = 0;
5598 uint64_t bit;
5599 char *p;
5601 p = buf;
5603 /* This is a devel error. It is safer to stop here. */
5604 DISSECTOR_ASSERT(width >= 1);
5606 bit = UINT64_C(1) << (width - 1);
5607 for (;;) {
5608 if (mask & bit) {
5609 /* This bit is part of the field. Show its value. */
5610 if (val & bit)
5611 *p++ = '1';
5612 else
5613 *p++ = '0';
5614 } else {
5615 /* This bit is not part of the field. */
5616 *p++ = '.';
5618 bit >>= 1;
5619 i++;
5620 if (i >= width)
5621 break;
5622 if (i % 4 == 0)
5623 *p++ = ' ';
5625 *p = '\0';
5626 return p;
5629 static char *
5630 decode_bitfield_value(char *buf, const uint64_t val, const uint64_t mask, const int width)
5632 char *p;
5634 p = other_decode_bitfield_value(buf, val, mask, width);
5635 p = g_stpcpy(p, " = ");
5637 return p;
5640 static char *
5641 other_decode_bitfield_varint_value(char *buf, uint64_t val, uint64_t mask, const int width)
5643 int i = 0;
5644 uint64_t bit;
5645 char *p;
5647 p = buf;
5649 /* This is a devel error. It is safer to stop here. */
5650 DISSECTOR_ASSERT(width >= 1);
5652 bit = UINT64_C(1) << (width - 1);
5653 for (;;) {
5654 if (((8-(i % 8)) != 8) && /* MSB is never used for value. */
5655 (mask & bit)) {
5656 /* This bit is part of the field. Show its value. */
5657 if (val & bit)
5658 *p++ = '1';
5659 else
5660 *p++ = '0';
5661 } else {
5662 /* This bit is not part of the field. */
5663 *p++ = '.';
5665 bit >>= 1;
5666 i++;
5667 if (i >= width)
5668 break;
5669 if (i % 4 == 0)
5670 *p++ = ' ';
5673 *p = '\0';
5674 return p;
5677 static char *
5678 decode_bitfield_varint_value(char *buf, const uint64_t val, const uint64_t mask, const int width)
5680 char *p;
5682 p = other_decode_bitfield_varint_value(buf, val, mask, width);
5683 p = g_stpcpy(p, " = ");
5685 return p;
5688 /* Add a FT_FLOAT to a proto_tree */
5689 proto_item *
5690 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5691 int length, float value)
5693 proto_item *pi;
5694 header_field_info *hfinfo;
5696 CHECK_FOR_NULL_TREE(tree);
5698 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5700 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_FLOAT);
5702 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5703 proto_tree_set_float(PNODE_FINFO(pi), value);
5705 return pi;
5708 proto_item *
5709 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5710 int start, int length, float value,
5711 const char *format, ...)
5713 proto_item *pi;
5714 va_list ap;
5716 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
5717 if (pi != tree) {
5718 va_start(ap, format);
5719 proto_tree_set_representation_value(pi, format, ap);
5720 va_end(ap);
5723 return pi;
5726 proto_item *
5727 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5728 int start, int length, float value,
5729 const char *format, ...)
5731 proto_item *pi;
5732 va_list ap;
5734 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
5735 if (pi != tree) {
5736 TRY_TO_FAKE_THIS_REPR(pi);
5738 va_start(ap, format);
5739 proto_tree_set_representation(pi, format, ap);
5740 va_end(ap);
5743 return pi;
5746 /* Set the FT_FLOAT value */
5747 static void
5748 proto_tree_set_float(field_info *fi, float value)
5750 fvalue_set_floating(fi->value, value);
5753 /* Add a FT_DOUBLE to a proto_tree */
5754 proto_item *
5755 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5756 int length, double value)
5758 proto_item *pi;
5759 header_field_info *hfinfo;
5761 CHECK_FOR_NULL_TREE(tree);
5763 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5765 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_DOUBLE);
5767 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5768 proto_tree_set_double(PNODE_FINFO(pi), value);
5770 return pi;
5773 proto_item *
5774 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5775 int start, int length, double value,
5776 const char *format, ...)
5778 proto_item *pi;
5779 va_list ap;
5781 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
5782 if (pi != tree) {
5783 va_start(ap, format);
5784 proto_tree_set_representation_value(pi, format, ap);
5785 va_end(ap);
5788 return pi;
5791 proto_item *
5792 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5793 int start, int length, double value,
5794 const char *format, ...)
5796 proto_item *pi;
5797 va_list ap;
5799 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
5800 if (pi != tree) {
5801 TRY_TO_FAKE_THIS_REPR(pi);
5803 va_start(ap, format);
5804 proto_tree_set_representation(pi, format, ap);
5805 va_end(ap);
5808 return pi;
5811 /* Set the FT_DOUBLE value */
5812 static void
5813 proto_tree_set_double(field_info *fi, double value)
5815 fvalue_set_floating(fi->value, value);
5818 /* Add FT_CHAR or FT_UINT{8,16,24,32} to a proto_tree */
5819 proto_item *
5820 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5821 int length, uint32_t value)
5823 proto_item *pi = NULL;
5824 header_field_info *hfinfo;
5826 CHECK_FOR_NULL_TREE(tree);
5828 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5830 switch (hfinfo->type) {
5831 case FT_CHAR:
5832 case FT_UINT8:
5833 case FT_UINT16:
5834 case FT_UINT24:
5835 case FT_UINT32:
5836 case FT_FRAMENUM:
5837 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5838 proto_tree_set_uint(PNODE_FINFO(pi), value);
5839 break;
5841 default:
5842 REPORT_DISSECTOR_BUG("field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, FT_UINT32, or FT_FRAMENUM",
5843 hfinfo->abbrev);
5846 return pi;
5849 proto_item *
5850 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5851 int start, int length, uint32_t value,
5852 const char *format, ...)
5854 proto_item *pi;
5855 va_list ap;
5857 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
5858 if (pi != tree) {
5859 va_start(ap, format);
5860 proto_tree_set_representation_value(pi, format, ap);
5861 va_end(ap);
5864 return pi;
5867 proto_item *
5868 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5869 int start, int length, uint32_t value,
5870 const char *format, ...)
5872 proto_item *pi;
5873 va_list ap;
5875 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
5876 if (pi != tree) {
5877 TRY_TO_FAKE_THIS_REPR(pi);
5879 va_start(ap, format);
5880 proto_tree_set_representation(pi, format, ap);
5881 va_end(ap);
5884 return pi;
5887 /* Set the FT_UINT{8,16,24,32} value */
5888 static void
5889 proto_tree_set_uint(field_info *fi, uint32_t value)
5891 const header_field_info *hfinfo;
5892 uint32_t integer;
5894 hfinfo = fi->hfinfo;
5895 integer = value;
5897 if (hfinfo->bitmask) {
5898 /* Mask out irrelevant portions */
5899 integer &= (uint32_t)(hfinfo->bitmask);
5901 /* Shift bits */
5902 integer >>= hfinfo_bitshift(hfinfo);
5904 FI_SET_FLAG(fi, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo)));
5905 FI_SET_FLAG(fi, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo)));
5908 fvalue_set_uinteger(fi->value, integer);
5911 /* Add FT_UINT{40,48,56,64} to a proto_tree */
5912 proto_item *
5913 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
5914 int length, uint64_t value)
5916 proto_item *pi = NULL;
5917 header_field_info *hfinfo;
5919 CHECK_FOR_NULL_TREE(tree);
5921 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5923 switch (hfinfo->type) {
5924 case FT_UINT40:
5925 case FT_UINT48:
5926 case FT_UINT56:
5927 case FT_UINT64:
5928 case FT_FRAMENUM:
5929 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5930 proto_tree_set_uint64(PNODE_FINFO(pi), value);
5931 break;
5933 default:
5934 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, FT_UINT64, or FT_FRAMENUM",
5935 hfinfo->abbrev);
5938 return pi;
5941 proto_item *
5942 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5943 int start, int length, uint64_t value,
5944 const char *format, ...)
5946 proto_item *pi;
5947 va_list ap;
5949 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
5950 if (pi != tree) {
5951 va_start(ap, format);
5952 proto_tree_set_representation_value(pi, format, ap);
5953 va_end(ap);
5956 return pi;
5959 proto_item *
5960 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5961 int start, int length, uint64_t value,
5962 const char *format, ...)
5964 proto_item *pi;
5965 va_list ap;
5967 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
5968 if (pi != tree) {
5969 TRY_TO_FAKE_THIS_REPR(pi);
5971 va_start(ap, format);
5972 proto_tree_set_representation(pi, format, ap);
5973 va_end(ap);
5976 return pi;
5979 /* Set the FT_UINT{40,48,56,64} value */
5980 static void
5981 proto_tree_set_uint64(field_info *fi, uint64_t value)
5983 const header_field_info *hfinfo;
5984 uint64_t integer;
5986 hfinfo = fi->hfinfo;
5987 integer = value;
5989 if (hfinfo->bitmask) {
5990 /* Mask out irrelevant portions */
5991 integer &= hfinfo->bitmask;
5993 /* Shift bits */
5994 integer >>= hfinfo_bitshift(hfinfo);
5996 FI_SET_FLAG(fi, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo)));
5997 FI_SET_FLAG(fi, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo)));
6000 fvalue_set_uinteger64(fi->value, integer);
6003 /* Add FT_INT{8,16,24,32} to a proto_tree */
6004 proto_item *
6005 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
6006 int length, int32_t value)
6008 proto_item *pi = NULL;
6009 header_field_info *hfinfo;
6011 CHECK_FOR_NULL_TREE(tree);
6013 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
6015 switch (hfinfo->type) {
6016 case FT_INT8:
6017 case FT_INT16:
6018 case FT_INT24:
6019 case FT_INT32:
6020 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
6021 proto_tree_set_int(PNODE_FINFO(pi), value);
6022 break;
6024 default:
6025 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
6026 hfinfo->abbrev);
6029 return pi;
6032 proto_item *
6033 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
6034 int start, int length, int32_t value,
6035 const char *format, ...)
6037 proto_item *pi;
6038 va_list ap;
6040 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
6041 if (pi != tree) {
6042 va_start(ap, format);
6043 proto_tree_set_representation_value(pi, format, ap);
6044 va_end(ap);
6047 return pi;
6050 proto_item *
6051 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
6052 int start, int length, int32_t value,
6053 const char *format, ...)
6055 proto_item *pi;
6056 va_list ap;
6058 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
6059 if (pi != tree) {
6060 TRY_TO_FAKE_THIS_REPR(pi);
6062 va_start(ap, format);
6063 proto_tree_set_representation(pi, format, ap);
6064 va_end(ap);
6067 return pi;
6070 /* Set the FT_INT{8,16,24,32} value */
6071 static void
6072 proto_tree_set_int(field_info *fi, int32_t value)
6074 const header_field_info *hfinfo;
6075 uint32_t integer;
6076 int no_of_bits;
6078 hfinfo = fi->hfinfo;
6079 integer = (uint32_t) value;
6081 if (hfinfo->bitmask) {
6082 /* Mask out irrelevant portions */
6083 integer &= (uint32_t)(hfinfo->bitmask);
6085 /* Shift bits */
6086 integer >>= hfinfo_bitshift(hfinfo);
6088 no_of_bits = ws_count_ones(hfinfo->bitmask);
6089 integer = ws_sign_ext32(integer, no_of_bits);
6091 FI_SET_FLAG(fi, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo)));
6092 FI_SET_FLAG(fi, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo)));
6095 fvalue_set_sinteger(fi->value, integer);
6098 /* Add FT_INT{40,48,56,64} to a proto_tree */
6099 proto_item *
6100 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
6101 int length, int64_t value)
6103 proto_item *pi = NULL;
6104 header_field_info *hfinfo;
6106 CHECK_FOR_NULL_TREE(tree);
6108 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
6110 switch (hfinfo->type) {
6111 case FT_INT40:
6112 case FT_INT48:
6113 case FT_INT56:
6114 case FT_INT64:
6115 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
6116 proto_tree_set_int64(PNODE_FINFO(pi), value);
6117 break;
6119 default:
6120 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
6121 hfinfo->abbrev);
6124 return pi;
6127 proto_item *
6128 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
6129 int start, int length, int64_t value,
6130 const char *format, ...)
6132 proto_item *pi;
6133 va_list ap;
6135 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
6136 if (pi != tree) {
6137 va_start(ap, format);
6138 proto_tree_set_representation_value(pi, format, ap);
6139 va_end(ap);
6142 return pi;
6145 /* Set the FT_INT{40,48,56,64} value */
6146 static void
6147 proto_tree_set_int64(field_info *fi, int64_t value)
6149 const header_field_info *hfinfo;
6150 uint64_t integer;
6151 int no_of_bits;
6153 hfinfo = fi->hfinfo;
6154 integer = value;
6156 if (hfinfo->bitmask) {
6157 /* Mask out irrelevant portions */
6158 integer &= hfinfo->bitmask;
6160 /* Shift bits */
6161 integer >>= hfinfo_bitshift(hfinfo);
6163 no_of_bits = ws_count_ones(hfinfo->bitmask);
6164 integer = ws_sign_ext64(integer, no_of_bits);
6166 FI_SET_FLAG(fi, FI_BITS_OFFSET(hfinfo_bitoffset(hfinfo)));
6167 FI_SET_FLAG(fi, FI_BITS_SIZE(hfinfo_mask_bitwidth(hfinfo)));
6170 fvalue_set_sinteger64(fi->value, integer);
6173 proto_item *
6174 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
6175 int start, int length, int64_t value,
6176 const char *format, ...)
6178 proto_item *pi;
6179 va_list ap;
6181 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
6182 if (pi != tree) {
6183 TRY_TO_FAKE_THIS_REPR(pi);
6185 va_start(ap, format);
6186 proto_tree_set_representation(pi, format, ap);
6187 va_end(ap);
6190 return pi;
6193 /* Add a FT_EUI64 to a proto_tree */
6194 proto_item *
6195 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start,
6196 int length, const uint64_t value)
6198 proto_item *pi;
6199 header_field_info *hfinfo;
6201 CHECK_FOR_NULL_TREE(tree);
6203 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
6205 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_EUI64);
6207 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
6208 proto_tree_set_eui64(PNODE_FINFO(pi), value);
6210 return pi;
6213 proto_item *
6214 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
6215 int start, int length, const uint64_t value,
6216 const char *format, ...)
6218 proto_item *pi;
6219 va_list ap;
6221 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
6222 if (pi != tree) {
6223 va_start(ap, format);
6224 proto_tree_set_representation_value(pi, format, ap);
6225 va_end(ap);
6228 return pi;
6231 proto_item *
6232 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
6233 int start, int length, const uint64_t value,
6234 const char *format, ...)
6236 proto_item *pi;
6237 va_list ap;
6239 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
6240 if (pi != tree) {
6241 TRY_TO_FAKE_THIS_REPR(pi);
6243 va_start(ap, format);
6244 proto_tree_set_representation(pi, format, ap);
6245 va_end(ap);
6248 return pi;
6251 /* Set the FT_EUI64 value */
6252 static void
6253 proto_tree_set_eui64(field_info *fi, const uint64_t value)
6255 fvalue_set_uinteger64(fi->value, value);
6257 static void
6258 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, int start, const unsigned encoding)
6260 if (encoding)
6262 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
6263 } else {
6264 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
6268 proto_item *
6269 proto_tree_add_mac48_detail(const mac_hf_list_t *list_specific,
6270 const mac_hf_list_t *list_generic,
6271 int idx, tvbuff_t *tvb,
6272 proto_tree *tree, int offset)
6274 const uint8_t addr[6];
6275 const char *addr_name = NULL;
6276 const char *oui_name = NULL;
6277 proto_item *addr_item = NULL;
6278 proto_tree *addr_tree = NULL;
6279 proto_item *ret_val = NULL;
6281 if (tree == NULL || list_specific == NULL) {
6282 return NULL;
6285 /* Resolve what we can of the address */
6286 tvb_memcpy(tvb, (void *)addr, offset, 6);
6287 if (list_specific->hf_addr_resolved || (list_generic && list_generic->hf_addr_resolved)) {
6288 addr_name = get_ether_name(addr);
6290 if (list_specific->hf_oui_resolved || (list_generic && list_generic->hf_oui_resolved)) {
6291 oui_name = get_manuf_name_if_known(addr, sizeof(addr));
6294 /* Add the item for the specific address type */
6295 ret_val = proto_tree_add_item(tree, *list_specific->hf_addr, tvb, offset, 6, ENC_NA);
6296 if (idx >= 0) {
6297 addr_tree = proto_item_add_subtree(ret_val, idx);
6299 else {
6300 addr_tree = tree;
6303 if (list_specific->hf_addr_resolved != NULL) {
6304 addr_item = proto_tree_add_string(addr_tree, *list_specific->hf_addr_resolved,
6305 tvb, offset, 6, addr_name);
6306 proto_item_set_generated(addr_item);
6307 proto_item_set_hidden(addr_item);
6310 if (list_specific->hf_oui != NULL) {
6311 addr_item = proto_tree_add_item(addr_tree, *list_specific->hf_oui, tvb, offset, 3, ENC_NA);
6312 proto_item_set_generated(addr_item);
6313 proto_item_set_hidden(addr_item);
6315 if (oui_name != NULL && list_specific->hf_oui_resolved != NULL) {
6316 addr_item = proto_tree_add_string(addr_tree, *list_specific->hf_oui_resolved, tvb, offset, 6, oui_name);
6317 proto_item_set_generated(addr_item);
6318 proto_item_set_hidden(addr_item);
6322 if (list_specific->hf_lg != NULL) {
6323 proto_tree_add_item(addr_tree, *list_specific->hf_lg, tvb, offset, 3, ENC_BIG_ENDIAN);
6325 if (list_specific->hf_ig != NULL) {
6326 proto_tree_add_item(addr_tree, *list_specific->hf_ig, tvb, offset, 3, ENC_BIG_ENDIAN);
6329 /* Were we given a list for generic address fields? If not, stop here */
6330 if (list_generic == NULL) {
6331 return ret_val;
6334 addr_item = proto_tree_add_item(addr_tree, *list_generic->hf_addr, tvb, offset, 6, ENC_NA);
6335 proto_item_set_hidden(addr_item);
6337 if (list_generic->hf_addr_resolved != NULL) {
6338 addr_item = proto_tree_add_string(addr_tree, *list_generic->hf_addr_resolved,
6339 tvb, offset, 6, addr_name);
6340 proto_item_set_generated(addr_item);
6341 proto_item_set_hidden(addr_item);
6344 if (list_generic->hf_oui != NULL) {
6345 addr_item = proto_tree_add_item(addr_tree, *list_generic->hf_oui, tvb, offset, 3, ENC_NA);
6346 proto_item_set_generated(addr_item);
6347 proto_item_set_hidden(addr_item);
6349 if (oui_name != NULL && list_generic->hf_oui_resolved != NULL) {
6350 addr_item = proto_tree_add_string(addr_tree, *list_generic->hf_oui_resolved, tvb, offset, 6, oui_name);
6351 proto_item_set_generated(addr_item);
6352 proto_item_set_hidden(addr_item);
6356 if (list_generic->hf_lg != NULL) {
6357 addr_item = proto_tree_add_item(addr_tree, *list_generic->hf_lg, tvb, offset, 3, ENC_BIG_ENDIAN);
6358 proto_item_set_hidden(addr_item);
6360 if (list_generic->hf_ig != NULL) {
6361 addr_item = proto_tree_add_item(addr_tree, *list_generic->hf_ig, tvb, offset, 3, ENC_BIG_ENDIAN);
6362 proto_item_set_hidden(addr_item);
6364 return ret_val;
6367 static proto_item *
6368 proto_tree_add_fake_node(proto_tree *tree, const header_field_info *hfinfo)
6370 proto_node *pnode, *tnode, *sibling;
6371 field_info *tfi;
6372 unsigned depth = 1;
6374 ws_assert(tree);
6377 * Restrict our depth. proto_tree_traverse_pre_order and
6378 * proto_tree_traverse_post_order (and possibly others) are recursive
6379 * so we need to be mindful of our stack size.
6381 if (tree->first_child == NULL) {
6382 for (tnode = tree; tnode != NULL; tnode = tnode->parent) {
6383 depth++;
6384 if (G_UNLIKELY(depth > prefs.gui_max_tree_depth)) {
6385 THROW_MESSAGE(DissectorError, wmem_strdup_printf(PNODE_POOL(tree),
6386 "Maximum tree depth %d exceeded for \"%s\" - \"%s\" (%s:%u) (Maximum depth can be increased in advanced preferences)",
6387 prefs.gui_max_tree_depth,
6388 hfinfo->name, hfinfo->abbrev, G_STRFUNC, __LINE__));
6394 * Make sure "tree" is ready to have subtrees under it, by
6395 * checking whether it's been given an ett_ value.
6397 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
6398 * node of the protocol tree. That node is not displayed,
6399 * so it doesn't need an ett_ value to remember whether it
6400 * was expanded.
6402 tnode = tree;
6403 tfi = PNODE_FINFO(tnode);
6404 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
6405 REPORT_DISSECTOR_BUG("\"%s\" - \"%s\" tfi->tree_type: %d invalid (%s:%u)",
6406 hfinfo->name, hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__);
6407 /* XXX - is it safe to continue here? */
6410 pnode = wmem_new(PNODE_POOL(tree), proto_node);
6411 PROTO_NODE_INIT(pnode);
6412 pnode->parent = tnode;
6413 PNODE_HFINFO(pnode) = hfinfo;
6414 PNODE_FINFO(pnode) = NULL; // Faked
6415 pnode->tree_data = PTREE_DATA(tree);
6417 if (tnode->last_child != NULL) {
6418 sibling = tnode->last_child;
6419 DISSECTOR_ASSERT(sibling->next == NULL);
6420 sibling->next = pnode;
6421 } else
6422 tnode->first_child = pnode;
6423 tnode->last_child = pnode;
6425 /* We should not be adding a fake node for an interesting field */
6426 ws_assert(hfinfo->ref_type != HF_REF_TYPE_DIRECT && hfinfo->ref_type != HF_REF_TYPE_PRINT);
6428 /* XXX - Should the proto_item have a header_field_info member, at least
6429 * for faked items, to know what hfi was faked? (Some dissectors look at
6430 * the tree items directly.)
6432 return (proto_item *)pnode;
6435 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
6436 static proto_item *
6437 proto_tree_add_node(proto_tree *tree, field_info *fi)
6439 proto_node *pnode, *tnode, *sibling;
6440 field_info *tfi;
6441 unsigned depth = 1;
6443 ws_assert(tree);
6446 * Restrict our depth. proto_tree_traverse_pre_order and
6447 * proto_tree_traverse_post_order (and possibly others) are recursive
6448 * so we need to be mindful of our stack size.
6450 if (tree->first_child == NULL) {
6451 for (tnode = tree; tnode != NULL; tnode = tnode->parent) {
6452 depth++;
6453 if (G_UNLIKELY(depth > prefs.gui_max_tree_depth)) {
6454 fvalue_free(fi->value);
6455 fi->value = NULL;
6456 THROW_MESSAGE(DissectorError, wmem_strdup_printf(PNODE_POOL(tree),
6457 "Maximum tree depth %d exceeded for \"%s\" - \"%s\" (%s:%u) (Maximum depth can be increased in advanced preferences)",
6458 prefs.gui_max_tree_depth,
6459 fi->hfinfo->name, fi->hfinfo->abbrev, G_STRFUNC, __LINE__));
6465 * Make sure "tree" is ready to have subtrees under it, by
6466 * checking whether it's been given an ett_ value.
6468 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
6469 * node of the protocol tree. That node is not displayed,
6470 * so it doesn't need an ett_ value to remember whether it
6471 * was expanded.
6473 tnode = tree;
6474 tfi = PNODE_FINFO(tnode);
6475 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
6476 /* Since we are not adding fi to a node, its fvalue won't get
6477 * freed by proto_tree_free_node(), so free it now.
6479 fvalue_free(fi->value);
6480 fi->value = NULL;
6481 REPORT_DISSECTOR_BUG("\"%s\" - \"%s\" tfi->tree_type: %d invalid (%s:%u)",
6482 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__);
6483 /* XXX - is it safe to continue here? */
6486 pnode = wmem_new(PNODE_POOL(tree), proto_node);
6487 PROTO_NODE_INIT(pnode);
6488 pnode->parent = tnode;
6489 PNODE_HFINFO(pnode) = fi->hfinfo;
6490 PNODE_FINFO(pnode) = fi;
6491 pnode->tree_data = PTREE_DATA(tree);
6493 if (tnode->last_child != NULL) {
6494 sibling = tnode->last_child;
6495 DISSECTOR_ASSERT(sibling->next == NULL);
6496 sibling->next = pnode;
6497 } else
6498 tnode->first_child = pnode;
6499 tnode->last_child = pnode;
6501 tree_data_add_maybe_interesting_field(pnode->tree_data, fi);
6503 return (proto_item *)pnode;
6507 /* Generic way to allocate field_info and add to proto_tree.
6508 * Sets *pfi to address of newly-allocated field_info struct */
6509 static proto_item *
6510 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, int start,
6511 int *length)
6513 proto_item *pi;
6514 field_info *fi;
6515 int item_length;
6517 get_hfi_length(hfinfo, tvb, start, length, &item_length, ENC_NA);
6518 fi = new_field_info(tree, hfinfo, tvb, start, item_length);
6519 pi = proto_tree_add_node(tree, fi);
6521 return pi;
6525 static void
6526 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const int start, int *length,
6527 int *item_length, const unsigned encoding)
6529 int length_remaining;
6532 * We only allow a null tvbuff if the item has a zero length,
6533 * i.e. if there's no data backing it.
6535 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
6538 * XXX - in some protocols, there are 32-bit unsigned length
6539 * fields, so lengths in protocol tree and tvbuff routines
6540 * should really be unsigned. We should have, for those
6541 * field types for which "to the end of the tvbuff" makes sense,
6542 * additional routines that take no length argument and
6543 * add fields that run to the end of the tvbuff.
6545 if (*length == -1) {
6547 * For FT_NONE, FT_PROTOCOL, FT_BYTES, FT_STRING,
6548 * FT_STRINGZPAD, and FT_STRINGZTRUNC fields, a length
6549 * of -1 means "set the length to what remains in the
6550 * tvbuff".
6552 * The assumption is either that
6554 * 1) the length of the item can only be determined
6555 * by dissection (typically true of items with
6556 * subitems, which are probably FT_NONE or
6557 * FT_PROTOCOL)
6559 * or
6561 * 2) if the tvbuff is "short" (either due to a short
6562 * snapshot length or due to lack of reassembly of
6563 * fragments/segments/whatever), we want to display
6564 * what's available in the field (probably FT_BYTES
6565 * or FT_STRING) and then throw an exception later
6567 * or
6569 * 3) the field is defined to be "what's left in the
6570 * packet"
6572 * so we set the length to what remains in the tvbuff so
6573 * that, if we throw an exception while dissecting, it
6574 * has what is probably the right value.
6576 * For FT_STRINGZ, it means "the string is null-terminated,
6577 * not null-padded; set the length to the actual length
6578 * of the string", and if the tvbuff if short, we just
6579 * throw an exception.
6581 * For ENC_VARINT_PROTOBUF|ENC_VARINT_QUIC|ENC_VARIANT_ZIGZAG|ENC_VARINT_SDNV, it means "find the end of the string",
6582 * and if the tvbuff if short, we just throw an exception.
6584 * It's not valid for any other type of field. For those
6585 * fields, we treat -1 the same way we treat other
6586 * negative values - we assume the length is a Really
6587 * Big Positive Number, and throw a ReportedBoundsError
6588 * exception, under the assumption that the Really Big
6589 * Length would run past the end of the packet.
6591 if ((FT_IS_INT(hfinfo->type)) || (FT_IS_UINT(hfinfo->type))) {
6592 if (encoding & (ENC_VARINT_PROTOBUF|ENC_VARINT_ZIGZAG|ENC_VARINT_SDNV)) {
6594 * Leave the length as -1, so our caller knows
6595 * it was -1.
6597 *item_length = *length;
6598 return;
6599 } else if (encoding & ENC_VARINT_QUIC) {
6600 switch (tvb_get_uint8(tvb, start) >> 6)
6602 case 0: /* 0b00 => 1 byte length (6 bits Usable) */
6603 *item_length = 1;
6604 break;
6605 case 1: /* 0b01 => 2 bytes length (14 bits Usable) */
6606 *item_length = 2;
6607 break;
6608 case 2: /* 0b10 => 4 bytes length (30 bits Usable) */
6609 *item_length = 4;
6610 break;
6611 case 3: /* 0b11 => 8 bytes length (62 bits Usable) */
6612 *item_length = 8;
6613 break;
6618 switch (hfinfo->type) {
6620 case FT_PROTOCOL:
6621 case FT_NONE:
6622 case FT_BYTES:
6623 case FT_STRING:
6624 case FT_STRINGZPAD:
6625 case FT_STRINGZTRUNC:
6627 * We allow FT_PROTOCOLs to be zero-length -
6628 * for example, an ONC RPC NULL procedure has
6629 * neither arguments nor reply, so the
6630 * payload for that protocol is empty.
6632 * We also allow the others to be zero-length -
6633 * because that's the way the code has been for a
6634 * long, long time.
6636 * However, we want to ensure that the start
6637 * offset is not *past* the byte past the end
6638 * of the tvbuff: we throw an exception in that
6639 * case.
6641 *length = tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
6642 DISSECTOR_ASSERT(*length >= 0);
6643 break;
6645 case FT_STRINGZ:
6647 * Leave the length as -1, so our caller knows
6648 * it was -1.
6650 break;
6652 default:
6653 THROW(ReportedBoundsError);
6654 DISSECTOR_ASSERT_NOT_REACHED();
6656 *item_length = *length;
6657 } else {
6658 *item_length = *length;
6659 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
6661 * These types are for interior nodes of the
6662 * tree, and don't have data associated with
6663 * them; if the length is negative (XXX - see
6664 * above) or goes past the end of the tvbuff,
6665 * cut it short at the end of the tvbuff.
6666 * That way, if this field is selected in
6667 * Wireshark, we don't highlight stuff past
6668 * the end of the data.
6670 /* XXX - what to do, if we don't have a tvb? */
6671 if (tvb) {
6672 length_remaining = tvb_captured_length_remaining(tvb, start);
6673 if (*item_length < 0 ||
6674 (*item_length > 0 &&
6675 (length_remaining < *item_length)))
6676 *item_length = length_remaining;
6679 if (*item_length < 0) {
6680 THROW(ReportedBoundsError);
6685 static int
6686 get_full_length(header_field_info *hfinfo, tvbuff_t *tvb, const int start,
6687 int length, unsigned item_length, const int encoding)
6689 uint32_t n;
6692 * We need to get the correct item length here.
6693 * That's normally done by proto_tree_new_item(),
6694 * but we won't be calling it.
6696 switch (hfinfo->type) {
6698 case FT_NONE:
6699 case FT_PROTOCOL:
6700 case FT_BYTES:
6702 * The length is the specified length.
6704 break;
6706 case FT_UINT_BYTES:
6707 n = get_uint_value(NULL, tvb, start, length, encoding);
6708 item_length += n;
6709 if ((int)item_length < length) {
6710 THROW(ReportedBoundsError);
6712 break;
6714 /* XXX - make these just FT_UINT? */
6715 case FT_UINT8:
6716 case FT_UINT16:
6717 case FT_UINT24:
6718 case FT_UINT32:
6719 case FT_UINT40:
6720 case FT_UINT48:
6721 case FT_UINT56:
6722 case FT_UINT64:
6723 /* XXX - make these just FT_INT? */
6724 case FT_INT8:
6725 case FT_INT16:
6726 case FT_INT24:
6727 case FT_INT32:
6728 case FT_INT40:
6729 case FT_INT48:
6730 case FT_INT56:
6731 case FT_INT64:
6732 if (encoding & ENC_VARINT_MASK) {
6733 if (length < -1) {
6734 report_type_length_mismatch(NULL, "a FT_[U]INT", length, true);
6736 if (length == -1) {
6737 uint64_t dummy;
6738 /* This can throw an exception */
6739 /* XXX - do this without fetching the varint? */
6740 length = tvb_get_varint(tvb, start, FT_VARINT_MAX_LEN, &dummy, encoding);
6741 if (length == 0) {
6742 THROW(ReportedBoundsError);
6745 item_length = length;
6746 break;
6750 * The length is the specified length.
6752 break;
6754 case FT_BOOLEAN:
6755 case FT_CHAR:
6756 case FT_IPv4:
6757 case FT_IPXNET:
6758 case FT_IPv6:
6759 case FT_FCWWN:
6760 case FT_AX25:
6761 case FT_VINES:
6762 case FT_ETHER:
6763 case FT_EUI64:
6764 case FT_GUID:
6765 case FT_OID:
6766 case FT_REL_OID:
6767 case FT_SYSTEM_ID:
6768 case FT_FLOAT:
6769 case FT_DOUBLE:
6770 case FT_STRING:
6772 * The length is the specified length.
6774 break;
6776 case FT_STRINGZ:
6777 if (length < -1) {
6778 report_type_length_mismatch(NULL, "a string", length, true);
6780 if (length == -1) {
6781 /* This can throw an exception */
6782 /* XXX - do this without fetching the string? */
6783 wmem_free(NULL, tvb_get_stringz_enc(NULL, tvb, start, &length, encoding));
6785 item_length = length;
6786 break;
6788 case FT_UINT_STRING:
6789 n = get_uint_value(NULL, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
6790 item_length += n;
6791 if ((int)item_length < length) {
6792 THROW(ReportedBoundsError);
6794 break;
6796 case FT_STRINGZPAD:
6797 case FT_STRINGZTRUNC:
6798 case FT_ABSOLUTE_TIME:
6799 case FT_RELATIVE_TIME:
6800 case FT_IEEE_11073_SFLOAT:
6801 case FT_IEEE_11073_FLOAT:
6803 * The length is the specified length.
6805 break;
6807 default:
6808 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in gset_full_length()",
6809 hfinfo->abbrev,
6810 hfinfo->type,
6811 ftype_name(hfinfo->type));
6812 break;
6814 return item_length;
6817 // This was arbitrarily chosen, but if you're adding 50K items to the tree
6818 // without advancing the offset you should probably take a long, hard look
6819 // at what you're doing.
6820 // We *could* make this a configurable option, but I (Gerald) would like to
6821 // avoid adding yet another nerd knob.
6822 # define PROTO_TREE_MAX_IDLE 50000
6823 static field_info *
6824 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
6825 const int start, const int item_length)
6827 field_info *fi;
6829 FIELD_INFO_NEW(PNODE_POOL(tree), fi);
6831 fi->hfinfo = hfinfo;
6832 fi->start = start;
6833 fi->start += (tvb)?tvb_raw_offset(tvb):0;
6834 // If our start offset hasn't advanced after adding many items it probably
6835 // means we're in a large or infinite loop.
6836 if (fi->start > 0) {
6837 if (fi->start <= PTREE_DATA(tree)->max_start) {
6838 PTREE_DATA(tree)->start_idle_count++;
6839 DISSECTOR_ASSERT_HINT(PTREE_DATA(tree)->start_idle_count < PROTO_TREE_MAX_IDLE, fi->hfinfo->abbrev);
6840 } else {
6841 PTREE_DATA(tree)->max_start = fi->start;
6842 PTREE_DATA(tree)->start_idle_count = 0;
6845 fi->length = item_length;
6846 fi->tree_type = -1;
6847 fi->flags = 0;
6848 if (!PTREE_DATA(tree)->visible) {
6849 /* If the tree is not visible, set the item hidden, unless we
6850 * need the representation or length and can't fake them.
6852 if (hfinfo->ref_type != HF_REF_TYPE_PRINT && (hfinfo->type != FT_PROTOCOL || PTREE_DATA(tree)->fake_protocols)) {
6853 FI_SET_FLAG(fi, FI_HIDDEN);
6856 fi->value = fvalue_new(fi->hfinfo->type);
6857 fi->rep = NULL;
6859 /* add the data source tvbuff */
6860 fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
6862 fi->appendix_start = 0;
6863 fi->appendix_length = 0;
6865 fi->total_layer_num = tree->tree_data->pinfo->curr_layer_num;
6866 fi->proto_layer_num = tree->tree_data->pinfo->curr_proto_layer_num;
6868 return fi;
6871 static size_t proto_find_value_pos(const header_field_info *hfinfo, const char *representation)
6873 if (hfinfo->display & BASE_NO_DISPLAY_VALUE) {
6874 return 0;
6877 /* Search for field name */
6878 char *ptr = strstr(representation, hfinfo->name);
6879 if (!ptr) {
6880 return 0;
6883 /* Check if field name ends with the ": " delimiter */
6884 ptr += strlen(hfinfo->name);
6885 if (strncmp(ptr, ": ", 2) == 0) {
6886 ptr += 2;
6889 /* Return offset to after field name */
6890 return ptr - representation;
6893 /* If the protocol tree is to be visible, set the representation of a
6894 proto_tree entry with the name of the field for the item and with
6895 the value formatted with the supplied printf-style format and
6896 argument list. */
6897 static void
6898 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
6900 ws_assert(pi);
6902 /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
6903 * items string representation */
6904 if (PTREE_DATA(pi)->visible || !proto_item_is_hidden(pi)) {
6905 size_t name_pos, ret = 0;
6906 char *str;
6907 field_info *fi = PITEM_FINFO(pi);
6908 const header_field_info *hf;
6910 DISSECTOR_ASSERT(fi);
6912 hf = fi->hfinfo;
6914 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
6915 if (hf->bitmask && (hf->type == FT_BOOLEAN || FT_IS_UINT(hf->type))) {
6916 uint64_t val;
6917 char *p;
6919 if (FT_IS_UINT32(hf->type))
6920 val = fvalue_get_uinteger(fi->value);
6921 else
6922 val = fvalue_get_uinteger64(fi->value);
6924 val <<= hfinfo_bitshift(hf);
6926 p = decode_bitfield_value(fi->rep->representation, val, hf->bitmask, hfinfo_container_bitwidth(hf));
6927 ret = (p - fi->rep->representation);
6930 /* put in the hf name */
6931 name_pos = ret = label_concat(fi->rep->representation, ret, hf->name);
6933 ret = label_concat(fi->rep->representation, ret, ": ");
6934 /* If possible, Put in the value of the string */
6935 str = wmem_strdup_vprintf(PNODE_POOL(pi), format, ap);
6936 WS_UTF_8_CHECK(str, -1);
6937 fi->rep->value_pos = ret;
6938 ret = ws_label_strcpy(fi->rep->representation, ITEM_LABEL_LENGTH, ret, str, 0);
6939 if (ret >= ITEM_LABEL_LENGTH) {
6940 /* Uh oh, we don't have enough room. Tell the user
6941 * that the field is truncated.
6943 label_mark_truncated(fi->rep->representation, name_pos, &fi->rep->value_pos);
6945 fi->rep->value_len = strlen(fi->rep->representation) - fi->rep->value_pos;
6949 /* If the protocol tree is to be visible, set the representation of a
6950 proto_tree entry with the representation formatted with the supplied
6951 printf-style format and argument list. */
6952 static void
6953 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
6955 size_t ret; /*tmp return value */
6956 char *str;
6957 field_info *fi = PITEM_FINFO(pi);
6959 DISSECTOR_ASSERT(fi);
6961 if (!proto_item_is_hidden(pi)) {
6962 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
6964 str = wmem_strdup_vprintf(PNODE_POOL(pi), format, ap);
6965 WS_UTF_8_CHECK(str, -1);
6966 fi->rep->value_pos = proto_find_value_pos(fi->hfinfo, str);
6967 ret = ws_label_strcpy(fi->rep->representation, ITEM_LABEL_LENGTH, 0, str, 0);
6968 if (ret >= ITEM_LABEL_LENGTH) {
6969 /* Uh oh, we don't have enough room. Tell the user
6970 * that the field is truncated.
6972 LABEL_MARK_TRUNCATED_START(fi->rep->representation, &fi->rep->value_pos);
6974 fi->rep->value_len = strlen(fi->rep->representation) - fi->rep->value_pos;
6978 static int
6979 protoo_strlcpy(char *dest, const char *src, size_t dest_size)
6981 if (dest_size == 0) return 0;
6983 size_t res = g_strlcpy(dest, src, dest_size);
6985 /* At most dest_size - 1 characters will be copied
6986 * (unless dest_size is 0). */
6987 if (res >= dest_size)
6988 res = dest_size - 1;
6989 return (int) res;
6992 static header_field_info *
6993 hfinfo_same_name_get_prev(const header_field_info *hfinfo)
6995 header_field_info *dup_hfinfo;
6997 if (hfinfo->same_name_prev_id == -1)
6998 return NULL;
6999 PROTO_REGISTRAR_GET_NTH(hfinfo->same_name_prev_id, dup_hfinfo);
7000 return dup_hfinfo;
7003 static void
7004 hfinfo_remove_from_gpa_name_map(const header_field_info *hfinfo)
7006 g_free(last_field_name);
7007 last_field_name = NULL;
7009 if (!hfinfo->same_name_next && hfinfo->same_name_prev_id == -1) {
7010 /* No hfinfo with the same name */
7011 g_hash_table_steal(gpa_name_map, hfinfo->abbrev);
7012 return;
7015 if (hfinfo->same_name_next) {
7016 hfinfo->same_name_next->same_name_prev_id = hfinfo->same_name_prev_id;
7019 if (hfinfo->same_name_prev_id != -1) {
7020 header_field_info *same_name_prev = hfinfo_same_name_get_prev(hfinfo);
7021 same_name_prev->same_name_next = hfinfo->same_name_next;
7022 if (!hfinfo->same_name_next) {
7023 /* It's always the latest added hfinfo which is stored in gpa_name_map */
7024 g_hash_table_insert(gpa_name_map, (void *) (same_name_prev->abbrev), same_name_prev);
7030 proto_item_fill_display_label(const field_info *finfo, char *display_label_str, const int label_str_size)
7032 const header_field_info *hfinfo = finfo->hfinfo;
7033 int label_len = 0;
7034 char *tmp_str;
7035 const char *str;
7036 const uint8_t *bytes;
7037 uint32_t number;
7038 uint64_t number64;
7039 const char *hf_str_val;
7040 char number_buf[NUMBER_LABEL_LENGTH];
7041 const char *number_out;
7042 address addr;
7043 const ipv4_addr_and_mask *ipv4;
7044 const ipv6_addr_and_prefix *ipv6;
7046 switch (hfinfo->type) {
7048 case FT_NONE:
7049 case FT_PROTOCOL:
7050 return protoo_strlcpy(display_label_str, UTF8_CHECK_MARK, label_str_size);
7052 case FT_UINT_BYTES:
7053 case FT_BYTES:
7054 tmp_str = format_bytes_hfinfo_maxlen(NULL,
7055 hfinfo,
7056 fvalue_get_bytes_data(finfo->value),
7057 (unsigned)fvalue_length2(finfo->value),
7058 label_str_size);
7059 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7060 wmem_free(NULL, tmp_str);
7061 break;
7063 case FT_ABSOLUTE_TIME:
7065 int flags = ABS_TIME_TO_STR_SHOW_ZONE;
7066 if (prefs.display_abs_time_ascii < ABS_TIME_ASCII_COLUMN) {
7067 flags |= ABS_TIME_TO_STR_ISO8601;
7069 tmp_str = abs_time_to_str_ex(NULL, fvalue_get_time(finfo->value), hfinfo->display, flags);
7070 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7071 wmem_free(NULL, tmp_str);
7072 break;
7075 case FT_RELATIVE_TIME:
7076 tmp_str = rel_time_to_secs_str(NULL, fvalue_get_time(finfo->value));
7077 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7078 wmem_free(NULL, tmp_str);
7079 break;
7081 case FT_BOOLEAN:
7082 number64 = fvalue_get_uinteger64(finfo->value);
7083 label_len = protoo_strlcpy(display_label_str,
7084 tfs_get_string(!!number64, hfinfo->strings), label_str_size);
7085 break;
7087 case FT_CHAR:
7088 number = fvalue_get_uinteger(finfo->value);
7090 if (FIELD_DISPLAY(hfinfo->display) == BASE_CUSTOM) {
7091 char tmp[ITEM_LABEL_LENGTH];
7092 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
7094 DISSECTOR_ASSERT(fmtfunc);
7095 fmtfunc(tmp, number);
7097 label_len = protoo_strlcpy(display_label_str, tmp, label_str_size);
7099 } else if (hfinfo->strings) {
7100 number_out = hf_try_val_to_str(number, hfinfo);
7102 if (!number_out) {
7103 number_out = hfinfo_char_value_format_display(BASE_HEX, number_buf, number);
7106 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
7108 } else {
7109 number_out = hfinfo_char_value_format(hfinfo, number_buf, number);
7111 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
7114 break;
7116 /* XXX - make these just FT_NUMBER? */
7117 case FT_INT8:
7118 case FT_INT16:
7119 case FT_INT24:
7120 case FT_INT32:
7121 case FT_UINT8:
7122 case FT_UINT16:
7123 case FT_UINT24:
7124 case FT_UINT32:
7125 case FT_FRAMENUM:
7126 hf_str_val = NULL;
7127 number = FT_IS_INT(hfinfo->type) ?
7128 (uint32_t) fvalue_get_sinteger(finfo->value) :
7129 fvalue_get_uinteger(finfo->value);
7131 if (FIELD_DISPLAY(hfinfo->display) == BASE_CUSTOM) {
7132 char tmp[ITEM_LABEL_LENGTH];
7133 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
7135 DISSECTOR_ASSERT(fmtfunc);
7136 fmtfunc(tmp, number);
7138 label_len = protoo_strlcpy(display_label_str, tmp, label_str_size);
7140 } else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) {
7141 if (hfinfo->display & BASE_UNIT_STRING) {
7142 number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
7143 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
7144 hf_str_val = hf_try_val_to_str(number, hfinfo);
7145 label_len += protoo_strlcpy(display_label_str+label_len, hf_str_val, label_str_size-label_len);
7146 } else {
7147 number_out = hf_try_val_to_str(number, hfinfo);
7149 if (!number_out) {
7150 number_out = hfinfo_number_value_format_display(hfinfo, hfinfo->display, number_buf, number);
7153 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
7155 } else {
7156 number_out = hfinfo_number_value_format(hfinfo, number_buf, number);
7158 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
7161 break;
7163 case FT_INT40:
7164 case FT_INT48:
7165 case FT_INT56:
7166 case FT_INT64:
7167 case FT_UINT40:
7168 case FT_UINT48:
7169 case FT_UINT56:
7170 case FT_UINT64:
7171 hf_str_val = NULL;
7172 number64 = FT_IS_INT(hfinfo->type) ?
7173 (uint64_t) fvalue_get_sinteger64(finfo->value) :
7174 fvalue_get_uinteger64(finfo->value);
7176 if (FIELD_DISPLAY(hfinfo->display) == BASE_CUSTOM) {
7177 char tmp[ITEM_LABEL_LENGTH];
7178 custom_fmt_func_64_t fmtfunc64 = (custom_fmt_func_64_t)hfinfo->strings;
7180 DISSECTOR_ASSERT(fmtfunc64);
7181 fmtfunc64(tmp, number64);
7183 label_len = protoo_strlcpy(display_label_str, tmp, label_str_size);
7184 } else if (hfinfo->strings) {
7185 if (hfinfo->display & BASE_UNIT_STRING) {
7186 number_out = hfinfo_numeric_value_format64(hfinfo, number_buf, number64);
7187 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
7188 hf_str_val = hf_try_val64_to_str(number64, hfinfo);
7189 label_len += protoo_strlcpy(display_label_str+label_len, hf_str_val, label_str_size-label_len);
7190 } else {
7191 number_out = hf_try_val64_to_str(number64, hfinfo);
7193 if (!number_out)
7194 number_out = hfinfo_number_value_format_display64(hfinfo, hfinfo->display, number_buf, number64);
7196 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
7198 } else {
7199 number_out = hfinfo_number_value_format64(hfinfo, number_buf, number64);
7201 label_len = protoo_strlcpy(display_label_str, number_out, label_str_size);
7204 break;
7206 case FT_EUI64:
7207 tmp_str = eui64_to_str(NULL, fvalue_get_uinteger64(finfo->value));
7208 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7209 wmem_free(NULL, tmp_str);
7210 break;
7212 case FT_IPv4:
7213 ipv4 = fvalue_get_ipv4(finfo->value);
7214 //XXX: Should we ignore the mask?
7215 set_address_ipv4(&addr, ipv4);
7216 tmp_str = address_to_display(NULL, &addr);
7217 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7218 wmem_free(NULL, tmp_str);
7219 free_address(&addr);
7220 break;
7222 case FT_IPv6:
7223 ipv6 = fvalue_get_ipv6(finfo->value);
7224 set_address_ipv6(&addr, ipv6);
7225 tmp_str = address_to_display(NULL, &addr);
7226 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7227 wmem_free(NULL, tmp_str);
7228 free_address(&addr);
7229 break;
7231 case FT_FCWWN:
7232 set_address (&addr, AT_FCWWN, FCWWN_ADDR_LEN, fvalue_get_bytes_data(finfo->value));
7233 tmp_str = address_to_display(NULL, &addr);
7234 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7235 wmem_free(NULL, tmp_str);
7236 break;
7238 case FT_ETHER:
7239 set_address (&addr, AT_ETHER, FT_ETHER_LEN, fvalue_get_bytes_data(finfo->value));
7240 tmp_str = address_to_display(NULL, &addr);
7241 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7242 wmem_free(NULL, tmp_str);
7243 break;
7245 case FT_GUID:
7246 tmp_str = guid_to_str(NULL, fvalue_get_guid(finfo->value));
7247 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7248 wmem_free(NULL, tmp_str);
7249 break;
7251 case FT_REL_OID:
7252 bytes = fvalue_get_bytes_data(finfo->value);
7253 tmp_str = rel_oid_resolved_from_encoded(NULL, bytes, (int)fvalue_length2(finfo->value));
7254 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7255 wmem_free(NULL, tmp_str);
7256 break;
7258 case FT_OID:
7259 bytes = fvalue_get_bytes_data(finfo->value);
7260 tmp_str = oid_resolved_from_encoded(NULL, bytes, (int)fvalue_length2(finfo->value));
7261 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7262 wmem_free(NULL, tmp_str);
7263 break;
7265 case FT_SYSTEM_ID:
7266 bytes = fvalue_get_bytes_data(finfo->value);
7267 tmp_str = print_system_id(NULL, bytes, (int)fvalue_length2(finfo->value));
7268 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7269 wmem_free(NULL, tmp_str);
7270 break;
7272 case FT_FLOAT:
7273 case FT_DOUBLE:
7274 label_len = (int)fill_display_label_float(finfo, display_label_str);
7275 break;
7277 case FT_STRING:
7278 case FT_STRINGZ:
7279 case FT_UINT_STRING:
7280 case FT_STRINGZPAD:
7281 case FT_STRINGZTRUNC:
7282 str = fvalue_get_string(finfo->value);
7283 label_len = (int)ws_label_strcpy(display_label_str, label_str_size, 0, str, label_strcat_flags(hfinfo));
7284 if (label_len >= label_str_size) {
7285 /* Truncation occurred. Get the real length
7286 * copied (not including '\0') */
7287 label_len = label_str_size ? label_str_size - 1 : 0;
7289 break;
7291 default:
7292 /* First try ftype string representation */
7293 tmp_str = fvalue_to_string_repr(NULL, finfo->value, FTREPR_DISPLAY, hfinfo->display);
7294 if (!tmp_str) {
7295 /* Default to show as bytes */
7296 bytes = fvalue_get_bytes_data(finfo->value);
7297 tmp_str = bytes_to_str(NULL, bytes, fvalue_length2(finfo->value));
7299 label_len = protoo_strlcpy(display_label_str, tmp_str, label_str_size);
7300 wmem_free(NULL, tmp_str);
7301 break;
7303 return label_len;
7306 /* -------------------------- */
7307 /* Sets the text for a custom column from proto fields.
7309 * @param[out] result The "resolved" column text (human readable, uses strings)
7310 * @param[out] expr The "unresolved" column text (values, display repr)
7311 * @return The filter (abbrev) for the field (XXX: Only the first if multifield)
7313 const char *
7314 proto_custom_set(proto_tree* tree, GSList *field_ids, int occurrence, bool display_details,
7315 char *result, char *expr, const int size)
7317 int len, prev_len, last, i, offset_r = 0, offset_e = 0;
7318 GPtrArray *finfos;
7319 field_info *finfo = NULL;
7320 header_field_info* hfinfo;
7321 const char *abbrev = NULL;
7323 const char *hf_str_val;
7324 char *str;
7325 col_custom_t *field_idx;
7326 int field_id;
7327 int ii = 0;
7329 ws_assert(field_ids != NULL);
7330 while ((field_idx = (col_custom_t *) g_slist_nth_data(field_ids, ii++))) {
7331 field_id = field_idx->field_id;
7332 if (field_id == 0) {
7333 GPtrArray *fvals = NULL;
7334 bool passed = dfilter_apply_full(field_idx->dfilter, tree, &fvals);
7335 if (fvals != NULL) {
7337 // XXX - Handling occurrences is unusual when more
7338 // than one field is involved, e.g. there's four
7339 // results for tcp.port + tcp.port. We may really
7340 // want to apply it to the operands, not the output.
7341 // Note that occurrences are not quite the same as
7342 // the layer operator (should the grammar support
7343 // both?)
7344 /* Calculate single index or set outer boundaries */
7345 len = g_ptr_array_len(fvals);
7346 if (occurrence < 0) {
7347 i = occurrence + len;
7348 last = i;
7349 } else if (occurrence > 0) {
7350 i = occurrence - 1;
7351 last = i;
7352 } else {
7353 i = 0;
7354 last = len - 1;
7356 if (i < 0 || i >= len) {
7357 g_ptr_array_unref(fvals);
7358 continue;
7360 for (; i <= last; i++) {
7361 /* XXX - We could have a "resolved" result
7362 * for types where the value depends only
7363 * on the type, e.g. FT_IPv4, and not on
7364 * hfinfo->strings. Supporting the latter
7365 * requires knowing which hfinfo matched
7366 * if there are multiple with the same
7367 * abbreviation. In any case, we need to
7368 * know the expected return type of the
7369 * field expression.
7371 str = fvalue_to_string_repr(NULL, fvals->pdata[i], FTREPR_DISPLAY, BASE_NONE);
7372 if (offset_r && (offset_r < (size - 1)))
7373 result[offset_r++] = ',';
7374 if (offset_e && (offset_e < (size - 1)))
7375 expr[offset_e++] = ',';
7376 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
7377 offset_e += protoo_strlcpy(expr+offset_e, str, size-offset_e);
7378 g_free(str);
7380 g_ptr_array_unref(fvals);
7381 } else if (passed) {
7382 // XXX - Occurrence doesn't make sense for a test
7383 // output, it should be applied to the operands.
7384 if (offset_r && (offset_r < (size - 1)))
7385 result[offset_r++] = ',';
7386 if (offset_e && (offset_e < (size - 1)))
7387 expr[offset_e++] = ',';
7388 /* Prevent multiple check marks */
7389 if (strstr(result, UTF8_CHECK_MARK ",") == NULL) {
7390 offset_r += protoo_strlcpy(result+offset_r, UTF8_CHECK_MARK, size-offset_r);
7391 } else {
7392 result[--offset_r] = '\0'; /* Remove the added trailing ',' */
7394 if (strstr(expr, UTF8_CHECK_MARK ",") == NULL) {
7395 offset_e += protoo_strlcpy(expr+offset_e, UTF8_CHECK_MARK, size-offset_e);
7396 } else {
7397 expr[--offset_e] = '\0'; /* Remove the added trailing ',' */
7400 continue;
7402 PROTO_REGISTRAR_GET_NTH((unsigned)field_id, hfinfo);
7404 /* do we need to rewind ? */
7405 if (!hfinfo)
7406 return "";
7408 if (occurrence < 0) {
7409 /* Search other direction */
7410 while (hfinfo->same_name_prev_id != -1) {
7411 PROTO_REGISTRAR_GET_NTH(hfinfo->same_name_prev_id, hfinfo);
7415 prev_len = 0; /* Reset handled occurrences */
7417 while (hfinfo) {
7418 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
7420 if (!finfos || !(len = g_ptr_array_len(finfos))) {
7421 if (occurrence < 0) {
7422 hfinfo = hfinfo->same_name_next;
7423 } else {
7424 hfinfo = hfinfo_same_name_get_prev(hfinfo);
7426 continue;
7429 /* Are there enough occurrences of the field? */
7430 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
7431 if (occurrence < 0) {
7432 hfinfo = hfinfo->same_name_next;
7433 } else {
7434 hfinfo = hfinfo_same_name_get_prev(hfinfo);
7436 prev_len += len;
7437 continue;
7440 /* Calculate single index or set outer boundaries */
7441 if (occurrence < 0) {
7442 i = occurrence + len + prev_len;
7443 last = i;
7444 } else if (occurrence > 0) {
7445 i = occurrence - 1 - prev_len;
7446 last = i;
7447 } else {
7448 i = 0;
7449 last = len - 1;
7452 prev_len += len; /* Count handled occurrences */
7454 while (i <= last) {
7455 finfo = (field_info *)g_ptr_array_index(finfos, i);
7457 if (offset_r && (offset_r < (size - 1)))
7458 result[offset_r++] = ',';
7460 if (display_details) {
7461 char representation[ITEM_LABEL_LENGTH];
7462 size_t offset = 0;
7464 if (finfo->rep && finfo->rep->value_len) {
7465 g_strlcpy(representation, &finfo->rep->representation[finfo->rep->value_pos],
7466 MIN(finfo->rep->value_len + 1, ITEM_LABEL_LENGTH));
7467 } else {
7468 proto_item_fill_label(finfo, representation, &offset);
7470 offset_r += protoo_strlcpy(result+offset_r, &representation[offset], size-offset_r);
7471 } else {
7472 switch (hfinfo->type) {
7474 case FT_NONE:
7475 case FT_PROTOCOL:
7476 /* Prevent multiple check marks */
7477 if (strstr(result, UTF8_CHECK_MARK ",") == NULL) {
7478 offset_r += proto_item_fill_display_label(finfo, result+offset_r, size-offset_r);
7479 } else {
7480 result[--offset_r] = '\0'; /* Remove the added trailing ',' again */
7482 break;
7484 default:
7485 offset_r += proto_item_fill_display_label(finfo, result+offset_r, size-offset_r);
7486 break;
7490 if (offset_e && (offset_e < (size - 1)))
7491 expr[offset_e++] = ',';
7493 if (hfinfo->strings && hfinfo->type != FT_FRAMENUM && FIELD_DISPLAY(hfinfo->display) == BASE_NONE && (FT_IS_INT(hfinfo->type) || FT_IS_UINT(hfinfo->type))) {
7494 /* Integer types with BASE_NONE never get the numeric value. */
7495 if (FT_IS_INT32(hfinfo->type)) {
7496 hf_str_val = hf_try_val_to_str_const(fvalue_get_sinteger(finfo->value), hfinfo, "Unknown");
7497 } else if (FT_IS_UINT32(hfinfo->type)) {
7498 hf_str_val = hf_try_val_to_str_const(fvalue_get_uinteger(finfo->value), hfinfo, "Unknown");
7499 } else if (FT_IS_INT64(hfinfo->type)) {
7500 hf_str_val = hf_try_val64_to_str_const(fvalue_get_sinteger64(finfo->value), hfinfo, "Unknown");
7501 } else { // if (FT_IS_UINT64(hfinfo->type)) {
7502 hf_str_val = hf_try_val64_to_str_const(fvalue_get_uinteger64(finfo->value), hfinfo, "Unknown");
7504 snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
7505 offset_e = (int)strlen(expr);
7506 } else if (hfinfo->type == FT_NONE || hfinfo->type == FT_PROTOCOL) {
7507 /* Prevent multiple check marks */
7508 if (strstr(expr, UTF8_CHECK_MARK ",") == NULL) {
7509 offset_e += proto_item_fill_display_label(finfo, expr+offset_e, size-offset_e);
7510 } else {
7511 expr[--offset_e] = '\0'; /* Remove the added trailing ',' again */
7513 } else {
7514 str = fvalue_to_string_repr(NULL, finfo->value, FTREPR_RAW, finfo->hfinfo->display);
7515 offset_e += protoo_strlcpy(expr+offset_e, str, size-offset_e);
7516 wmem_free(NULL, str);
7518 i++;
7521 /* XXX: Why is only the first abbreviation returned for a multifield
7522 * custom column? */
7523 if (!abbrev) {
7524 /* Store abbrev for return value */
7525 abbrev = hfinfo->abbrev;
7528 if (occurrence == 0) {
7529 /* Fetch next hfinfo with same name (abbrev) */
7530 hfinfo = hfinfo_same_name_get_prev(hfinfo);
7531 } else {
7532 hfinfo = NULL;
7537 if (offset_r >= (size - 1)) {
7538 mark_truncated(result, 0, size, NULL);
7540 if (offset_e >= (size - 1)) {
7541 mark_truncated(expr, 0, size, NULL);
7543 return abbrev ? abbrev : "";
7546 char *
7547 proto_custom_get_filter(epan_dissect_t* edt, GSList *field_ids, int occurrence)
7549 int len, prev_len, last, i;
7550 GPtrArray *finfos;
7551 field_info *finfo = NULL;
7552 header_field_info* hfinfo;
7554 char *filter = NULL;
7555 GPtrArray *filter_array;
7557 col_custom_t *col_custom;
7558 int field_id;
7560 ws_assert(field_ids != NULL);
7561 filter_array = g_ptr_array_new_full(g_slist_length(field_ids), g_free);
7562 for (GSList *iter = field_ids; iter; iter = iter->next) {
7563 col_custom = (col_custom_t*)iter->data;
7564 field_id = col_custom->field_id;
7565 if (field_id == 0) {
7566 GPtrArray *fvals = NULL;
7567 bool passed = dfilter_apply_full(col_custom->dfilter, edt->tree, &fvals);
7568 if (fvals != NULL) {
7569 // XXX - Handling occurrences is unusual when more
7570 // than one field is involved, e.g. there's four
7571 // results for tcp.port + tcp.port. We really
7572 // want to apply it to the operands, not the output.
7573 /* Calculate single index or set outer boundaries */
7574 len = g_ptr_array_len(fvals);
7575 if (occurrence < 0) {
7576 i = occurrence + len;
7577 last = i;
7578 } else if (occurrence > 0) {
7579 i = occurrence - 1;
7580 last = i;
7581 } else {
7582 i = 0;
7583 last = len - 1;
7585 if (i < 0 || i >= len) {
7586 g_ptr_array_unref(fvals);
7587 continue;
7589 for (; i <= last; i++) {
7590 /* XXX - Should multiple values for one
7591 * field use set membership to reduce
7592 * verbosity, here and below? */
7593 char *str = fvalue_to_string_repr(NULL, fvals->pdata[i], FTREPR_DFILTER, BASE_NONE);
7594 filter = wmem_strdup_printf(NULL, "%s == %s", col_custom->dftext, str);
7595 wmem_free(NULL, str);
7596 if (!g_ptr_array_find_with_equal_func(filter_array, filter, g_str_equal, NULL)) {
7597 g_ptr_array_add(filter_array, filter);
7600 g_ptr_array_unref(fvals);
7601 } else if (passed) {
7602 filter = wmem_strdup(NULL, col_custom->dftext);
7603 if (!g_ptr_array_find_with_equal_func(filter_array, filter, g_str_equal, NULL)) {
7604 g_ptr_array_add(filter_array, filter);
7606 } else {
7607 filter = wmem_strdup_printf(NULL, "!(%s)", col_custom->dftext);
7608 if (!g_ptr_array_find_with_equal_func(filter_array, filter, g_str_equal, NULL)) {
7609 g_ptr_array_add(filter_array, filter);
7612 continue;
7615 PROTO_REGISTRAR_GET_NTH((unsigned)field_id, hfinfo);
7617 /* do we need to rewind ? */
7618 if (!hfinfo)
7619 return NULL;
7621 if (occurrence < 0) {
7622 /* Search other direction */
7623 while (hfinfo->same_name_prev_id != -1) {
7624 PROTO_REGISTRAR_GET_NTH(hfinfo->same_name_prev_id, hfinfo);
7628 prev_len = 0; /* Reset handled occurrences */
7630 while (hfinfo) {
7631 finfos = proto_get_finfo_ptr_array(edt->tree, hfinfo->id);
7633 if (!finfos || !(len = g_ptr_array_len(finfos))) {
7634 if (occurrence < 0) {
7635 hfinfo = hfinfo->same_name_next;
7636 } else {
7637 hfinfo = hfinfo_same_name_get_prev(hfinfo);
7639 continue;
7642 /* Are there enough occurrences of the field? */
7643 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
7644 if (occurrence < 0) {
7645 hfinfo = hfinfo->same_name_next;
7646 } else {
7647 hfinfo = hfinfo_same_name_get_prev(hfinfo);
7649 prev_len += len;
7650 continue;
7653 /* Calculate single index or set outer boundaries */
7654 if (occurrence < 0) {
7655 i = occurrence + len + prev_len;
7656 last = i;
7657 } else if (occurrence > 0) {
7658 i = occurrence - 1 - prev_len;
7659 last = i;
7660 } else {
7661 i = 0;
7662 last = len - 1;
7665 prev_len += len; /* Count handled occurrences */
7667 while (i <= last) {
7668 finfo = (field_info *)g_ptr_array_index(finfos, i);
7670 filter = proto_construct_match_selected_string(finfo, edt);
7671 if (filter) {
7672 /* Only add the same expression once (especially for FT_PROTOCOL).
7673 * The ptr array doesn't have NULL entries so g_str_equal is fine.
7675 if (!g_ptr_array_find_with_equal_func(filter_array, filter, g_str_equal, NULL)) {
7676 g_ptr_array_add(filter_array, filter);
7679 i++;
7682 if (occurrence == 0) {
7683 /* Fetch next hfinfo with same name (abbrev) */
7684 hfinfo = hfinfo_same_name_get_prev(hfinfo);
7685 } else {
7686 hfinfo = NULL;
7691 g_ptr_array_add(filter_array, NULL);
7693 /* XXX: Should this be || or && ? */
7694 char *output = g_strjoinv(" || ", (char **)filter_array->pdata);
7696 g_ptr_array_free(filter_array, true);
7698 return output;
7701 /* Set text of proto_item after having already been created. */
7702 void
7703 proto_item_set_text(proto_item *pi, const char *format, ...)
7705 field_info *fi = NULL;
7706 va_list ap;
7708 TRY_TO_FAKE_THIS_REPR_VOID(pi);
7710 fi = PITEM_FINFO(pi);
7711 if (fi == NULL)
7712 return;
7714 if (fi->rep) {
7715 ITEM_LABEL_FREE(PNODE_POOL(pi), fi->rep);
7716 fi->rep = NULL;
7719 va_start(ap, format);
7720 proto_tree_set_representation(pi, format, ap);
7721 va_end(ap);
7724 /* Append to text of proto_item after having already been created. */
7725 void
7726 proto_item_append_text(proto_item *pi, const char *format, ...)
7728 field_info *fi = NULL;
7729 size_t curlen;
7730 char *str;
7731 va_list ap;
7733 TRY_TO_FAKE_THIS_REPR_VOID(pi);
7735 fi = PITEM_FINFO(pi);
7736 if (fi == NULL) {
7737 return;
7740 if (!proto_item_is_hidden(pi)) {
7742 * If we don't already have a representation,
7743 * generate the default representation.
7745 if (fi->rep == NULL) {
7746 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
7747 proto_item_fill_label(fi, fi->rep->representation, &fi->rep->value_pos);
7748 /* Check for special case append value to FT_NONE or FT_PROTOCOL */
7749 if ((fi->hfinfo->type == FT_NONE || fi->hfinfo->type == FT_PROTOCOL) &&
7750 (strncmp(format, ": ", 2) == 0)) {
7751 fi->rep->value_pos += 2;
7754 if (fi->rep) {
7755 curlen = strlen(fi->rep->representation);
7756 /* curlen doesn't include the \0 byte.
7757 * XXX: If curlen + 4 > ITEM_LABEL_LENGTH, we can't tell if
7758 * the representation has already been truncated (of an up
7759 * to 4 byte UTF-8 character) or is just at the maximum length
7760 * unless we search for " [truncated]" (which may not be
7761 * at the start.)
7762 * It's safer to do nothing.
7764 if (ITEM_LABEL_LENGTH > (curlen + 4)) {
7765 va_start(ap, format);
7766 str = wmem_strdup_vprintf(PNODE_POOL(pi), format, ap);
7767 va_end(ap);
7768 WS_UTF_8_CHECK(str, -1);
7769 /* Keep fi->rep->value_pos */
7770 curlen = ws_label_strcpy(fi->rep->representation, ITEM_LABEL_LENGTH, curlen, str, 0);
7771 if (curlen >= ITEM_LABEL_LENGTH) {
7772 /* Uh oh, we don't have enough room. Tell the user
7773 * that the field is truncated.
7775 LABEL_MARK_TRUNCATED_START(fi->rep->representation, &fi->rep->value_pos);
7777 fi->rep->value_len = strlen(fi->rep->representation) - fi->rep->value_pos;
7783 /* Prepend to text of proto_item after having already been created. */
7784 void
7785 proto_item_prepend_text(proto_item *pi, const char *format, ...)
7787 field_info *fi = NULL;
7788 size_t pos;
7789 char representation[ITEM_LABEL_LENGTH];
7790 char *str;
7791 va_list ap;
7793 TRY_TO_FAKE_THIS_REPR_VOID(pi);
7795 fi = PITEM_FINFO(pi);
7796 if (fi == NULL) {
7797 return;
7800 if (!proto_item_is_hidden(pi)) {
7802 * If we don't already have a representation,
7803 * generate the default representation.
7805 if (fi->rep == NULL) {
7806 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
7807 proto_item_fill_label(fi, representation, &fi->rep->value_pos);
7808 } else
7809 (void) g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
7811 va_start(ap, format);
7812 str = wmem_strdup_vprintf(PNODE_POOL(pi), format, ap);
7813 va_end(ap);
7814 WS_UTF_8_CHECK(str, -1);
7815 fi->rep->value_pos += strlen(str);
7816 pos = ws_label_strcpy(fi->rep->representation, ITEM_LABEL_LENGTH, 0, str, 0);
7817 pos = ws_label_strcpy(fi->rep->representation, ITEM_LABEL_LENGTH, pos, representation, 0);
7818 /* XXX: As above, if the old representation is close to the label
7819 * length, it might already be marked as truncated. */
7820 if (pos >= ITEM_LABEL_LENGTH && (strlen(representation) + 4) <= ITEM_LABEL_LENGTH) {
7821 /* Uh oh, we don't have enough room. Tell the user
7822 * that the field is truncated.
7824 LABEL_MARK_TRUNCATED_START(fi->rep->representation, &fi->rep->value_pos);
7826 fi->rep->value_len = strlen(fi->rep->representation) - fi->rep->value_pos;
7830 static void
7831 finfo_set_len(field_info *fi, const int length)
7833 int length_remaining;
7835 DISSECTOR_ASSERT_HINT(length >= 0, fi->hfinfo->abbrev);
7836 length_remaining = tvb_captured_length_remaining(fi->ds_tvb, fi->start);
7837 if (length > length_remaining)
7838 fi->length = length_remaining;
7839 else
7840 fi->length = length;
7842 /* If we have an FT_PROTOCOL we need to set the length of the fvalue tvbuff as well. */
7843 if (fvalue_type_ftenum(fi->value) == FT_PROTOCOL) {
7844 fvalue_set_protocol_length(fi->value, fi->length);
7848 * You cannot just make the "len" field of a GByteArray
7849 * larger, if there's no data to back that length;
7850 * you can only make it smaller.
7852 if (fvalue_type_ftenum(fi->value) == FT_BYTES && fi->length > 0) {
7853 GBytes *bytes = fvalue_get_bytes(fi->value);
7854 size_t size;
7855 const void *data = g_bytes_get_data(bytes, &size);
7856 if ((size_t)fi->length <= size) {
7857 fvalue_set_bytes_data(fi->value, data, fi->length);
7859 g_bytes_unref(bytes);
7863 void
7864 proto_item_set_len(proto_item *pi, const int length)
7866 field_info *fi;
7868 if (pi == NULL)
7869 return;
7871 fi = PITEM_FINFO(pi);
7872 if (fi == NULL)
7873 return;
7875 finfo_set_len(fi, length);
7879 * Sets the length of the item based on its start and on the specified
7880 * offset, which is the offset past the end of the item; as the start
7881 * in the item is relative to the beginning of the data source tvbuff,
7882 * we need to pass in a tvbuff - the end offset is relative to the beginning
7883 * of that tvbuff.
7885 void
7886 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, int end)
7888 field_info *fi;
7889 int length;
7891 if (pi == NULL)
7892 return;
7894 fi = PITEM_FINFO(pi);
7895 if (fi == NULL)
7896 return;
7898 end += tvb_raw_offset(tvb);
7899 DISSECTOR_ASSERT(end >= fi->start);
7900 length = end - fi->start;
7902 finfo_set_len(fi, length);
7906 proto_item_get_len(const proto_item *pi)
7908 field_info *fi;
7910 if (!pi)
7911 return -1;
7912 fi = PITEM_FINFO(pi);
7913 return fi ? fi->length : -1;
7916 void
7917 proto_item_set_bits_offset_len(proto_item *ti, int bits_offset, int bits_len) {
7918 if (!ti) {
7919 return;
7921 FI_SET_FLAG(PNODE_FINFO(ti), FI_BITS_OFFSET(bits_offset));
7922 FI_SET_FLAG(PNODE_FINFO(ti), FI_BITS_SIZE(bits_len));
7925 char *
7926 proto_item_get_display_repr(wmem_allocator_t *scope, proto_item *pi)
7928 field_info *fi;
7930 if (!pi)
7931 return wmem_strdup(scope, "");
7932 fi = PITEM_FINFO(pi);
7933 if (!fi)
7934 return wmem_strdup(scope, "");
7935 DISSECTOR_ASSERT(fi->hfinfo != NULL);
7936 return fvalue_to_string_repr(scope, fi->value, FTREPR_DISPLAY, fi->hfinfo->display);
7939 proto_tree *
7940 proto_tree_create_root(packet_info *pinfo)
7942 proto_node *pnode;
7944 /* Initialize the proto_node */
7945 pnode = g_slice_new(proto_tree);
7946 PROTO_NODE_INIT(pnode);
7947 pnode->parent = NULL;
7948 PNODE_FINFO(pnode) = NULL;
7949 pnode->tree_data = g_slice_new(tree_data_t);
7951 /* Make sure we can access pinfo everywhere */
7952 pnode->tree_data->pinfo = pinfo;
7954 /* Don't initialize the tree_data_t. Wait until we know we need it */
7955 pnode->tree_data->interesting_hfids = NULL;
7957 /* Set the default to false so it's easier to
7958 * find errors; if we expect to see the protocol tree
7959 * but for some reason the default 'visible' is not
7960 * changed, then we'll find out very quickly. */
7961 pnode->tree_data->visible = false;
7963 /* Make sure that we fake protocols (if possible) */
7964 pnode->tree_data->fake_protocols = true;
7966 /* Keep track of the number of children */
7967 pnode->tree_data->count = 0;
7969 /* Initialize our loop checks */
7970 pnode->tree_data->max_start = 0;
7971 pnode->tree_data->start_idle_count = 0;
7973 return (proto_tree *)pnode;
7977 /* "prime" a proto_tree with a single hfid that a dfilter
7978 * is interested in. */
7979 void
7980 proto_tree_prime_with_hfid(proto_tree *tree _U_, const int hfid)
7982 header_field_info *hfinfo;
7984 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
7985 /* this field is referenced by a filter so increase the refcount.
7986 also increase the refcount for the parent, i.e the protocol.
7987 Don't increase the refcount if we're already printing the
7988 type, as that is a superset of direct reference.
7990 if (hfinfo->ref_type != HF_REF_TYPE_PRINT) {
7991 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
7993 /* only increase the refcount if there is a parent.
7994 if this is a protocol and not a field then parent will be -1
7995 and there is no parent to add any refcounting for.
7997 if (hfinfo->parent != -1) {
7998 header_field_info *parent_hfinfo;
7999 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
8001 /* Mark parent as indirectly referenced unless it is already directly
8002 * referenced, i.e. the user has specified the parent in a filter.
8004 if (parent_hfinfo->ref_type == HF_REF_TYPE_NONE)
8005 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
8009 /* "prime" a proto_tree with a single hfid that a dfilter
8010 * is interested in. */
8011 void
8012 proto_tree_prime_with_hfid_print(proto_tree *tree _U_, const int hfid)
8014 header_field_info *hfinfo;
8016 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
8017 /* this field is referenced by an (output) filter so increase the refcount.
8018 also increase the refcount for the parent, i.e the protocol.
8020 hfinfo->ref_type = HF_REF_TYPE_PRINT;
8021 /* only increase the refcount if there is a parent.
8022 if this is a protocol and not a field then parent will be -1
8023 and there is no parent to add any refcounting for.
8025 if (hfinfo->parent != -1) {
8026 header_field_info *parent_hfinfo;
8027 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
8029 /* Mark parent as indirectly referenced unless it is already directly
8030 * referenced, i.e. the user has specified the parent in a filter.
8032 if (parent_hfinfo->ref_type == HF_REF_TYPE_NONE)
8033 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
8037 proto_tree *
8038 proto_item_add_subtree(proto_item *pi, const int idx) {
8039 field_info *fi;
8041 if (!pi)
8042 return NULL;
8044 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
8046 fi = PITEM_FINFO(pi);
8047 if (!fi)
8048 return (proto_tree *)pi;
8050 fi->tree_type = idx;
8052 return (proto_tree *)pi;
8055 proto_tree *
8056 proto_item_get_subtree(proto_item *pi) {
8057 field_info *fi;
8059 if (!pi)
8060 return NULL;
8061 fi = PITEM_FINFO(pi);
8062 if ( (fi) && (fi->tree_type == -1) )
8063 return NULL;
8064 return (proto_tree *)pi;
8067 proto_item *
8068 proto_item_get_parent(const proto_item *ti) {
8069 if (!ti)
8070 return NULL;
8071 return ti->parent;
8074 proto_item *
8075 proto_item_get_parent_nth(proto_item *ti, int gen) {
8076 if (!ti)
8077 return NULL;
8078 while (gen--) {
8079 ti = ti->parent;
8080 if (!ti)
8081 return NULL;
8083 return ti;
8087 proto_item *
8088 proto_tree_get_parent(proto_tree *tree) {
8089 if (!tree)
8090 return NULL;
8091 return (proto_item *)tree;
8094 proto_tree *
8095 proto_tree_get_parent_tree(proto_tree *tree) {
8096 if (!tree)
8097 return NULL;
8099 /* we're the root tree, there's no parent
8100 return ourselves so the caller has at least a tree to attach to */
8101 if (!tree->parent)
8102 return tree;
8104 return (proto_tree *)tree->parent;
8107 proto_tree *
8108 proto_tree_get_root(proto_tree *tree) {
8109 if (!tree)
8110 return NULL;
8111 while (tree->parent) {
8112 tree = tree->parent;
8114 return tree;
8117 void
8118 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
8119 proto_item *item_to_move)
8121 /* This function doesn't generate any values. It only reorganizes the prococol tree
8122 * so we can bail out immediately if it isn't visible. */
8123 if (!tree || !PTREE_DATA(tree)->visible)
8124 return;
8126 DISSECTOR_ASSERT(item_to_move->parent == tree);
8127 DISSECTOR_ASSERT(fixed_item->parent == tree);
8129 /*** cut item_to_move out ***/
8131 /* is item_to_move the first? */
8132 if (tree->first_child == item_to_move) {
8133 /* simply change first child to next */
8134 tree->first_child = item_to_move->next;
8136 DISSECTOR_ASSERT(tree->last_child != item_to_move);
8137 } else {
8138 proto_item *curr_item;
8139 /* find previous and change it's next */
8140 for (curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
8141 if (curr_item->next == item_to_move) {
8142 break;
8146 DISSECTOR_ASSERT(curr_item);
8148 curr_item->next = item_to_move->next;
8150 /* fix last_child if required */
8151 if (tree->last_child == item_to_move) {
8152 tree->last_child = curr_item;
8156 /*** insert to_move after fixed ***/
8157 item_to_move->next = fixed_item->next;
8158 fixed_item->next = item_to_move;
8159 if (tree->last_child == fixed_item) {
8160 tree->last_child = item_to_move;
8164 void
8165 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, int start,
8166 const int length)
8168 field_info *fi;
8170 if (tree == NULL)
8171 return;
8173 fi = PTREE_FINFO(tree);
8174 if (fi == NULL)
8175 return;
8177 start += tvb_raw_offset(tvb);
8178 DISSECTOR_ASSERT(start >= 0);
8179 DISSECTOR_ASSERT(length >= 0);
8181 fi->appendix_start = start;
8182 fi->appendix_length = length;
8185 static void
8186 check_protocol_filter_name_or_fail(const char *filter_name)
8188 /* Require at least two characters. */
8189 if (filter_name[0] == '\0' || filter_name[1] == '\0') {
8190 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" cannot have length less than two.", filter_name);
8193 if (proto_check_field_name(filter_name) != '\0') {
8194 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" has one or more invalid characters."
8195 " Allowed are letters, digits, '-', '_' and non-repeating '.'."
8196 " This might be caused by an inappropriate plugin or a development error.", filter_name);
8199 /* Check that it doesn't match some very common numeric forms. */
8200 if (filter_name[0] == '0' &&
8201 (filter_name[1] == 'x' || filter_name[1] == 'X' ||
8202 filter_name[1] == 'b' || filter_name[1] == 'B')) {
8203 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" cannot start with \"%c%c\".",
8204 filter_name, filter_name[0], filter_name[1]);
8207 /* Names starting with a digit must not contain a minus sign (currently not checked at runtime). */
8209 /* Check that it contains at least one letter. */
8210 bool have_letter = false;
8211 for (const char *s = filter_name; *s != '\0'; s++) {
8212 if (g_ascii_isalpha(*s)) {
8213 have_letter = true;
8214 break;
8217 if (!have_letter) {
8218 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" must contain at least one letter a-z.",
8219 filter_name);
8222 /* Check for reserved keywords. */
8223 if (g_hash_table_contains(proto_reserved_filter_names, filter_name)) {
8224 REPORT_DISSECTOR_BUG("Protocol filter name \"%s\" is invalid because it is a reserved keyword."
8225 " This might be caused by an inappropriate plugin or a development error.", filter_name);
8230 proto_register_protocol(const char *name, const char *short_name,
8231 const char *filter_name)
8233 protocol_t *protocol;
8234 header_field_info *hfinfo;
8237 * Make sure there's not already a protocol with any of those
8238 * names. Crash if there is, as that's an error in the code
8239 * or an inappropriate plugin.
8240 * This situation has to be fixed to not register more than one
8241 * protocol with the same name.
8244 if (g_hash_table_lookup(proto_names, name)) {
8245 /* ws_error will terminate the program */
8246 REPORT_DISSECTOR_BUG("Duplicate protocol name \"%s\"!"
8247 " This might be caused by an inappropriate plugin or a development error.", name);
8250 if (g_hash_table_lookup(proto_short_names, short_name)) {
8251 REPORT_DISSECTOR_BUG("Duplicate protocol short_name \"%s\"!"
8252 " This might be caused by an inappropriate plugin or a development error.", short_name);
8255 check_protocol_filter_name_or_fail(filter_name);
8257 if (g_hash_table_lookup(proto_filter_names, filter_name)) {
8258 REPORT_DISSECTOR_BUG("Duplicate protocol filter_name \"%s\"!"
8259 " This might be caused by an inappropriate plugin or a development error.", filter_name);
8263 * Add this protocol to the list of known protocols;
8264 * the list is sorted by protocol short name.
8266 protocol = g_new(protocol_t, 1);
8267 protocol->name = name;
8268 protocol->short_name = short_name;
8269 protocol->filter_name = filter_name;
8270 protocol->fields = NULL; /* Delegate until actually needed */
8271 protocol->is_enabled = true; /* protocol is enabled by default */
8272 protocol->enabled_by_default = true; /* see previous comment */
8273 protocol->can_toggle = true;
8274 protocol->parent_proto_id = -1;
8275 protocol->heur_list = NULL;
8277 /* List will be sorted later by name, when all protocols completed registering */
8278 protocols = g_list_prepend(protocols, protocol);
8279 g_hash_table_insert(proto_names, (void *)name, protocol);
8280 g_hash_table_insert(proto_filter_names, (void *)filter_name, protocol);
8281 g_hash_table_insert(proto_short_names, (void *)short_name, protocol);
8283 /* Here we allocate a new header_field_info struct */
8284 hfinfo = g_slice_new(header_field_info);
8285 hfinfo->name = name;
8286 hfinfo->abbrev = filter_name;
8287 hfinfo->type = FT_PROTOCOL;
8288 hfinfo->display = BASE_NONE;
8289 hfinfo->strings = protocol;
8290 hfinfo->bitmask = 0;
8291 hfinfo->ref_type = HF_REF_TYPE_NONE;
8292 hfinfo->blurb = NULL;
8293 hfinfo->parent = -1; /* This field differentiates protos and fields */
8295 protocol->proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
8296 return protocol->proto_id;
8300 proto_register_protocol_in_name_only(const char *name, const char *short_name, const char *filter_name, int parent_proto, enum ftenum field_type)
8302 protocol_t *protocol;
8303 header_field_info *hfinfo;
8306 * Helper protocols don't need the strict rules as a "regular" protocol
8307 * Just register it in a list and make a hf_ field from it
8309 if ((field_type != FT_PROTOCOL) && (field_type != FT_BYTES)) {
8310 REPORT_DISSECTOR_BUG("Pino \"%s\" must be of type FT_PROTOCOL or FT_BYTES.", name);
8313 if (parent_proto <= 0) {
8314 REPORT_DISSECTOR_BUG("Must have a valid parent protocol for helper protocol \"%s\"!"
8315 " This might be caused by an inappropriate plugin or a development error.", name);
8318 check_protocol_filter_name_or_fail(filter_name);
8320 /* Add this protocol to the list of helper protocols (just so it can be properly freed) */
8321 protocol = g_new(protocol_t, 1);
8322 protocol->name = name;
8323 protocol->short_name = short_name;
8324 protocol->filter_name = filter_name;
8325 protocol->fields = NULL; /* Delegate until actually needed */
8327 /* Enabling and toggling is really determined by parent protocol,
8328 but provide default values here */
8329 protocol->is_enabled = true;
8330 protocol->enabled_by_default = true;
8331 protocol->can_toggle = true;
8333 protocol->parent_proto_id = parent_proto;
8334 protocol->heur_list = NULL;
8336 /* List will be sorted later by name, when all protocols completed registering */
8337 protocols = g_list_prepend(protocols, protocol);
8339 /* Here we allocate a new header_field_info struct */
8340 hfinfo = g_slice_new(header_field_info);
8341 hfinfo->name = name;
8342 hfinfo->abbrev = filter_name;
8343 hfinfo->type = field_type;
8344 hfinfo->display = BASE_NONE;
8345 if (field_type == FT_BYTES) {
8346 hfinfo->display |= (BASE_NO_DISPLAY_VALUE|BASE_PROTOCOL_INFO);
8348 hfinfo->strings = protocol;
8349 hfinfo->bitmask = 0;
8350 hfinfo->ref_type = HF_REF_TYPE_NONE;
8351 hfinfo->blurb = NULL;
8352 hfinfo->parent = -1; /* This field differentiates protos and fields */
8354 protocol->proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
8355 return protocol->proto_id;
8358 bool
8359 proto_deregister_protocol(const char *short_name)
8361 protocol_t *protocol;
8362 header_field_info *hfinfo;
8363 int proto_id;
8364 unsigned i;
8366 proto_id = proto_get_id_by_short_name(short_name);
8367 protocol = find_protocol_by_id(proto_id);
8368 if (protocol == NULL)
8369 return false;
8371 g_hash_table_remove(proto_names, protocol->name);
8372 g_hash_table_remove(proto_short_names, (void *)short_name);
8373 g_hash_table_remove(proto_filter_names, (void *)protocol->filter_name);
8375 if (protocol->fields) {
8376 for (i = 0; i < protocol->fields->len; i++) {
8377 hfinfo = (header_field_info *)g_ptr_array_index(protocol->fields, i);
8378 hfinfo_remove_from_gpa_name_map(hfinfo);
8379 expert_deregister_expertinfo(hfinfo->abbrev);
8380 g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[hfinfo->id]);
8382 g_ptr_array_free(protocol->fields, true);
8383 protocol->fields = NULL;
8386 g_list_free(protocol->heur_list);
8388 /* Remove this protocol from the list of known protocols */
8389 protocols = g_list_remove(protocols, protocol);
8391 g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[proto_id]);
8392 g_hash_table_steal(gpa_name_map, protocol->filter_name);
8394 g_free(last_field_name);
8395 last_field_name = NULL;
8397 return true;
8400 void
8401 proto_register_alias(const int proto_id, const char *alias_name)
8403 protocol_t *protocol;
8405 protocol = find_protocol_by_id(proto_id);
8406 if (alias_name && protocol) {
8407 g_hash_table_insert(gpa_protocol_aliases, (void *) alias_name, (void *)protocol->filter_name);
8412 * Routines to use to iterate over the protocols.
8413 * The argument passed to the iterator routines is an opaque cookie to
8414 * their callers; it's the GList pointer for the current element in
8415 * the list.
8416 * The ID of the protocol is returned, or -1 if there is no protocol.
8419 proto_get_first_protocol(void **cookie)
8421 protocol_t *protocol;
8423 if (protocols == NULL)
8424 return -1;
8425 *cookie = protocols;
8426 protocol = (protocol_t *)protocols->data;
8427 return protocol->proto_id;
8431 proto_get_data_protocol(void *cookie)
8433 GList *list_item = (GList *)cookie;
8435 protocol_t *protocol = (protocol_t *)list_item->data;
8436 return protocol->proto_id;
8440 proto_get_next_protocol(void **cookie)
8442 GList *list_item = (GList *)*cookie;
8443 protocol_t *protocol;
8445 list_item = g_list_next(list_item);
8446 if (list_item == NULL)
8447 return -1;
8448 *cookie = list_item;
8449 protocol = (protocol_t *)list_item->data;
8450 return protocol->proto_id;
8453 header_field_info *
8454 proto_get_first_protocol_field(const int proto_id, void **cookie)
8456 protocol_t *protocol = find_protocol_by_id(proto_id);
8458 if ((protocol == NULL) || (protocol->fields == NULL) || (protocol->fields->len == 0))
8459 return NULL;
8461 *cookie = GUINT_TO_POINTER(0);
8462 return (header_field_info *)g_ptr_array_index(protocol->fields, 0);
8465 header_field_info *
8466 proto_get_next_protocol_field(const int proto_id, void **cookie)
8468 protocol_t *protocol = find_protocol_by_id(proto_id);
8469 unsigned i = GPOINTER_TO_UINT(*cookie);
8471 i++;
8473 if ((protocol->fields == NULL) || (i >= protocol->fields->len))
8474 return NULL;
8476 *cookie = GUINT_TO_POINTER(i);
8477 return (header_field_info *)g_ptr_array_index(protocol->fields, i);
8480 protocol_t *
8481 find_protocol_by_id(const int proto_id)
8483 header_field_info *hfinfo;
8485 if (proto_id <= 0)
8486 return NULL;
8488 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
8489 if (hfinfo->type != FT_PROTOCOL) {
8490 DISSECTOR_ASSERT(hfinfo->display & BASE_PROTOCOL_INFO);
8492 return (protocol_t *)hfinfo->strings;
8496 proto_get_id(const protocol_t *protocol)
8498 return protocol->proto_id;
8501 bool
8502 proto_name_already_registered(const char *name)
8504 DISSECTOR_ASSERT_HINT(name, "No name present");
8506 if (g_hash_table_lookup(proto_names, name) != NULL)
8507 return true;
8508 return false;
8512 proto_get_id_by_filter_name(const char *filter_name)
8514 const protocol_t *protocol = NULL;
8516 DISSECTOR_ASSERT_HINT(filter_name, "No filter name present");
8518 protocol = (const protocol_t *)g_hash_table_lookup(proto_filter_names, filter_name);
8520 if (protocol == NULL)
8521 return -1;
8522 return protocol->proto_id;
8526 proto_get_id_by_short_name(const char *short_name)
8528 const protocol_t *protocol = NULL;
8530 DISSECTOR_ASSERT_HINT(short_name, "No short name present");
8532 protocol = (const protocol_t *)g_hash_table_lookup(proto_short_names, short_name);
8534 if (protocol == NULL)
8535 return -1;
8536 return protocol->proto_id;
8539 const char *
8540 proto_get_protocol_name(const int proto_id)
8542 protocol_t *protocol;
8544 protocol = find_protocol_by_id(proto_id);
8546 if (protocol == NULL)
8547 return NULL;
8548 return protocol->name;
8551 const char *
8552 proto_get_protocol_short_name(const protocol_t *protocol)
8554 if (protocol == NULL)
8555 return "(none)";
8556 return protocol->short_name;
8559 const char *
8560 proto_get_protocol_long_name(const protocol_t *protocol)
8562 if (protocol == NULL)
8563 return "(none)";
8564 return protocol->name;
8567 const char *
8568 proto_get_protocol_filter_name(const int proto_id)
8570 protocol_t *protocol;
8572 protocol = find_protocol_by_id(proto_id);
8573 if (protocol == NULL)
8574 return "(none)";
8575 return protocol->filter_name;
8578 void proto_add_heuristic_dissector(protocol_t *protocol, const char *short_name)
8580 heur_dtbl_entry_t* heuristic_dissector;
8582 if (protocol == NULL)
8583 return;
8585 heuristic_dissector = find_heur_dissector_by_unique_short_name(short_name);
8586 if (heuristic_dissector != NULL)
8588 protocol->heur_list = g_list_prepend (protocol->heur_list, heuristic_dissector);
8592 void proto_heuristic_dissector_foreach(const protocol_t *protocol, GFunc func, void *user_data)
8594 if (protocol == NULL)
8595 return;
8597 g_list_foreach(protocol->heur_list, func, user_data);
8600 void
8601 proto_get_frame_protocols(const wmem_list_t *layers, bool *is_ip,
8602 bool *is_tcp, bool *is_udp,
8603 bool *is_sctp, bool *is_tls,
8604 bool *is_rtp,
8605 bool *is_lte_rlc)
8607 wmem_list_frame_t *protos = wmem_list_head(layers);
8608 int proto_id;
8609 const char *proto_name;
8611 /* Walk the list of a available protocols in the packet and
8612 attempt to find "major" ones. */
8613 /* It might make more sense to assemble and return a bitfield. */
8614 while (protos != NULL)
8616 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
8617 proto_name = proto_get_protocol_filter_name(proto_id);
8619 if (is_ip && ((!strcmp(proto_name, "ip")) ||
8620 (!strcmp(proto_name, "ipv6")))) {
8621 *is_ip = true;
8622 } else if (is_tcp && !strcmp(proto_name, "tcp")) {
8623 *is_tcp = true;
8624 } else if (is_udp && !strcmp(proto_name, "udp")) {
8625 *is_udp = true;
8626 } else if (is_sctp && !strcmp(proto_name, "sctp")) {
8627 *is_sctp = true;
8628 } else if (is_tls && !strcmp(proto_name, "tls")) {
8629 *is_tls = true;
8630 } else if (is_rtp && !strcmp(proto_name, "rtp")) {
8631 *is_rtp = true;
8632 } else if (is_lte_rlc && (!strcmp(proto_name, "rlc-lte") || !strcmp(proto_name, "rlc-nr"))) {
8633 *is_lte_rlc = true;
8636 protos = wmem_list_frame_next(protos);
8640 bool
8641 proto_is_frame_protocol(const wmem_list_t *layers, const char* proto_name)
8643 wmem_list_frame_t *protos = wmem_list_head(layers);
8644 int proto_id;
8645 const char *name;
8647 /* Walk the list of a available protocols in the packet and
8648 attempt to find the specified protocol. */
8649 while (protos != NULL)
8651 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
8652 name = proto_get_protocol_filter_name(proto_id);
8654 if (!strcmp(name, proto_name))
8656 return true;
8659 protos = wmem_list_frame_next(protos);
8662 return false;
8665 char *
8666 proto_list_layers(const packet_info *pinfo)
8668 wmem_strbuf_t *buf;
8669 wmem_list_frame_t *layers = wmem_list_head(pinfo->layers);
8671 buf = wmem_strbuf_new_sized(pinfo->pool, 128);
8673 /* Walk the list of layers in the packet and
8674 return a string of all entries. */
8675 while (layers != NULL)
8677 wmem_strbuf_append(buf, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(layers))));
8679 layers = wmem_list_frame_next(layers);
8680 if (layers != NULL) {
8681 wmem_strbuf_append_c(buf, ':');
8685 return wmem_strbuf_finalize(buf);
8688 bool
8689 proto_is_pino(const protocol_t *protocol)
8691 return (protocol->parent_proto_id != -1);
8694 bool
8695 // NOLINTNEXTLINE(misc-no-recursion)
8696 proto_is_protocol_enabled(const protocol_t *protocol)
8698 if (protocol == NULL)
8699 return false;
8701 //parent protocol determines enable/disable for helper dissectors
8702 if (proto_is_pino(protocol))
8703 return proto_is_protocol_enabled(find_protocol_by_id(protocol->parent_proto_id));
8705 return protocol->is_enabled;
8708 bool
8709 // NOLINTNEXTLINE(misc-no-recursion)
8710 proto_is_protocol_enabled_by_default(const protocol_t *protocol)
8712 //parent protocol determines enable/disable for helper dissectors
8713 if (proto_is_pino(protocol))
8714 return proto_is_protocol_enabled_by_default(find_protocol_by_id(protocol->parent_proto_id));
8716 return protocol->enabled_by_default;
8719 bool
8720 // NOLINTNEXTLINE(misc-no-recursion)
8721 proto_can_toggle_protocol(const int proto_id)
8723 protocol_t *protocol;
8725 protocol = find_protocol_by_id(proto_id);
8726 //parent protocol determines toggling for helper dissectors
8727 if (proto_is_pino(protocol))
8728 return proto_can_toggle_protocol(protocol->parent_proto_id);
8730 return protocol->can_toggle;
8733 void
8734 proto_disable_by_default(const int proto_id)
8736 protocol_t *protocol;
8738 protocol = find_protocol_by_id(proto_id);
8739 DISSECTOR_ASSERT(protocol->can_toggle);
8740 DISSECTOR_ASSERT(proto_is_pino(protocol) == false);
8741 protocol->is_enabled = false;
8742 protocol->enabled_by_default = false;
8745 void
8746 proto_set_decoding(const int proto_id, const bool enabled)
8748 protocol_t *protocol;
8750 protocol = find_protocol_by_id(proto_id);
8751 DISSECTOR_ASSERT(protocol->can_toggle);
8752 DISSECTOR_ASSERT(proto_is_pino(protocol) == false);
8753 protocol->is_enabled = enabled;
8756 void
8757 proto_disable_all(void)
8759 /* This doesn't explicitly disable heuristic protocols,
8760 * but the heuristic doesn't get called if the parent
8761 * protocol isn't enabled.
8763 protocol_t *protocol;
8764 GList *list_item = protocols;
8766 if (protocols == NULL)
8767 return;
8769 while (list_item) {
8770 protocol = (protocol_t *)list_item->data;
8771 if (protocol->can_toggle) {
8772 protocol->is_enabled = false;
8774 list_item = g_list_next(list_item);
8778 static void
8779 heur_reenable_cb(void *data, void *user_data _U_)
8781 heur_dtbl_entry_t *heur = (heur_dtbl_entry_t*)data;
8783 heur->enabled = heur->enabled_by_default;
8786 void
8787 proto_reenable_all(void)
8789 protocol_t *protocol;
8790 GList *list_item = protocols;
8792 if (protocols == NULL)
8793 return;
8795 while (list_item) {
8796 protocol = (protocol_t *)list_item->data;
8797 if (protocol->can_toggle)
8798 protocol->is_enabled = protocol->enabled_by_default;
8799 proto_heuristic_dissector_foreach(protocol, heur_reenable_cb, NULL);
8800 list_item = g_list_next(list_item);
8804 void
8805 proto_set_cant_toggle(const int proto_id)
8807 protocol_t *protocol;
8809 protocol = find_protocol_by_id(proto_id);
8810 protocol->can_toggle = false;
8813 static int
8814 proto_register_field_common(protocol_t *proto, header_field_info *hfi, const int parent)
8816 if (proto != NULL) {
8817 g_ptr_array_add(proto->fields, hfi);
8820 return proto_register_field_init(hfi, parent);
8823 /* for use with static arrays only, since we don't allocate our own copies
8824 of the header_field_info struct contained within the hf_register_info struct */
8825 void
8826 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
8828 hf_register_info *ptr = hf;
8829 protocol_t *proto;
8830 int i;
8832 proto = find_protocol_by_id(parent);
8834 if (proto->fields == NULL) {
8835 proto->fields = g_ptr_array_sized_new(num_records);
8838 for (i = 0; i < num_records; i++, ptr++) {
8840 * Make sure we haven't registered this yet.
8841 * Most fields have variables associated with them
8842 * that are initialized to -1; some have array elements,
8843 * or possibly uninitialized variables, so we also allow
8844 * 0 (which is unlikely to be the field ID we get back
8845 * from "proto_register_field_init()").
8847 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
8848 REPORT_DISSECTOR_BUG(
8849 "Duplicate field detected in call to proto_register_field_array: %s is already registered",
8850 ptr->hfinfo.abbrev);
8851 return;
8854 *ptr->p_id = proto_register_field_common(proto, &ptr->hfinfo, parent);
8858 /* deregister already registered fields */
8859 void
8860 proto_deregister_field (const int parent, int hf_id)
8862 header_field_info *hfi;
8863 protocol_t *proto;
8864 unsigned i;
8866 g_free(last_field_name);
8867 last_field_name = NULL;
8869 if (hf_id == -1 || hf_id == 0)
8870 return;
8872 proto = find_protocol_by_id (parent);
8873 if (!proto || proto->fields == NULL) {
8874 return;
8877 for (i = 0; i < proto->fields->len; i++) {
8878 hfi = (header_field_info *)g_ptr_array_index(proto->fields, i);
8879 if (hfi->id == hf_id) {
8880 /* Found the hf_id in this protocol */
8881 g_hash_table_steal(gpa_name_map, hfi->abbrev);
8882 g_ptr_array_remove_index_fast(proto->fields, i);
8883 g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[hf_id]);
8884 return;
8889 void
8890 proto_add_deregistered_data (void *data)
8892 g_ptr_array_add(deregistered_data, data);
8895 void
8896 proto_add_deregistered_slice (size_t block_size, void *mem_block)
8898 struct g_slice_data *slice_data = g_slice_new(struct g_slice_data);
8900 slice_data->block_size = block_size;
8901 slice_data->mem_block = mem_block;
8903 g_ptr_array_add(deregistered_slice, slice_data);
8906 void proto_free_field_strings (ftenum_t field_type, unsigned int field_display, const void *field_strings)
8908 if (field_strings == NULL) {
8909 return;
8912 switch (field_type) {
8913 case FT_FRAMENUM:
8914 /* This is just an integer represented as a pointer */
8915 break;
8916 case FT_PROTOCOL: {
8917 protocol_t *protocol = (protocol_t *)field_strings;
8918 g_free((char *)protocol->short_name);
8919 break;
8921 case FT_BOOLEAN: {
8922 true_false_string *tf = (true_false_string *)field_strings;
8923 g_free((char *)tf->true_string);
8924 g_free((char *)tf->false_string);
8925 break;
8927 case FT_UINT40:
8928 case FT_INT40:
8929 case FT_UINT48:
8930 case FT_INT48:
8931 case FT_UINT56:
8932 case FT_INT56:
8933 case FT_UINT64:
8934 case FT_INT64: {
8935 if (field_display & BASE_UNIT_STRING) {
8936 unit_name_string *unit = (unit_name_string *)field_strings;
8937 g_free((char *)unit->singular);
8938 g_free((char *)unit->plural);
8939 } else if (field_display & BASE_RANGE_STRING) {
8940 range_string *rs = (range_string *)field_strings;
8941 while (rs->strptr) {
8942 g_free((char *)rs->strptr);
8943 rs++;
8945 } else if (field_display & BASE_EXT_STRING) {
8946 val64_string_ext *vse = (val64_string_ext *)field_strings;
8947 val64_string *vs = (val64_string *)vse->_vs_p;
8948 while (vs->strptr) {
8949 g_free((char *)vs->strptr);
8950 vs++;
8952 val64_string_ext_free(vse);
8953 field_strings = NULL;
8954 } else if (field_display == BASE_CUSTOM) {
8955 /* this will be a pointer to a function, don't free that */
8956 field_strings = NULL;
8957 } else {
8958 val64_string *vs64 = (val64_string *)field_strings;
8959 while (vs64->strptr) {
8960 g_free((char *)vs64->strptr);
8961 vs64++;
8964 break;
8966 case FT_CHAR:
8967 case FT_UINT8:
8968 case FT_INT8:
8969 case FT_UINT16:
8970 case FT_INT16:
8971 case FT_UINT24:
8972 case FT_INT24:
8973 case FT_UINT32:
8974 case FT_INT32:
8975 case FT_FLOAT:
8976 case FT_DOUBLE: {
8977 if (field_display & BASE_UNIT_STRING) {
8978 unit_name_string *unit = (unit_name_string *)field_strings;
8979 g_free((char *)unit->singular);
8980 g_free((char *)unit->plural);
8981 } else if (field_display & BASE_RANGE_STRING) {
8982 range_string *rs = (range_string *)field_strings;
8983 while (rs->strptr) {
8984 g_free((char *)rs->strptr);
8985 rs++;
8987 } else if (field_display & BASE_EXT_STRING) {
8988 value_string_ext *vse = (value_string_ext *)field_strings;
8989 value_string *vs = (value_string *)vse->_vs_p;
8990 while (vs->strptr) {
8991 g_free((char *)vs->strptr);
8992 vs++;
8994 value_string_ext_free(vse);
8995 field_strings = NULL;
8996 } else if (field_display == BASE_CUSTOM) {
8997 /* this will be a pointer to a function, don't free that */
8998 field_strings = NULL;
8999 } else {
9000 value_string *vs = (value_string *)field_strings;
9001 while (vs->strptr) {
9002 g_free((char *)vs->strptr);
9003 vs++;
9006 break;
9007 default:
9008 break;
9012 if (field_type != FT_FRAMENUM) {
9013 g_free((void *)field_strings);
9017 static void
9018 free_deregistered_field (void *data, void *user_data _U_)
9020 header_field_info *hfi = (header_field_info *) data;
9021 int hf_id = hfi->id;
9023 g_free((char *)hfi->name);
9024 g_free((char *)hfi->abbrev);
9025 g_free((char *)hfi->blurb);
9027 proto_free_field_strings(hfi->type, hfi->display, hfi->strings);
9029 if (hfi->parent == -1)
9030 g_slice_free(header_field_info, hfi);
9032 gpa_hfinfo.hfi[hf_id] = NULL; /* Invalidate this hf_id / proto_id */
9035 static void
9036 free_deregistered_data (void *data, void *user_data _U_)
9038 g_free (data);
9041 static void
9042 free_deregistered_slice (void *data, void *user_data _U_)
9044 struct g_slice_data *slice_data = (struct g_slice_data *)data;
9046 g_slice_free1(slice_data->block_size, slice_data->mem_block);
9047 g_slice_free(struct g_slice_data, slice_data);
9050 /* free deregistered fields and data */
9051 void
9052 proto_free_deregistered_fields (void)
9054 expert_free_deregistered_expertinfos();
9056 g_ptr_array_foreach(deregistered_fields, free_deregistered_field, NULL);
9057 g_ptr_array_free(deregistered_fields, true);
9058 deregistered_fields = g_ptr_array_new();
9060 g_ptr_array_foreach(deregistered_data, free_deregistered_data, NULL);
9061 g_ptr_array_free(deregistered_data, true);
9062 deregistered_data = g_ptr_array_new();
9064 g_ptr_array_foreach(deregistered_slice, free_deregistered_slice, NULL);
9065 g_ptr_array_free(deregistered_slice, true);
9066 deregistered_slice = g_ptr_array_new();
9069 static const value_string hf_display[] = {
9070 { BASE_NONE, "BASE_NONE" },
9071 { BASE_DEC, "BASE_DEC" },
9072 { BASE_HEX, "BASE_HEX" },
9073 { BASE_OCT, "BASE_OCT" },
9074 { BASE_DEC_HEX, "BASE_DEC_HEX" },
9075 { BASE_HEX_DEC, "BASE_HEX_DEC" },
9076 { BASE_CUSTOM, "BASE_CUSTOM" },
9077 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
9078 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
9079 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
9080 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
9081 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
9082 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
9083 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
9084 { BASE_NONE|BASE_VAL64_STRING, "BASE_NONE|BASE_VAL64_STRING" },
9085 { BASE_DEC|BASE_VAL64_STRING, "BASE_DEC|BASE_VAL64_STRING" },
9086 { BASE_HEX|BASE_VAL64_STRING, "BASE_HEX|BASE_VAL64_STRING" },
9087 { BASE_OCT|BASE_VAL64_STRING, "BASE_OCT|BASE_VAL64_STRING" },
9088 { BASE_DEC_HEX|BASE_VAL64_STRING, "BASE_DEC_HEX|BASE_VAL64_STRING" },
9089 { BASE_HEX_DEC|BASE_VAL64_STRING, "BASE_HEX_DEC|BASE_VAL64_STRING" },
9090 { BASE_CUSTOM|BASE_VAL64_STRING, "BASE_CUSTOM|BASE_VAL64_STRING" },
9091 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
9092 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_UTC" },
9093 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_DOY_UTC" },
9094 { BASE_PT_UDP, "BASE_PT_UDP" },
9095 { BASE_PT_TCP, "BASE_PT_TCP" },
9096 { BASE_PT_DCCP, "BASE_PT_DCCP" },
9097 { BASE_PT_SCTP, "BASE_PT_SCTP" },
9098 { BASE_OUI, "BASE_OUI" },
9099 { 0, NULL } };
9101 const char* proto_field_display_to_string(int field_display)
9103 return val_to_str_const(field_display, hf_display, "Unknown");
9106 static inline port_type
9107 display_to_port_type(field_display_e e)
9109 switch (e) {
9110 case BASE_PT_UDP:
9111 return PT_UDP;
9112 case BASE_PT_TCP:
9113 return PT_TCP;
9114 case BASE_PT_DCCP:
9115 return PT_DCCP;
9116 case BASE_PT_SCTP:
9117 return PT_SCTP;
9118 default:
9119 break;
9121 return PT_NONE;
9124 /* temporary function containing assert part for easier profiling */
9125 static void
9126 tmp_fld_check_assert(header_field_info *hfinfo)
9128 char* tmp_str;
9130 /* The field must have a name (with length > 0) */
9131 if (!hfinfo->name || !hfinfo->name[0]) {
9132 if (hfinfo->abbrev)
9133 /* Try to identify the field */
9134 REPORT_DISSECTOR_BUG("Field (abbrev='%s') does not have a name",
9135 hfinfo->abbrev);
9136 else
9137 /* Hum, no luck */
9138 REPORT_DISSECTOR_BUG("Field does not have a name (nor an abbreviation)");
9141 /* fields with an empty string for an abbreviation aren't filterable */
9142 if (!hfinfo->abbrev || !hfinfo->abbrev[0])
9143 REPORT_DISSECTOR_BUG("Field '%s' does not have an abbreviation", hfinfo->name);
9145 /* These types of fields are allowed to have value_strings,
9146 * true_false_strings or a protocol_t struct
9148 if (hfinfo->strings != NULL && FIELD_DISPLAY(hfinfo->display) != BASE_CUSTOM) {
9149 switch (hfinfo->type) {
9152 * These types are allowed to support display value_strings,
9153 * value64_strings, the extended versions of the previous
9154 * two, range strings, or unit strings.
9156 case FT_CHAR:
9157 case FT_UINT8:
9158 case FT_UINT16:
9159 case FT_UINT24:
9160 case FT_UINT32:
9161 case FT_UINT40:
9162 case FT_UINT48:
9163 case FT_UINT56:
9164 case FT_UINT64:
9165 case FT_INT8:
9166 case FT_INT16:
9167 case FT_INT24:
9168 case FT_INT32:
9169 case FT_INT40:
9170 case FT_INT48:
9171 case FT_INT56:
9172 case FT_INT64:
9173 case FT_BOOLEAN:
9174 case FT_PROTOCOL:
9175 break;
9178 * This is allowed to have a value of type
9179 * enum ft_framenum_type to indicate what relationship
9180 * the frame in question has to the frame in which
9181 * the field is put.
9183 case FT_FRAMENUM:
9184 break;
9187 * These types are allowed to support only unit strings.
9189 case FT_FLOAT:
9190 case FT_DOUBLE:
9191 if (!(hfinfo->display & BASE_UNIT_STRING)) {
9192 REPORT_DISSECTOR_BUG("Field '%s' (%s) has a non-unit-strings 'strings' value but is of type %s"
9193 " (which is only allowed to have unit strings)",
9194 hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type));
9196 break;
9199 * This type is only allowed to support a string if it's
9200 * a protocol (for pinos).
9202 case FT_BYTES:
9203 if (!(hfinfo->display & BASE_PROTOCOL_INFO)) {
9204 REPORT_DISSECTOR_BUG("Field '%s' (%s) has a non-protocol-info 'strings' value but is of type %s"
9205 " (which is only allowed to have protocol-info strings)",
9206 hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type));
9208 break;
9210 default:
9211 REPORT_DISSECTOR_BUG("Field '%s' (%s) has a 'strings' value but is of type %s"
9212 " (which is not allowed to have strings)",
9213 hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type));
9217 /* TODO: This check may slow down startup, and output quite a few warnings.
9218 It would be good to be able to enable this (and possibly other checks?)
9219 in non-release builds. */
9220 #ifdef ENABLE_CHECK_FILTER
9221 /* Check for duplicate value_string values.
9222 There are lots that have the same value *and* string, so for now only
9223 report those that have same value but different string. */
9224 if ((hfinfo->strings != NULL) &&
9225 !(hfinfo->display & BASE_RANGE_STRING) &&
9226 !(hfinfo->display & BASE_UNIT_STRING) &&
9227 !((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) &&
9229 (hfinfo->type == FT_CHAR) ||
9230 (hfinfo->type == FT_UINT8) ||
9231 (hfinfo->type == FT_UINT16) ||
9232 (hfinfo->type == FT_UINT24) ||
9233 (hfinfo->type == FT_UINT32) ||
9234 (hfinfo->type == FT_INT8) ||
9235 (hfinfo->type == FT_INT16) ||
9236 (hfinfo->type == FT_INT24) ||
9237 (hfinfo->type == FT_INT32) )) {
9239 if (hfinfo->display & BASE_EXT_STRING) {
9240 if (hfinfo->display & BASE_VAL64_STRING) {
9241 const val64_string *start_values = VAL64_STRING_EXT_VS_P((const val64_string_ext*)hfinfo->strings);
9242 CHECK_HF_VALUE(val64_string, PRIu64, start_values);
9243 } else {
9244 const value_string *start_values = VALUE_STRING_EXT_VS_P((const value_string_ext*)hfinfo->strings);
9245 CHECK_HF_VALUE(value_string, "u", start_values);
9247 } else {
9248 const value_string *start_values = (const value_string*)hfinfo->strings;
9249 CHECK_HF_VALUE(value_string, "u", start_values);
9253 if (hfinfo->type == FT_BOOLEAN) {
9254 const true_false_string *tfs = (const true_false_string*)hfinfo->strings;
9255 if (tfs) {
9256 if (strcmp(tfs->false_string, tfs->true_string) == 0) {
9257 ws_warning("Field '%s' (%s) has identical true and false strings (\"%s\", \"%s\")",
9258 hfinfo->name, hfinfo->abbrev,
9259 tfs->false_string, tfs->true_string);
9264 if (hfinfo->display & BASE_RANGE_STRING) {
9265 const range_string *rs = (const range_string*)(hfinfo->strings);
9266 if (rs) {
9267 const range_string *this_it = rs;
9269 do {
9270 if (this_it->value_max < this_it->value_min) {
9271 ws_warning("value_range_string error: %s (%s) entry for \"%s\" - max(%"PRIu64" 0x%"PRIx64") is less than min(%"PRIu64" 0x%"PRIx64")",
9272 hfinfo->name, hfinfo->abbrev,
9273 this_it->strptr,
9274 this_it->value_max, this_it->value_max,
9275 this_it->value_min, this_it->value_min);
9276 ++this_it;
9277 continue;
9280 for (const range_string *prev_it=rs; prev_it < this_it; ++prev_it) {
9281 /* Not OK if this one is completely hidden by an earlier one! */
9282 if ((prev_it->value_min <= this_it->value_min) && (prev_it->value_max >= this_it->value_max)) {
9283 ws_warning("value_range_string error: %s (%s) hidden by earlier entry "
9284 "(prev=\"%s\": %"PRIu64" 0x%"PRIx64" -> %"PRIu64" 0x%"PRIx64") (this=\"%s\": %"PRIu64" 0x%"PRIx64" -> %"PRIu64" 0x%"PRIx64")",
9285 hfinfo->name, hfinfo->abbrev,
9286 prev_it->strptr, prev_it->value_min, prev_it->value_min,
9287 prev_it->value_max, prev_it->value_max,
9288 this_it->strptr, this_it->value_min, this_it->value_min,
9289 this_it->value_max, this_it->value_max);
9292 ++this_it;
9293 } while (this_it->strptr);
9296 #endif
9298 switch (hfinfo->type) {
9300 case FT_CHAR:
9301 /* Require the char type to have BASE_HEX, BASE_OCT,
9302 * BASE_CUSTOM, or BASE_NONE as its base.
9304 * If the display value is BASE_NONE and there is a
9305 * strings conversion then the dissector writer is
9306 * telling us that the field's numerical value is
9307 * meaningless; we'll avoid showing the value to the
9308 * user.
9310 switch (FIELD_DISPLAY(hfinfo->display)) {
9311 case BASE_HEX:
9312 case BASE_OCT:
9313 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
9314 break;
9315 case BASE_NONE:
9316 if (hfinfo->strings == NULL)
9317 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an integral value (%s)"
9318 " but is being displayed as BASE_NONE but"
9319 " without a strings conversion",
9320 hfinfo->name, hfinfo->abbrev,
9321 ftype_name(hfinfo->type));
9322 break;
9323 default:
9324 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
9325 REPORT_DISSECTOR_BUG("Field '%s' (%s) is a character value (%s)"
9326 " but is being displayed as %s",
9327 hfinfo->name, hfinfo->abbrev,
9328 ftype_name(hfinfo->type), tmp_str);
9329 //wmem_free(NULL, tmp_str);
9331 if (hfinfo->display & BASE_UNIT_STRING) {
9332 REPORT_DISSECTOR_BUG("Field '%s' (%s) is a character value (%s) but has a unit string",
9333 hfinfo->name, hfinfo->abbrev,
9334 ftype_name(hfinfo->type));
9336 break;
9337 case FT_INT8:
9338 case FT_INT16:
9339 case FT_INT24:
9340 case FT_INT32:
9341 case FT_INT40:
9342 case FT_INT48:
9343 case FT_INT56:
9344 case FT_INT64:
9345 /* Hexadecimal and octal are, in printf() and everywhere
9346 * else, unsigned so don't allow dissectors to register a
9347 * signed field to be displayed unsigned. (Else how would
9348 * we display negative values?)
9350 switch (FIELD_DISPLAY(hfinfo->display)) {
9351 case BASE_HEX:
9352 case BASE_OCT:
9353 case BASE_DEC_HEX:
9354 case BASE_HEX_DEC:
9355 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
9356 REPORT_DISSECTOR_BUG("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)",
9357 hfinfo->name, hfinfo->abbrev,
9358 ftype_name(hfinfo->type), tmp_str);
9359 //wmem_free(NULL, tmp_str);
9361 /* FALL THROUGH */
9362 case FT_UINT8:
9363 case FT_UINT16:
9364 case FT_UINT24:
9365 case FT_UINT32:
9366 case FT_UINT40:
9367 case FT_UINT48:
9368 case FT_UINT56:
9369 case FT_UINT64:
9370 if (IS_BASE_PORT(hfinfo->display)) {
9371 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
9372 if (hfinfo->type != FT_UINT16) {
9373 REPORT_DISSECTOR_BUG("Field '%s' (%s) has 'display' value %s but it can only be used with FT_UINT16, not %s",
9374 hfinfo->name, hfinfo->abbrev,
9375 tmp_str, ftype_name(hfinfo->type));
9377 if (hfinfo->strings != NULL) {
9378 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s (%s) but has a strings value",
9379 hfinfo->name, hfinfo->abbrev,
9380 ftype_name(hfinfo->type), tmp_str);
9382 if (hfinfo->bitmask != 0) {
9383 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s (%s) but has a bitmask",
9384 hfinfo->name, hfinfo->abbrev,
9385 ftype_name(hfinfo->type), tmp_str);
9387 wmem_free(NULL, tmp_str);
9388 break;
9391 if (hfinfo->display == BASE_OUI) {
9392 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
9393 if (hfinfo->type != FT_UINT24) {
9394 REPORT_DISSECTOR_BUG("Field '%s' (%s) has 'display' value %s but it can only be used with FT_UINT24, not %s",
9395 hfinfo->name, hfinfo->abbrev,
9396 tmp_str, ftype_name(hfinfo->type));
9398 if (hfinfo->strings != NULL) {
9399 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s (%s) but has a strings value",
9400 hfinfo->name, hfinfo->abbrev,
9401 ftype_name(hfinfo->type), tmp_str);
9403 if (hfinfo->bitmask != 0) {
9404 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s (%s) but has a bitmask",
9405 hfinfo->name, hfinfo->abbrev,
9406 ftype_name(hfinfo->type), tmp_str);
9408 wmem_free(NULL, tmp_str);
9409 break;
9412 /* Require integral types (other than frame number,
9413 * which is always displayed in decimal) to have a
9414 * number base.
9416 * If the display value is BASE_NONE and there is a
9417 * strings conversion then the dissector writer is
9418 * telling us that the field's numerical value is
9419 * meaningless; we'll avoid showing the value to the
9420 * user.
9422 switch (FIELD_DISPLAY(hfinfo->display)) {
9423 case BASE_DEC:
9424 case BASE_HEX:
9425 case BASE_OCT:
9426 case BASE_DEC_HEX:
9427 case BASE_HEX_DEC:
9428 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
9429 break;
9430 case BASE_NONE:
9431 if (hfinfo->strings == NULL) {
9432 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an integral value (%s)"
9433 " but is being displayed as BASE_NONE but"
9434 " without a strings conversion",
9435 hfinfo->name, hfinfo->abbrev,
9436 ftype_name(hfinfo->type));
9438 if (hfinfo->display & BASE_SPECIAL_VALS) {
9439 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an integral value (%s)"
9440 " that is being displayed as BASE_NONE but"
9441 " with BASE_SPECIAL_VALS",
9442 hfinfo->name, hfinfo->abbrev,
9443 ftype_name(hfinfo->type));
9445 break;
9447 default:
9448 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
9449 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an integral value (%s)"
9450 " but is being displayed as %s",
9451 hfinfo->name, hfinfo->abbrev,
9452 ftype_name(hfinfo->type), tmp_str);
9453 //wmem_free(NULL, tmp_str);
9455 break;
9456 case FT_BYTES:
9457 case FT_UINT_BYTES:
9458 /* Require bytes to have a "display type" that could
9459 * add a character between displayed bytes.
9461 switch (FIELD_DISPLAY(hfinfo->display)) {
9462 case BASE_NONE:
9463 case SEP_DOT:
9464 case SEP_DASH:
9465 case SEP_COLON:
9466 case SEP_SPACE:
9467 break;
9468 default:
9469 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
9470 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an byte array but is being displayed as %s instead of BASE_NONE, SEP_DOT, SEP_DASH, SEP_COLON, or SEP_SPACE",
9471 hfinfo->name, hfinfo->abbrev, tmp_str);
9472 //wmem_free(NULL, tmp_str);
9474 if (hfinfo->bitmask != 0)
9475 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9476 hfinfo->name, hfinfo->abbrev,
9477 ftype_name(hfinfo->type));
9478 //allowed to support string if its a protocol (for pinos)
9479 if ((hfinfo->strings != NULL) && (!(hfinfo->display & BASE_PROTOCOL_INFO)))
9480 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a strings value",
9481 hfinfo->name, hfinfo->abbrev,
9482 ftype_name(hfinfo->type));
9483 break;
9485 case FT_PROTOCOL:
9486 case FT_FRAMENUM:
9487 if (hfinfo->display != BASE_NONE) {
9488 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
9489 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE",
9490 hfinfo->name, hfinfo->abbrev,
9491 ftype_name(hfinfo->type), tmp_str);
9492 //wmem_free(NULL, tmp_str);
9494 if (hfinfo->bitmask != 0)
9495 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9496 hfinfo->name, hfinfo->abbrev,
9497 ftype_name(hfinfo->type));
9498 break;
9500 case FT_BOOLEAN:
9501 break;
9503 case FT_ABSOLUTE_TIME:
9504 if (!FIELD_DISPLAY_IS_ABSOLUTE_TIME(hfinfo->display)) {
9505 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
9506 REPORT_DISSECTOR_BUG("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time",
9507 hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type), tmp_str);
9508 //wmem_free(NULL, tmp_str);
9510 if (hfinfo->bitmask != 0)
9511 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9512 hfinfo->name, hfinfo->abbrev,
9513 ftype_name(hfinfo->type));
9514 break;
9516 case FT_STRING:
9517 case FT_STRINGZ:
9518 case FT_UINT_STRING:
9519 case FT_STRINGZPAD:
9520 case FT_STRINGZTRUNC:
9521 switch (FIELD_DISPLAY(hfinfo->display)) {
9522 case BASE_NONE:
9523 case BASE_STR_WSP:
9524 break;
9526 default:
9527 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
9528 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an string value (%s)"
9529 " but is being displayed as %s",
9530 hfinfo->name, hfinfo->abbrev,
9531 ftype_name(hfinfo->type), tmp_str);
9532 //wmem_free(NULL, tmp_str);
9535 if (hfinfo->bitmask != 0)
9536 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9537 hfinfo->name, hfinfo->abbrev,
9538 ftype_name(hfinfo->type));
9539 if (hfinfo->strings != NULL)
9540 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a strings value",
9541 hfinfo->name, hfinfo->abbrev,
9542 ftype_name(hfinfo->type));
9543 break;
9545 case FT_IPv4:
9546 switch (hfinfo->display) {
9547 case BASE_NONE:
9548 case BASE_NETMASK:
9549 break;
9551 default:
9552 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
9553 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an IPv4 value (%s)"
9554 " but is being displayed as %s",
9555 hfinfo->name, hfinfo->abbrev,
9556 ftype_name(hfinfo->type), tmp_str);
9557 //wmem_free(NULL, tmp_str);
9558 break;
9560 break;
9561 case FT_FLOAT:
9562 case FT_DOUBLE:
9563 switch (FIELD_DISPLAY(hfinfo->display)) {
9564 case BASE_NONE:
9565 case BASE_DEC:
9566 case BASE_HEX:
9567 case BASE_EXP:
9568 case BASE_CUSTOM:
9569 break;
9570 default:
9571 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
9572 REPORT_DISSECTOR_BUG("Field '%s' (%s) is a float value (%s)"
9573 " but is being displayed as %s",
9574 hfinfo->name, hfinfo->abbrev,
9575 ftype_name(hfinfo->type), tmp_str);
9576 //wmem_free(NULL, tmp_str);
9578 if (hfinfo->bitmask != 0)
9579 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9580 hfinfo->name, hfinfo->abbrev,
9581 ftype_name(hfinfo->type));
9582 if (FIELD_DISPLAY(hfinfo->display) != BASE_CUSTOM && (hfinfo->strings != NULL) && !(hfinfo->display & BASE_UNIT_STRING))
9583 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a strings value",
9584 hfinfo->name, hfinfo->abbrev,
9585 ftype_name(hfinfo->type));
9586 break;
9587 default:
9588 if (hfinfo->display != BASE_NONE) {
9589 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
9590 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE",
9591 hfinfo->name, hfinfo->abbrev,
9592 ftype_name(hfinfo->type),
9593 tmp_str);
9594 //wmem_free(NULL, tmp_str);
9596 if (hfinfo->bitmask != 0)
9597 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a bitmask",
9598 hfinfo->name, hfinfo->abbrev,
9599 ftype_name(hfinfo->type));
9600 if (hfinfo->strings != NULL)
9601 REPORT_DISSECTOR_BUG("Field '%s' (%s) is an %s but has a strings value",
9602 hfinfo->name, hfinfo->abbrev,
9603 ftype_name(hfinfo->type));
9604 break;
9608 static void
9609 register_type_length_mismatch(void)
9611 static ei_register_info ei[] = {
9612 { &ei_type_length_mismatch_error, { "_ws.type_length.mismatch", PI_MALFORMED, PI_ERROR, "Trying to fetch X with length Y", EXPFILL }},
9613 { &ei_type_length_mismatch_warn, { "_ws.type_length.mismatch", PI_MALFORMED, PI_WARN, "Trying to fetch X with length Y", EXPFILL }},
9616 expert_module_t* expert_type_length_mismatch;
9618 proto_type_length_mismatch = proto_register_protocol("Type Length Mismatch", "Type length mismatch", "_ws.type_length");
9620 expert_type_length_mismatch = expert_register_protocol(proto_type_length_mismatch);
9621 expert_register_field_array(expert_type_length_mismatch, ei, array_length(ei));
9623 /* "Type Length Mismatch" isn't really a protocol, it's an error indication;
9624 disabling them makes no sense. */
9625 proto_set_cant_toggle(proto_type_length_mismatch);
9628 static void
9629 register_byte_array_string_decodinws_error(void)
9631 static ei_register_info ei[] = {
9632 { &ei_byte_array_string_decoding_failed_error,
9633 { "_ws.byte_array_string.decoding_error.failed", PI_MALFORMED, PI_ERROR,
9634 "Failed to decode byte array from string", EXPFILL
9639 expert_module_t* expert_byte_array_string_decoding_error;
9641 proto_byte_array_string_decoding_error =
9642 proto_register_protocol("Byte Array-String Decoding Error",
9643 "Byte Array-string decoding error",
9644 "_ws.byte_array_string.decoding_error");
9646 expert_byte_array_string_decoding_error =
9647 expert_register_protocol(proto_byte_array_string_decoding_error);
9648 expert_register_field_array(expert_byte_array_string_decoding_error, ei, array_length(ei));
9650 /* "Byte Array-String Decoding Error" isn't really a protocol, it's an error indication;
9651 disabling them makes no sense. */
9652 proto_set_cant_toggle(proto_byte_array_string_decoding_error);
9655 static void
9656 register_date_time_string_decodinws_error(void)
9658 static ei_register_info ei[] = {
9659 { &ei_date_time_string_decoding_failed_error,
9660 { "_ws.date_time_string.decoding_error.failed", PI_MALFORMED, PI_ERROR,
9661 "Failed to decode date and time from string", EXPFILL
9666 expert_module_t* expert_date_time_string_decoding_error;
9668 proto_date_time_string_decoding_error =
9669 proto_register_protocol("Date and Time-String Decoding Error",
9670 "Date and Time-string decoding error",
9671 "_ws.date_time_string.decoding_error");
9673 expert_date_time_string_decoding_error =
9674 expert_register_protocol(proto_date_time_string_decoding_error);
9675 expert_register_field_array(expert_date_time_string_decoding_error, ei, array_length(ei));
9677 /* "Date and Time-String Decoding Error" isn't really a protocol, it's an error indication;
9678 disabling them makes no sense. */
9679 proto_set_cant_toggle(proto_date_time_string_decoding_error);
9682 static void
9683 register_string_errors(void)
9685 static ei_register_info ei[] = {
9686 { &ei_string_trailing_characters,
9687 { "_ws.string.trailing_stray_characters", PI_UNDECODED, PI_WARN, "Trailing stray characters", EXPFILL }
9691 expert_module_t* expert_string_errors;
9693 proto_string_errors = proto_register_protocol("String Errors", "String errors", "_ws.string");
9695 expert_string_errors = expert_register_protocol(proto_string_errors);
9696 expert_register_field_array(expert_string_errors, ei, array_length(ei));
9698 /* "String Errors" isn't really a protocol, it's an error indication;
9699 disabling them makes no sense. */
9700 proto_set_cant_toggle(proto_string_errors);
9703 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM (300000+PRE_ALLOC_EXPERT_FIELDS_MEM)
9704 static int
9705 proto_register_field_init(header_field_info *hfinfo, const int parent)
9708 tmp_fld_check_assert(hfinfo);
9710 hfinfo->parent = parent;
9711 hfinfo->same_name_next = NULL;
9712 hfinfo->same_name_prev_id = -1;
9714 /* if we always add and never delete, then id == len - 1 is correct */
9715 if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
9716 if (!gpa_hfinfo.hfi) {
9717 gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
9718 gpa_hfinfo.hfi = (header_field_info **)g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
9719 /* The entry with index 0 is not used. */
9720 gpa_hfinfo.hfi[0] = NULL;
9721 gpa_hfinfo.len = 1;
9722 } else {
9723 gpa_hfinfo.allocated_len += 1000;
9724 gpa_hfinfo.hfi = (header_field_info **)g_realloc(gpa_hfinfo.hfi,
9725 sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
9726 /*ws_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
9729 gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
9730 gpa_hfinfo.len++;
9731 hfinfo->id = gpa_hfinfo.len - 1;
9733 /* if we have real names, enter this field in the name tree */
9734 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
9736 header_field_info *same_name_next_hfinfo;
9737 unsigned char c;
9739 /* Check that the filter name (abbreviation) is legal;
9740 * it must contain only alphanumerics, '-', "_", and ".". */
9741 c = proto_check_field_name(hfinfo->abbrev);
9742 if (c) {
9743 if (c == '.') {
9744 REPORT_DISSECTOR_BUG("Invalid leading, duplicated or trailing '.' found in filter name '%s'", hfinfo->abbrev);
9745 } else if (g_ascii_isprint(c)) {
9746 REPORT_DISSECTOR_BUG("Invalid character '%c' in filter name '%s'", c, hfinfo->abbrev);
9747 } else {
9748 REPORT_DISSECTOR_BUG("Invalid byte \\%03o in filter name '%s'", c, hfinfo->abbrev);
9752 /* We allow multiple hfinfo's to be registered under the same
9753 * abbreviation. This was done for X.25, as, depending
9754 * on whether it's modulo-8 or modulo-128 operation,
9755 * some bitfield fields may be in different bits of
9756 * a byte, and we want to be able to refer to that field
9757 * with one name regardless of whether the packets
9758 * are modulo-8 or modulo-128 packets. */
9760 same_name_hfinfo = NULL;
9762 g_hash_table_insert(gpa_name_map, (void *) (hfinfo->abbrev), hfinfo);
9763 /* GLIB 2.x - if it is already present
9764 * the previous hfinfo with the same name is saved
9765 * to same_name_hfinfo by value destroy callback */
9766 if (same_name_hfinfo) {
9767 /* There's already a field with this name.
9768 * Put the current field *before* that field
9769 * in the list of fields with this name, Thus,
9770 * we end up with an effectively
9771 * doubly-linked-list of same-named hfinfo's,
9772 * with the head of the list (stored in the
9773 * hash) being the last seen hfinfo.
9775 same_name_next_hfinfo =
9776 same_name_hfinfo->same_name_next;
9778 hfinfo->same_name_next = same_name_next_hfinfo;
9779 if (same_name_next_hfinfo)
9780 same_name_next_hfinfo->same_name_prev_id = hfinfo->id;
9782 same_name_hfinfo->same_name_next = hfinfo;
9783 hfinfo->same_name_prev_id = same_name_hfinfo->id;
9784 #ifdef ENABLE_CHECK_FILTER
9785 while (same_name_hfinfo) {
9786 if (!ftype_similar_types(hfinfo->type, same_name_hfinfo->type))
9787 ws_warning("'%s' exists multiple times with incompatible types: %s and %s", hfinfo->abbrev, ftype_name(hfinfo->type), ftype_name(same_name_hfinfo->type));
9788 same_name_hfinfo = same_name_hfinfo->same_name_next;
9790 #endif
9794 return hfinfo->id;
9797 void
9798 proto_register_subtree_array(int * const *indices, const int num_indices)
9800 int i;
9801 int *const *ptr = indices;
9804 * If we've already allocated the array of tree types, expand
9805 * it; this lets plugins such as mate add tree types after
9806 * the initial startup. (If we haven't already allocated it,
9807 * we don't allocate it; on the first pass, we just assign
9808 * ett values and keep track of how many we've assigned, and
9809 * when we're finished registering all dissectors we allocate
9810 * the array, so that we do only one allocation rather than
9811 * wasting CPU time and memory by growing the array for each
9812 * dissector that registers ett values.)
9814 if (tree_is_expanded != NULL) {
9815 tree_is_expanded = (uint32_t *)g_realloc(tree_is_expanded, (1+((num_tree_types + num_indices)/32)) * sizeof(uint32_t));
9817 /* set new items to 0 */
9818 /* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of uint32_t to 0) */
9819 for (i = num_tree_types; i < num_tree_types + num_indices; i++)
9820 tree_is_expanded[i >> 5] &= ~(1U << (i & 31));
9824 * Assign "num_indices" subtree numbers starting at "num_tree_types",
9825 * returning the indices through the pointers in the array whose
9826 * first element is pointed to by "indices", and update
9827 * "num_tree_types" appropriately.
9829 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
9830 if (**ptr != -1 && **ptr != 0) {
9831 REPORT_DISSECTOR_BUG("register_subtree_array: subtree item type (ett_...) not -1 or 0 !"
9832 " This is a development error:"
9833 " Either the subtree item type has already been assigned or"
9834 " was not initialized to -1 or 0.");
9836 **ptr = num_tree_types;
9840 static void
9841 mark_truncated(char *label_str, size_t name_pos, const size_t size, size_t *value_pos)
9843 static const char trunc_str[] = " [" UTF8_HORIZONTAL_ELLIPSIS "]";
9844 const size_t trunc_len = sizeof(trunc_str)-1;
9845 char *last_char;
9847 /* ..... field_name: dataaaaaaaaaaaaa
9849 * ^^^^^ name_pos
9851 * ..... field_name […]: dataaaaaaaaaaaaa
9853 * name_pos==0 means that we have only data or only a field_name
9856 if (name_pos < size - trunc_len) {
9857 memmove(label_str + name_pos + trunc_len, label_str + name_pos, size - name_pos - trunc_len);
9858 memcpy(label_str + name_pos, trunc_str, trunc_len);
9860 /* in general, label_str is UTF-8
9861 we can truncate it only at the beginning of a new character
9862 we go backwards from the byte right after our buffer and
9863 find the next starting byte of a UTF-8 character, this is
9864 where we cut
9865 there's no need to use g_utf8_find_prev_char(), the search
9866 will always succeed since we copied trunc_str into the
9867 buffer */
9868 /* g_utf8_prev_char does not deference the memory address
9869 * passed in (until after decrementing it, so it is perfectly
9870 * legal to pass in a pointer one past the last element.
9872 last_char = g_utf8_prev_char(label_str + size);
9873 *last_char = '\0';
9875 if (value_pos && *value_pos > 0) {
9876 if (name_pos == 0) {
9877 *value_pos += trunc_len;
9878 } else {
9879 /* Move one back to include trunc_str in the value. */
9880 *value_pos -= 1;
9883 } else if (name_pos < size)
9884 (void) g_strlcpy(label_str + name_pos, trunc_str, size - name_pos);
9887 static void
9888 label_mark_truncated(char *label_str, size_t name_pos, size_t *value_pos)
9890 mark_truncated(label_str, name_pos, ITEM_LABEL_LENGTH, value_pos);
9893 static size_t
9894 label_fill(char *label_str, size_t pos, const header_field_info *hfinfo, const char *text, size_t *value_pos)
9896 size_t name_pos;
9898 /* "%s: %s", hfinfo->name, text */
9899 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
9900 if (!(hfinfo->display & BASE_NO_DISPLAY_VALUE)) {
9901 pos = label_concat(label_str, pos, ": ");
9902 if (value_pos) {
9903 *value_pos = pos;
9905 pos = ws_label_strcpy(label_str, ITEM_LABEL_LENGTH, pos, text ? text : "(null)", label_strcat_flags(hfinfo));
9908 if (pos >= ITEM_LABEL_LENGTH) {
9909 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
9910 label_mark_truncated(label_str, name_pos, value_pos);
9913 return pos;
9916 static size_t
9917 label_fill_descr(char *label_str, size_t pos, const header_field_info *hfinfo, const char *text, const char *descr, size_t *value_pos)
9919 size_t name_pos;
9921 /* "%s: %s (%s)", hfinfo->name, text, descr */
9922 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
9923 if (!(hfinfo->display & BASE_NO_DISPLAY_VALUE)) {
9924 pos = label_concat(label_str, pos, ": ");
9925 if (value_pos) {
9926 *value_pos = pos;
9928 if (hfinfo->display & BASE_UNIT_STRING) {
9929 pos = label_concat(label_str, pos, descr ? descr : "(null)");
9930 pos = label_concat(label_str, pos, text ? text : "(null)");
9931 } else {
9932 pos = label_concat(label_str, pos, text ? text : "(null)");
9933 pos = label_concat(label_str, pos, " (");
9934 pos = label_concat(label_str, pos, descr ? descr : "(null)");
9935 pos = label_concat(label_str, pos, ")");
9939 if (pos >= ITEM_LABEL_LENGTH) {
9940 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
9941 label_mark_truncated(label_str, name_pos, value_pos);
9944 return pos;
9947 void
9948 proto_item_fill_label(const field_info *fi, char *label_str, size_t *value_pos)
9950 const header_field_info *hfinfo;
9951 const char *str;
9952 const uint8_t *bytes;
9953 uint32_t integer;
9954 uint64_t integer64;
9955 const ipv4_addr_and_mask *ipv4;
9956 const ipv6_addr_and_prefix *ipv6;
9957 const e_guid_t *guid;
9958 char *name;
9959 address addr;
9960 char *addr_str;
9961 char *tmp;
9963 if (!label_str) {
9964 ws_warning("NULL label_str passed to proto_item_fill_label.");
9965 return;
9968 label_str[0]= '\0';
9970 if (!fi) {
9971 return;
9974 hfinfo = fi->hfinfo;
9976 switch (hfinfo->type) {
9977 case FT_NONE:
9978 case FT_PROTOCOL:
9979 (void) g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
9980 if (value_pos) {
9981 *value_pos = strlen(hfinfo->name);
9983 break;
9985 case FT_BOOLEAN:
9986 fill_label_boolean(fi, label_str, value_pos);
9987 break;
9989 case FT_BYTES:
9990 case FT_UINT_BYTES:
9991 tmp = format_bytes_hfinfo(NULL, hfinfo,
9992 fvalue_get_bytes_data(fi->value),
9993 (unsigned)fvalue_length2(fi->value));
9994 label_fill(label_str, 0, hfinfo, tmp, value_pos);
9995 wmem_free(NULL, tmp);
9996 break;
9998 case FT_CHAR:
9999 if (hfinfo->bitmask) {
10000 fill_label_bitfield_char(fi, label_str, value_pos);
10001 } else {
10002 fill_label_char(fi, label_str, value_pos);
10004 break;
10006 /* Four types of integers to take care of:
10007 * Bitfield, with val_string
10008 * Bitfield, w/o val_string
10009 * Non-bitfield, with val_string
10010 * Non-bitfield, w/o val_string
10012 case FT_UINT8:
10013 case FT_UINT16:
10014 case FT_UINT24:
10015 case FT_UINT32:
10016 if (hfinfo->bitmask) {
10017 fill_label_bitfield(fi, label_str, value_pos, false);
10018 } else {
10019 fill_label_number(fi, label_str, value_pos, false);
10021 break;
10023 case FT_FRAMENUM:
10024 fill_label_number(fi, label_str, value_pos, false);
10025 break;
10027 case FT_UINT40:
10028 case FT_UINT48:
10029 case FT_UINT56:
10030 case FT_UINT64:
10031 if (hfinfo->bitmask) {
10032 fill_label_bitfield64(fi, label_str, value_pos, false);
10033 } else {
10034 fill_label_number64(fi, label_str, value_pos, false);
10036 break;
10038 case FT_INT8:
10039 case FT_INT16:
10040 case FT_INT24:
10041 case FT_INT32:
10042 if (hfinfo->bitmask) {
10043 fill_label_bitfield(fi, label_str, value_pos, true);
10044 } else {
10045 fill_label_number(fi, label_str, value_pos, true);
10047 break;
10049 case FT_INT40:
10050 case FT_INT48:
10051 case FT_INT56:
10052 case FT_INT64:
10053 if (hfinfo->bitmask) {
10054 fill_label_bitfield64(fi, label_str, value_pos, true);
10055 } else {
10056 fill_label_number64(fi, label_str, value_pos, true);
10058 break;
10060 case FT_FLOAT:
10061 case FT_DOUBLE:
10062 fill_label_float(fi, label_str, value_pos);
10063 break;
10065 case FT_ABSOLUTE_TIME:
10067 int flags = ABS_TIME_TO_STR_SHOW_ZONE;
10068 if (prefs.display_abs_time_ascii < ABS_TIME_ASCII_TREE) {
10069 flags |= ABS_TIME_TO_STR_ISO8601;
10071 tmp = abs_time_to_str_ex(NULL, fvalue_get_time(fi->value), hfinfo->display, flags);
10072 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10073 wmem_free(NULL, tmp);
10074 break;
10076 case FT_RELATIVE_TIME:
10077 tmp = rel_time_to_str(NULL, fvalue_get_time(fi->value));
10078 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10079 wmem_free(NULL, tmp);
10080 break;
10082 case FT_IPXNET:
10083 integer = fvalue_get_uinteger(fi->value);
10084 tmp = get_ipxnet_name(NULL, integer);
10085 addr_str = wmem_strdup_printf(NULL, "0x%08X", integer);
10086 label_fill_descr(label_str, 0, hfinfo, tmp, addr_str, value_pos);
10087 wmem_free(NULL, tmp);
10088 wmem_free(NULL, addr_str);
10089 break;
10091 case FT_VINES:
10092 addr.type = AT_VINES;
10093 addr.len = VINES_ADDR_LEN;
10094 addr.data = fvalue_get_bytes_data(fi->value);
10096 addr_str = (char*)address_to_str(NULL, &addr);
10097 label_fill(label_str, 0, hfinfo, addr_str, value_pos);
10098 wmem_free(NULL, addr_str);
10099 break;
10101 case FT_ETHER:
10102 bytes = fvalue_get_bytes_data(fi->value);
10104 addr.type = AT_ETHER;
10105 addr.len = 6;
10106 addr.data = bytes;
10108 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
10109 label_fill(label_str, 0, hfinfo, addr_str, value_pos);
10110 wmem_free(NULL, addr_str);
10111 break;
10113 case FT_IPv4:
10114 ipv4 = fvalue_get_ipv4(fi->value);
10115 set_address_ipv4(&addr, ipv4);
10117 if (hfinfo->display == BASE_NETMASK) {
10118 addr_str = (char*)address_to_str(NULL, &addr);
10119 } else {
10120 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
10122 label_fill(label_str, 0, hfinfo, addr_str, value_pos);
10123 wmem_free(NULL, addr_str);
10124 free_address(&addr);
10125 break;
10127 case FT_IPv6:
10128 ipv6 = fvalue_get_ipv6(fi->value);
10129 set_address_ipv6(&addr, ipv6);
10131 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
10132 label_fill(label_str, 0, hfinfo, addr_str, value_pos);
10133 wmem_free(NULL, addr_str);
10134 free_address(&addr);
10135 break;
10137 case FT_FCWWN:
10138 bytes = fvalue_get_bytes_data(fi->value);
10139 addr.type = AT_FCWWN;
10140 addr.len = FCWWN_ADDR_LEN;
10141 addr.data = bytes;
10143 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
10144 label_fill(label_str, 0, hfinfo, addr_str, value_pos);
10145 wmem_free(NULL, addr_str);
10146 break;
10148 case FT_GUID:
10149 guid = fvalue_get_guid(fi->value);
10150 tmp = guid_to_str(NULL, guid);
10151 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10152 wmem_free(NULL, tmp);
10153 break;
10155 case FT_OID:
10156 bytes = fvalue_get_bytes_data(fi->value);
10157 name = oid_resolved_from_encoded(NULL, bytes, (int)fvalue_length2(fi->value));
10158 tmp = oid_encoded2string(NULL, bytes, (unsigned)fvalue_length2(fi->value));
10159 if (name) {
10160 label_fill_descr(label_str, 0, hfinfo, tmp, name, value_pos);
10161 wmem_free(NULL, name);
10162 } else {
10163 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10165 wmem_free(NULL, tmp);
10166 break;
10168 case FT_REL_OID:
10169 bytes = fvalue_get_bytes_data(fi->value);
10170 name = rel_oid_resolved_from_encoded(NULL, bytes, (int)fvalue_length2(fi->value));
10171 tmp = rel_oid_encoded2string(NULL, bytes, (unsigned)fvalue_length2(fi->value));
10172 if (name) {
10173 label_fill_descr(label_str, 0, hfinfo, tmp, name, value_pos);
10174 wmem_free(NULL, name);
10175 } else {
10176 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10178 wmem_free(NULL, tmp);
10179 break;
10181 case FT_SYSTEM_ID:
10182 bytes = fvalue_get_bytes_data(fi->value);
10183 tmp = print_system_id(NULL, bytes, (int)fvalue_length2(fi->value));
10184 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10185 wmem_free(NULL, tmp);
10186 break;
10188 case FT_EUI64:
10189 integer64 = fvalue_get_uinteger64(fi->value);
10190 addr_str = eui64_to_str(NULL, integer64);
10191 tmp = (char*)eui64_to_display(NULL, integer64);
10192 label_fill_descr(label_str, 0, hfinfo, tmp, addr_str, value_pos);
10193 wmem_free(NULL, tmp);
10194 wmem_free(NULL, addr_str);
10195 break;
10196 case FT_STRING:
10197 case FT_STRINGZ:
10198 case FT_UINT_STRING:
10199 case FT_STRINGZPAD:
10200 case FT_STRINGZTRUNC:
10201 case FT_AX25:
10202 str = fvalue_get_string(fi->value);
10203 label_fill(label_str, 0, hfinfo, str, value_pos);
10204 break;
10206 case FT_IEEE_11073_SFLOAT:
10207 case FT_IEEE_11073_FLOAT:
10208 tmp = fvalue_to_string_repr(NULL, fi->value, FTREPR_DISPLAY, hfinfo->display);
10209 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10210 wmem_free(NULL, tmp);
10211 break;
10213 default:
10214 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_item_fill_label()",
10215 hfinfo->abbrev,
10216 hfinfo->type,
10217 ftype_name(hfinfo->type));
10218 break;
10222 static void
10223 fill_label_boolean(const field_info *fi, char *label_str, size_t *value_pos)
10225 char *p;
10226 int bitfield_byte_length = 0, bitwidth;
10227 uint64_t unshifted_value;
10228 uint64_t value;
10230 const header_field_info *hfinfo = fi->hfinfo;
10232 value = fvalue_get_uinteger64(fi->value);
10233 if (hfinfo->bitmask) {
10234 /* Figure out the bit width */
10235 bitwidth = hfinfo_container_bitwidth(hfinfo);
10237 /* Un-shift bits */
10238 unshifted_value = value;
10239 unshifted_value <<= hfinfo_bitshift(hfinfo);
10241 /* Create the bitfield first */
10242 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
10243 bitfield_byte_length = (int) (p - label_str);
10246 /* Fill in the textual info */
10247 label_fill(label_str, bitfield_byte_length, hfinfo, tfs_get_string(!!value, hfinfo->strings), value_pos);
10250 static const char *
10251 hf_try_val_to_str(uint32_t value, const header_field_info *hfinfo)
10253 if (hfinfo->display & BASE_RANGE_STRING)
10254 return try_rval_to_str(value, (const range_string *) hfinfo->strings);
10256 if (hfinfo->display & BASE_EXT_STRING) {
10257 if (hfinfo->display & BASE_VAL64_STRING)
10258 return try_val64_to_str_ext(value, (val64_string_ext *) hfinfo->strings);
10259 else
10260 return try_val_to_str_ext(value, (value_string_ext *) hfinfo->strings);
10263 if (hfinfo->display & BASE_VAL64_STRING)
10264 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
10266 if (hfinfo->display & BASE_UNIT_STRING)
10267 return unit_name_string_get_value(value, (const struct unit_name_string*) hfinfo->strings);
10269 return try_val_to_str(value, (const value_string *) hfinfo->strings);
10272 static const char *
10273 hf_try_val64_to_str(uint64_t value, const header_field_info *hfinfo)
10275 if (hfinfo->display & BASE_VAL64_STRING) {
10276 if (hfinfo->display & BASE_EXT_STRING)
10277 return try_val64_to_str_ext(value, (val64_string_ext *) hfinfo->strings);
10278 else
10279 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
10282 if (hfinfo->display & BASE_RANGE_STRING)
10283 return try_rval64_to_str(value, (const range_string *) hfinfo->strings);
10285 if (hfinfo->display & BASE_UNIT_STRING)
10286 return unit_name_string_get_value64(value, (const struct unit_name_string*) hfinfo->strings);
10288 /* If this is reached somebody registered a 64-bit field with a 32-bit
10289 * value-string, which isn't right. */
10290 REPORT_DISSECTOR_BUG("field %s is a 64-bit field with a 32-bit value_string",
10291 hfinfo->abbrev);
10293 /* This is necessary to squelch MSVC errors; is there
10294 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
10295 never returns? */
10296 return NULL;
10299 static const char *
10300 hf_try_double_val_to_str(double value, const header_field_info *hfinfo)
10302 if (hfinfo->display & BASE_UNIT_STRING)
10303 return unit_name_string_get_double(value, (const struct unit_name_string*)hfinfo->strings);
10305 REPORT_DISSECTOR_BUG("field %s (FT_DOUBLE) has no base_unit_string", hfinfo->abbrev);
10307 /* This is necessary to squelch MSVC errors; is there
10308 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
10309 never returns? */
10310 return NULL;
10313 static const char *
10314 hf_try_val_to_str_const(uint32_t value, const header_field_info *hfinfo, const char *unknown_str)
10316 const char *str = hf_try_val_to_str(value, hfinfo);
10318 return (str) ? str : unknown_str;
10321 static const char *
10322 hf_try_val64_to_str_const(uint64_t value, const header_field_info *hfinfo, const char *unknown_str)
10324 const char *str = hf_try_val64_to_str(value, hfinfo);
10326 return (str) ? str : unknown_str;
10329 /* Fills data for bitfield chars with val_strings */
10330 static void
10331 fill_label_bitfield_char(const field_info *fi, char *label_str, size_t *value_pos)
10333 char *p;
10334 int bitfield_byte_length, bitwidth;
10335 uint32_t unshifted_value;
10336 uint32_t value;
10338 char buf[32];
10339 const char *out;
10341 const header_field_info *hfinfo = fi->hfinfo;
10343 /* Figure out the bit width */
10344 bitwidth = hfinfo_container_bitwidth(hfinfo);
10346 /* Un-shift bits */
10347 value = fvalue_get_uinteger(fi->value);
10349 unshifted_value = value;
10350 if (hfinfo->bitmask) {
10351 unshifted_value <<= hfinfo_bitshift(hfinfo);
10354 /* Create the bitfield first */
10355 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
10356 bitfield_byte_length = (int) (p - label_str);
10358 /* Fill in the textual info using stored (shifted) value */
10359 if (hfinfo->display == BASE_CUSTOM) {
10360 char tmp[ITEM_LABEL_LENGTH];
10361 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
10363 DISSECTOR_ASSERT(fmtfunc);
10364 fmtfunc(tmp, value);
10365 label_fill(label_str, bitfield_byte_length, hfinfo, tmp, value_pos);
10367 else if (hfinfo->strings) {
10368 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
10370 out = hfinfo_char_vals_format(hfinfo, buf, value);
10371 if (out == NULL) /* BASE_NONE so don't put integer in descr */
10372 label_fill(label_str, bitfield_byte_length, hfinfo, val_str, value_pos);
10373 else
10374 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out, value_pos);
10376 else {
10377 out = hfinfo_char_value_format(hfinfo, buf, value);
10379 label_fill(label_str, bitfield_byte_length, hfinfo, out, value_pos);
10383 /* Fills data for bitfield ints with val_strings */
10384 static void
10385 fill_label_bitfield(const field_info *fi, char *label_str, size_t *value_pos, bool is_signed)
10387 char *p;
10388 int bitfield_byte_length, bitwidth;
10389 uint32_t value, unshifted_value;
10390 char buf[NUMBER_LABEL_LENGTH];
10391 const char *out;
10393 const header_field_info *hfinfo = fi->hfinfo;
10395 /* Figure out the bit width */
10396 if (fi->flags & FI_VARINT)
10397 bitwidth = fi->length*8;
10398 else
10399 bitwidth = hfinfo_container_bitwidth(hfinfo);
10401 /* Un-shift bits */
10402 if (is_signed)
10403 value = fvalue_get_sinteger(fi->value);
10404 else
10405 value = fvalue_get_uinteger(fi->value);
10407 unshifted_value = value;
10408 if (hfinfo->bitmask) {
10409 unshifted_value <<= hfinfo_bitshift(hfinfo);
10412 /* Create the bitfield first */
10413 if (fi->flags & FI_VARINT)
10414 p = decode_bitfield_varint_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
10415 else
10416 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
10417 bitfield_byte_length = (int) (p - label_str);
10419 /* Fill in the textual info using stored (shifted) value */
10420 if (hfinfo->display == BASE_CUSTOM) {
10421 char tmp[ITEM_LABEL_LENGTH];
10422 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
10424 DISSECTOR_ASSERT(fmtfunc);
10425 fmtfunc(tmp, value);
10426 label_fill(label_str, bitfield_byte_length, hfinfo, tmp, value_pos);
10428 else if (hfinfo->strings) {
10429 const char *val_str = hf_try_val_to_str(value, hfinfo);
10431 out = hfinfo_number_vals_format(hfinfo, buf, value);
10432 if (hfinfo->display & BASE_SPECIAL_VALS) {
10434 * Unique values only display value_string string
10435 * if there is a match. Otherwise it's just a number
10437 if (val_str) {
10438 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out, value_pos);
10439 } else {
10440 label_fill(label_str, bitfield_byte_length, hfinfo, out, value_pos);
10442 } else {
10443 if (val_str == NULL)
10444 val_str = "Unknown";
10446 if (out == NULL) /* BASE_NONE so don't put integer in descr */
10447 label_fill(label_str, bitfield_byte_length, hfinfo, val_str, value_pos);
10448 else
10449 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out, value_pos);
10452 else {
10453 out = hfinfo_number_value_format(hfinfo, buf, value);
10455 label_fill(label_str, bitfield_byte_length, hfinfo, out, value_pos);
10459 static void
10460 fill_label_bitfield64(const field_info *fi, char *label_str, size_t *value_pos, bool is_signed)
10462 char *p;
10463 int bitfield_byte_length, bitwidth;
10464 uint64_t value, unshifted_value;
10465 char buf[NUMBER_LABEL_LENGTH];
10466 const char *out;
10468 const header_field_info *hfinfo = fi->hfinfo;
10470 /* Figure out the bit width */
10471 if (fi->flags & FI_VARINT)
10472 bitwidth = fi->length*8;
10473 else
10474 bitwidth = hfinfo_container_bitwidth(hfinfo);
10476 /* Un-shift bits */
10477 if (is_signed)
10478 value = fvalue_get_sinteger64(fi->value);
10479 else
10480 value = fvalue_get_uinteger64(fi->value);
10482 unshifted_value = value;
10483 if (hfinfo->bitmask) {
10484 unshifted_value <<= hfinfo_bitshift(hfinfo);
10487 /* Create the bitfield first */
10488 if (fi->flags & FI_VARINT)
10489 p = decode_bitfield_varint_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
10490 else
10491 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
10492 bitfield_byte_length = (int) (p - label_str);
10494 /* Fill in the textual info using stored (shifted) value */
10495 if (hfinfo->display == BASE_CUSTOM) {
10496 char tmp[ITEM_LABEL_LENGTH];
10497 const custom_fmt_func_64_t fmtfunc64 = (const custom_fmt_func_64_t)hfinfo->strings;
10499 DISSECTOR_ASSERT(fmtfunc64);
10500 fmtfunc64(tmp, value);
10501 label_fill(label_str, bitfield_byte_length, hfinfo, tmp, value_pos);
10503 else if (hfinfo->strings) {
10504 const char *val_str = hf_try_val64_to_str(value, hfinfo);
10506 out = hfinfo_number_vals_format64(hfinfo, buf, value);
10507 if (hfinfo->display & BASE_SPECIAL_VALS) {
10509 * Unique values only display value_string string
10510 * if there is a match. Otherwise it's just a number
10512 if (val_str) {
10513 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out, value_pos);
10514 } else {
10515 label_fill(label_str, bitfield_byte_length, hfinfo, out, value_pos);
10517 } else {
10518 if (val_str == NULL)
10519 val_str = "Unknown";
10521 if (out == NULL) /* BASE_NONE so don't put integer in descr */
10522 label_fill(label_str, bitfield_byte_length, hfinfo, val_str, value_pos);
10523 else
10524 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out, value_pos);
10527 else {
10528 out = hfinfo_number_value_format64(hfinfo, buf, value);
10530 label_fill(label_str, bitfield_byte_length, hfinfo, out, value_pos);
10534 static void
10535 fill_label_char(const field_info *fi, char *label_str, size_t *value_pos)
10537 const header_field_info *hfinfo = fi->hfinfo;
10538 uint32_t value;
10540 char buf[32];
10541 const char *out;
10543 value = fvalue_get_uinteger(fi->value);
10545 /* Fill in the textual info */
10546 if (hfinfo->display == BASE_CUSTOM) {
10547 char tmp[ITEM_LABEL_LENGTH];
10548 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
10550 DISSECTOR_ASSERT(fmtfunc);
10551 fmtfunc(tmp, value);
10552 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10554 else if (hfinfo->strings) {
10555 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
10557 out = hfinfo_char_vals_format(hfinfo, buf, value);
10558 label_fill_descr(label_str, 0, hfinfo, val_str, out, value_pos);
10560 else {
10561 out = hfinfo_char_value_format(hfinfo, buf, value);
10563 label_fill(label_str, 0, hfinfo, out, value_pos);
10567 static void
10568 fill_label_number(const field_info *fi, char *label_str, size_t *value_pos, bool is_signed)
10570 const header_field_info *hfinfo = fi->hfinfo;
10571 uint32_t value;
10573 char buf[NUMBER_LABEL_LENGTH];
10574 const char *out;
10576 if (is_signed)
10577 value = fvalue_get_sinteger(fi->value);
10578 else
10579 value = fvalue_get_uinteger(fi->value);
10581 /* Fill in the textual info */
10582 if (hfinfo->display == BASE_CUSTOM) {
10583 char tmp[ITEM_LABEL_LENGTH];
10584 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
10586 DISSECTOR_ASSERT(fmtfunc);
10587 fmtfunc(tmp, value);
10588 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10590 else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) {
10592 * It makes no sense to have a value-string table for a
10593 * frame-number field - they're just integers giving
10594 * the ordinal frame number.
10596 const char *val_str = hf_try_val_to_str(value, hfinfo);
10598 out = hfinfo_number_vals_format(hfinfo, buf, value);
10599 if (hfinfo->display & BASE_SPECIAL_VALS) {
10601 * Unique values only display value_string string
10602 * if there is a match. Otherwise it's just a number
10604 if (val_str) {
10605 label_fill_descr(label_str, 0, hfinfo, val_str, out, value_pos);
10606 } else {
10607 label_fill(label_str, 0, hfinfo, out, value_pos);
10609 } else {
10610 if (val_str == NULL)
10611 val_str = "Unknown";
10613 if (out == NULL) /* BASE_NONE so don't put integer in descr */
10614 label_fill(label_str, 0, hfinfo, val_str, value_pos);
10615 else
10616 label_fill_descr(label_str, 0, hfinfo, val_str, out, value_pos);
10619 else if (IS_BASE_PORT(hfinfo->display)) {
10620 char tmp[ITEM_LABEL_LENGTH];
10622 port_with_resolution_to_str_buf(tmp, sizeof(tmp),
10623 display_to_port_type((field_display_e)hfinfo->display), value);
10624 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10626 else {
10627 out = hfinfo_number_value_format(hfinfo, buf, value);
10629 label_fill(label_str, 0, hfinfo, out, value_pos);
10633 static void
10634 fill_label_number64(const field_info *fi, char *label_str, size_t *value_pos, bool is_signed)
10636 const header_field_info *hfinfo = fi->hfinfo;
10637 uint64_t value;
10639 char buf[NUMBER_LABEL_LENGTH];
10640 const char *out;
10642 if (is_signed)
10643 value = fvalue_get_sinteger64(fi->value);
10644 else
10645 value = fvalue_get_uinteger64(fi->value);
10647 /* Fill in the textual info */
10648 if (hfinfo->display == BASE_CUSTOM) {
10649 char tmp[ITEM_LABEL_LENGTH];
10650 const custom_fmt_func_64_t fmtfunc64 = (const custom_fmt_func_64_t)hfinfo->strings;
10652 DISSECTOR_ASSERT(fmtfunc64);
10653 fmtfunc64(tmp, value);
10654 label_fill(label_str, 0, hfinfo, tmp, value_pos);
10656 else if (hfinfo->strings) {
10657 const char *val_str = hf_try_val64_to_str(value, hfinfo);
10659 out = hfinfo_number_vals_format64(hfinfo, buf, value);
10660 if (hfinfo->display & BASE_SPECIAL_VALS) {
10662 * Unique values only display value_string string
10663 * if there is a match. Otherwise it's just a number
10665 if (val_str) {
10666 label_fill_descr(label_str, 0, hfinfo, val_str, out, value_pos);
10667 } else {
10668 label_fill(label_str, 0, hfinfo, out, value_pos);
10670 } else {
10671 if (val_str == NULL)
10672 val_str = "Unknown";
10674 if (out == NULL) /* BASE_NONE so don't put integer in descr */
10675 label_fill(label_str, 0, hfinfo, val_str, value_pos);
10676 else
10677 label_fill_descr(label_str, 0, hfinfo, val_str, out, value_pos);
10680 else {
10681 out = hfinfo_number_value_format64(hfinfo, buf, value);
10683 label_fill(label_str, 0, hfinfo, out, value_pos);
10687 static size_t
10688 fill_display_label_float(const field_info *fi, char *label_str)
10690 int display;
10691 int digits;
10692 int n;
10693 double value;
10695 display = FIELD_DISPLAY(fi->hfinfo->display);
10696 value = fvalue_get_floating(fi->value);
10698 if (display == BASE_CUSTOM) {
10699 const custom_fmt_func_double_t fmtfunc = (const custom_fmt_func_double_t)fi->hfinfo->strings;
10700 DISSECTOR_ASSERT(fmtfunc);
10701 fmtfunc(label_str, value);
10702 return strlen(label_str);
10705 switch (display) {
10706 case BASE_NONE:
10707 if (fi->hfinfo->type == FT_FLOAT)
10708 digits = FLT_DIG;
10709 else
10710 digits = DBL_DIG;
10712 n = snprintf(label_str, ITEM_LABEL_LENGTH, "%.*g", digits, value);
10713 break;
10714 case BASE_DEC:
10715 n = snprintf(label_str, ITEM_LABEL_LENGTH, "%f", value);
10716 break;
10717 case BASE_HEX:
10718 n = snprintf(label_str, ITEM_LABEL_LENGTH, "%a", value);
10719 break;
10720 case BASE_EXP:
10721 n = snprintf(label_str, ITEM_LABEL_LENGTH, "%e", value);
10722 break;
10723 default:
10724 ws_assert_not_reached();
10726 if (n < 0) {
10727 return 0; /* error */
10729 if ((fi->hfinfo->strings) && (fi->hfinfo->display & BASE_UNIT_STRING)) {
10730 const char *hf_str_val;
10731 hf_str_val = hf_try_double_val_to_str(value, fi->hfinfo);
10732 n += protoo_strlcpy(label_str + n, hf_str_val, ITEM_LABEL_LENGTH - n);
10734 if (n > ITEM_LABEL_LENGTH) {
10735 ws_warning("label length too small");
10736 return strlen(label_str);
10739 return n;
10742 void
10743 fill_label_float(const field_info *fi, char *label_str, size_t *value_pos)
10745 char tmp[ITEM_LABEL_LENGTH];
10747 fill_display_label_float(fi, tmp);
10748 label_fill(label_str, 0, fi->hfinfo, tmp, value_pos);
10752 hfinfo_bitshift(const header_field_info *hfinfo)
10754 return ws_ctz(hfinfo->bitmask);
10758 static int
10759 hfinfo_bitoffset(const header_field_info *hfinfo)
10761 if (!hfinfo->bitmask) {
10762 return 0;
10765 /* ilog2 = first set bit, counting 0 as the last bit; we want 0
10766 * as the first bit */
10767 return hfinfo_container_bitwidth(hfinfo) - 1 - ws_ilog2(hfinfo->bitmask);
10770 static int
10771 hfinfo_mask_bitwidth(const header_field_info *hfinfo)
10773 if (!hfinfo->bitmask) {
10774 return 0;
10777 /* ilog2 = first set bit, ctz = last set bit */
10778 return ws_ilog2(hfinfo->bitmask) - ws_ctz(hfinfo->bitmask) + 1;
10781 static int
10782 hfinfo_type_bitwidth(enum ftenum type)
10784 int bitwidth = 0;
10786 switch (type) {
10787 case FT_CHAR:
10788 case FT_UINT8:
10789 case FT_INT8:
10790 bitwidth = 8;
10791 break;
10792 case FT_UINT16:
10793 case FT_INT16:
10794 bitwidth = 16;
10795 break;
10796 case FT_UINT24:
10797 case FT_INT24:
10798 bitwidth = 24;
10799 break;
10800 case FT_UINT32:
10801 case FT_INT32:
10802 bitwidth = 32;
10803 break;
10804 case FT_UINT40:
10805 case FT_INT40:
10806 bitwidth = 40;
10807 break;
10808 case FT_UINT48:
10809 case FT_INT48:
10810 bitwidth = 48;
10811 break;
10812 case FT_UINT56:
10813 case FT_INT56:
10814 bitwidth = 56;
10815 break;
10816 case FT_UINT64:
10817 case FT_INT64:
10818 bitwidth = 64;
10819 break;
10820 default:
10821 DISSECTOR_ASSERT_NOT_REACHED();
10824 return bitwidth;
10828 static int
10829 hfinfo_container_bitwidth(const header_field_info *hfinfo)
10831 if (!hfinfo->bitmask) {
10832 return 0;
10835 if (hfinfo->type == FT_BOOLEAN) {
10836 return hfinfo->display; /* hacky? :) */
10839 return hfinfo_type_bitwidth(hfinfo->type);
10842 static int
10843 hfinfo_hex_digits(const header_field_info *hfinfo)
10845 int bitwidth;
10847 /* If we have a bitmask, hfinfo->type is the width of the container, so not
10848 * appropriate to determine the number of hex digits for the field.
10849 * So instead, we compute it from the bitmask.
10851 if (hfinfo->bitmask != 0) {
10852 bitwidth = hfinfo_mask_bitwidth(hfinfo);
10853 } else {
10854 bitwidth = hfinfo_type_bitwidth(hfinfo->type);
10857 /* Divide by 4, rounding up, to get number of hex digits. */
10858 return (bitwidth + 3) / 4;
10861 const char *
10862 hfinfo_char_value_format_display(int display, char buf[7], uint32_t value)
10864 char *ptr = &buf[6];
10865 static const char hex_digits[16] =
10866 { '0', '1', '2', '3', '4', '5', '6', '7',
10867 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
10869 *ptr = '\0';
10870 *(--ptr) = '\'';
10871 /* Properly format value */
10872 if (g_ascii_isprint(value)) {
10874 * Printable, so just show the character, and, if it needs
10875 * to be escaped, escape it.
10877 *(--ptr) = value;
10878 if (value == '\\' || value == '\'')
10879 *(--ptr) = '\\';
10880 } else {
10882 * Non-printable; show it as an escape sequence.
10884 switch (value) {
10886 case '\0':
10888 * Show a NUL with only one digit.
10890 *(--ptr) = '0';
10891 break;
10893 case '\a':
10894 *(--ptr) = 'a';
10895 break;
10897 case '\b':
10898 *(--ptr) = 'b';
10899 break;
10901 case '\f':
10902 *(--ptr) = 'f';
10903 break;
10905 case '\n':
10906 *(--ptr) = 'n';
10907 break;
10909 case '\r':
10910 *(--ptr) = 'r';
10911 break;
10913 case '\t':
10914 *(--ptr) = 't';
10915 break;
10917 case '\v':
10918 *(--ptr) = 'v';
10919 break;
10921 default:
10922 switch (FIELD_DISPLAY(display)) {
10924 case BASE_OCT:
10925 *(--ptr) = (value & 0x7) + '0';
10926 value >>= 3;
10927 *(--ptr) = (value & 0x7) + '0';
10928 value >>= 3;
10929 *(--ptr) = (value & 0x7) + '0';
10930 break;
10932 case BASE_HEX:
10933 *(--ptr) = hex_digits[value & 0x0F];
10934 value >>= 4;
10935 *(--ptr) = hex_digits[value & 0x0F];
10936 *(--ptr) = 'x';
10937 break;
10939 default:
10940 REPORT_DISSECTOR_BUG("Invalid base: %d", FIELD_DISPLAY(display));
10943 *(--ptr) = '\\';
10945 *(--ptr) = '\'';
10946 return ptr;
10949 static const char *
10950 hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[NUMBER_LABEL_LENGTH], uint32_t value)
10952 char *ptr = &buf[NUMBER_LABEL_LENGTH-1];
10953 bool isint = FT_IS_INT(hfinfo->type);
10955 *ptr = '\0';
10956 /* Properly format value */
10957 switch (FIELD_DISPLAY(display)) {
10958 case BASE_DEC:
10959 return isint ? int_to_str_back(ptr, (int32_t) value) : uint_to_str_back(ptr, value);
10961 case BASE_DEC_HEX:
10962 *(--ptr) = ')';
10963 ptr = hex_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
10964 *(--ptr) = '(';
10965 *(--ptr) = ' ';
10966 ptr = isint ? int_to_str_back(ptr, (int32_t) value) : uint_to_str_back(ptr, value);
10967 return ptr;
10969 case BASE_OCT:
10970 return oct_to_str_back(ptr, value);
10972 case BASE_HEX:
10973 return hex_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
10975 case BASE_HEX_DEC:
10976 *(--ptr) = ')';
10977 ptr = isint ? int_to_str_back(ptr, (int32_t) value) : uint_to_str_back(ptr, value);
10978 *(--ptr) = '(';
10979 *(--ptr) = ' ';
10980 ptr = hex_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
10981 return ptr;
10983 case BASE_PT_UDP:
10984 case BASE_PT_TCP:
10985 case BASE_PT_DCCP:
10986 case BASE_PT_SCTP:
10987 port_with_resolution_to_str_buf(buf, NUMBER_LABEL_LENGTH,
10988 display_to_port_type((field_display_e)display), value);
10989 return buf;
10990 case BASE_OUI:
10992 uint8_t p_oui[3];
10993 const char *manuf_name;
10995 p_oui[0] = value >> 16 & 0xFF;
10996 p_oui[1] = value >> 8 & 0xFF;
10997 p_oui[2] = value & 0xFF;
10999 /* Attempt an OUI lookup. */
11000 manuf_name = uint_get_manuf_name_if_known(value);
11001 if (manuf_name == NULL) {
11002 /* Could not find an OUI. */
11003 snprintf(buf, NUMBER_LABEL_LENGTH, "%02x:%02x:%02x", p_oui[0], p_oui[1], p_oui[2]);
11005 else {
11006 /* Found an address string. */
11007 snprintf(buf, NUMBER_LABEL_LENGTH, "%02x:%02x:%02x (%s)", p_oui[0], p_oui[1], p_oui[2], manuf_name);
11009 return buf;
11012 default:
11013 REPORT_DISSECTOR_BUG("Invalid base: %d", FIELD_DISPLAY(display));
11015 return ptr;
11018 static const char *
11019 hfinfo_number_value_format_display64(const header_field_info *hfinfo, int display, char buf[NUMBER_LABEL_LENGTH], uint64_t value)
11021 char *ptr = &buf[NUMBER_LABEL_LENGTH-1];
11022 bool isint = FT_IS_INT(hfinfo->type);
11024 *ptr = '\0';
11025 /* Properly format value */
11026 switch (FIELD_DISPLAY(display)) {
11027 case BASE_DEC:
11028 return isint ? int64_to_str_back(ptr, (int64_t) value) : uint64_to_str_back(ptr, value);
11030 case BASE_DEC_HEX:
11031 *(--ptr) = ')';
11032 ptr = hex64_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
11033 *(--ptr) = '(';
11034 *(--ptr) = ' ';
11035 ptr = isint ? int64_to_str_back(ptr, (int64_t) value) : uint64_to_str_back(ptr, value);
11036 return ptr;
11038 case BASE_OCT:
11039 return oct64_to_str_back(ptr, value);
11041 case BASE_HEX:
11042 return hex64_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
11044 case BASE_HEX_DEC:
11045 *(--ptr) = ')';
11046 ptr = isint ? int64_to_str_back(ptr, (int64_t) value) : uint64_to_str_back(ptr, value);
11047 *(--ptr) = '(';
11048 *(--ptr) = ' ';
11049 ptr = hex64_to_str_back_len(ptr, value, hfinfo_hex_digits(hfinfo));
11050 return ptr;
11052 default:
11053 REPORT_DISSECTOR_BUG("Invalid base: %d", FIELD_DISPLAY(display));
11056 return ptr;
11059 static const char *
11060 hfinfo_number_value_format(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint32_t value)
11062 int display = hfinfo->display;
11064 if (hfinfo->type == FT_FRAMENUM) {
11066 * Frame numbers are always displayed in decimal.
11068 display = BASE_DEC;
11071 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
11074 static const char *
11075 hfinfo_number_value_format64(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint64_t value)
11077 int display = hfinfo->display;
11079 if (hfinfo->type == FT_FRAMENUM) {
11081 * Frame numbers are always displayed in decimal.
11083 display = BASE_DEC;
11086 return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
11089 static const char *
11090 hfinfo_char_value_format(const header_field_info *hfinfo, char buf[32], uint32_t value)
11092 /* Get the underlying BASE_ value */
11093 int display = FIELD_DISPLAY(hfinfo->display);
11095 return hfinfo_char_value_format_display(display, buf, value);
11098 static const char *
11099 hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint32_t value)
11101 /* Get the underlying BASE_ value */
11102 int display = FIELD_DISPLAY(hfinfo->display);
11104 if (hfinfo->type == FT_FRAMENUM) {
11106 * Frame numbers are always displayed in decimal.
11108 display = BASE_DEC;
11111 if (IS_BASE_PORT(display)) {
11112 display = BASE_DEC;
11113 } else if (display == BASE_OUI) {
11114 display = BASE_HEX;
11117 switch (display) {
11118 case BASE_NONE:
11119 /* case BASE_DEC: */
11120 case BASE_DEC_HEX:
11121 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
11122 case BASE_CUSTOM:
11123 display = BASE_DEC;
11124 break;
11126 /* case BASE_HEX: */
11127 case BASE_HEX_DEC:
11128 display = BASE_HEX;
11129 break;
11132 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
11135 static const char *
11136 hfinfo_numeric_value_format64(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint64_t value)
11138 /* Get the underlying BASE_ value */
11139 int display = FIELD_DISPLAY(hfinfo->display);
11141 if (hfinfo->type == FT_FRAMENUM) {
11143 * Frame numbers are always displayed in decimal.
11145 display = BASE_DEC;
11148 switch (display) {
11149 case BASE_NONE:
11150 /* case BASE_DEC: */
11151 case BASE_DEC_HEX:
11152 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
11153 case BASE_CUSTOM:
11154 display = BASE_DEC;
11155 break;
11157 /* case BASE_HEX: */
11158 case BASE_HEX_DEC:
11159 display = BASE_HEX;
11160 break;
11163 return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
11166 static const char *
11167 hfinfo_char_vals_format(const header_field_info *hfinfo, char buf[32], uint32_t value)
11169 /* Get the underlying BASE_ value */
11170 int display = FIELD_DISPLAY(hfinfo->display);
11172 return hfinfo_char_value_format_display(display, buf, value);
11175 static const char *
11176 hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint32_t value)
11178 /* Get the underlying BASE_ value */
11179 int display = FIELD_DISPLAY(hfinfo->display);
11181 if (display == BASE_NONE)
11182 return NULL;
11184 if (display == BASE_DEC_HEX)
11185 display = BASE_DEC;
11186 if (display == BASE_HEX_DEC)
11187 display = BASE_HEX;
11189 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
11192 static const char *
11193 hfinfo_number_vals_format64(const header_field_info *hfinfo, char buf[NUMBER_LABEL_LENGTH], uint64_t value)
11195 /* Get the underlying BASE_ value */
11196 int display = FIELD_DISPLAY(hfinfo->display);
11198 if (display == BASE_NONE)
11199 return NULL;
11201 if (display == BASE_DEC_HEX)
11202 display = BASE_DEC;
11203 if (display == BASE_HEX_DEC)
11204 display = BASE_HEX;
11206 return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
11209 const char *
11210 proto_registrar_get_name(const int n)
11212 header_field_info *hfinfo;
11214 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
11215 return hfinfo->name;
11218 const char *
11219 proto_registrar_get_abbrev(const int n)
11221 header_field_info *hfinfo;
11223 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
11224 return hfinfo->abbrev;
11227 enum ftenum
11228 proto_registrar_get_ftype(const int n)
11230 header_field_info *hfinfo;
11232 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
11233 return hfinfo->type;
11237 proto_registrar_get_parent(const int n)
11239 header_field_info *hfinfo;
11241 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
11242 return hfinfo->parent;
11245 bool
11246 proto_registrar_is_protocol(const int n)
11248 header_field_info *hfinfo;
11250 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
11251 return (((hfinfo->id != hf_text_only) && (hfinfo->parent == -1)) ? true : false);
11254 /* Returns length of field in packet (not necessarily the length
11255 * in our internal representation, as in the case of IPv4).
11256 * 0 means undeterminable at time of registration
11257 * -1 means the field is not registered. */
11259 proto_registrar_get_length(const int n)
11261 header_field_info *hfinfo;
11263 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
11264 return ftype_wire_size(hfinfo->type);
11267 /* Looks for a protocol or a field in a proto_tree. Returns true if
11268 * it exists anywhere, or false if it exists nowhere. */
11269 bool
11270 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
11272 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
11274 if (g_ptr_array_len(ptrs) > 0) {
11275 return true;
11277 else {
11278 return false;
11282 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
11283 * This only works if the hfindex was "primed" before the dissection
11284 * took place, as we just pass back the already-created GPtrArray*.
11285 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
11286 * handles that. */
11287 GPtrArray *
11288 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
11290 if (!tree)
11291 return NULL;
11293 if (PTREE_DATA(tree)->interesting_hfids != NULL)
11294 return (GPtrArray *)g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
11295 GINT_TO_POINTER(id));
11296 else
11297 return NULL;
11300 bool
11301 proto_tracking_interesting_fields(const proto_tree *tree)
11303 GHashTable *interesting_hfids;
11305 if (!tree)
11306 return false;
11308 interesting_hfids = PTREE_DATA(tree)->interesting_hfids;
11310 return (interesting_hfids != NULL) && g_hash_table_size(interesting_hfids);
11313 /* Helper struct for proto_find_info() and proto_all_finfos() */
11314 typedef struct {
11315 GPtrArray *array;
11316 int id;
11317 } ffdata_t;
11319 /* Helper function for proto_find_info() */
11320 static bool
11321 find_finfo(proto_node *node, void * data)
11323 field_info *fi = PNODE_FINFO(node);
11324 if (fi && fi->hfinfo) {
11325 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
11326 g_ptr_array_add(((ffdata_t*)data)->array, fi);
11330 /* Don't stop traversing. */
11331 return false;
11334 /* Helper function for proto_find_first_info() */
11335 static bool
11336 find_first_finfo(proto_node *node, void *data)
11338 field_info *fi = PNODE_FINFO(node);
11339 if (fi && fi->hfinfo) {
11340 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
11341 g_ptr_array_add(((ffdata_t*)data)->array, fi);
11343 /* Stop traversing. */
11344 return true;
11348 /* Continue traversing. */
11349 return false;
11352 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
11353 * This works on any proto_tree, primed or unprimed, but actually searches
11354 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
11355 * The caller does need to free the returned GPtrArray with
11356 * g_ptr_array_free(<array>, true).
11358 GPtrArray *
11359 proto_find_finfo(proto_tree *tree, const int id)
11361 ffdata_t ffdata;
11363 ffdata.array = g_ptr_array_new();
11364 ffdata.id = id;
11366 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
11368 return ffdata.array;
11371 /* Return GPtrArray* of first field_info pointers for the searched hfindex that appear in a tree.
11372 * This works on any proto_tree, primed or unprimed, but actually searches
11373 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
11374 * The caller does need to free the returned GPtrArray with
11375 * g_ptr_array_free(<array>, true).
11377 GPtrArray *
11378 proto_find_first_finfo(proto_tree *tree, const int id)
11380 ffdata_t ffdata;
11382 ffdata.array = g_ptr_array_new();
11383 ffdata.id = id;
11385 proto_tree_traverse_pre_order(tree, find_first_finfo, &ffdata);
11387 return ffdata.array;
11390 /* Helper function for proto_all_finfos() */
11391 static bool
11392 every_finfo(proto_node *node, void * data)
11394 field_info *fi = PNODE_FINFO(node);
11395 if (fi && fi->hfinfo) {
11396 g_ptr_array_add(((ffdata_t*)data)->array, fi);
11399 /* Don't stop traversing. */
11400 return false;
11403 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree.
11404 * The caller does need to free the returned GPtrArray with
11405 * g_ptr_array_free(<array>, true).
11407 GPtrArray *
11408 proto_all_finfos(proto_tree *tree)
11410 ffdata_t ffdata;
11412 /* Pre allocate enough space to hold all fields in most cases */
11413 ffdata.array = g_ptr_array_sized_new(512);
11414 ffdata.id = 0;
11416 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
11418 return ffdata.array;
11422 typedef struct {
11423 unsigned offset;
11424 field_info *finfo;
11425 tvbuff_t *tvb;
11426 } offset_search_t;
11428 static bool
11429 check_for_offset(proto_node *node, void * data)
11431 field_info *fi = PNODE_FINFO(node);
11432 offset_search_t *offsearch = (offset_search_t *)data;
11434 /* !fi == the top most container node which holds nothing */
11435 if (fi && !proto_item_is_hidden(node) && !proto_item_is_generated(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
11436 if (offsearch->offset >= (unsigned) fi->start &&
11437 offsearch->offset < (unsigned) (fi->start + fi->length)) {
11439 offsearch->finfo = fi;
11440 return false; /* keep traversing */
11443 return false; /* keep traversing */
11446 /* Search a proto_tree backwards (from leaves to root) looking for the field
11447 * whose start/length occupies 'offset' */
11448 /* XXX - I couldn't find an easy way to search backwards, so I search
11449 * forwards, w/o stopping. Therefore, the last finfo I find will the be
11450 * the one I want to return to the user. This algorithm is inefficient
11451 * and could be re-done, but I'd have to handle all the children and
11452 * siblings of each node myself. When I have more time I'll do that.
11453 * (yeah right) */
11454 field_info *
11455 proto_find_field_from_offset(proto_tree *tree, unsigned offset, tvbuff_t *tvb)
11457 offset_search_t offsearch;
11459 offsearch.offset = offset;
11460 offsearch.finfo = NULL;
11461 offsearch.tvb = tvb;
11463 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
11465 return offsearch.finfo;
11468 typedef struct {
11469 int length;
11470 char *buf;
11471 } decoded_data_t;
11473 static bool
11474 check_for_undecoded(proto_node *node, void * data)
11476 field_info *fi = PNODE_FINFO(node);
11477 decoded_data_t* decoded = (decoded_data_t*)data;
11478 int i;
11479 unsigned byte;
11480 unsigned bit;
11482 if (fi && fi->hfinfo->type != FT_PROTOCOL) {
11483 for (i = fi->start; i < fi->start + fi->length && i < decoded->length; i++) {
11484 byte = i / 8;
11485 bit = i % 8;
11486 decoded->buf[byte] |= (1 << bit);
11490 return false;
11493 char*
11494 proto_find_undecoded_data(proto_tree *tree, unsigned length)
11496 decoded_data_t decoded;
11497 decoded.length = length;
11498 decoded.buf = (char*)wmem_alloc0(PNODE_POOL(tree), length / 8 + 1);
11500 proto_tree_traverse_pre_order(tree, check_for_undecoded, &decoded);
11501 return decoded.buf;
11504 /* Dumps the protocols in the registration database to stdout. An independent
11505 * program can take this output and format it into nice tables or HTML or
11506 * whatever.
11508 * There is one record per line. The fields are tab-delimited.
11510 * Field 1 = protocol name
11511 * Field 2 = protocol short name
11512 * Field 3 = protocol filter name
11513 * Field 4 = protocol enabled
11514 * Field 5 = protocol enabled by default
11515 * Field 6 = protocol can toggle
11517 void
11518 proto_registrar_dump_protocols(void)
11520 protocol_t *protocol;
11521 int i;
11522 void *cookie = NULL;
11525 i = proto_get_first_protocol(&cookie);
11526 while (i != -1) {
11527 protocol = find_protocol_by_id(i);
11528 printf("%s\t%s\t%s\t%c\t%c\t%c\n",
11529 protocol->name,
11530 protocol->short_name,
11531 protocol->filter_name,
11532 (proto_is_protocol_enabled_by_default(protocol) ? 'T' : 'F'),
11533 (proto_is_protocol_enabled(protocol) ? 'T' : 'F'),
11534 (proto_can_toggle_protocol(protocol->proto_id) ? 'T' : 'F'));
11535 i = proto_get_next_protocol(&cookie);
11539 /* Dumps the value_strings, extended value string headers, range_strings
11540 * or true/false strings for fields that have them.
11541 * There is one record per line. Fields are tab-delimited.
11542 * There are four types of records: Value String, Extended Value String Header,
11543 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
11544 * the type of record.
11546 * Note that a record will be generated only if the value_string,... is referenced
11547 * in a registered hfinfo entry.
11550 * Value Strings
11551 * -------------
11552 * Field 1 = 'V'
11553 * Field 2 = Field abbreviation to which this value string corresponds
11554 * Field 3 = Integer value
11555 * Field 4 = String
11557 * Extended Value String Headers
11558 * -----------------------------
11559 * Field 1 = 'E'
11560 * Field 2 = Field abbreviation to which this extended value string header corresponds
11561 * Field 3 = Extended Value String "Name"
11562 * Field 4 = Number of entries in the associated value_string array
11563 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
11565 * Range Strings
11566 * -------------
11567 * Field 1 = 'R'
11568 * Field 2 = Field abbreviation to which this range string corresponds
11569 * Field 3 = Integer value: lower bound
11570 * Field 4 = Integer value: upper bound
11571 * Field 5 = String
11573 * True/False Strings
11574 * ------------------
11575 * Field 1 = 'T'
11576 * Field 2 = Field abbreviation to which this true/false string corresponds
11577 * Field 3 = True String
11578 * Field 4 = False String
11580 void
11581 proto_registrar_dump_values(void)
11583 header_field_info *hfinfo;
11584 int i, len, vi;
11585 const value_string *vals;
11586 const val64_string *vals64;
11587 const range_string *range;
11588 const true_false_string *tfs;
11589 const unit_name_string *units;
11591 len = gpa_hfinfo.len;
11592 for (i = 0; i < len ; i++) {
11593 if (gpa_hfinfo.hfi[i] == NULL)
11594 continue; /* This is a deregistered protocol or field */
11596 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
11598 if (hfinfo->id == hf_text_only) {
11599 continue;
11602 /* ignore protocols */
11603 if (proto_registrar_is_protocol(i)) {
11604 continue;
11606 /* process header fields */
11607 #if 0 /* XXX: We apparently allow fields with the same name but with differing "strings" content */
11609 * If this field isn't at the head of the list of
11610 * fields with this name, skip this field - all
11611 * fields with the same name are really just versions
11612 * of the same field stored in different bits, and
11613 * should have the same type/radix/value list, and
11614 * just differ in their bit masks. (If a field isn't
11615 * a bitfield, but can be, say, 1 or 2 bytes long,
11616 * it can just be made FT_UINT16, meaning the
11617 * *maximum* length is 2 bytes, and be used
11618 * for all lengths.)
11620 if (hfinfo->same_name_prev_id != -1)
11621 continue;
11622 #endif
11623 vals = NULL;
11624 vals64 = NULL;
11625 range = NULL;
11626 tfs = NULL;
11627 units = NULL;
11629 if (hfinfo->strings != NULL) {
11630 if (FIELD_DISPLAY(hfinfo->display) != BASE_CUSTOM &&
11631 (hfinfo->type == FT_CHAR ||
11632 hfinfo->type == FT_UINT8 ||
11633 hfinfo->type == FT_UINT16 ||
11634 hfinfo->type == FT_UINT24 ||
11635 hfinfo->type == FT_UINT32 ||
11636 hfinfo->type == FT_UINT40 ||
11637 hfinfo->type == FT_UINT48 ||
11638 hfinfo->type == FT_UINT56 ||
11639 hfinfo->type == FT_UINT64 ||
11640 hfinfo->type == FT_INT8 ||
11641 hfinfo->type == FT_INT16 ||
11642 hfinfo->type == FT_INT24 ||
11643 hfinfo->type == FT_INT32 ||
11644 hfinfo->type == FT_INT40 ||
11645 hfinfo->type == FT_INT48 ||
11646 hfinfo->type == FT_INT56 ||
11647 hfinfo->type == FT_INT64 ||
11648 hfinfo->type == FT_FLOAT ||
11649 hfinfo->type == FT_DOUBLE)) {
11651 if (hfinfo->display & BASE_RANGE_STRING) {
11652 range = (const range_string *)hfinfo->strings;
11653 } else if (hfinfo->display & BASE_EXT_STRING) {
11654 if (hfinfo->display & BASE_VAL64_STRING) {
11655 vals64 = VAL64_STRING_EXT_VS_P((const val64_string_ext *)hfinfo->strings);
11656 } else {
11657 vals = VALUE_STRING_EXT_VS_P((const value_string_ext *)hfinfo->strings);
11659 } else if (hfinfo->display & BASE_VAL64_STRING) {
11660 vals64 = (const val64_string *)hfinfo->strings;
11661 } else if (hfinfo->display & BASE_UNIT_STRING) {
11662 units = (const unit_name_string *)hfinfo->strings;
11663 } else {
11664 vals = (const value_string *)hfinfo->strings;
11667 else if (hfinfo->type == FT_BOOLEAN) {
11668 tfs = (const struct true_false_string *)hfinfo->strings;
11672 /* Print value strings? */
11673 if (vals) {
11674 if (hfinfo->display & BASE_EXT_STRING) {
11675 if (hfinfo->display & BASE_VAL64_STRING) {
11676 val64_string_ext *vse_p = (val64_string_ext *)hfinfo->strings;
11677 if (!val64_string_ext_validate(vse_p)) {
11678 ws_warning("Invalid val64_string_ext ptr for: %s", hfinfo->abbrev);
11679 continue;
11681 try_val64_to_str_ext(0, vse_p); /* "prime" the extended val64_string */
11682 printf("E\t%s\t%u\t%s\t%s\n",
11683 hfinfo->abbrev,
11684 VAL64_STRING_EXT_VS_NUM_ENTRIES(vse_p),
11685 VAL64_STRING_EXT_VS_NAME(vse_p),
11686 val64_string_ext_match_type_str(vse_p));
11687 } else {
11688 value_string_ext *vse_p = (value_string_ext *)hfinfo->strings;
11689 if (!value_string_ext_validate(vse_p)) {
11690 ws_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
11691 continue;
11693 try_val_to_str_ext(0, vse_p); /* "prime" the extended value_string */
11694 printf("E\t%s\t%u\t%s\t%s\n",
11695 hfinfo->abbrev,
11696 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
11697 VALUE_STRING_EXT_VS_NAME(vse_p),
11698 value_string_ext_match_type_str(vse_p));
11701 vi = 0;
11702 while (vals[vi].strptr) {
11703 /* Print in the proper base */
11704 if (hfinfo->type == FT_CHAR) {
11705 if (g_ascii_isprint(vals[vi].value)) {
11706 printf("V\t%s\t'%c'\t%s\n",
11707 hfinfo->abbrev,
11708 vals[vi].value,
11709 vals[vi].strptr);
11710 } else {
11711 if (hfinfo->display == BASE_HEX) {
11712 printf("V\t%s\t'\\x%02x'\t%s\n",
11713 hfinfo->abbrev,
11714 vals[vi].value,
11715 vals[vi].strptr);
11717 else {
11718 printf("V\t%s\t'\\%03o'\t%s\n",
11719 hfinfo->abbrev,
11720 vals[vi].value,
11721 vals[vi].strptr);
11724 } else {
11725 if (hfinfo->display == BASE_HEX) {
11726 printf("V\t%s\t0x%x\t%s\n",
11727 hfinfo->abbrev,
11728 vals[vi].value,
11729 vals[vi].strptr);
11731 else {
11732 printf("V\t%s\t%u\t%s\n",
11733 hfinfo->abbrev,
11734 vals[vi].value,
11735 vals[vi].strptr);
11738 vi++;
11741 else if (vals64) {
11742 vi = 0;
11743 while (vals64[vi].strptr) {
11744 printf("V64\t%s\t%" PRIu64 "\t%s\n",
11745 hfinfo->abbrev,
11746 vals64[vi].value,
11747 vals64[vi].strptr);
11748 vi++;
11752 /* print range strings? */
11753 else if (range) {
11754 vi = 0;
11755 while (range[vi].strptr) {
11756 /* Print in the proper base */
11757 if (FIELD_DISPLAY(hfinfo->display) == BASE_HEX) {
11758 printf("R\t%s\t0x%"PRIx64"\t0x%"PRIx64"\t%s\n",
11759 hfinfo->abbrev,
11760 range[vi].value_min,
11761 range[vi].value_max,
11762 range[vi].strptr);
11764 else {
11765 printf("R\t%s\t%"PRIu64"\t%"PRIu64"\t%s\n",
11766 hfinfo->abbrev,
11767 range[vi].value_min,
11768 range[vi].value_max,
11769 range[vi].strptr);
11771 vi++;
11775 /* Print true/false strings? */
11776 else if (tfs) {
11777 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
11778 tfs->true_string, tfs->false_string);
11780 /* Print unit strings? */
11781 else if (units) {
11782 printf("U\t%s\t%s\t%s\n", hfinfo->abbrev,
11783 units->singular, units->plural ? units->plural : "(no plural)");
11788 /* Prints the number of registered fields.
11789 * Useful for determining an appropriate value for
11790 * PROTO_PRE_ALLOC_HF_FIELDS_MEM.
11792 * Returns false if PROTO_PRE_ALLOC_HF_FIELDS_MEM is larger than or equal to
11793 * the number of fields, true otherwise.
11795 bool
11796 proto_registrar_dump_fieldcount(void)
11798 uint32_t i;
11799 header_field_info *hfinfo;
11800 uint32_t deregistered_count = 0;
11801 uint32_t same_name_count = 0;
11802 uint32_t protocol_count = 0;
11804 for (i = 0; i < gpa_hfinfo.len; i++) {
11805 if (gpa_hfinfo.hfi[i] == NULL) {
11806 deregistered_count++;
11807 continue; /* This is a deregistered protocol or header field */
11810 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
11812 if (proto_registrar_is_protocol(i))
11813 protocol_count++;
11815 if (hfinfo->same_name_prev_id != -1)
11816 same_name_count++;
11819 printf("There are %u header fields registered, of which:\n"
11820 "\t%u are deregistered\n"
11821 "\t%u are protocols\n"
11822 "\t%u have the same name as another field\n\n",
11823 gpa_hfinfo.len, deregistered_count, protocol_count,
11824 same_name_count);
11826 printf("%d fields were pre-allocated.\n%s", PROTO_PRE_ALLOC_HF_FIELDS_MEM,
11827 (gpa_hfinfo.allocated_len > PROTO_PRE_ALLOC_HF_FIELDS_MEM) ?
11828 "* * Please increase PROTO_PRE_ALLOC_HF_FIELDS_MEM (in epan/proto.c)! * *\n\n" :
11829 "\n");
11831 printf("The header field table consumes %u KiB of memory.\n",
11832 (unsigned int)(gpa_hfinfo.allocated_len * sizeof(header_field_info *) / 1024));
11833 printf("The fields themselves consume %u KiB of memory.\n",
11834 (unsigned int)(gpa_hfinfo.len * sizeof(header_field_info) / 1024));
11836 return (gpa_hfinfo.allocated_len > PROTO_PRE_ALLOC_HF_FIELDS_MEM);
11839 static void
11840 elastic_add_base_mapping(json_dumper *dumper)
11842 json_dumper_set_member_name(dumper, "settings");
11843 json_dumper_begin_object(dumper);
11844 json_dumper_set_member_name(dumper, "index.mapping.total_fields.limit");
11845 json_dumper_value_anyf(dumper, "%d", 1000000);
11846 json_dumper_end_object(dumper);
11849 static char*
11850 ws_type_to_elastic(unsigned type _U_)
11852 switch(type) {
11853 case FT_UINT16:
11854 case FT_INT16:
11855 case FT_INT32:
11856 case FT_UINT24:
11857 case FT_INT24:
11858 return "integer";
11859 case FT_INT8:
11860 case FT_UINT8:
11861 return "short";
11862 case FT_FRAMENUM:
11863 case FT_UINT32:
11864 case FT_UINT40:
11865 case FT_UINT48:
11866 case FT_UINT56:
11867 case FT_UINT64: // Actually it's not handled by 'long' elastic type.
11868 case FT_INT48:
11869 case FT_INT64:
11870 return "long";
11871 case FT_FLOAT:
11872 case FT_DOUBLE:
11873 return "float";
11874 case FT_IPv6:
11875 case FT_IPv4:
11876 return "ip";
11877 case FT_ABSOLUTE_TIME:
11878 case FT_RELATIVE_TIME:
11879 return "date";
11880 case FT_BYTES:
11881 case FT_UINT_BYTES:
11882 return "byte";
11883 case FT_BOOLEAN:
11884 return "boolean";
11885 default:
11886 return NULL;
11890 static char*
11891 dot_to_underscore(char* str)
11893 unsigned i;
11894 for (i = 0; i < strlen(str); i++) {
11895 if (str[i] == '.')
11896 str[i] = '_';
11898 return str;
11901 /* Dumps a mapping file for ElasticSearch
11903 void
11904 proto_registrar_dump_elastic(const char* filter)
11906 header_field_info *hfinfo;
11907 header_field_info *parent_hfinfo;
11908 unsigned i;
11909 bool open_object = true;
11910 const char* prev_proto = NULL;
11911 char* str;
11912 char** protos = NULL;
11913 char* proto;
11914 bool found;
11915 unsigned j;
11916 char* type;
11917 char* prev_item = NULL;
11919 /* We have filtering protocols. Extract them. */
11920 if (filter) {
11921 protos = g_strsplit(filter, ",", -1);
11925 * To help tracking down the json tree, objects have been appended with a comment:
11926 * n.label -> where n is the indentation level and label the name of the object
11929 json_dumper dumper = {
11930 .output_file = stdout,
11931 .flags = JSON_DUMPER_FLAGS_PRETTY_PRINT,
11933 json_dumper_begin_object(&dumper); // 1.root
11934 elastic_add_base_mapping(&dumper);
11936 json_dumper_set_member_name(&dumper, "mappings");
11937 json_dumper_begin_object(&dumper); // 2.mappings
11938 json_dumper_set_member_name(&dumper, "dynamic");
11939 json_dumper_value_anyf(&dumper, "false");
11941 json_dumper_set_member_name(&dumper, "properties");
11942 json_dumper_begin_object(&dumper); // 3.properties
11943 json_dumper_set_member_name(&dumper, "timestamp");
11944 json_dumper_begin_object(&dumper); // 4.timestamp
11945 json_dumper_set_member_name(&dumper, "type");
11946 json_dumper_value_string(&dumper, "date");
11947 json_dumper_end_object(&dumper); // 4.timestamp
11949 json_dumper_set_member_name(&dumper, "layers");
11950 json_dumper_begin_object(&dumper); // 4.layers
11951 json_dumper_set_member_name(&dumper, "properties");
11952 json_dumper_begin_object(&dumper); // 5.properties
11954 for (i = 0; i < gpa_hfinfo.len; i++) {
11955 if (gpa_hfinfo.hfi[i] == NULL)
11956 continue; /* This is a deregistered protocol or header field */
11958 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
11961 * Skip the pseudo-field for "proto_tree_add_text()" since
11962 * we don't want it in the list of filterable protocols.
11964 if (hfinfo->id == hf_text_only)
11965 continue;
11967 if (!proto_registrar_is_protocol(i)) {
11968 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
11971 * Skip the field if filter protocols have been set and this one's
11972 * parent is not listed.
11974 if (protos) {
11975 found = false;
11976 j = 0;
11977 proto = protos[0];
11978 while(proto) {
11979 if (!g_strcmp0(proto, parent_hfinfo->abbrev)) {
11980 found = true;
11981 break;
11983 j++;
11984 proto = protos[j];
11986 if (!found)
11987 continue;
11990 if (prev_proto && g_strcmp0(parent_hfinfo->abbrev, prev_proto)) {
11991 json_dumper_end_object(&dumper); // 7.properties
11992 json_dumper_end_object(&dumper); // 8.parent_hfinfo->abbrev
11993 open_object = true;
11996 prev_proto = parent_hfinfo->abbrev;
11998 if (open_object) {
11999 json_dumper_set_member_name(&dumper, parent_hfinfo->abbrev);
12000 json_dumper_begin_object(&dumper); // 6.parent_hfinfo->abbrev
12001 json_dumper_set_member_name(&dumper, "properties");
12002 json_dumper_begin_object(&dumper); // 7.properties
12003 open_object = false;
12005 /* Skip the fields that would map into string. This is the default in elasticsearch. */
12006 type = ws_type_to_elastic(hfinfo->type);
12007 /* when type is NULL, we have the default mapping: string */
12008 if (type) {
12009 str = ws_strdup_printf("%s_%s", prev_proto, hfinfo->abbrev);
12010 dot_to_underscore(str);
12011 if (g_strcmp0(prev_item, str)) {
12012 json_dumper_set_member_name(&dumper, str);
12013 json_dumper_begin_object(&dumper); // 8.hfinfo->abbrev
12014 json_dumper_set_member_name(&dumper, "type");
12015 json_dumper_value_string(&dumper, type);
12016 json_dumper_end_object(&dumper); // 8.hfinfo->abbrev
12018 g_free(prev_item);
12019 prev_item = str;
12023 g_free(prev_item);
12025 if (prev_proto) {
12026 json_dumper_end_object(&dumper); // 7.properties
12027 json_dumper_end_object(&dumper); // 6.parent_hfinfo->abbrev
12030 json_dumper_end_object(&dumper); // 5.properties
12031 json_dumper_end_object(&dumper); // 4.layers
12032 json_dumper_end_object(&dumper); // 3.properties
12033 json_dumper_end_object(&dumper); // 2.mappings
12034 json_dumper_end_object(&dumper); // 1.root
12035 bool ret = json_dumper_finish(&dumper);
12036 DISSECTOR_ASSERT(ret);
12038 g_strfreev(protos);
12041 /* Dumps the contents of the registration database to stdout. An independent
12042 * program can take this output and format it into nice tables or HTML or
12043 * whatever.
12045 * There is one record per line. Each record is either a protocol or a header
12046 * field, differentiated by the first field. The fields are tab-delimited.
12048 * Protocols
12049 * ---------
12050 * Field 1 = 'P'
12051 * Field 2 = descriptive protocol name
12052 * Field 3 = protocol abbreviation
12054 * Header Fields
12055 * -------------
12056 * Field 1 = 'F'
12057 * Field 2 = descriptive field name
12058 * Field 3 = field abbreviation
12059 * Field 4 = type ( textual representation of the ftenum type )
12060 * Field 5 = parent protocol abbreviation
12061 * Field 6 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
12062 * Field 7 = bitmask: format: hex: 0x....
12063 * Field 8 = blurb describing field
12065 void
12066 proto_registrar_dump_fields(void)
12068 header_field_info *hfinfo, *parent_hfinfo;
12069 int i, len;
12070 const char *enum_name;
12071 const char *base_name;
12072 const char *blurb;
12073 char width[5];
12075 len = gpa_hfinfo.len;
12076 for (i = 0; i < len ; i++) {
12077 if (gpa_hfinfo.hfi[i] == NULL)
12078 continue; /* This is a deregistered protocol or header field */
12080 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
12083 * Skip the pseudo-field for "proto_tree_add_text()" since
12084 * we don't want it in the list of filterable fields.
12086 if (hfinfo->id == hf_text_only)
12087 continue;
12089 /* format for protocols */
12090 if (proto_registrar_is_protocol(i)) {
12091 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
12093 /* format for header fields */
12094 else {
12096 * If this field isn't at the head of the list of
12097 * fields with this name, skip this field - all
12098 * fields with the same name are really just versions
12099 * of the same field stored in different bits, and
12100 * should have the same type/radix/value list, and
12101 * just differ in their bit masks. (If a field isn't
12102 * a bitfield, but can be, say, 1 or 2 bytes long,
12103 * it can just be made FT_UINT16, meaning the
12104 * *maximum* length is 2 bytes, and be used
12105 * for all lengths.)
12107 if (hfinfo->same_name_prev_id != -1)
12108 continue;
12110 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
12112 enum_name = ftype_name(hfinfo->type);
12113 base_name = "";
12115 if (hfinfo->type == FT_CHAR ||
12116 hfinfo->type == FT_UINT8 ||
12117 hfinfo->type == FT_UINT16 ||
12118 hfinfo->type == FT_UINT24 ||
12119 hfinfo->type == FT_UINT32 ||
12120 hfinfo->type == FT_UINT40 ||
12121 hfinfo->type == FT_UINT48 ||
12122 hfinfo->type == FT_UINT56 ||
12123 hfinfo->type == FT_UINT64 ||
12124 hfinfo->type == FT_INT8 ||
12125 hfinfo->type == FT_INT16 ||
12126 hfinfo->type == FT_INT24 ||
12127 hfinfo->type == FT_INT32 ||
12128 hfinfo->type == FT_INT40 ||
12129 hfinfo->type == FT_INT48 ||
12130 hfinfo->type == FT_INT56 ||
12131 hfinfo->type == FT_INT64) {
12133 switch (FIELD_DISPLAY(hfinfo->display)) {
12134 case BASE_NONE:
12135 case BASE_DEC:
12136 case BASE_HEX:
12137 case BASE_OCT:
12138 case BASE_DEC_HEX:
12139 case BASE_HEX_DEC:
12140 case BASE_CUSTOM:
12141 case BASE_PT_UDP:
12142 case BASE_PT_TCP:
12143 case BASE_PT_DCCP:
12144 case BASE_PT_SCTP:
12145 case BASE_OUI:
12146 base_name = val_to_str_const(FIELD_DISPLAY(hfinfo->display), hf_display, "????");
12147 break;
12148 default:
12149 base_name = "????";
12150 break;
12152 } else if (hfinfo->type == FT_BOOLEAN) {
12153 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
12154 snprintf(width, sizeof(width), "%d", hfinfo->display);
12155 base_name = width;
12158 blurb = hfinfo->blurb;
12159 if (blurb == NULL)
12160 blurb = "";
12161 else if (strlen(blurb) == 0)
12162 blurb = "\"\"";
12164 printf("F\t%s\t%s\t%s\t%s\t%s\t0x%" PRIx64 "\t%s\n",
12165 hfinfo->name, hfinfo->abbrev, enum_name,
12166 parent_hfinfo->abbrev, base_name,
12167 hfinfo->bitmask, blurb);
12172 /* Dumps all abbreviated field and protocol completions of the given string to
12173 * stdout. An independent program may use this for command-line tab completion
12174 * of fields.
12176 bool
12177 proto_registrar_dump_field_completions(const char *prefix)
12179 header_field_info *hfinfo;
12180 int i, len;
12181 size_t prefix_len;
12182 bool matched = false;
12184 prefix_len = strlen(prefix);
12185 len = gpa_hfinfo.len;
12186 for (i = 0; i < len ; i++) {
12187 if (gpa_hfinfo.hfi[i] == NULL)
12188 continue; /* This is a deregistered protocol or header field */
12190 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
12193 * Skip the pseudo-field for "proto_tree_add_text()" since
12194 * we don't want it in the list of filterable fields.
12196 if (hfinfo->id == hf_text_only)
12197 continue;
12199 /* format for protocols */
12200 if (proto_registrar_is_protocol(i)) {
12201 if(0 == strncmp(hfinfo->abbrev, prefix, prefix_len)) {
12202 matched = true;
12203 printf("%s\t%s\n", hfinfo->abbrev, hfinfo->name);
12206 /* format for header fields */
12207 else {
12209 * If this field isn't at the head of the list of
12210 * fields with this name, skip this field - all
12211 * fields with the same name are really just versions
12212 * of the same field stored in different bits, and
12213 * should have the same type/radix/value list, and
12214 * just differ in their bit masks. (If a field isn't
12215 * a bitfield, but can be, say, 1 or 2 bytes long,
12216 * it can just be made FT_UINT16, meaning the
12217 * *maximum* length is 2 bytes, and be used
12218 * for all lengths.)
12220 if (hfinfo->same_name_prev_id != -1)
12221 continue;
12223 if(0 == strncmp(hfinfo->abbrev, prefix, prefix_len)) {
12224 matched = true;
12225 printf("%s\t%s\n", hfinfo->abbrev, hfinfo->name);
12229 return matched;
12232 /* Dumps field types and descriptive names to stdout. An independent
12233 * program can take this output and format it into nice tables or HTML or
12234 * whatever.
12236 * There is one record per line. The fields are tab-delimited.
12238 * Field 1 = field type name, e.g. FT_UINT8
12239 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
12241 void
12242 proto_registrar_dump_ftypes(void)
12244 int fte;
12246 for (fte = 0; fte < FT_NUM_TYPES; fte++) {
12247 printf("%s\t%s\n", ftype_name((ftenum_t)fte), ftype_pretty_name((ftenum_t)fte));
12251 /* This function indicates whether it's possible to construct a
12252 * "match selected" display filter string for the specified field,
12253 * returns an indication of whether it's possible, and, if it's
12254 * possible and "filter" is non-null, constructs the filter and
12255 * sets "*filter" to point to it.
12256 * You do not need to [g_]free() this string since it will be automatically
12257 * freed once the next packet is dissected.
12259 static bool
12260 construct_match_selected_string(const field_info *finfo, epan_dissect_t *edt,
12261 char **filter)
12263 const header_field_info *hfinfo;
12264 char *ptr;
12265 int buf_len;
12266 int i;
12267 int start, length, length_remaining;
12268 uint8_t c;
12270 if (!finfo)
12271 return false;
12273 hfinfo = finfo->hfinfo;
12274 DISSECTOR_ASSERT(hfinfo);
12276 /* If we have BASE_NONE and strings (a non-NULL FIELDCONVERT),
12277 * then "the numeric value ... is not used when preparing
12278 * filters for the field in question." If it's any other
12279 * base, we'll generate the filter normally (which will
12280 * be numeric, even though the human-readable string does
12281 * work for filtering.)
12283 * XXX - It might be nice to use fvalue_to_string_repr() in
12284 * "proto_item_fill_label()" as well, although, there, you'd
12285 * have to deal with the base *and* with resolved values for
12286 * addresses.
12288 * Perhaps in addition to taking the repr type (DISPLAY
12289 * or DFILTER) and the display (base), fvalue_to_string_repr()
12290 * should have the the "strings" values in the header_field_info
12291 * structure for the field as a parameter, so it can have
12292 * if the field is Boolean or an enumerated integer type,
12293 * the tables used to generate human-readable values.
12295 if (hfinfo->strings && FIELD_DISPLAY(hfinfo->display) == BASE_NONE) {
12296 const char *str = NULL;
12298 switch (hfinfo->type) {
12300 case FT_INT8:
12301 case FT_INT16:
12302 case FT_INT24:
12303 case FT_INT32:
12304 str = hf_try_val_to_str(fvalue_get_sinteger(finfo->value), hfinfo);
12305 break;
12307 case FT_CHAR:
12308 case FT_UINT8:
12309 case FT_UINT16:
12310 case FT_UINT24:
12311 case FT_UINT32:
12312 str = hf_try_val_to_str(fvalue_get_uinteger(finfo->value), hfinfo);
12313 break;
12315 default:
12316 break;
12319 if (str != NULL && filter != NULL) {
12320 *filter = wmem_strdup_printf(NULL, "%s == \"%s\"", hfinfo->abbrev, str);
12321 return true;
12325 switch (hfinfo->type) {
12327 case FT_PROTOCOL:
12328 if (filter != NULL)
12329 *filter = wmem_strdup(NULL, finfo->hfinfo->abbrev);
12330 break;
12332 case FT_NONE:
12334 * If the length is 0, just match the name of the
12335 * field.
12337 * (Also check for negative values, just in case,
12338 * as we'll cast it to an unsigned value later.)
12340 length = finfo->length;
12341 if (length == 0) {
12342 if (filter != NULL)
12343 *filter = wmem_strdup(NULL, finfo->hfinfo->abbrev);
12344 break;
12346 if (length < 0)
12347 return false;
12350 * This doesn't have a value, so we'd match
12351 * on the raw bytes at this address.
12353 * Should we be allowed to access to the raw bytes?
12354 * If "edt" is NULL, the answer is "no".
12356 if (edt == NULL)
12357 return false;
12360 * Is this field part of the raw frame tvbuff?
12361 * If not, we can't use "frame[N:M]" to match
12362 * it.
12364 * XXX - should this be frame-relative, or
12365 * protocol-relative?
12367 * XXX - does this fallback for non-registered
12368 * fields even make sense?
12370 if (finfo->ds_tvb != edt->tvb)
12371 return false; /* you lose */
12374 * Don't go past the end of that tvbuff.
12376 length_remaining = tvb_captured_length_remaining(finfo->ds_tvb, finfo->start);
12377 if (length > length_remaining)
12378 length = length_remaining;
12379 if (length <= 0)
12380 return false;
12382 if (filter != NULL) {
12383 start = finfo->start;
12384 buf_len = 32 + length * 3;
12385 *filter = (char *)wmem_alloc0(NULL, buf_len);
12386 ptr = *filter;
12388 ptr += snprintf(ptr, buf_len-(ptr-*filter),
12389 "frame[%d:%d] == ", finfo->start, length);
12390 for (i=0; i<length; i++) {
12391 c = tvb_get_uint8(finfo->ds_tvb, start);
12392 start++;
12393 if (i == 0 ) {
12394 ptr += snprintf(ptr, buf_len-(ptr-*filter), "%02x", c);
12396 else {
12397 ptr += snprintf(ptr, buf_len-(ptr-*filter), ":%02x", c);
12401 break;
12403 /* By default, use the fvalue's "to_string_repr" method. */
12404 default:
12405 if (filter != NULL) {
12406 char *str = fvalue_to_string_repr(NULL, finfo->value, FTREPR_DFILTER, finfo->hfinfo->display);
12407 *filter = wmem_strdup_printf(NULL, "%s == %s", hfinfo->abbrev, str);
12408 wmem_free(NULL, str);
12410 break;
12413 return true;
12417 * Returns true if we can do a "match selected" on the field, false
12418 * otherwise.
12420 bool
12421 proto_can_match_selected(const field_info *finfo, epan_dissect_t *edt)
12423 return construct_match_selected_string(finfo, edt, NULL);
12426 /* This function attempts to construct a "match selected" display filter
12427 * string for the specified field; if it can do so, it returns a pointer
12428 * to the string, otherwise it returns NULL.
12430 * The string is wmem allocated and must be freed with "wmem_free(NULL, ...)".
12432 char *
12433 proto_construct_match_selected_string(const field_info *finfo, epan_dissect_t *edt)
12435 char *filter = NULL;
12437 if (!construct_match_selected_string(finfo, edt, &filter))
12439 wmem_free(NULL, filter);
12440 return NULL;
12442 return filter;
12445 /* This function is common code for all proto_tree_add_bitmask... functions.
12448 static bool
12449 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
12450 const int len, const int ett, int * const *fields,
12451 const int flags, bool first,
12452 bool use_parent_tree,
12453 proto_tree* tree, uint64_t value)
12455 uint64_t available_bits = UINT64_MAX;
12456 uint64_t bitmask = 0;
12457 uint64_t tmpval;
12458 header_field_info *hf;
12459 uint32_t integer32;
12460 int bit_offset;
12461 int no_of_bits;
12463 if (!*fields)
12464 REPORT_DISSECTOR_BUG("Illegal call of proto_item_add_bitmask_tree without fields");
12466 if (len < 0 || len > 8)
12467 REPORT_DISSECTOR_BUG("Invalid len: %d", len);
12469 * packet-frame.c uses len=0 since the value is taken from the packet
12470 * metadata, not the packet bytes. In that case, assume that all bits
12471 * in the provided value are valid.
12473 if (len > 0) {
12474 available_bits >>= (8 - (unsigned)len)*8;
12477 if (use_parent_tree == false)
12478 tree = proto_item_add_subtree(item, ett);
12480 while (*fields) {
12481 uint64_t present_bits;
12482 PROTO_REGISTRAR_GET_NTH(**fields,hf);
12483 DISSECTOR_ASSERT_HINT(hf->bitmask != 0, hf->abbrev);
12485 bitmask |= hf->bitmask;
12487 /* Skip fields that aren't fully present */
12488 present_bits = available_bits & hf->bitmask;
12489 if (present_bits != hf->bitmask) {
12490 fields++;
12491 continue;
12494 switch (hf->type) {
12495 case FT_CHAR:
12496 case FT_UINT8:
12497 case FT_UINT16:
12498 case FT_UINT24:
12499 case FT_UINT32:
12500 proto_tree_add_uint(tree, **fields, tvb, offset, len, (uint32_t)value);
12501 break;
12503 case FT_INT8:
12504 case FT_INT16:
12505 case FT_INT24:
12506 case FT_INT32:
12507 proto_tree_add_int(tree, **fields, tvb, offset, len, (int32_t)value);
12508 break;
12510 case FT_UINT40:
12511 case FT_UINT48:
12512 case FT_UINT56:
12513 case FT_UINT64:
12514 proto_tree_add_uint64(tree, **fields, tvb, offset, len, value);
12515 break;
12517 case FT_INT40:
12518 case FT_INT48:
12519 case FT_INT56:
12520 case FT_INT64:
12521 proto_tree_add_int64(tree, **fields, tvb, offset, len, (int64_t)value);
12522 break;
12524 case FT_BOOLEAN:
12525 proto_tree_add_boolean(tree, **fields, tvb, offset, len, value);
12526 break;
12528 default:
12529 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_item_add_bitmask_tree()",
12530 hf->abbrev,
12531 hf->type,
12532 ftype_name(hf->type));
12533 break;
12535 if (flags & BMT_NO_APPEND) {
12536 fields++;
12537 continue;
12539 tmpval = (value & hf->bitmask) >> hfinfo_bitshift(hf);
12541 /* XXX: README.developer and the comments have always defined
12542 * BMT_NO_INT as "only boolean flags are added to the title /
12543 * don't add non-boolean (integral) fields", but the
12544 * implementation has always added BASE_CUSTOM and fields with
12545 * value_strings, though not fields with unit_strings.
12546 * Possibly this is because some dissectors use a FT_UINT8
12547 * with a value_string for fields that should be a FT_BOOLEAN.
12549 switch (hf->type) {
12550 case FT_CHAR:
12551 if (hf->display == BASE_CUSTOM) {
12552 char lbl[ITEM_LABEL_LENGTH];
12553 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
12555 DISSECTOR_ASSERT(fmtfunc);
12556 fmtfunc(lbl, (uint32_t) tmpval);
12557 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12558 hf->name, lbl);
12559 first = false;
12561 else if (hf->strings) {
12562 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12563 hf->name, hf_try_val_to_str_const((uint32_t) tmpval, hf, "Unknown"));
12564 first = false;
12566 else if (!(flags & BMT_NO_INT)) {
12567 char buf[32];
12568 const char *out;
12570 if (!first) {
12571 proto_item_append_text(item, ", ");
12574 out = hfinfo_char_value_format(hf, buf, (uint32_t) tmpval);
12575 proto_item_append_text(item, "%s: %s", hf->name, out);
12576 first = false;
12579 break;
12581 case FT_UINT8:
12582 case FT_UINT16:
12583 case FT_UINT24:
12584 case FT_UINT32:
12585 if (hf->display == BASE_CUSTOM) {
12586 char lbl[ITEM_LABEL_LENGTH];
12587 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
12589 DISSECTOR_ASSERT(fmtfunc);
12590 fmtfunc(lbl, (uint32_t) tmpval);
12591 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12592 hf->name, lbl);
12593 first = false;
12595 else if ((hf->strings) &&(!(hf->display & (BASE_UNIT_STRING|BASE_SPECIAL_VALS)))) {
12596 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12597 hf->name, hf_try_val_to_str_const((uint32_t) tmpval, hf, "Unknown"));
12598 first = false;
12600 else if (!(flags & BMT_NO_INT)) {
12601 char buf[NUMBER_LABEL_LENGTH];
12602 const char *out = NULL;
12604 if (!first) {
12605 proto_item_append_text(item, ", ");
12608 if (hf->strings && hf->display & BASE_SPECIAL_VALS) {
12609 out = hf_try_val_to_str((uint32_t) tmpval, hf);
12611 if (out == NULL) {
12612 out = hfinfo_number_value_format(hf, buf, (uint32_t) tmpval);
12614 proto_item_append_text(item, "%s: %s", hf->name, out);
12615 if (hf->strings && hf->display & BASE_UNIT_STRING) {
12616 proto_item_append_text(item, "%s", unit_name_string_get_value((uint32_t) tmpval, (const unit_name_string*)hf->strings));
12618 first = false;
12621 break;
12623 case FT_INT8:
12624 case FT_INT16:
12625 case FT_INT24:
12626 case FT_INT32:
12627 integer32 = (uint32_t) tmpval;
12628 if (hf->bitmask) {
12629 no_of_bits = ws_count_ones(hf->bitmask);
12630 integer32 = ws_sign_ext32(integer32, no_of_bits);
12632 if (hf->display == BASE_CUSTOM) {
12633 char lbl[ITEM_LABEL_LENGTH];
12634 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
12636 DISSECTOR_ASSERT(fmtfunc);
12637 fmtfunc(lbl, (int32_t) integer32);
12638 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12639 hf->name, lbl);
12640 first = false;
12642 else if ((hf->strings) &&(!(hf->display & (BASE_UNIT_STRING|BASE_SPECIAL_VALS)))) {
12643 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12644 hf->name, hf_try_val_to_str_const((int32_t) integer32, hf, "Unknown"));
12645 first = false;
12647 else if (!(flags & BMT_NO_INT)) {
12648 char buf[NUMBER_LABEL_LENGTH];
12649 const char *out = NULL;
12651 if (!first) {
12652 proto_item_append_text(item, ", ");
12655 if (hf->strings && hf->display & BASE_SPECIAL_VALS) {
12656 out = hf_try_val_to_str((int32_t) integer32, hf);
12658 if (out == NULL) {
12659 out = hfinfo_number_value_format(hf, buf, (int32_t) integer32);
12661 proto_item_append_text(item, "%s: %s", hf->name, out);
12662 if (hf->display & BASE_UNIT_STRING) {
12663 proto_item_append_text(item, "%s", unit_name_string_get_value((uint32_t) tmpval, (const unit_name_string*)hf->strings));
12665 first = false;
12668 break;
12670 case FT_UINT40:
12671 case FT_UINT48:
12672 case FT_UINT56:
12673 case FT_UINT64:
12674 if (hf->display == BASE_CUSTOM) {
12675 char lbl[ITEM_LABEL_LENGTH];
12676 const custom_fmt_func_64_t fmtfunc = (const custom_fmt_func_64_t)hf->strings;
12678 DISSECTOR_ASSERT(fmtfunc);
12679 fmtfunc(lbl, tmpval);
12680 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12681 hf->name, lbl);
12682 first = false;
12684 else if ((hf->strings) &&(!(hf->display & (BASE_UNIT_STRING|BASE_SPECIAL_VALS)))) {
12685 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12686 hf->name, hf_try_val64_to_str_const(tmpval, hf, "Unknown"));
12687 first = false;
12689 else if (!(flags & BMT_NO_INT)) {
12690 char buf[NUMBER_LABEL_LENGTH];
12691 const char *out = NULL;
12693 if (!first) {
12694 proto_item_append_text(item, ", ");
12697 if (hf->strings && hf->display & BASE_SPECIAL_VALS) {
12698 out = hf_try_val64_to_str(tmpval, hf);
12700 if (out == NULL) {
12701 out = hfinfo_number_value_format64(hf, buf, tmpval);
12703 proto_item_append_text(item, "%s: %s", hf->name, out);
12704 if (hf->strings && hf->display & BASE_UNIT_STRING) {
12705 proto_item_append_text(item, "%s", unit_name_string_get_value64(tmpval, (const unit_name_string*)hf->strings));
12707 first = false;
12710 break;
12712 case FT_INT40:
12713 case FT_INT48:
12714 case FT_INT56:
12715 case FT_INT64:
12716 if (hf->bitmask) {
12717 no_of_bits = ws_count_ones(hf->bitmask);
12718 tmpval = ws_sign_ext64(tmpval, no_of_bits);
12720 if (hf->display == BASE_CUSTOM) {
12721 char lbl[ITEM_LABEL_LENGTH];
12722 const custom_fmt_func_64_t fmtfunc = (const custom_fmt_func_64_t)hf->strings;
12724 DISSECTOR_ASSERT(fmtfunc);
12725 fmtfunc(lbl, (int64_t) tmpval);
12726 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12727 hf->name, lbl);
12728 first = false;
12730 else if ((hf->strings) &&(!(hf->display & (BASE_UNIT_STRING|BASE_SPECIAL_VALS)))) {
12731 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12732 hf->name, hf_try_val64_to_str_const((int64_t) tmpval, hf, "Unknown"));
12733 first = false;
12735 else if (!(flags & BMT_NO_INT)) {
12736 char buf[NUMBER_LABEL_LENGTH];
12737 const char *out = NULL;
12739 if (!first) {
12740 proto_item_append_text(item, ", ");
12743 if (hf->strings && hf->display & BASE_SPECIAL_VALS) {
12744 out = hf_try_val64_to_str((int64_t) tmpval, hf);
12746 if (out == NULL) {
12747 out = hfinfo_number_value_format64(hf, buf, (int64_t) tmpval);
12749 proto_item_append_text(item, "%s: %s", hf->name, out);
12750 if (hf->strings && hf->display & BASE_UNIT_STRING) {
12751 proto_item_append_text(item, "%s", unit_name_string_get_value64(tmpval, (const unit_name_string*)hf->strings));
12753 first = false;
12756 break;
12758 case FT_BOOLEAN:
12759 if (hf->strings && !(flags & BMT_NO_TFS)) {
12760 /* If we have true/false strings, emit full - otherwise messages
12761 might look weird */
12762 const struct true_false_string *tfs =
12763 (const struct true_false_string *)hf->strings;
12765 if (tmpval) {
12766 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12767 hf->name, tfs->true_string);
12768 first = false;
12769 } else if (!(flags & BMT_NO_FALSE)) {
12770 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
12771 hf->name, tfs->false_string);
12772 first = false;
12774 } else if (hf->bitmask & value) {
12775 /* If the flag is set, show the name */
12776 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
12777 first = false;
12779 break;
12780 default:
12781 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_item_add_bitmask_tree()",
12782 hf->abbrev,
12783 hf->type,
12784 ftype_name(hf->type));
12785 break;
12788 fields++;
12791 /* XXX: We don't pass the hfi into this function. Perhaps we should,
12792 * but then again most dissectors don't set the bitmask field for
12793 * the higher level bitmask hfi, so calculate the bitmask from the
12794 * fields present. */
12795 if (item) {
12796 bit_offset = len*8 - 1 - ws_ilog2(bitmask);
12797 no_of_bits = ws_ilog2(bitmask) - ws_ctz(bitmask) + 1;
12798 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
12799 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
12801 return first;
12804 /* This function will dissect a sequence of bytes that describe a
12805 * bitmask and supply the value of that sequence through a pointer.
12806 * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
12807 * to be dissected.
12808 * This field will form an expansion under which the individual fields of the
12809 * bitmask is dissected and displayed.
12810 * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
12812 * fields is an array of pointers to int that lists all the fields of the
12813 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
12814 * or another integer of the same type/size as hf_hdr with a mask specified.
12815 * This array is terminated by a NULL entry.
12817 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
12818 * FT_integer fields that have a value_string attached will have the
12819 * matched string displayed on the expansion line.
12821 proto_item *
12822 proto_tree_add_bitmask_ret_uint64(proto_tree *parent_tree, tvbuff_t *tvb,
12823 const unsigned offset, const int hf_hdr,
12824 const int ett, int * const *fields,
12825 const unsigned encoding, uint64_t *retval)
12827 return proto_tree_add_bitmask_with_flags_ret_uint64(parent_tree, tvb, offset, hf_hdr, ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS, retval);
12830 /* This function will dissect a sequence of bytes that describe a
12831 * bitmask.
12832 * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
12833 * to be dissected.
12834 * This field will form an expansion under which the individual fields of the
12835 * bitmask is dissected and displayed.
12836 * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
12838 * fields is an array of pointers to int that lists all the fields of the
12839 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
12840 * or another integer of the same type/size as hf_hdr with a mask specified.
12841 * This array is terminated by a NULL entry.
12843 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
12844 * FT_integer fields that have a value_string attached will have the
12845 * matched string displayed on the expansion line.
12847 proto_item *
12848 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
12849 const unsigned offset, const int hf_hdr,
12850 const int ett, int * const *fields,
12851 const unsigned encoding)
12853 return proto_tree_add_bitmask_with_flags(parent_tree, tvb, offset, hf_hdr, ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS);
12856 /* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
12857 * what data is appended to the header.
12859 proto_item *
12860 proto_tree_add_bitmask_with_flags_ret_uint64(proto_tree *parent_tree, tvbuff_t *tvb, const unsigned offset,
12861 const int hf_hdr, const int ett, int * const *fields, const unsigned encoding, const int flags,
12862 uint64_t *retval)
12864 proto_item *item = NULL;
12865 header_field_info *hf;
12866 int len;
12867 uint64_t value;
12869 PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
12870 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
12871 len = ftype_wire_size(hf->type);
12872 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
12874 if (parent_tree) {
12875 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
12876 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
12877 flags, false, false, NULL, value);
12880 *retval = value;
12881 if (hf->bitmask) {
12882 /* Mask out irrelevant portions */
12883 *retval &= hf->bitmask;
12884 /* Shift bits */
12885 *retval >>= hfinfo_bitshift(hf);
12888 return item;
12891 /* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
12892 * what data is appended to the header.
12894 proto_item *
12895 proto_tree_add_bitmask_with_flags(proto_tree *parent_tree, tvbuff_t *tvb, const unsigned offset,
12896 const int hf_hdr, const int ett, int * const *fields, const unsigned encoding, const int flags)
12898 proto_item *item = NULL;
12899 header_field_info *hf;
12900 int len;
12901 uint64_t value;
12903 PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
12904 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
12906 if (parent_tree) {
12907 len = ftype_wire_size(hf->type);
12908 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
12909 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
12910 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
12911 flags, false, false, NULL, value);
12914 return item;
12917 /* Similar to proto_tree_add_bitmask(), but with a passed in value (presumably because it
12918 can't be retrieved directly from tvb) */
12919 proto_item *
12920 proto_tree_add_bitmask_value(proto_tree *parent_tree, tvbuff_t *tvb, const unsigned offset,
12921 const int hf_hdr, const int ett, int * const *fields, const uint64_t value)
12923 return proto_tree_add_bitmask_value_with_flags(parent_tree, tvb, offset,
12924 hf_hdr, ett, fields, value, BMT_NO_INT|BMT_NO_TFS);
12927 /* Similar to proto_tree_add_bitmask_value(), but with control of flag values */
12928 WS_DLL_PUBLIC proto_item *
12929 proto_tree_add_bitmask_value_with_flags(proto_tree *parent_tree, tvbuff_t *tvb, const unsigned offset,
12930 const int hf_hdr, const int ett, int * const *fields, const uint64_t value, const int flags)
12932 proto_item *item = NULL;
12933 header_field_info *hf;
12934 int len;
12936 PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
12937 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
12938 /* the proto_tree_add_uint/_uint64() calls below
12939 will fail if tvb==NULL and len!=0 */
12940 len = tvb ? ftype_wire_size(hf->type) : 0;
12942 if (parent_tree) {
12943 if (len <= 4)
12944 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len, (uint32_t)value);
12945 else
12946 item = proto_tree_add_uint64(parent_tree, hf_hdr, tvb, offset, len, value);
12948 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
12949 flags, false, false, NULL, value);
12952 return item;
12955 /* Similar to proto_tree_add_bitmask(), but with no "header" item to group all of the fields */
12956 void
12957 proto_tree_add_bitmask_list(proto_tree *tree, tvbuff_t *tvb, const unsigned offset,
12958 const int len, int * const *fields, const unsigned encoding)
12960 uint64_t value;
12962 if (tree) {
12963 value = get_uint64_value(tree, tvb, offset, len, encoding);
12964 proto_item_add_bitmask_tree(NULL, tvb, offset, len, -1, fields,
12965 BMT_NO_APPEND, false, true, tree, value);
12969 WS_DLL_PUBLIC void
12970 proto_tree_add_bitmask_list_ret_uint64(proto_tree *tree, tvbuff_t *tvb, const unsigned offset,
12971 const int len, int * const *fields, const unsigned encoding, uint64_t *retval)
12973 uint64_t value;
12975 value = get_uint64_value(tree, tvb, offset, len, encoding);
12976 if (tree) {
12977 proto_item_add_bitmask_tree(NULL, tvb, offset, len, -1, fields,
12978 BMT_NO_APPEND, false, true, tree, value);
12980 if (retval) {
12981 *retval = value;
12985 WS_DLL_PUBLIC void
12986 proto_tree_add_bitmask_list_value(proto_tree *tree, tvbuff_t *tvb, const unsigned offset,
12987 const int len, int * const *fields, const uint64_t value)
12989 if (tree) {
12990 proto_item_add_bitmask_tree(NULL, tvb, offset, len, -1, fields,
12991 BMT_NO_APPEND, false, true, tree, value);
12996 /* The same as proto_tree_add_bitmask(), but using a caller-supplied length.
12997 * This is intended to support bitmask fields whose lengths can vary, perhaps
12998 * as the underlying standard evolves over time.
12999 * With this API there is the possibility of being called to display more or
13000 * less data than the dissector was coded to support.
13001 * In such cases, it is assumed that bitmasks are extended on the MSb end.
13002 * Thus when presented with "too much" or "too little" data, MSbits will be
13003 * ignored or MSfields sacrificed.
13005 * Only fields for which all defined bits are available are displayed.
13007 proto_item *
13008 proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb,
13009 const unsigned offset, const unsigned len, const int hf_hdr,
13010 const int ett, int * const *fields, struct expert_field* exp,
13011 const unsigned encoding)
13013 proto_item *item = NULL;
13014 header_field_info *hf;
13015 unsigned decodable_len;
13016 unsigned decodable_offset;
13017 uint32_t decodable_value;
13018 uint64_t value;
13020 PROTO_REGISTRAR_GET_NTH(hf_hdr, hf);
13021 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
13023 decodable_offset = offset;
13024 decodable_len = MIN(len, (unsigned) ftype_wire_size(hf->type));
13026 /* If we are ftype_wire_size-limited,
13027 * make sure we decode as many LSBs as possible.
13029 if (encoding == ENC_BIG_ENDIAN) {
13030 decodable_offset += (len - decodable_len);
13033 if (parent_tree) {
13034 decodable_value = get_uint_value(parent_tree, tvb, decodable_offset,
13035 decodable_len, encoding);
13037 /* The root item covers all the bytes even if we can't decode them all */
13038 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len,
13039 decodable_value);
13042 if (decodable_len < len) {
13043 /* Dissector likely requires updating for new protocol revision */
13044 expert_add_info_format(NULL, item, exp,
13045 "Only least-significant %d of %d bytes decoded",
13046 decodable_len, len);
13049 if (item) {
13050 value = get_uint64_value(parent_tree, tvb, decodable_offset, decodable_len, encoding);
13051 proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len,
13052 ett, fields, BMT_NO_INT|BMT_NO_TFS, false, false, NULL, value);
13055 return item;
13058 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
13059 proto_item *
13060 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
13061 const unsigned offset, const unsigned len,
13062 const char *name, const char *fallback,
13063 const int ett, int * const *fields,
13064 const unsigned encoding, const int flags)
13066 proto_item *item = NULL;
13067 uint64_t value;
13069 if (parent_tree) {
13070 item = proto_tree_add_text_internal(parent_tree, tvb, offset, len, "%s", name ? name : "");
13071 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
13072 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
13073 flags, true, false, NULL, value) && fallback) {
13074 /* Still at first item - append 'fallback' text if any */
13075 proto_item_append_text(item, "%s", fallback);
13079 return item;
13082 proto_item *
13083 proto_tree_add_bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
13084 const unsigned bit_offset, const int no_of_bits,
13085 const unsigned encoding)
13087 header_field_info *hfinfo;
13088 int octet_length;
13089 int octet_offset;
13091 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
13093 if (no_of_bits < 0) {
13094 THROW(ReportedBoundsError);
13096 octet_length = (no_of_bits + 7) >> 3;
13097 octet_offset = bit_offset >> 3;
13098 test_length(hfinfo, tvb, octet_offset, octet_length, encoding);
13100 /* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
13101 * but only after doing a bunch more work (which we can, in the common
13102 * case, shortcut here).
13104 CHECK_FOR_NULL_TREE(tree);
13105 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
13107 return proto_tree_add_bits_ret_val(tree, hfindex, tvb, bit_offset, no_of_bits, NULL, encoding);
13111 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
13112 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
13113 * Offset should be given in bits from the start of the tvb.
13116 static proto_item *
13117 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
13118 const unsigned bit_offset, const int no_of_bits,
13119 uint64_t *return_value, const unsigned encoding)
13121 int offset;
13122 unsigned length;
13123 uint8_t tot_no_bits;
13124 char *bf_str;
13125 char lbl_str[ITEM_LABEL_LENGTH];
13126 uint64_t value = 0;
13127 uint8_t *bytes = NULL;
13128 size_t bytes_length = 0;
13130 proto_item *pi;
13131 header_field_info *hf_field;
13133 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
13134 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
13136 if (hf_field->bitmask != 0) {
13137 REPORT_DISSECTOR_BUG("Incompatible use of proto_tree_add_bits_ret_val"
13138 " with field '%s' (%s) with bitmask != 0",
13139 hf_field->abbrev, hf_field->name);
13142 if (no_of_bits < 0) {
13143 THROW(ReportedBoundsError);
13144 } else if (no_of_bits == 0) {
13145 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_ret_val() has a bit width of 0",
13146 hf_field->abbrev);
13149 /* Byte align offset */
13150 offset = bit_offset>>3;
13153 * Calculate the number of octets used to hold the bits
13155 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
13156 length = (tot_no_bits + 7) >> 3;
13158 if (no_of_bits < 65) {
13159 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
13160 } else if (hf_field->type != FT_BYTES) {
13161 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_ret_val() has a bit width of %u > 65",
13162 hf_field->abbrev, no_of_bits);
13163 return NULL;
13166 /* Sign extend for signed types */
13167 switch (hf_field->type) {
13168 case FT_INT8:
13169 case FT_INT16:
13170 case FT_INT24:
13171 case FT_INT32:
13172 case FT_INT40:
13173 case FT_INT48:
13174 case FT_INT56:
13175 case FT_INT64:
13176 value = ws_sign_ext64(value, no_of_bits);
13177 break;
13179 default:
13180 break;
13183 if (return_value) {
13184 *return_value = value;
13187 /* Coast clear. Try and fake it */
13188 CHECK_FOR_NULL_TREE(tree);
13189 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13191 bf_str = decode_bits_in_field(PNODE_POOL(tree), bit_offset, no_of_bits, value, encoding);
13193 switch (hf_field->type) {
13194 case FT_BOOLEAN:
13195 /* Boolean field */
13196 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, value,
13197 "%s = %s: %s",
13198 bf_str, hf_field->name, tfs_get_string(!!value, hf_field->strings));
13199 break;
13201 case FT_CHAR:
13202 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (uint32_t)value);
13203 fill_label_char(PITEM_FINFO(pi), lbl_str, NULL);
13204 break;
13206 case FT_UINT8:
13207 case FT_UINT16:
13208 case FT_UINT24:
13209 case FT_UINT32:
13210 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (uint32_t)value);
13211 fill_label_number(PITEM_FINFO(pi), lbl_str, NULL, false);
13212 break;
13214 case FT_INT8:
13215 case FT_INT16:
13216 case FT_INT24:
13217 case FT_INT32:
13218 pi = proto_tree_add_int(tree, hfindex, tvb, offset, length, (int32_t)value);
13219 fill_label_number(PITEM_FINFO(pi), lbl_str, NULL, true);
13220 break;
13222 case FT_UINT40:
13223 case FT_UINT48:
13224 case FT_UINT56:
13225 case FT_UINT64:
13226 pi = proto_tree_add_uint64(tree, hfindex, tvb, offset, length, value);
13227 fill_label_number64(PITEM_FINFO(pi), lbl_str, NULL, false);
13228 break;
13230 case FT_INT40:
13231 case FT_INT48:
13232 case FT_INT56:
13233 case FT_INT64:
13234 pi = proto_tree_add_int64(tree, hfindex, tvb, offset, length, (int64_t)value);
13235 fill_label_number64(PITEM_FINFO(pi), lbl_str, NULL, true);
13236 break;
13238 case FT_BYTES:
13239 bytes = tvb_get_bits_array(PNODE_POOL(tree), tvb, bit_offset, no_of_bits, &bytes_length, encoding);
13240 pi = proto_tree_add_bytes_with_length(tree, hfindex, tvb, offset, length, bytes, (int) bytes_length);
13241 proto_item_fill_label(PITEM_FINFO(pi), lbl_str, NULL);
13242 proto_item_set_text(pi, "%s", lbl_str);
13243 return pi;
13245 /* TODO: should handle FT_UINT_BYTES ? */
13247 default:
13248 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_tree_add_bits_ret_val()",
13249 hf_field->abbrev,
13250 hf_field->type,
13251 ftype_name(hf_field->type));
13252 return NULL;
13255 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
13256 return pi;
13259 proto_item *
13260 proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
13261 const unsigned bit_offset, const crumb_spec_t *crumb_spec,
13262 uint64_t *return_value)
13264 proto_item *pi;
13265 int no_of_bits;
13266 int octet_offset;
13267 unsigned mask_initial_bit_offset;
13268 unsigned mask_greatest_bit_offset;
13269 unsigned octet_length;
13270 uint8_t i;
13271 char bf_str[256];
13272 char lbl_str[ITEM_LABEL_LENGTH];
13273 uint64_t value;
13274 uint64_t composite_bitmask;
13275 uint64_t composite_bitmap;
13277 header_field_info *hf_field;
13279 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
13280 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
13282 if (hf_field->bitmask != 0) {
13283 REPORT_DISSECTOR_BUG("Incompatible use of proto_tree_add_split_bits_item_ret_val"
13284 " with field '%s' (%s) with bitmask != 0",
13285 hf_field->abbrev, hf_field->name);
13288 mask_initial_bit_offset = bit_offset % 8;
13290 no_of_bits = 0;
13291 value = 0;
13292 i = 0;
13293 mask_greatest_bit_offset = 0;
13294 composite_bitmask = 0;
13295 composite_bitmap = 0;
13297 while (crumb_spec[i].crumb_bit_length != 0) {
13298 uint64_t crumb_mask, crumb_value;
13299 uint8_t crumb_end_bit_offset;
13301 crumb_value = tvb_get_bits64(tvb,
13302 bit_offset + crumb_spec[i].crumb_bit_offset,
13303 crumb_spec[i].crumb_bit_length,
13304 ENC_BIG_ENDIAN);
13305 value += crumb_value;
13306 no_of_bits += crumb_spec[i].crumb_bit_length;
13307 DISSECTOR_ASSERT_HINT(no_of_bits <= 64, "a value larger than 64 bits cannot be represented");
13309 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
13310 octet containing the initial offset.
13311 If the mask is beyond 32 bits, then give up on bit map display.
13312 This could be improved in future, probably showing a table
13313 of 32 or 64 bits per row */
13314 if (mask_greatest_bit_offset < 32) {
13315 crumb_end_bit_offset = mask_initial_bit_offset
13316 + crumb_spec[i].crumb_bit_offset
13317 + crumb_spec[i].crumb_bit_length;
13318 crumb_mask = (UINT64_C(1) << crumb_spec[i].crumb_bit_length) - 1;
13320 if (crumb_end_bit_offset > mask_greatest_bit_offset) {
13321 mask_greatest_bit_offset = crumb_end_bit_offset;
13323 /* Currently the bitmap of the crumbs are only shown if
13324 * smaller than 32 bits. Do not bother calculating the
13325 * mask if it is larger than that. */
13326 if (crumb_end_bit_offset <= 32) {
13327 composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset));
13328 composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset));
13331 /* Shift left for the next segment */
13332 value <<= crumb_spec[++i].crumb_bit_length;
13335 /* Sign extend for signed types */
13336 switch (hf_field->type) {
13337 case FT_INT8:
13338 case FT_INT16:
13339 case FT_INT24:
13340 case FT_INT32:
13341 case FT_INT40:
13342 case FT_INT48:
13343 case FT_INT56:
13344 case FT_INT64:
13345 value = ws_sign_ext64(value, no_of_bits);
13346 break;
13347 default:
13348 break;
13351 if (return_value) {
13352 *return_value = value;
13355 /* Coast clear. Try and fake it */
13356 CHECK_FOR_NULL_TREE(tree);
13357 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13359 /* initialise the format string */
13360 bf_str[0] = '\0';
13362 octet_offset = bit_offset >> 3;
13364 /* Round up mask length to nearest octet */
13365 octet_length = ((mask_greatest_bit_offset + 7) >> 3);
13366 mask_greatest_bit_offset = octet_length << 3;
13368 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
13369 It would be a useful enhancement to eliminate this restriction. */
13370 if (mask_greatest_bit_offset > 0 && mask_greatest_bit_offset <= 32) {
13371 other_decode_bitfield_value(bf_str,
13372 (uint32_t)(composite_bitmap >> (64 - mask_greatest_bit_offset)),
13373 (uint32_t)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
13374 mask_greatest_bit_offset);
13375 } else {
13376 /* If the bitmask is too large, try to describe its contents. */
13377 snprintf(bf_str, sizeof(bf_str), "%d bits", no_of_bits);
13380 switch (hf_field->type) {
13381 case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
13382 /* Boolean field */
13383 return proto_tree_add_boolean_format(tree, hfindex,
13384 tvb, octet_offset, octet_length, value,
13385 "%s = %s: %s",
13386 bf_str, hf_field->name, tfs_get_string(!!value, hf_field->strings));
13387 break;
13389 case FT_CHAR:
13390 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (uint32_t)value);
13391 fill_label_char(PITEM_FINFO(pi), lbl_str, NULL);
13392 break;
13394 case FT_UINT8:
13395 case FT_UINT16:
13396 case FT_UINT24:
13397 case FT_UINT32:
13398 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (uint32_t)value);
13399 fill_label_number(PITEM_FINFO(pi), lbl_str, NULL, false);
13400 break;
13402 case FT_INT8:
13403 case FT_INT16:
13404 case FT_INT24:
13405 case FT_INT32:
13406 pi = proto_tree_add_int(tree, hfindex, tvb, octet_offset, octet_length, (int32_t)value);
13407 fill_label_number(PITEM_FINFO(pi), lbl_str, NULL, true);
13408 break;
13410 case FT_UINT40:
13411 case FT_UINT48:
13412 case FT_UINT56:
13413 case FT_UINT64:
13414 pi = proto_tree_add_uint64(tree, hfindex, tvb, octet_offset, octet_length, value);
13415 fill_label_number64(PITEM_FINFO(pi), lbl_str, NULL, false);
13416 break;
13418 case FT_INT40:
13419 case FT_INT48:
13420 case FT_INT56:
13421 case FT_INT64:
13422 pi = proto_tree_add_int64(tree, hfindex, tvb, octet_offset, octet_length, (int64_t)value);
13423 fill_label_number64(PITEM_FINFO(pi), lbl_str, NULL, true);
13424 break;
13426 default:
13427 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_tree_add_split_bits_item_ret_val()",
13428 hf_field->abbrev,
13429 hf_field->type,
13430 ftype_name(hf_field->type));
13431 return NULL;
13433 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
13434 return pi;
13437 void
13438 proto_tree_add_split_bits_crumb(proto_tree *tree, const int hfindex, tvbuff_t *tvb, const unsigned bit_offset,
13439 const crumb_spec_t *crumb_spec, uint16_t crumb_index)
13441 header_field_info *hfinfo;
13442 int start = bit_offset >> 3;
13443 int length = ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1;
13445 /* We have to duplicate this length check from proto_tree_add_text_internal in order to check for a null tree
13446 * so that we can use the tree's memory scope in calculating the string */
13447 if (length == -1) {
13448 tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
13449 } else {
13450 tvb_ensure_bytes_exist(tvb, start, length);
13452 if (!tree) return;
13454 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
13455 proto_tree_add_text_internal(tree, tvb, start, length,
13456 "%s crumb %d of %s (decoded above)",
13457 decode_bits_in_field(PNODE_POOL(tree), bit_offset, crumb_spec[crumb_index].crumb_bit_length,
13458 tvb_get_bits(tvb,
13459 bit_offset,
13460 crumb_spec[crumb_index].crumb_bit_length,
13461 ENC_BIG_ENDIAN),
13462 ENC_BIG_ENDIAN),
13463 crumb_index,
13464 hfinfo->name);
13467 proto_item *
13468 proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
13469 const unsigned bit_offset, const int no_of_bits,
13470 uint64_t *return_value, const unsigned encoding)
13472 proto_item *item;
13474 if ((item = _proto_tree_add_bits_ret_val(tree, hfindex, tvb,
13475 bit_offset, no_of_bits,
13476 return_value, encoding))) {
13477 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
13478 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
13480 return item;
13483 static proto_item *
13484 _proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
13485 tvbuff_t *tvb, const unsigned bit_offset,
13486 const int no_of_bits, void *value_ptr,
13487 const unsigned encoding, char *value_str)
13489 int offset;
13490 unsigned length;
13491 uint8_t tot_no_bits;
13492 char *str;
13493 uint64_t value = 0;
13494 header_field_info *hf_field;
13496 /* We do not have to return a value, try to fake it as soon as possible */
13497 CHECK_FOR_NULL_TREE(tree);
13498 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13500 if (hf_field->bitmask != 0) {
13501 REPORT_DISSECTOR_BUG("Incompatible use of proto_tree_add_bits_format_value"
13502 " with field '%s' (%s) with bitmask != 0",
13503 hf_field->abbrev, hf_field->name);
13506 if (no_of_bits < 0) {
13507 THROW(ReportedBoundsError);
13508 } else if (no_of_bits == 0) {
13509 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_format_value() has a bit width of 0",
13510 hf_field->abbrev);
13513 /* Byte align offset */
13514 offset = bit_offset>>3;
13517 * Calculate the number of octets used to hold the bits
13519 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
13520 length = tot_no_bits>>3;
13521 /* If we are using part of the next octet, increase length by 1 */
13522 if (tot_no_bits & 0x07)
13523 length++;
13525 if (no_of_bits < 65) {
13526 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
13527 } else {
13528 REPORT_DISSECTOR_BUG("field %s passed to proto_tree_add_bits_format_value() has a bit width of %u > 65",
13529 hf_field->abbrev, no_of_bits);
13530 return NULL;
13533 str = decode_bits_in_field(PNODE_POOL(tree), bit_offset, no_of_bits, value, encoding);
13535 (void) g_strlcat(str, " = ", 256+64);
13536 (void) g_strlcat(str, hf_field->name, 256+64);
13539 * This function does not receive an actual value but a dimensionless pointer to that value.
13540 * For this reason, the type of the header field is examined in order to determine
13541 * what kind of value we should read from this address.
13542 * The caller of this function must make sure that for the specific header field type the address of
13543 * a compatible value is provided.
13545 switch (hf_field->type) {
13546 case FT_BOOLEAN:
13547 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, *(uint64_t *)value_ptr,
13548 "%s: %s", str, value_str);
13549 break;
13551 case FT_CHAR:
13552 case FT_UINT8:
13553 case FT_UINT16:
13554 case FT_UINT24:
13555 case FT_UINT32:
13556 return proto_tree_add_uint_format(tree, hfindex, tvb, offset, length, *(uint32_t *)value_ptr,
13557 "%s: %s", str, value_str);
13558 break;
13560 case FT_UINT40:
13561 case FT_UINT48:
13562 case FT_UINT56:
13563 case FT_UINT64:
13564 return proto_tree_add_uint64_format(tree, hfindex, tvb, offset, length, *(uint64_t *)value_ptr,
13565 "%s: %s", str, value_str);
13566 break;
13568 case FT_INT8:
13569 case FT_INT16:
13570 case FT_INT24:
13571 case FT_INT32:
13572 return proto_tree_add_int_format(tree, hfindex, tvb, offset, length, *(int32_t *)value_ptr,
13573 "%s: %s", str, value_str);
13574 break;
13576 case FT_INT40:
13577 case FT_INT48:
13578 case FT_INT56:
13579 case FT_INT64:
13580 return proto_tree_add_int64_format(tree, hfindex, tvb, offset, length, *(int64_t *)value_ptr,
13581 "%s: %s", str, value_str);
13582 break;
13584 case FT_FLOAT:
13585 return proto_tree_add_float_format(tree, hfindex, tvb, offset, length, *(float *)value_ptr,
13586 "%s: %s", str, value_str);
13587 break;
13589 default:
13590 REPORT_DISSECTOR_BUG("field %s has type %d (%s) not handled in proto_tree_add_bits_format_value()",
13591 hf_field->abbrev,
13592 hf_field->type,
13593 ftype_name(hf_field->type));
13594 return NULL;
13598 static proto_item *
13599 proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
13600 tvbuff_t *tvb, const unsigned bit_offset,
13601 const int no_of_bits, void *value_ptr,
13602 const unsigned encoding, char *value_str)
13604 proto_item *item;
13606 if ((item = _proto_tree_add_bits_format_value(tree, hfindex,
13607 tvb, bit_offset, no_of_bits,
13608 value_ptr, encoding, value_str))) {
13609 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
13610 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
13612 return item;
13615 #define CREATE_VALUE_STRING(tree,dst,format,ap) \
13616 va_start(ap, format); \
13617 dst = wmem_strdup_vprintf(PNODE_POOL(tree), format, ap); \
13618 va_end(ap);
13620 proto_item *
13621 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hfindex,
13622 tvbuff_t *tvb, const unsigned bit_offset,
13623 const int no_of_bits, uint32_t value,
13624 const unsigned encoding,
13625 const char *format, ...)
13627 va_list ap;
13628 char *dst;
13629 header_field_info *hf_field;
13631 CHECK_FOR_NULL_TREE(tree);
13633 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13635 switch (hf_field->type) {
13636 case FT_UINT8:
13637 case FT_UINT16:
13638 case FT_UINT24:
13639 case FT_UINT32:
13640 break;
13642 default:
13643 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
13644 hf_field->abbrev);
13645 return NULL;
13648 CREATE_VALUE_STRING(tree, dst, format, ap);
13650 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
13653 proto_item *
13654 proto_tree_add_uint64_bits_format_value(proto_tree *tree, const int hfindex,
13655 tvbuff_t *tvb, const unsigned bit_offset,
13656 const int no_of_bits, uint64_t value,
13657 const unsigned encoding,
13658 const char *format, ...)
13660 va_list ap;
13661 char *dst;
13662 header_field_info *hf_field;
13664 CHECK_FOR_NULL_TREE(tree);
13666 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13668 switch (hf_field->type) {
13669 case FT_UINT40:
13670 case FT_UINT48:
13671 case FT_UINT56:
13672 case FT_UINT64:
13673 break;
13675 default:
13676 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, or FT_UINT64",
13677 hf_field->abbrev);
13678 return NULL;
13681 CREATE_VALUE_STRING(tree, dst, format, ap);
13683 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
13686 proto_item *
13687 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hfindex,
13688 tvbuff_t *tvb, const unsigned bit_offset,
13689 const int no_of_bits, float value,
13690 const unsigned encoding,
13691 const char *format, ...)
13693 va_list ap;
13694 char *dst;
13695 header_field_info *hf_field;
13697 CHECK_FOR_NULL_TREE(tree);
13699 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13701 DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_FLOAT);
13703 CREATE_VALUE_STRING(tree, dst, format, ap);
13705 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
13708 proto_item *
13709 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hfindex,
13710 tvbuff_t *tvb, const unsigned bit_offset,
13711 const int no_of_bits, int32_t value,
13712 const unsigned encoding,
13713 const char *format, ...)
13715 va_list ap;
13716 char *dst;
13717 header_field_info *hf_field;
13719 CHECK_FOR_NULL_TREE(tree);
13721 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13723 switch (hf_field->type) {
13724 case FT_INT8:
13725 case FT_INT16:
13726 case FT_INT24:
13727 case FT_INT32:
13728 break;
13730 default:
13731 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
13732 hf_field->abbrev);
13733 return NULL;
13736 CREATE_VALUE_STRING(tree, dst, format, ap);
13738 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
13741 proto_item *
13742 proto_tree_add_int64_bits_format_value(proto_tree *tree, const int hfindex,
13743 tvbuff_t *tvb, const unsigned bit_offset,
13744 const int no_of_bits, int64_t value,
13745 const unsigned encoding,
13746 const char *format, ...)
13748 va_list ap;
13749 char *dst;
13750 header_field_info *hf_field;
13752 CHECK_FOR_NULL_TREE(tree);
13754 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13756 switch (hf_field->type) {
13757 case FT_INT40:
13758 case FT_INT48:
13759 case FT_INT56:
13760 case FT_INT64:
13761 break;
13763 default:
13764 REPORT_DISSECTOR_BUG("field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
13765 hf_field->abbrev);
13766 return NULL;
13769 CREATE_VALUE_STRING(tree, dst, format, ap);
13771 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
13774 proto_item *
13775 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hfindex,
13776 tvbuff_t *tvb, const unsigned bit_offset,
13777 const int no_of_bits, uint64_t value,
13778 const unsigned encoding,
13779 const char *format, ...)
13781 va_list ap;
13782 char *dst;
13783 header_field_info *hf_field;
13785 CHECK_FOR_NULL_TREE(tree);
13787 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
13789 DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_BOOLEAN);
13791 CREATE_VALUE_STRING(tree, dst, format, ap);
13793 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, encoding, dst);
13796 proto_item *
13797 proto_tree_add_ts_23_038_7bits_packed_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
13798 const unsigned bit_offset, const int no_of_chars)
13800 proto_item *pi;
13801 header_field_info *hfinfo;
13802 int byte_length;
13803 int byte_offset;
13804 char *string;
13806 CHECK_FOR_NULL_TREE(tree);
13808 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
13810 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_STRING);
13812 byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3;
13813 byte_offset = bit_offset >> 3;
13815 string = tvb_get_ts_23_038_7bits_string_packed(PNODE_POOL(tree), tvb, bit_offset, no_of_chars);
13817 pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length);
13818 DISSECTOR_ASSERT(byte_length >= 0);
13819 proto_tree_set_string(PNODE_FINFO(pi), string);
13821 return pi;
13824 proto_item *
13825 proto_tree_add_ascii_7bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
13826 const unsigned bit_offset, const int no_of_chars)
13828 proto_item *pi;
13829 header_field_info *hfinfo;
13830 int byte_length;
13831 int byte_offset;
13832 char *string;
13834 CHECK_FOR_NULL_TREE(tree);
13836 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
13838 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_STRING);
13840 byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3;
13841 byte_offset = bit_offset >> 3;
13843 string = tvb_get_ascii_7bits_string(PNODE_POOL(tree), tvb, bit_offset, no_of_chars);
13845 pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length);
13846 DISSECTOR_ASSERT(byte_length >= 0);
13847 proto_tree_set_string(PNODE_FINFO(pi), string);
13849 return pi;
13852 const value_string proto_checksum_vals[] = {
13853 { PROTO_CHECKSUM_E_BAD, "Bad" },
13854 { PROTO_CHECKSUM_E_GOOD, "Good" },
13855 { PROTO_CHECKSUM_E_UNVERIFIED, "Unverified" },
13856 { PROTO_CHECKSUM_E_NOT_PRESENT, "Not present" },
13857 { PROTO_CHECKSUM_E_ILLEGAL, "Illegal" },
13859 { 0, NULL }
13862 proto_item *
13863 proto_tree_add_checksum(proto_tree *tree, tvbuff_t *tvb, const unsigned offset,
13864 const int hf_checksum, const int hf_checksum_status, struct expert_field* bad_checksum_expert,
13865 packet_info *pinfo, uint32_t computed_checksum, const unsigned encoding, const unsigned flags)
13867 header_field_info *hfinfo;
13868 uint32_t checksum;
13869 uint32_t len;
13870 proto_item* ti = NULL;
13871 proto_item* ti2;
13872 bool incorrect_checksum = true;
13874 PROTO_REGISTRAR_GET_NTH(hf_checksum, hfinfo);
13876 switch (hfinfo->type) {
13877 case FT_UINT8:
13878 len = 1;
13879 break;
13880 case FT_UINT16:
13881 len = 2;
13882 break;
13883 case FT_UINT24:
13884 len = 3;
13885 break;
13886 case FT_UINT32:
13887 len = 4;
13888 break;
13889 default:
13890 REPORT_DISSECTOR_BUG("field %s is not of type FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
13891 hfinfo->abbrev);
13894 if (flags & PROTO_CHECKSUM_NOT_PRESENT) {
13895 ti = proto_tree_add_uint_format_value(tree, hf_checksum, tvb, offset, len, 0, "[missing]");
13896 proto_item_set_generated(ti);
13897 if (hf_checksum_status != -1) {
13898 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, len, PROTO_CHECKSUM_E_NOT_PRESENT);
13899 proto_item_set_generated(ti2);
13901 return ti;
13904 if (flags & PROTO_CHECKSUM_GENERATED) {
13905 ti = proto_tree_add_uint(tree, hf_checksum, tvb, offset, len, computed_checksum);
13906 proto_item_set_generated(ti);
13907 } else {
13908 ti = proto_tree_add_item_ret_uint(tree, hf_checksum, tvb, offset, len, encoding, &checksum);
13909 if (flags & PROTO_CHECKSUM_VERIFY) {
13910 if (flags & (PROTO_CHECKSUM_IN_CKSUM|PROTO_CHECKSUM_ZERO)) {
13911 if (computed_checksum == 0) {
13912 proto_item_append_text(ti, " [correct]");
13913 if (hf_checksum_status != -1) {
13914 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
13915 proto_item_set_generated(ti2);
13917 incorrect_checksum = false;
13918 } else if (flags & PROTO_CHECKSUM_IN_CKSUM) {
13919 computed_checksum = in_cksum_shouldbe(checksum, computed_checksum);
13921 } else {
13922 if (checksum == computed_checksum) {
13923 proto_item_append_text(ti, " [correct]");
13924 if (hf_checksum_status != -1) {
13925 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
13926 proto_item_set_generated(ti2);
13928 incorrect_checksum = false;
13932 if (incorrect_checksum) {
13933 if (hf_checksum_status != -1) {
13934 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_BAD);
13935 proto_item_set_generated(ti2);
13937 if (flags & PROTO_CHECKSUM_ZERO) {
13938 proto_item_append_text(ti, " [incorrect]");
13939 if (bad_checksum_expert != NULL)
13940 expert_add_info_format(pinfo, ti, bad_checksum_expert, "%s", expert_get_summary(bad_checksum_expert));
13941 } else {
13942 proto_item_append_text(ti, " incorrect, should be 0x%0*x", len*2, computed_checksum);
13943 if (bad_checksum_expert != NULL)
13944 expert_add_info_format(pinfo, ti, bad_checksum_expert, "%s [should be 0x%0*x]", expert_get_summary(bad_checksum_expert), len * 2, computed_checksum);
13947 } else {
13948 if (hf_checksum_status != -1) {
13949 proto_item_append_text(ti, " [unverified]");
13950 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_UNVERIFIED);
13951 proto_item_set_generated(ti2);
13956 return ti;
13959 proto_item *
13960 proto_tree_add_checksum_bytes(proto_tree *tree, tvbuff_t *tvb, const unsigned offset,
13961 const int hf_checksum, const int hf_checksum_status, struct expert_field* bad_checksum_expert,
13962 packet_info *pinfo, const uint8_t *computed_checksum, size_t checksum_len, const unsigned flags)
13964 header_field_info *hfinfo;
13965 uint8_t *checksum = NULL;
13966 proto_item* ti = NULL;
13967 proto_item* ti2;
13968 bool incorrect_checksum = true;
13970 PROTO_REGISTRAR_GET_NTH(hf_checksum, hfinfo);
13972 if (hfinfo->type != FT_BYTES) {
13973 REPORT_DISSECTOR_BUG("field %s is not of type FT_BYTES",
13974 hfinfo->abbrev);
13977 if (flags & PROTO_CHECKSUM_NOT_PRESENT) {
13978 ti = proto_tree_add_bytes_format_value(tree, hf_checksum, tvb, offset, (int)checksum_len, 0, "[missing]");
13979 proto_item_set_generated(ti);
13980 if (hf_checksum_status != -1) {
13981 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, (int)checksum_len, PROTO_CHECKSUM_E_NOT_PRESENT);
13982 proto_item_set_generated(ti2);
13984 return ti;
13987 if (flags & PROTO_CHECKSUM_GENERATED) {
13988 ti = proto_tree_add_bytes(tree, hf_checksum, tvb, offset, (int)checksum_len, computed_checksum);
13989 proto_item_set_generated(ti);
13990 } else {
13991 checksum = (uint8_t*)wmem_alloc0_array(wmem_packet_scope(), uint8_t, checksum_len);
13992 tvb_memcpy(tvb, checksum, offset, checksum_len);
13993 ti = proto_tree_add_bytes(tree, hf_checksum, tvb, offset, (int)checksum_len, checksum);
13994 if (flags & PROTO_CHECKSUM_VERIFY) {
13995 if (flags & (PROTO_CHECKSUM_IN_CKSUM|PROTO_CHECKSUM_ZERO)) {
13996 if (computed_checksum == 0) {
13997 proto_item_append_text(ti, " [correct]");
13998 if (hf_checksum_status != -1) {
13999 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
14000 proto_item_set_generated(ti2);
14002 incorrect_checksum = false;
14004 } else {
14005 if (memcmp(computed_checksum, checksum, checksum_len) == 0) {
14006 proto_item_append_text(ti, " [correct]");
14007 if (hf_checksum_status != -1) {
14008 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
14009 proto_item_set_generated(ti2);
14011 incorrect_checksum = false;
14015 if (incorrect_checksum) {
14016 if (hf_checksum_status != -1) {
14017 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_BAD);
14018 proto_item_set_generated(ti2);
14020 if (flags & PROTO_CHECKSUM_ZERO) {
14021 proto_item_append_text(ti, " [incorrect]");
14022 if (bad_checksum_expert != NULL)
14023 expert_add_info_format(pinfo, ti, bad_checksum_expert, "%s", expert_get_summary(bad_checksum_expert));
14024 } else {
14025 size_t computed_checksum_str_len = (2 * checksum_len * sizeof(char)) + 1;
14026 char *computed_checksum_str = (char*)wmem_alloc0_array(wmem_packet_scope(), char, computed_checksum_str_len);
14027 for (size_t counter = 0; counter < checksum_len; ++counter) {
14028 snprintf(
14029 /* On ecah iteration inserts two characters */
14030 (char*)&computed_checksum_str[counter << 1],
14031 computed_checksum_str_len - (counter << 1),
14032 "%02x",
14033 computed_checksum[counter]);
14035 proto_item_append_text(ti, " incorrect, should be 0x%s", computed_checksum_str);
14036 if (bad_checksum_expert != NULL)
14037 expert_add_info_format(pinfo, ti, bad_checksum_expert, "%s [should be 0x%s]", expert_get_summary(bad_checksum_expert), computed_checksum_str);
14040 } else {
14041 if (hf_checksum_status != -1) {
14042 proto_item_append_text(ti, " [unverified]");
14043 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_UNVERIFIED);
14044 proto_item_set_generated(ti2);
14049 return ti;
14052 unsigned char
14053 proto_check_field_name(const char *field_name)
14055 return module_check_valid_name(field_name, false);
14058 unsigned char
14059 proto_check_field_name_lower(const char *field_name)
14061 return module_check_valid_name(field_name, true);
14064 bool
14065 tree_expanded(int tree_type)
14067 if (tree_type <= 0) {
14068 return false;
14070 ws_assert(tree_type >= 0 && tree_type < num_tree_types);
14071 return tree_is_expanded[tree_type >> 5] & (1U << (tree_type & 31));
14074 void
14075 tree_expanded_set(int tree_type, bool value)
14077 ws_assert(tree_type >= 0 && tree_type < num_tree_types);
14079 if (value)
14080 tree_is_expanded[tree_type >> 5] |= (1U << (tree_type & 31));
14081 else
14082 tree_is_expanded[tree_type >> 5] &= ~(1U << (tree_type & 31));
14086 * Editor modelines - https://www.wireshark.org/tools/modelines.html
14088 * Local variables:
14089 * c-basic-offset: 8
14090 * tab-width: 8
14091 * indent-tabs-mode: t
14092 * End:
14094 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
14095 * :indentSize=8:tabSize=8:noTabs=false: