2 * Routines for protocol tree
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
31 #include <wsutil/bits_ctz.h>
32 #include <wsutil/bits_count_ones.h>
33 #include <wsutil/sign_ext.h>
35 #include <ftypes/ftypes-int.h>
38 #include "exceptions.h"
39 #include "ptvcursor.h"
41 #include "addr_resolv.h"
42 #include "address_types.h"
45 #include "epan_dissect.h"
47 #include "wmem/wmem.h"
49 #include "asm_utils.h"
50 #include "column-utils.h"
51 #include "to_str-int.h"
53 #include "osi-utils.h"
55 #include "show_exception.h"
58 #include <wsutil/plugins.h>
59 #include <wsutil/ws_printf.h> /* ws_debug_printf/ws_g_warning */
60 #include <wsutil/glib-compat.h>
62 /* Ptvcursor limits */
63 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
64 #define SUBTREE_MAX_LEVELS 256
66 /* Throw an exception if our tree exceeds these. */
67 /* XXX - These should probably be preferences */
68 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
69 #define MAX_TREE_LEVELS (5 * 100)
71 typedef struct __subtree_lvl {
78 subtree_lvl *pushed_tree;
79 guint8 pushed_tree_index;
80 guint8 pushed_tree_max;
86 #define cVALS(x) (const value_string*)(x)
88 /** See inlined comments.
89 @param tree the tree to append this item to
90 @param free_block a code block to call to free resources if this returns
91 @return NULL if 'tree' is null */
92 #define CHECK_FOR_NULL_TREE_AND_FREE(tree, free_block) \
98 /** See inlined comments.
99 @param tree the tree to append this item to
100 @param free_block a code block to call to free resources if this returns
101 @return NULL if 'tree' is null */
102 #define CHECK_FOR_NULL_TREE(tree) \
103 CHECK_FOR_NULL_TREE_AND_FREE(tree, ((void)0))
105 /** See inlined comments.
106 @param tree the tree to append this item to
107 @param hfindex field index
108 @param hfinfo header_field
109 @param free_block a code block to call to free resources if this returns
110 @return the header field matching 'hfinfo' */
111 #define TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, free_block) \
112 /* If this item is not referenced we don't have to do much work \
113 at all but we should still return a node so that field items \
114 below this node (think proto_item_add_subtree()) will still \
115 have somewhere to attach to or else filtering will not work \
116 (they would be ignored since tree would be NULL). \
117 DON'T try to fake a node where PTREE_FINFO(tree) is NULL \
118 since dissectors that want to do proto_item_set_len() or \
119 other operations that dereference this would crash. \
120 We fake FT_PROTOCOL unless some clients have requested us \
123 PTREE_DATA(tree)->count++; \
124 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) { \
126 if (getenv("WIRESHARK_ABORT_ON_TOO_MANY_ITEMS") != NULL) \
127 g_error("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS); \
128 /* Let the exception handler add items to the tree */ \
129 PTREE_DATA(tree)->count = 0; \
130 THROW_MESSAGE(DissectorError, \
131 wmem_strdup_printf(wmem_packet_scope(), "More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS)); \
133 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
134 if (!(PTREE_DATA(tree)->visible)) { \
135 if (PTREE_FINFO(tree)) { \
136 if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
137 && (hfinfo->type != FT_PROTOCOL || \
138 PTREE_DATA(tree)->fake_protocols)) { \
140 /* just return tree back to the caller */\
146 /** See inlined comments.
147 @param tree the tree to append this item to
148 @param hfindex field index
149 @param hfinfo header_field
150 @return the header field matching 'hfinfo' */
151 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
152 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfindex, hfinfo, ((void)0))
155 /** See inlined comments.
156 @param pi the created protocol item we're about to return */
157 #define TRY_TO_FAKE_THIS_REPR(pi) \
159 if (!(PTREE_DATA(pi)->visible)) { \
160 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
161 * items string representation */ \
164 /* Same as above but returning void */
165 #define TRY_TO_FAKE_THIS_REPR_VOID(pi) \
168 if (!(PTREE_DATA(pi)->visible)) { \
169 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
170 * items string representation */ \
173 /* Similar to above, but allows a NULL tree */
174 #define TRY_TO_FAKE_THIS_REPR_NESTED(pi) \
175 if ((pi == NULL) || (!(PTREE_DATA(pi)->visible))) { \
176 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
177 * items string representation */ \
181 static const char *hf_try_val_to_str(guint32 value, const header_field_info *hfinfo);
182 static const char *hf_try_val64_to_str(guint64 value, const header_field_info *hfinfo);
183 static int hfinfo_container_bitwidth(const header_field_info *hfinfo);
185 static void label_mark_truncated(char *label_str, gsize name_pos);
186 #define LABEL_MARK_TRUNCATED_START(label_str) label_mark_truncated(label_str, 0)
188 static void fill_label_boolean(field_info *fi, gchar *label_str);
189 static void fill_label_bitfield_char(field_info *fi, gchar *label_str);
190 static void fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed);
191 static void fill_label_bitfield64(field_info *fi, gchar *label_str, gboolean is_signed);
192 static void fill_label_bitfield_varint(field_info *fi, gchar *label_str, gboolean is_signed);
193 static void fill_label_bitfield_varint64(field_info *fi, gchar *label_str, gboolean is_signed);
194 static void fill_label_char(field_info *fi, gchar *label_str);
195 static void fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed);
196 static void fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed);
198 static const char *hfinfo_char_value_format_display(int display, char buf[7], guint32 value);
199 static const char *hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value);
200 static const char *hfinfo_number_value_format_display64(const header_field_info *hfinfo, int display, char buf[48], guint64 value);
201 static const char *hfinfo_char_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
202 static const char *hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
203 static const char *hfinfo_number_vals_format64(const header_field_info *hfinfo, char buf[48], guint64 value);
204 static const char *hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
205 static const char *hfinfo_number_value_format64(const header_field_info *hfinfo, char buf[48], guint64 value);
206 static const char *hfinfo_char_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
207 static const char *hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
208 static const char *hfinfo_numeric_value_format64(const header_field_info *hfinfo, char buf[48], guint64 value);
210 static void proto_cleanup_base(void);
213 proto_tree_add_node(proto_tree *tree, field_info *fi);
216 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
217 gint *item_length, const guint encoding);
220 get_full_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
221 gint length, guint item_length, const gint encoding);
224 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
225 const gint start, const gint item_length);
228 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
229 gint start, gint *length);
232 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
234 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
237 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb, const char* field_data);
239 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
241 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
243 proto_tree_set_bytes_gbytearray(field_info *fi, const GByteArray *value);
245 proto_tree_set_time(field_info *fi, const nstime_t *value_ptr);
247 proto_tree_set_string(field_info *fi, const char* value);
249 proto_tree_set_ax25(field_info *fi, const guint8* value);
251 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start);
253 proto_tree_set_vines(field_info *fi, const guint8* value);
255 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start);
257 proto_tree_set_ether(field_info *fi, const guint8* value);
259 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
261 proto_tree_set_ipxnet(field_info *fi, guint32 value);
263 proto_tree_set_ipv4(field_info *fi, guint32 value);
265 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
267 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
269 proto_tree_set_fcwwn_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
271 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
273 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
275 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
277 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
279 proto_tree_set_system_id(field_info *fi, const guint8* value_ptr, gint length);
281 proto_tree_set_system_id_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
283 proto_tree_set_boolean(field_info *fi, guint64 value);
285 proto_tree_set_float(field_info *fi, float value);
287 proto_tree_set_double(field_info *fi, double value);
289 proto_tree_set_uint(field_info *fi, guint32 value);
291 proto_tree_set_int(field_info *fi, gint32 value);
293 proto_tree_set_uint64(field_info *fi, guint64 value);
295 proto_tree_set_int64(field_info *fi, gint64 value);
297 proto_tree_set_eui64(field_info *fi, const guint64 value);
299 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
301 /* Handle type length mismatch (now filterable) expert info */
302 static int proto_type_length_mismatch = -1;
303 static expert_field ei_type_length_mismatch_error = EI_INIT;
304 static expert_field ei_type_length_mismatch_warn = EI_INIT;
305 static void register_type_length_mismatch(void);
307 /* Handle number string decoding errors with expert info */
308 static int proto_number_string_decoding_error = -1;
309 static expert_field ei_number_string_decoding_failed_error = EI_INIT;
310 static expert_field ei_number_string_decoding_erange_error = EI_INIT;
311 static void register_number_string_decoding_error(void);
313 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
315 /* special-case header field used within proto.c */
316 static header_field_info hfi_text_only =
317 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
318 int hf_text_only = -1;
320 /* Structure for information about a protocol */
322 const char *name; /* long description */
323 const char *short_name; /* short description */
324 const char *filter_name; /* name of this protocol in filters */
325 GPtrArray *fields; /* fields for this protocol */
326 int proto_id; /* field ID for this protocol */
327 gboolean is_enabled; /* TRUE if protocol is enabled */
328 gboolean enabled_by_default; /* TRUE if protocol is enabled by default */
329 gboolean can_toggle; /* TRUE if is_enabled can be changed */
330 int parent_proto_id; /* Used to identify "pino"s (Protocol In Name Only).
331 For dissectors that need a protocol name so they
332 can be added to a dissector table, but use the
333 parent_proto_id for things like enable/disable */
334 GList *heur_list; /* Heuristic dissectors associated with this protocol */
337 /* List of all protocols */
338 static GList *protocols = NULL;
339 static GList *pino_protocols = NULL;
341 /* Deregistered fields */
342 static GPtrArray *deregistered_fields = NULL;
343 static GPtrArray *deregistered_data = NULL;
345 /* indexed by prefix, contains initializers */
346 static GHashTable* prefixes = NULL;
348 /* Contains information about a field when a dissector calls
349 * proto_tree_add_item. */
350 #define FIELD_INFO_NEW(pool, fi) fi = wmem_new(pool, field_info)
351 #define FIELD_INFO_FREE(pool, fi) wmem_free(pool, fi)
353 /* Contains the space for proto_nodes. */
354 #define PROTO_NODE_INIT(node) \
355 node->first_child = NULL; \
356 node->last_child = NULL; \
359 #define PROTO_NODE_FREE(pool, node) \
360 wmem_free(pool, node)
362 /* String space for protocol and field items for the GUI */
363 #define ITEM_LABEL_NEW(pool, il) \
364 il = wmem_new(pool, item_label_t);
365 #define ITEM_LABEL_FREE(pool, il) \
368 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
369 if((guint)hfindex >= gpa_hfinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG")) \
370 g_error("Unregistered hf! index=%d", hfindex); \
371 DISSECTOR_ASSERT_HINT((guint)hfindex < gpa_hfinfo.len, "Unregistered hf!"); \
372 DISSECTOR_ASSERT_HINT(gpa_hfinfo.hfi[hfindex] != NULL, "Unregistered hf!"); \
373 hfinfo = gpa_hfinfo.hfi[hfindex];
375 /* List which stores protocols and fields that have been registered */
376 typedef struct _gpa_hfinfo_t {
378 guint32 allocated_len;
379 header_field_info **hfi;
382 static gpa_hfinfo_t gpa_hfinfo;
384 /* Hash table of abbreviations and IDs */
385 static GHashTable *gpa_name_map = NULL;
386 static header_field_info *same_name_hfinfo;
388 * We're called repeatedly with the same field name when sorting a column.
389 * Cache our last gpa_name_map hit for faster lookups.
391 static char *last_field_name = NULL;
392 static header_field_info *last_hfinfo;
394 static void save_same_name_hfinfo(gpointer data)
396 same_name_hfinfo = (header_field_info*)data;
399 /* Cached value for VINES address type (used for FT_VINES) */
400 static int vines_address_type = -1;
402 /* Points to the first element of an array of bits, indexed by
403 a subtree item type; that array element is TRUE if subtrees of
404 an item of that type are to be expanded. */
405 static guint32 *tree_is_expanded;
407 /* Number of elements in that array. */
410 /* Name hashtables for fast detection of duplicate names */
411 static GHashTable* proto_names = NULL;
412 static GHashTable* proto_short_names = NULL;
413 static GHashTable* proto_filter_names = NULL;
416 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
418 const protocol_t *p1 = (const protocol_t *)p1_arg;
419 const protocol_t *p2 = (const protocol_t *)p2_arg;
421 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
426 * List of dissector plugins.
429 void (*register_protoinfo)(void); /* routine to call to register protocol information */
430 void (*reg_handoff)(void); /* routine to call to register dissector handoff */
433 static GSList *dissector_plugins = NULL;
436 * Callback for each plugin found.
440 check_for_dissector_plugin(GModule *handle)
443 void (*register_protoinfo)(void);
444 void (*reg_handoff)(void);
445 dissector_plugin *plugin;
448 * Do we have a register routine?
450 if (g_module_symbol(handle, "plugin_register", &gp)) {
451 register_protoinfo = (void (*)(void))gp;
454 register_protoinfo = NULL;
458 * Do we have a reg_handoff routine?
460 if (g_module_symbol(handle, "plugin_reg_handoff", &gp)) {
461 reg_handoff = (void (*)(void))gp;
468 * If we have neither, we're not a dissector plugin.
470 if (register_protoinfo == NULL && reg_handoff == NULL)
474 * Add this one to the list of dissector plugins.
476 plugin = (dissector_plugin *)g_malloc(sizeof (dissector_plugin));
477 plugin->register_protoinfo = register_protoinfo;
478 plugin->reg_handoff = reg_handoff;
479 dissector_plugins = g_slist_prepend(dissector_plugins, plugin);
485 register_dissector_plugin(gpointer data, gpointer user_data _U_)
487 dissector_plugin *plugin = (dissector_plugin *)data;
489 if (plugin->register_protoinfo)
490 (plugin->register_protoinfo)();
494 reg_handoff_dissector_plugin(gpointer data, gpointer user_data _U_)
496 dissector_plugin *plugin = (dissector_plugin *)data;
498 if (plugin->reg_handoff)
499 (plugin->reg_handoff)();
503 * Register dissector plugin type.
506 register_dissector_plugin_type(void)
508 add_plugin_type("dissector", check_for_dissector_plugin);
512 dissector_plugin_destroy(gpointer p)
517 #endif /* HAVE_PLUGINS */
519 /* initialize data structures and register protocols and fields */
521 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
522 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
524 gpointer client_data)
526 proto_cleanup_base();
528 proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
529 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
530 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
533 gpa_hfinfo.allocated_len = 0;
534 gpa_hfinfo.hfi = NULL;
535 gpa_name_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, save_same_name_hfinfo);
536 deregistered_fields = g_ptr_array_new();
537 deregistered_data = g_ptr_array_new();
539 /* Initialize the ftype subsystem */
542 /* Initialize the addres type subsystem */
543 address_types_initialize();
545 /* Register one special-case FT_TEXT_ONLY field for use when
546 converting wireshark to new-style proto_tree. These fields
547 are merely strings on the GUI tree; they are not filterable */
548 hf_text_only = proto_register_field_init(&hfi_text_only, -1);
550 /* Register the pseudo-protocols used for exceptions. */
551 register_show_exception();
552 register_type_length_mismatch();
553 register_number_string_decoding_error();
555 /* Have each built-in dissector register its protocols, fields,
556 dissector tables, and dissectors to be called through a
557 handle, and do whatever one-time initialization it needs to
559 register_all_protocols_func(cb, client_data);
561 /* Now that the VINES dissector has registered it's address
562 type, grab the value for the field type */
563 vines_address_type = address_type_get_by_name("AT_VINES");
565 /* Now call the registration routines for all disssector
568 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
569 g_slist_foreach(dissector_plugins, register_dissector_plugin, NULL);
572 /* Now call the "handoff registration" routines of all built-in
573 dissectors; those routines register the dissector in other
574 dissectors' handoff tables, and fetch any dissector handles
576 register_all_handoffs_func(cb, client_data);
579 /* Now do the same with plugins. */
581 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
582 g_slist_foreach(dissector_plugins, reg_handoff_dissector_plugin, NULL);
585 /* sort the protocols by protocol name */
586 protocols = g_list_sort(protocols, proto_compare_name);
588 /* We've assigned all the subtree type values; allocate the array
589 for them, and zero it out. */
590 tree_is_expanded = g_new0(guint32, (num_tree_types/32)+1);
594 proto_cleanup_base(void)
596 protocol_t *protocol;
597 header_field_info *hfinfo;
599 /* Free the abbrev/ID hash table */
601 g_hash_table_destroy(gpa_name_map);
604 g_free(last_field_name);
605 last_field_name = NULL;
608 protocol = (protocol_t *)protocols->data;
609 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
610 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
612 g_slice_free(header_field_info, hfinfo);
613 if (protocol->fields) {
614 g_ptr_array_free(protocol->fields, TRUE);
616 g_list_free(protocol->heur_list);
617 protocols = g_list_remove(protocols, protocol);
621 while (pino_protocols) {
622 protocol = (protocol_t *)pino_protocols->data;
623 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
624 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
625 DISSECTOR_ASSERT(protocol->fields == NULL); //helpers should not have any registered fields
626 g_slice_free(header_field_info, hfinfo);
627 DISSECTOR_ASSERT(protocol->heur_list == NULL); //helpers should not have a heuristic list
628 pino_protocols = g_list_remove(pino_protocols, protocol);
633 g_hash_table_destroy(proto_names);
637 if (proto_short_names) {
638 g_hash_table_destroy(proto_short_names);
639 proto_short_names = NULL;
642 if (proto_filter_names) {
643 g_hash_table_destroy(proto_filter_names);
644 proto_filter_names = NULL;
647 if (gpa_hfinfo.allocated_len) {
649 gpa_hfinfo.allocated_len = 0;
650 g_free(gpa_hfinfo.hfi);
651 gpa_hfinfo.hfi = NULL;
654 if (deregistered_fields) {
655 g_ptr_array_free(deregistered_fields, FALSE);
656 deregistered_fields = NULL;
659 if (deregistered_data) {
660 g_ptr_array_free(deregistered_data, FALSE);
661 deregistered_data = NULL;
664 g_free(tree_is_expanded);
665 tree_is_expanded = NULL;
668 g_hash_table_destroy(prefixes);
674 proto_cleanup_base();
677 if (dissector_plugins) {
678 g_slist_free_full(dissector_plugins, dissector_plugin_destroy);
679 dissector_plugins = NULL;
685 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
688 proto_node *pnode = tree;
692 if (func(pnode, data))
695 child = pnode->first_child;
696 while (child != NULL) {
698 * The routine we call might modify the child, e.g. by
699 * freeing it, so we get the child's successor before
700 * calling that routine.
703 child = current->next;
704 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
712 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
715 proto_node *pnode = tree;
719 child = pnode->first_child;
720 while (child != NULL) {
722 * The routine we call might modify the child, e.g. by
723 * freeing it, so we get the child's successor before
724 * calling that routine.
727 child = current->next;
728 if (proto_tree_traverse_post_order((proto_tree *)current, func, data))
731 if (func(pnode, data))
738 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
741 proto_node *node = tree;
747 node = node->first_child;
748 while (node != NULL) {
750 node = current->next;
751 func((proto_tree *)current, data);
756 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
758 GPtrArray *ptrs = (GPtrArray *)value;
759 gint hfid = GPOINTER_TO_UINT(key);
760 header_field_info *hfinfo;
762 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
763 if (hfinfo->ref_type != HF_REF_TYPE_NONE) {
764 /* when a field is referenced by a filter this also
765 affects the refcount for the parent protocol so we need
766 to adjust the refcount for the parent as well
768 if (hfinfo->parent != -1) {
769 header_field_info *parent_hfinfo;
770 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
771 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
773 hfinfo->ref_type = HF_REF_TYPE_NONE;
776 g_ptr_array_free(ptrs, TRUE);
780 proto_tree_free_node(proto_node *node, gpointer data _U_)
782 field_info *finfo = PNODE_FINFO(node);
784 proto_tree_children_foreach(node, proto_tree_free_node, NULL);
786 FVALUE_CLEANUP(&finfo->value);
790 proto_tree_reset(proto_tree *tree)
792 tree_data_t *tree_data = PTREE_DATA(tree);
794 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
797 if (tree_data->interesting_hfids) {
798 /* Free all the GPtrArray's in the interesting_hfids hash. */
799 g_hash_table_foreach(tree_data->interesting_hfids,
800 free_GPtrArray_value, NULL);
802 /* And then remove all values. */
803 g_hash_table_remove_all(tree_data->interesting_hfids);
806 /* Reset track of the number of children */
807 tree_data->count = 0;
809 PROTO_NODE_INIT(tree);
812 /* frees the resources that the dissection a proto_tree uses */
814 proto_tree_free(proto_tree *tree)
816 tree_data_t *tree_data = PTREE_DATA(tree);
818 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
821 if (tree_data->interesting_hfids) {
822 /* Free all the GPtrArray's in the interesting_hfids hash. */
823 g_hash_table_foreach(tree_data->interesting_hfids,
824 free_GPtrArray_value, NULL);
826 /* And then destroy the hash. */
827 g_hash_table_destroy(tree_data->interesting_hfids);
830 g_slice_free(tree_data_t, tree_data);
832 g_slice_free(proto_tree, tree);
835 /* Is the parsing being done for a visible proto_tree or an invisible one?
836 * By setting this correctly, the proto_tree creation is sped up by not
837 * having to call g_vsnprintf and copy strings around.
840 proto_tree_set_visible(proto_tree *tree, gboolean visible)
842 gboolean old_visible = PTREE_DATA(tree)->visible;
844 PTREE_DATA(tree)->visible = visible;
850 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
852 PTREE_DATA(tree)->fake_protocols = fake_protocols;
855 /* Assume dissector set only its protocol fields.
856 This function is called by dissectors and allows the speeding up of filtering
857 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
858 and thus skip calling most of the expensive proto_tree_add_...()
860 If the tree is visible we implicitly assume the field is referenced.
863 proto_field_is_referenced(proto_tree *tree, int proto_id)
865 register header_field_info *hfinfo;
871 if (PTREE_DATA(tree)->visible)
874 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
875 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
878 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
885 /* Finds a record in the hfinfo array by id. */
887 proto_registrar_get_nth(guint hfindex)
889 register header_field_info *hfinfo;
891 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
896 /* Prefix initialization
897 * this allows for a dissector to register a display filter name prefix
898 * so that it can delay the initialization of the hf array as long as
902 /* compute a hash for the part before the dot of a display filter */
904 prefix_hash (gconstpointer key) {
905 /* end the string at the dot and compute its hash */
906 gchar* copy = g_strdup((const gchar *)key);
917 tmp = g_str_hash(copy);
922 /* are both strings equal up to the end or the dot? */
924 prefix_equal (gconstpointer ap, gconstpointer bp) {
925 const gchar* a = (const gchar *)ap;
926 const gchar* b = (const gchar *)bp;
932 if ( (ac == '.' || ac == '\0') && (bc == '.' || bc == '\0') ) return TRUE;
934 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
935 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
937 if (ac != bc) return FALSE;
943 /* Register a new prefix for "delayed" initialization of field arrays */
945 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
947 prefixes = g_hash_table_new(prefix_hash, prefix_equal);
950 g_hash_table_insert(prefixes, (gpointer)prefix, (gpointer)pi);
953 /* helper to call all prefix initializers */
955 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
956 ((prefix_initializer_t)v)((const char *)k);
960 /** Initialize every remaining uninitialized prefix. */
962 proto_initialize_all_prefixes(void) {
963 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
966 /* Finds a record in the hfinfo array by name.
967 * If it fails to find it in the already registered fields,
968 * it tries to find and call an initializer in the prefixes
969 * table and if so it looks again.
973 proto_registrar_get_byname(const char *field_name)
975 header_field_info *hfinfo;
976 prefix_initializer_t pi;
981 if (g_strcmp0(field_name, last_field_name) == 0) {
985 hfinfo = (header_field_info *)g_hash_table_lookup(gpa_name_map, field_name);
988 g_free(last_field_name);
989 last_field_name = g_strdup(field_name);
990 last_hfinfo = hfinfo;
997 if ((pi = (prefix_initializer_t)g_hash_table_lookup(prefixes, field_name) ) != NULL) {
999 g_hash_table_remove(prefixes, field_name);
1004 hfinfo = (header_field_info *)g_hash_table_lookup(gpa_name_map, field_name);
1007 g_free(last_field_name);
1008 last_field_name = g_strdup(field_name);
1009 last_hfinfo = hfinfo;
1015 proto_registrar_get_id_byname(const char *field_name)
1017 header_field_info *hfinfo;
1019 hfinfo = proto_registrar_get_byname(field_name);
1029 ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
1031 subtree_lvl *pushed_tree;
1033 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
1034 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
1036 pushed_tree = (subtree_lvl *)wmem_alloc(wmem_packet_scope(), sizeof(subtree_lvl) * ptvc->pushed_tree_max);
1037 DISSECTOR_ASSERT(pushed_tree != NULL);
1038 if (ptvc->pushed_tree)
1039 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
1040 ptvc->pushed_tree = pushed_tree;
1044 ptvcursor_free_subtree_levels(ptvcursor_t *ptvc)
1046 ptvc->pushed_tree = NULL;
1047 ptvc->pushed_tree_max = 0;
1048 DISSECTOR_ASSERT(ptvc->pushed_tree_index == 0);
1049 ptvc->pushed_tree_index = 0;
1052 /* Allocates an initializes a ptvcursor_t with 3 variables:
1053 * proto_tree, tvbuff, and offset. */
1055 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
1059 ptvc = (ptvcursor_t *)wmem_alloc(wmem_packet_scope(), sizeof(ptvcursor_t));
1062 ptvc->offset = offset;
1063 ptvc->pushed_tree = NULL;
1064 ptvc->pushed_tree_max = 0;
1065 ptvc->pushed_tree_index = 0;
1070 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
1072 ptvcursor_free(ptvcursor_t *ptvc)
1074 ptvcursor_free_subtree_levels(ptvc);
1078 /* Returns tvbuff. */
1080 ptvcursor_tvbuff(ptvcursor_t *ptvc)
1085 /* Returns current offset. */
1087 ptvcursor_current_offset(ptvcursor_t *ptvc)
1089 return ptvc->offset;
1093 ptvcursor_tree(ptvcursor_t *ptvc)
1102 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
1107 /* creates a subtree, sets it as the working tree and pushes the old working tree */
1109 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
1111 subtree_lvl *subtree;
1112 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
1113 ptvcursor_new_subtree_levels(ptvc);
1115 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
1116 subtree->tree = ptvc->tree;
1118 ptvc->pushed_tree_index++;
1119 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
1122 /* pops a subtree */
1124 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
1126 subtree_lvl *subtree;
1128 if (ptvc->pushed_tree_index <= 0)
1131 ptvc->pushed_tree_index--;
1132 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
1133 if (subtree->it != NULL)
1134 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
1136 ptvc->tree = subtree->tree;
1139 /* saves the current tvb offset and the item in the current subtree level */
1141 ptvcursor_subtree_set_item(ptvcursor_t *ptvc, proto_item *it)
1143 subtree_lvl *subtree;
1145 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
1147 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index - 1;
1149 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
1152 /* Creates a subtree and adds it to the cursor as the working tree but does not
1153 * save the old working tree */
1155 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
1157 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
1162 ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree, gint length)
1164 ptvcursor_push_subtree(ptvc, it, ett_subtree);
1165 if (length == SUBTREE_UNDEFINED_LENGTH)
1166 ptvcursor_subtree_set_item(ptvc, it);
1167 return ptvcursor_tree(ptvc);
1170 /* Add an item to the tree and create a subtree
1171 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1172 * In this case, when the subtree will be closed, the parent item length will
1173 * be equal to the advancement of the cursor since the creation of the subtree.
1176 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, gint length,
1177 const guint encoding, gint ett_subtree)
1181 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
1182 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
1186 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
1188 /* Add a text node to the tree and create a subtree
1189 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1190 * In this case, when the subtree will be closed, the item length will be equal
1191 * to the advancement of the cursor since the creation of the subtree.
1194 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
1195 gint ett_subtree, const char *format, ...)
1199 header_field_info *hfinfo;
1202 tree = ptvcursor_tree(ptvc);
1204 CHECK_FOR_NULL_TREE(tree);
1206 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1208 pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
1209 ptvcursor_current_offset(ptvc), length);
1211 TRY_TO_FAKE_THIS_REPR(pi);
1213 va_start(ap, format);
1214 proto_tree_set_representation(pi, format, ap);
1217 return ptvcursor_add_subtree_item(ptvc, pi, ett_subtree, length);
1220 /* Add a text-only node, leaving it to our caller to fill the text in */
1222 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1229 pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length);
1234 /* (INTERNAL USE ONLY) Add a text-only node to the proto_tree */
1236 proto_tree_add_text_internal(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
1237 const char *format, ...)
1241 header_field_info *hfinfo;
1244 length = tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
1246 tvb_ensure_bytes_exist(tvb, start, length);
1249 CHECK_FOR_NULL_TREE(tree);
1251 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1253 pi = proto_tree_add_text_node(tree, tvb, start, length);
1255 TRY_TO_FAKE_THIS_REPR(pi);
1257 va_start(ap, format);
1258 proto_tree_set_representation(pi, format, ap);
1264 /* (INTERNAL USE ONLY) Add a text-only node to the proto_tree (va_list version) */
1266 proto_tree_add_text_valist_internal(proto_tree *tree, tvbuff_t *tvb, gint start,
1267 gint length, const char *format, va_list ap)
1270 header_field_info *hfinfo;
1273 length = tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
1275 tvb_ensure_bytes_exist(tvb, start, length);
1278 CHECK_FOR_NULL_TREE(tree);
1280 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1282 pi = proto_tree_add_text_node(tree, tvb, start, length);
1284 TRY_TO_FAKE_THIS_REPR(pi);
1286 proto_tree_set_representation(pi, format, ap);
1291 /* Add a text-only node that creates a subtree underneath.
1294 proto_tree_add_subtree(proto_tree *tree, tvbuff_t *tvb, gint start, gint length, gint idx, proto_item **tree_item, const char *text)
1296 return proto_tree_add_subtree_format(tree, tvb, start, length, idx, tree_item, "%s", text);
1299 /* Add a text-only node that creates a subtree underneath.
1302 proto_tree_add_subtree_format(proto_tree *tree, tvbuff_t *tvb, gint start, gint length, gint idx, proto_item **tree_item, const char *format, ...)
1308 va_start(ap, format);
1309 pi = proto_tree_add_text_valist_internal(tree, tvb, start, length, format, ap);
1312 if (tree_item != NULL)
1315 pt = proto_item_add_subtree(pi, idx);
1320 /* Add a text-only node for debugging purposes. The caller doesn't need
1321 * to worry about tvbuff, start, or length. Debug message gets sent to
1324 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1329 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1332 va_start(ap, format);
1333 proto_tree_set_representation(pi, format, ap);
1336 va_start(ap, format);
1337 vprintf(format, ap);
1339 ws_debug_printf("\n");
1345 proto_tree_add_format_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1348 header_field_info *hfinfo;
1350 CHECK_FOR_NULL_TREE(tree);
1352 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1354 pi = proto_tree_add_text_node(tree, tvb, start, length);
1356 TRY_TO_FAKE_THIS_REPR(pi);
1358 proto_item_set_text(pi, "%s", tvb_format_text(tvb, start, length));
1364 proto_tree_add_format_wsp_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1367 header_field_info *hfinfo;
1370 CHECK_FOR_NULL_TREE(tree);
1372 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1374 pi = proto_tree_add_text_node(tree, tvb, start, length);
1376 TRY_TO_FAKE_THIS_REPR(pi);
1378 str = tvb_format_text_wsp(NULL, tvb, start, length);
1379 proto_item_set_text(pi, "%s", str);
1380 wmem_free(NULL, str);
1385 void proto_report_dissector_bug(const char *message)
1387 if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
1390 THROW_MESSAGE(DissectorError, message);
1393 /* We could probably get away with changing is_error to a minimum length value. */
1395 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
1398 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_error, "Trying to fetch %s with length %d", descr, length);
1400 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_warn, "Trying to fetch %s with length %d", descr, length);
1404 THROW(ReportedBoundsError);
1409 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1412 gboolean length_error;
1417 value = tvb_get_guint8(tvb, offset);
1421 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1422 : tvb_get_ntohs(tvb, offset);
1426 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1427 : tvb_get_ntoh24(tvb, offset);
1431 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1432 : tvb_get_ntohl(tvb, offset);
1437 length_error = TRUE;
1440 length_error = FALSE;
1441 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1442 : tvb_get_ntohl(tvb, offset);
1444 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1450 static inline guint64
1451 get_uint64_value(proto_tree *tree, tvbuff_t *tvb, gint offset, guint length, const guint encoding)
1454 gboolean length_error;
1459 value = tvb_get_guint8(tvb, offset);
1463 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1464 : tvb_get_ntohs(tvb, offset);
1468 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1469 : tvb_get_ntoh24(tvb, offset);
1473 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1474 : tvb_get_ntohl(tvb, offset);
1478 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh40(tvb, offset)
1479 : tvb_get_ntoh40(tvb, offset);
1483 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh48(tvb, offset)
1484 : tvb_get_ntoh48(tvb, offset);
1488 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh56(tvb, offset)
1489 : tvb_get_ntoh56(tvb, offset);
1493 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh64(tvb, offset)
1494 : tvb_get_ntoh64(tvb, offset);
1499 length_error = TRUE;
1502 length_error = FALSE;
1503 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh64(tvb, offset)
1504 : tvb_get_ntoh64(tvb, offset);
1506 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1513 get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1516 gboolean length_error;
1521 value = (gint8)tvb_get_guint8(tvb, offset);
1525 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1526 : tvb_get_ntohs(tvb, offset));
1530 value = encoding ? tvb_get_letoh24(tvb, offset)
1531 : tvb_get_ntoh24(tvb, offset);
1532 if (value & 0x00800000) {
1533 /* Sign bit is set; sign-extend it. */
1534 value |= 0xFF000000;
1539 value = encoding ? tvb_get_letohl(tvb, offset)
1540 : tvb_get_ntohl(tvb, offset);
1545 length_error = TRUE;
1548 length_error = FALSE;
1549 value = encoding ? tvb_get_letohl(tvb, offset)
1550 : tvb_get_ntohl(tvb, offset);
1552 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1558 /* Note: this returns an unsigned int64, but with the appropriate bit(s) set to
1559 * be cast-able as a gint64. This is weird, but what the code has always done.
1561 static inline guint64
1562 get_int64_value(proto_tree *tree, tvbuff_t *tvb, gint start, guint length, const guint encoding)
1564 guint64 value = get_uint64_value(tree, tvb, start, length, encoding);
1569 value = ws_sign_ext64(value, 56);
1572 value = ws_sign_ext64(value, 48);
1575 value = ws_sign_ext64(value, 40);
1578 value = ws_sign_ext64(value, 32);
1581 value = ws_sign_ext64(value, 24);
1584 value = ws_sign_ext64(value, 16);
1587 value = ws_sign_ext64(value, 8);
1595 static inline const guint8 *
1596 get_string_value(wmem_allocator_t *scope, tvbuff_t *tvb, gint start,
1597 gint length, gint *ret_length, const guint encoding)
1600 length = tvb_ensure_captured_length_remaining(tvb, start);
1602 *ret_length = length;
1603 return tvb_get_string_enc(scope, tvb, start, length, encoding);
1606 /* For FT_STRINGZ */
1607 static inline const guint8 *
1608 get_stringz_value(wmem_allocator_t *scope, proto_tree *tree, tvbuff_t *tvb,
1609 gint start, gint length, gint *ret_length, const guint encoding)
1611 const guint8 *value;
1614 report_type_length_mismatch(tree, "a string", length, TRUE);
1617 /* This can throw an exception */
1618 value = tvb_get_stringz_enc(scope, tvb, start, &length, encoding);
1619 } else if (length == 0) {
1622 /* In this case, length signifies the length of the string.
1624 * This could either be a null-padded string, which doesn't
1625 * necessarily have a '\0' at the end, or a null-terminated
1626 * string, with a trailing '\0'. (Yes, there are cases
1627 * where you have a string that's both counted and null-
1630 * In the first case, we must allocate a buffer of length
1631 * "length+1", to make room for a trailing '\0'.
1633 * In the second case, we don't assume that there is a
1634 * trailing '\0' there, as the packet might be malformed.
1635 * (XXX - should we throw an exception if there's no
1636 * trailing '\0'?) Therefore, we allocate a buffer of
1637 * length "length+1", and put in a trailing '\0', just to
1640 * (XXX - this would change if we made string values counted
1641 * rather than null-terminated.)
1643 value = tvb_get_string_enc(scope, tvb, start, length, encoding);
1645 *ret_length = length;
1649 /* For FT_UINT_STRING */
1650 static inline const guint8 *
1651 get_uint_string_value(wmem_allocator_t *scope, proto_tree *tree,
1652 tvbuff_t *tvb, gint start, gint length, gint *ret_length,
1653 const guint encoding)
1656 const guint8 *value;
1658 /* I believe it's ok if this is called with a NULL tree */
1659 n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1660 value = tvb_get_string_enc(scope, tvb, start + length, n, encoding);
1662 *ret_length = length;
1666 /* For FT_STRINGZPAD */
1667 static inline const guint8 *
1668 get_stringzpad_value(wmem_allocator_t *scope, tvbuff_t *tvb, gint start,
1669 gint length, gint *ret_length, const guint encoding)
1672 * XXX - currently, string values are null-
1673 * terminated, so a "zero-padded" string
1674 * isn't special. If we represent string
1675 * values as something that includes a counted
1676 * array of bytes, we'll need to strip
1680 length = tvb_ensure_captured_length_remaining(tvb, start);
1682 *ret_length = length;
1683 return tvb_get_string_enc(scope, tvb, start, length, encoding);
1687 * Epochs for various non-UN*X time stamp formats.
1689 #define NTP_BASETIME G_GUINT64_CONSTANT(2208988800) /* NTP */
1690 #define TOD_BASETIME G_GUINT64_CONSTANT(2208988800) /* System/3x0 and z/Architecture TOD clock */
1692 /* this can be called when there is no tree, so tree may be null */
1694 get_time_value(proto_tree *tree, tvbuff_t *tvb, const gint start,
1695 const gint length, const guint encoding, nstime_t *time_stamp,
1696 const gboolean is_relative)
1703 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1705 * 4-byte seconds, followed by 4-byte fractional
1706 * time in nanoseconds, both big-endian.
1707 * For absolute times, the seconds are seconds
1708 * since the UN*X epoch.
1710 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
1712 time_stamp->nsecs = tvb_get_ntohl(tvb, start+4);
1713 else if (length == 4) {
1715 * Backwards compatibility.
1717 time_stamp->nsecs = 0;
1719 report_type_length_mismatch(tree, "a timespec", length, TRUE);
1722 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1724 * 4-byte UNIX epoch, possibly followed by
1725 * 4-byte fractional time in nanoseconds,
1726 * both little-endian.
1727 * For absolute times, the seconds are seconds
1728 * since the UN*X epoch.
1730 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
1732 time_stamp->nsecs = tvb_get_letohl(tvb, start+4);
1733 else if (length == 4) {
1735 * Backwards compatibility.
1737 time_stamp->nsecs = 0;
1739 report_type_length_mismatch(tree, "a timespec", length, TRUE);
1742 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1744 * NTP time stamp, big-endian.
1745 * Only supported for absolute times.
1747 DISSECTOR_ASSERT(!is_relative);
1749 /* We need a temporary variable here so the unsigned math
1750 * works correctly (for years > 2036 according to RFC 2030
1753 tmpsecs = tvb_get_ntohl(tvb, start);
1755 time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
1757 time_stamp->secs = tmpsecs; /* 0 */
1761 * Convert 1/2^32s of a second to nanoseconds.
1763 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1764 } else if (length == 4) {
1766 * Backwards compatibility.
1768 time_stamp->nsecs = 0;
1770 report_type_length_mismatch(tree, "an NTP time stamp", length, TRUE);
1773 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1775 * NTP time stamp, little-endian.
1776 * Only supported for absolute times.
1778 DISSECTOR_ASSERT(!is_relative);
1780 tmpsecs = tvb_get_letohl(tvb, start);
1782 time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
1784 time_stamp->secs = tmpsecs; /* 0 */
1788 * Convert 1/2^32s of a second to nanoseconds.
1790 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1791 } else if (length == 4) {
1793 * Backwards compatibility.
1795 time_stamp->nsecs = 0;
1797 report_type_length_mismatch(tree, "an NTP time stamp", length, TRUE);
1800 case ENC_TIME_TOD|ENC_BIG_ENDIAN:
1802 * S/3x0 and z/Architecture TOD clock time stamp,
1804 * Only supported for absolute times.
1806 DISSECTOR_ASSERT(!is_relative);
1807 DISSECTOR_ASSERT(length == 8);
1810 todsecs = tvb_get_ntoh64(tvb, start) >> 12;
1811 time_stamp->secs = (time_t)((todsecs / 1000000) - TOD_BASETIME);
1812 time_stamp->nsecs = (int)((todsecs % 1000000) * 1000);
1814 report_type_length_mismatch(tree, "a TOD clock time stamp", length, TRUE);
1817 case ENC_TIME_TOD|ENC_LITTLE_ENDIAN:
1819 * S/3x0 and z/Architecture TOD clock time stamp,
1821 * Only supported for absolute times.
1823 DISSECTOR_ASSERT(!is_relative);
1826 todsecs = tvb_get_letoh64(tvb, start) >> 12 ;
1827 time_stamp->secs = (time_t)((todsecs / 1000000) - TOD_BASETIME);
1828 time_stamp->nsecs = (int)((todsecs % 1000000) * 1000);
1830 report_type_length_mismatch(tree, "a TOD clock time stamp", length, TRUE);
1833 case ENC_TIME_RTPS|ENC_BIG_ENDIAN:
1835 * Time stamp using the same seconds/fraction format
1836 * as NTP, but with the origin of the time stamp being
1837 * the UNIX epoch rather than the NTP epoch; big-
1840 * Only supported for absolute times.
1842 DISSECTOR_ASSERT(!is_relative);
1845 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
1847 * Convert 1/2^32s of a second to nanoseconds.
1849 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1851 report_type_length_mismatch(tree, "an RTPS time stamp", length, TRUE);
1854 case ENC_TIME_RTPS|ENC_LITTLE_ENDIAN:
1856 * Time stamp using the same seconds/fraction format
1857 * as NTP, but with the origin of the time stamp being
1858 * the UNIX epoch rather than the NTP epoch; little-
1861 * Only supported for absolute times.
1863 DISSECTOR_ASSERT(!is_relative);
1866 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
1868 * Convert 1/2^32s of a second to nanoseconds.
1870 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1872 report_type_length_mismatch(tree, "an RTPS time stamp", length, TRUE);
1875 case ENC_TIME_TIMEVAL|ENC_BIG_ENDIAN:
1877 * 4-byte seconds, followed by 4-byte fractional
1878 * time in microseconds, both big-endian.
1879 * For absolute times, the seconds are seconds
1880 * since the UN*X epoch.
1883 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
1884 time_stamp->nsecs = tvb_get_ntohl(tvb, start+4)*1000;
1886 report_type_length_mismatch(tree, "a timeval", length, TRUE);
1889 case ENC_TIME_TIMEVAL|ENC_LITTLE_ENDIAN:
1891 * 4-byte seconds, followed by 4-byte fractional
1892 * time in microseconds, both little-endian.
1893 * For absolute times, the seconds are seconds
1894 * since the UN*X epoch.
1897 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
1898 time_stamp->nsecs = tvb_get_letohl(tvb, start+4)*1000;
1900 report_type_length_mismatch(tree, "a timeval", length, TRUE);
1903 case ENC_TIME_SECS|ENC_BIG_ENDIAN:
1904 case ENC_TIME_SECS|ENC_LITTLE_ENDIAN:
1906 * Seconds, 1 to 8 bytes.
1907 * For absolute times, it's seconds since the
1910 if (length >= 1 && length <= 8) {
1911 time_stamp->secs = (time_t)get_uint64_value(tree, tvb, start, length, encoding);
1912 time_stamp->nsecs = 0;
1914 report_type_length_mismatch(tree, "a time-in-seconds time stamp", length, TRUE);
1917 case ENC_TIME_MSECS|ENC_BIG_ENDIAN:
1919 * Milliseconds, 1 to 8 bytes.
1920 * For absolute times, it's milliseconds since the
1923 if (length >= 1 && length <= 8) {
1926 msecs = get_uint64_value(tree, tvb, start, length, encoding);
1927 time_stamp->secs = (time_t)(msecs / 1000);
1928 time_stamp->nsecs = (int)(msecs % 1000)*1000000;
1930 report_type_length_mismatch(tree, "a time-in-milliseconds time stamp", length, TRUE);
1933 case ENC_TIME_RFC_3971|ENC_BIG_ENDIAN:
1935 * 1/64ths of a second since the UN*X epoch,
1938 * Only supported for absolute times.
1940 DISSECTOR_ASSERT(!is_relative);
1944 * The upper 48 bits are seconds since the
1947 time_stamp->secs = tvb_get_ntoh48(tvb, start);
1949 * The lower 16 bits are 1/2^16s of a second;
1950 * convert them to nanoseconds.
1952 * XXX - this may give the impression of higher
1953 * precision than you actually get.
1955 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohs(tvb, start+6)/65536.0));
1957 report_type_length_mismatch(tree, "an RFC 3971-style time stamp", length, TRUE);
1960 case ENC_TIME_RFC_3971|ENC_LITTLE_ENDIAN:
1962 * 1/64ths of a second since the UN*X epoch,
1965 * Only supported for absolute times.
1967 DISSECTOR_ASSERT(!is_relative);
1971 * XXX - this is assuming that, if anybody
1972 * were ever to use this format - RFC 3971
1973 * doesn't, because that's an Internet
1974 * protocol, and those use network byte
1975 * order, i.e. big-endian - they'd treat it
1976 * as a 64-bit count of 1/2^16s of a second,
1977 * putting the upper 48 bits at the end.
1979 * The lower 48 bits are seconds since the
1982 time_stamp->secs = tvb_get_letoh48(tvb, start+2);
1984 * The upper 16 bits are 1/2^16s of a second;
1985 * convert them to nanoseconds.
1987 * XXX - this may give the impression of higher
1988 * precision than you actually get.
1990 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohs(tvb, start)/65536.0));
1992 report_type_length_mismatch(tree, "an RFC 3971-style time stamp", length, TRUE);
1995 case ENC_TIME_SECS_NTP|ENC_BIG_ENDIAN:
1997 * NTP time stamp, with 1-second resolution (i.e.,
1998 * seconds since the NTP epoch), big-endian.
1999 * Only supported for absolute times.
2001 DISSECTOR_ASSERT(!is_relative);
2005 * We need a temporary variable here so the
2006 * unsigned math works correctly (for
2007 * years > 2036 according to RFC 2030
2010 tmpsecs = tvb_get_ntohl(tvb, start);
2012 time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
2014 time_stamp->secs = tmpsecs; /* 0 */
2015 time_stamp->nsecs = 0;
2017 report_type_length_mismatch(tree, "an NTP seconds-only time stamp", length, TRUE);
2020 case ENC_TIME_SECS_NTP|ENC_LITTLE_ENDIAN:
2022 * NTP time stamp, with 1-second resolution (i.e.,
2023 * seconds since the NTP epoch), little-endian.
2024 * Only supported for absolute times.
2026 DISSECTOR_ASSERT(!is_relative);
2029 tmpsecs = tvb_get_letohl(tvb, start);
2031 time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
2033 time_stamp->secs = tmpsecs; /* 0 */
2034 time_stamp->nsecs = 0;
2036 report_type_length_mismatch(tree, "an NTP seconds-only time stamp", length, TRUE);
2038 case ENC_TIME_MSEC_NTP | ENC_BIG_ENDIAN:
2040 * Milliseconds, 1 to 8 bytes.
2041 * For absolute times, it's milliseconds since the
2044 if (length >= 1 && length <= 8) {
2047 msecs = get_uint64_value(tree, tvb, start, length, encoding);
2048 tmpsecs = (guint32)(msecs / 1000);
2049 time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
2050 time_stamp->nsecs = (int)(msecs % 1000)*1000000;
2053 report_type_length_mismatch(tree, "a time-in-milliseconds NTP time stamp", length, TRUE);
2056 DISSECTOR_ASSERT_NOT_REACHED();
2062 tree_data_add_maybe_interesting_field(tree_data_t *tree_data, field_info *fi)
2064 const header_field_info *hfinfo = fi->hfinfo;
2066 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
2067 GPtrArray *ptrs = NULL;
2069 if (tree_data->interesting_hfids == NULL) {
2070 /* Initialize the hash because we now know that it is needed */
2071 tree_data->interesting_hfids =
2072 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
2073 } else if (g_hash_table_size(tree_data->interesting_hfids)) {
2074 ptrs = (GPtrArray *)g_hash_table_lookup(tree_data->interesting_hfids,
2075 GINT_TO_POINTER(hfinfo->id));
2079 /* First element triggers the creation of pointer array */
2080 ptrs = g_ptr_array_new();
2081 g_hash_table_insert(tree_data->interesting_hfids,
2082 GINT_TO_POINTER(hfinfo->id), ptrs);
2085 g_ptr_array_add(ptrs, fi);
2091 * Validates that field length bytes are available starting from
2092 * start (pos/neg). Throws an exception if they aren't.
2095 test_length(header_field_info *hfinfo, tvbuff_t *tvb,
2096 gint start, gint length, const guint encoding)
2103 if ((hfinfo->type == FT_STRINGZ) ||
2104 ((encoding & ENC_VARINT_PROTOBUF) && (IS_FT_UINT(hfinfo->type) || IS_FT_UINT(hfinfo->type)))) {
2105 /* If we're fetching until the end of the TVB, only validate
2106 * that the offset is within range.
2112 tvb_ensure_bytes_exist(tvb, start, size);
2115 /* Add an item to a proto_tree, using the text label registered to that item;
2116 the item is extracted from the tvbuff handed to it. */
2118 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
2119 tvbuff_t *tvb, gint start, gint length,
2127 const char *stringval;
2128 nstime_t time_stamp;
2129 gboolean length_error;
2131 switch (new_fi->hfinfo->type) {
2133 /* no value to set for FT_NONE */
2137 proto_tree_set_protocol_tvb(new_fi, tvb, new_fi->hfinfo->name);
2141 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
2146 * Map all non-zero values to little-endian for
2147 * backwards compatibility.
2150 encoding = ENC_LITTLE_ENDIAN;
2151 n = get_uint_value(tree, tvb, start, length, encoding);
2152 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
2154 /* Instead of calling proto_item_set_len(), since we don't yet
2155 * have a proto_item, we set the field_info's length ourselves. */
2156 new_fi->length = n + length;
2161 * Map all non-zero values to little-endian for
2162 * backwards compatibility.
2165 encoding = ENC_LITTLE_ENDIAN;
2166 proto_tree_set_boolean(new_fi,
2167 get_uint64_value(tree, tvb, start, length, encoding));
2171 /* XXX - make these just FT_UINT? */
2176 if (encoding & ENC_VARINT_PROTOBUF) {
2177 new_fi->length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value64);
2178 new_fi->flags |= FI_VARINT;
2179 value = (guint32)value64;
2182 * Map all non-zero values to little-endian for
2183 * backwards compatibility.
2186 encoding = ENC_LITTLE_ENDIAN;
2188 value = get_uint_value(tree, tvb, start, length, encoding);
2190 proto_tree_set_uint(new_fi, value);
2198 if (encoding & ENC_VARINT_PROTOBUF) {
2199 new_fi->length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value64);
2200 new_fi->flags |= FI_VARINT;
2203 * Map all other non-zero values to little-endian for
2204 * backwards compatibility.
2207 encoding = ENC_LITTLE_ENDIAN;
2209 value64 = get_uint64_value(tree, tvb, start, length, encoding);
2211 proto_tree_set_uint64(new_fi, value64);
2214 /* XXX - make these just FT_INT? */
2220 * Map all non-zero values to little-endian for
2221 * backwards compatibility.
2224 encoding = ENC_LITTLE_ENDIAN;
2225 proto_tree_set_int(new_fi,
2226 get_int_value(tree, tvb, start, length, encoding));
2234 * Map all non-zero values to little-endian for
2235 * backwards compatibility.
2238 encoding = ENC_LITTLE_ENDIAN;
2239 proto_tree_set_int64(new_fi,
2240 get_int64_value(tree, tvb, start, length, encoding));
2245 * Map all non-zero values to little-endian for
2246 * backwards compatibility.
2249 encoding = ENC_LITTLE_ENDIAN;
2250 if (length != FT_IPv4_LEN) {
2251 length_error = length < FT_IPv4_LEN ? TRUE : FALSE;
2252 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
2254 value = tvb_get_ipv4(tvb, start);
2256 * NOTE: to support code written when
2257 * proto_tree_add_item() took a gboolean as its
2258 * last argument, with FALSE meaning "big-endian"
2259 * and TRUE meaning "little-endian", we treat any
2260 * non-zero value of "encoding" as meaning
2263 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
2267 if (length != FT_IPXNET_LEN) {
2268 length_error = length < FT_IPXNET_LEN ? TRUE : FALSE;
2269 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
2271 proto_tree_set_ipxnet(new_fi,
2272 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, ENC_BIG_ENDIAN));
2276 if (length != FT_IPv6_LEN) {
2277 length_error = length < FT_IPv6_LEN ? TRUE : FALSE;
2278 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
2280 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
2284 if (length != FT_FCWWN_LEN) {
2285 length_error = length < FT_FCWWN_LEN ? TRUE : FALSE;
2286 report_type_length_mismatch(tree, "an FCWWN address", length, length_error);
2288 proto_tree_set_fcwwn_tvb(new_fi, tvb, start, length);
2293 length_error = length < 7 ? TRUE : FALSE;
2294 report_type_length_mismatch(tree, "an AX.25 address", length, length_error);
2296 proto_tree_set_ax25_tvb(new_fi, tvb, start);
2300 if (length != VINES_ADDR_LEN) {
2301 length_error = length < VINES_ADDR_LEN ? TRUE : FALSE;
2302 report_type_length_mismatch(tree, "a Vines address", length, length_error);
2304 proto_tree_set_vines_tvb(new_fi, tvb, start);
2308 if (length != FT_ETHER_LEN) {
2309 length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
2310 report_type_length_mismatch(tree, "a MAC address", length, length_error);
2312 proto_tree_set_ether_tvb(new_fi, tvb, start);
2317 * Map all non-zero values to little-endian for
2318 * backwards compatibility.
2321 encoding = ENC_LITTLE_ENDIAN;
2322 if (length != FT_EUI64_LEN) {
2323 length_error = length < FT_EUI64_LEN ? TRUE : FALSE;
2324 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
2326 proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
2330 * Map all non-zero values to little-endian for
2331 * backwards compatibility.
2334 encoding = ENC_LITTLE_ENDIAN;
2335 if (length != FT_GUID_LEN) {
2336 length_error = length < FT_GUID_LEN ? TRUE : FALSE;
2337 report_type_length_mismatch(tree, "a GUID", length, length_error);
2339 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
2344 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
2348 proto_tree_set_system_id_tvb(new_fi, tvb, start, length);
2353 * NOTE: to support code written when
2354 * proto_tree_add_item() took a gboolean as its
2355 * last argument, with FALSE meaning "big-endian"
2356 * and TRUE meaning "little-endian", we treat any
2357 * non-zero value of "encoding" as meaning
2360 * At some point in the future, we might
2361 * support non-IEEE-binary floating-point
2362 * formats in the encoding as well
2363 * (IEEE decimal, System/3x0, VAX).
2366 encoding = ENC_LITTLE_ENDIAN;
2368 length_error = length < 4 ? TRUE : FALSE;
2369 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
2372 floatval = tvb_get_letohieee_float(tvb, start);
2374 floatval = tvb_get_ntohieee_float(tvb, start);
2375 proto_tree_set_float(new_fi, floatval);
2380 * NOTE: to support code written when
2381 * proto_tree_add_item() took a gboolean as its
2382 * last argument, with FALSE meaning "big-endian"
2383 * and TRUE meaning "little-endian", we treat any
2384 * non-zero value of "encoding" as meaning
2387 * At some point in the future, we might
2388 * support non-IEEE-binary floating-point
2389 * formats in the encoding as well
2390 * (IEEE decimal, System/3x0, VAX).
2392 if (encoding == TRUE)
2393 encoding = ENC_LITTLE_ENDIAN;
2395 length_error = length < 8 ? TRUE : FALSE;
2396 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
2399 doubleval = tvb_get_letohieee_double(tvb, start);
2401 doubleval = tvb_get_ntohieee_double(tvb, start);
2402 proto_tree_set_double(new_fi, doubleval);
2406 stringval = get_string_value(wmem_packet_scope(),
2407 tvb, start, length, &length, encoding);
2408 proto_tree_set_string(new_fi, stringval);
2410 /* Instead of calling proto_item_set_len(), since we
2411 * don't yet have a proto_item, we set the
2412 * field_info's length ourselves.
2414 * XXX - our caller can't use that length to
2415 * advance an offset unless they arrange that
2416 * there always be a protocol tree into which
2417 * we're putting this item.
2419 new_fi->length = length;
2423 stringval = get_stringz_value(wmem_packet_scope(),
2424 tree, tvb, start, length, &length, encoding);
2425 proto_tree_set_string(new_fi, stringval);
2427 /* Instead of calling proto_item_set_len(),
2428 * since we don't yet have a proto_item, we
2429 * set the field_info's length ourselves.
2431 * XXX - our caller can't use that length to
2432 * advance an offset unless they arrange that
2433 * there always be a protocol tree into which
2434 * we're putting this item.
2436 new_fi->length = length;
2439 case FT_UINT_STRING:
2441 * NOTE: to support code written when
2442 * proto_tree_add_item() took a gboolean as its
2443 * last argument, with FALSE meaning "big-endian"
2444 * and TRUE meaning "little-endian", if the
2445 * encoding value is TRUE, treat that as
2446 * ASCII with a little-endian length.
2448 * This won't work for code that passes
2449 * arbitrary non-zero values; that code
2450 * will need to be fixed.
2452 if (encoding == TRUE)
2453 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
2454 stringval = get_uint_string_value(wmem_packet_scope(),
2455 tree, tvb, start, length, &length, encoding);
2456 proto_tree_set_string(new_fi, stringval);
2458 /* Instead of calling proto_item_set_len(), since we
2459 * don't yet have a proto_item, we set the
2460 * field_info's length ourselves.
2462 * XXX - our caller can't use that length to
2463 * advance an offset unless they arrange that
2464 * there always be a protocol tree into which
2465 * we're putting this item.
2467 new_fi->length = length;
2471 stringval = get_stringzpad_value(wmem_packet_scope(),
2472 tvb, start, length, &length, encoding);
2473 proto_tree_set_string(new_fi, stringval);
2475 /* Instead of calling proto_item_set_len(), since we
2476 * don't yet have a proto_item, we set the
2477 * field_info's length ourselves.
2479 * XXX - our caller can't use that length to
2480 * advance an offset unless they arrange that
2481 * there always be a protocol tree into which
2482 * we're putting this item.
2484 new_fi->length = length;
2487 case FT_ABSOLUTE_TIME:
2489 * Absolute times can be in any of a number of
2490 * formats, and they can be big-endian or
2493 * Historically FT_TIMEs were only timespecs;
2494 * the only question was whether they were stored
2495 * in big- or little-endian format.
2497 * For backwards compatibility, we interpret an
2498 * encoding of 1 as meaning "little-endian timespec",
2499 * so that passing TRUE is interpreted as that.
2501 if (encoding == TRUE)
2502 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
2504 if (length > 8 || length < 4) {
2505 length_error = length < 4 ? TRUE : FALSE;
2506 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
2509 get_time_value(tree, tvb, start, length, encoding, &time_stamp, FALSE);
2511 proto_tree_set_time(new_fi, &time_stamp);
2514 case FT_RELATIVE_TIME:
2516 * Relative times can be in any of a number of
2517 * formats, and they can be big-endian or
2520 * Historically FT_TIMEs were only timespecs;
2521 * the only question was whether they were stored
2522 * in big- or little-endian format.
2524 * For backwards compatibility, we interpret an
2525 * encoding of 1 as meaning "little-endian timespec",
2526 * so that passing TRUE is interpreted as that.
2528 if (encoding == TRUE)
2529 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
2531 if (length != 8 && length != 4) {
2532 length_error = length < 4 ? TRUE : FALSE;
2533 report_type_length_mismatch(tree, "a relative time value", length, length_error);
2536 get_time_value(tree, tvb, start, length, encoding, &time_stamp, TRUE);
2538 proto_tree_set_time(new_fi, &time_stamp);
2540 case FT_IEEE_11073_SFLOAT:
2542 encoding = ENC_LITTLE_ENDIAN;
2544 length_error = length < 2 ? TRUE : FALSE;
2545 report_type_length_mismatch(tree, "a IEEE 11073 SFLOAT", length, length_error);
2548 fvalue_set_uinteger(&new_fi->value, tvb_get_guint16(tvb, start, encoding));
2551 case FT_IEEE_11073_FLOAT:
2553 encoding = ENC_LITTLE_ENDIAN;
2555 length_error = length < 4 ? TRUE : FALSE;
2556 report_type_length_mismatch(tree, "a IEEE 11073 FLOAT", length, length_error);
2561 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
2562 new_fi->hfinfo->type,
2563 ftype_name(new_fi->hfinfo->type));
2564 DISSECTOR_ASSERT_NOT_REACHED();
2567 FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
2569 /* Don't add new node to proto_tree until now so that any exceptions
2570 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
2571 /* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
2572 * to know which item caused exception? */
2573 pi = proto_tree_add_node(tree, new_fi);
2579 proto_tree_add_item_ret_int(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2580 const gint start, gint length,
2581 const guint encoding, gint32 *retval)
2583 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
2587 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2589 switch (hfinfo->type){
2596 DISSECTOR_ASSERT_NOT_REACHED();
2599 /* length validation for native number encoding caught by get_uint_value() */
2600 /* length has to be -1 or > 0 regardless of encoding */
2601 if (length < -1 || length == 0)
2602 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2603 "Invalid length %d passed to proto_tree_add_item_ret_int",
2606 if (encoding & ENC_STRING) {
2607 REPORT_DISSECTOR_BUG("wrong encoding");
2609 /* I believe it's ok if this is called with a NULL tree */
2610 value = get_int_value(tree, tvb, start, length, encoding);
2615 if (hfinfo->bitmask) {
2616 /* Mask out irrelevant portions */
2617 *retval &= (guint32)(hfinfo->bitmask);
2619 *retval >>= hfinfo_bitshift(hfinfo);
2621 no_of_bits = ws_count_ones(hfinfo->bitmask);
2622 *retval = ws_sign_ext32(*retval, no_of_bits);
2625 CHECK_FOR_NULL_TREE(tree);
2627 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2629 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
2631 proto_tree_set_int(new_fi, value);
2633 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
2635 return proto_tree_add_node(tree, new_fi);
2639 proto_tree_add_item_ret_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2640 const gint start, gint length,
2641 const guint encoding, guint32 *retval)
2643 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
2647 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2649 switch (hfinfo->type){
2657 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2658 "field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
2662 /* length validation for native number encoding caught by get_uint_value() */
2663 /* length has to be -1 or > 0 regardless of encoding */
2664 if (length < -1 || length == 0)
2665 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2666 "Invalid length %d passed to proto_tree_add_item_ret_uint",
2669 if (encoding & ENC_STRING) {
2670 REPORT_DISSECTOR_BUG("wrong encoding");
2672 /* I believe it's ok if this is called with a NULL tree */
2673 /* XXX - modify if we ever support EBCDIC FT_CHAR */
2674 if (encoding & ENC_VARINT_PROTOBUF) {
2676 tvb_get_varint(tvb, start, length, &temp64);
2677 value = (guint32)temp64;
2679 value = get_uint_value(tree, tvb, start, length, encoding);
2684 if (hfinfo->bitmask) {
2685 /* Mask out irrelevant portions */
2686 *retval &= (guint32)(hfinfo->bitmask);
2688 *retval >>= hfinfo_bitshift(hfinfo);
2692 CHECK_FOR_NULL_TREE(tree);
2694 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2696 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
2698 proto_tree_set_uint(new_fi, value);
2700 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
2701 if (encoding & ENC_VARINT_PROTOBUF) {
2702 new_fi->flags |= FI_VARINT;
2704 return proto_tree_add_node(tree, new_fi);
2707 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
2708 * and returns proto_item* and uint value retreived*/
2710 ptvcursor_add_ret_uint(ptvcursor_t *ptvc, int hfindex, gint length,
2711 const guint encoding, guint32 *retval)
2714 header_field_info *hfinfo;
2719 offset = ptvc->offset;
2720 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2722 switch (hfinfo->type){
2730 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2731 "field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
2735 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
2736 test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);
2738 /* I believe it's ok if this is called with a NULL tree */
2739 /* XXX - modify if we ever support EBCDIC FT_CHAR */
2740 value = get_uint_value(ptvc->tree, ptvc->tvb, offset, item_length, encoding);
2744 if (hfinfo->bitmask) {
2745 /* Mask out irrelevant portions */
2746 *retval &= (guint32)(hfinfo->bitmask);
2748 *retval >>= hfinfo_bitshift(hfinfo);
2752 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
2753 item_length, encoding);
2755 CHECK_FOR_NULL_TREE(ptvc->tree);
2757 /* Coast clear. Try and fake it */
2758 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
2760 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
2762 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
2763 offset, length, encoding);
2766 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
2767 * and returns proto_item* and int value retreived*/
2769 ptvcursor_add_ret_int(ptvcursor_t *ptvc, int hfindex, gint length,
2770 const guint encoding, gint32 *retval)
2773 header_field_info *hfinfo;
2778 offset = ptvc->offset;
2779 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2781 switch (hfinfo->type){
2788 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2789 "field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
2793 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
2794 test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);
2796 /* I believe it's ok if this is called with a NULL tree */
2797 /* XXX - modify if we ever support EBCDIC FT_CHAR */
2798 value = get_int_value(ptvc->tree, ptvc->tvb, offset, item_length, encoding);
2803 if (hfinfo->bitmask) {
2804 /* Mask out irrelevant portions */
2805 *retval &= (guint32)(hfinfo->bitmask);
2807 *retval >>= hfinfo_bitshift(hfinfo);
2809 no_of_bits = ws_count_ones(hfinfo->bitmask);
2810 *retval = ws_sign_ext32(*retval, no_of_bits);
2813 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
2814 item_length, encoding);
2816 CHECK_FOR_NULL_TREE(ptvc->tree);
2818 /* Coast clear. Try and fake it */
2819 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
2821 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
2823 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
2824 offset, length, encoding);
2827 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
2828 * and returns proto_item* and string value retreived */
2830 ptvcursor_add_ret_string(ptvcursor_t* ptvc, int hf, gint length, const guint encoding, wmem_allocator_t *scope, const guint8 **retval)
2832 header_field_info *hfinfo;
2834 const guint8 *value;
2838 offset = ptvc->offset;
2840 PROTO_REGISTRAR_GET_NTH(hf, hfinfo);
2842 switch (hfinfo->type){
2844 value = get_string_value(scope, ptvc->tvb, offset, length, &item_length, encoding);
2847 value = get_stringz_value(scope, ptvc->tree, ptvc->tvb, offset, length, &item_length, encoding);
2849 case FT_UINT_STRING:
2850 value = get_uint_string_value(scope, ptvc->tree, ptvc->tvb, offset, length, &item_length, encoding);
2853 value = get_stringzpad_value(scope, ptvc->tvb, offset, length, &item_length, encoding);
2856 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2857 "field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, or FT_STRINGZPAD",
2864 ptvc->offset += item_length;
2866 CHECK_FOR_NULL_TREE(ptvc->tree);
2868 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfinfo->id, hfinfo);
2870 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
2872 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
2873 offset, length, encoding);
2876 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
2877 * and returns proto_item* and boolean value retreived */
2879 ptvcursor_add_ret_boolean(ptvcursor_t* ptvc, int hfindex, gint length, const guint encoding, gboolean *retval)
2881 header_field_info *hfinfo;
2885 guint64 value, bitval;
2887 offset = ptvc->offset;
2888 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2890 if (hfinfo->type != FT_BOOLEAN) {
2891 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2892 "field %s is not of type FT_BOOLEAN", hfinfo->abbrev));
2895 /* length validation for native number encoding caught by get_uint64_value() */
2896 /* length has to be -1 or > 0 regardless of encoding */
2897 if (length < -1 || length == 0)
2898 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2899 "Invalid length %d passed to proto_tree_add_item_ret_uint",
2902 if (encoding & ENC_STRING) {
2903 REPORT_DISSECTOR_BUG("wrong encoding");
2906 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
2907 test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);
2909 /* I believe it's ok if this is called with a NULL tree */
2910 value = get_uint64_value(ptvc->tree, ptvc->tvb, offset, length, encoding);
2914 if (hfinfo->bitmask) {
2915 /* Mask out irrelevant portions */
2916 bitval &= hfinfo->bitmask;
2918 *retval = (bitval != 0);
2921 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
2922 item_length, encoding);
2924 CHECK_FOR_NULL_TREE(ptvc->tree);
2926 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfinfo->id, hfinfo);
2928 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
2930 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
2931 offset, length, encoding);
2935 proto_tree_add_item_ret_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2936 const gint start, gint length, const guint encoding, guint64 *retval)
2938 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
2942 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2944 if (hfinfo->type != FT_UINT64) {
2945 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2946 "field %s is not of type FT_UINT64", hfinfo->abbrev));
2949 /* length validation for native number encoding caught by get_uint64_value() */
2950 /* length has to be -1 or > 0 regardless of encoding */
2951 if (length < -1 || length == 0)
2952 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2953 "Invalid length %d passed to proto_tree_add_item_ret_uint",
2956 if (encoding & ENC_STRING) {
2957 REPORT_DISSECTOR_BUG("wrong encoding");
2959 /* I believe it's ok if this is called with a NULL tree */
2960 if (encoding & ENC_VARINT_PROTOBUF) {
2961 tvb_get_varint(tvb, start, length, &value);
2963 value = get_uint64_value(tree, tvb, start, length, encoding);
2968 if (hfinfo->bitmask) {
2969 /* Mask out irrelevant portions */
2970 *retval &= hfinfo->bitmask;
2972 *retval >>= hfinfo_bitshift(hfinfo);
2976 CHECK_FOR_NULL_TREE(tree);
2978 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2980 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
2982 proto_tree_set_uint64(new_fi, value);
2984 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
2985 if (encoding & ENC_VARINT_PROTOBUF) {
2986 new_fi->flags |= FI_VARINT;
2989 return proto_tree_add_node(tree, new_fi);
2993 proto_tree_add_item_ret_varint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2994 const gint start, gint length, const guint encoding, guint64 *retval, gint *lenretval)
2996 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3000 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3002 if ((!IS_FT_INT(hfinfo->type)) && (!IS_FT_UINT(hfinfo->type))) {
3003 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
3004 "field %s is not of type FT_UINT or FT_INT", hfinfo->abbrev));
3007 /* length validation for native number encoding caught by get_uint64_value() */
3008 /* length has to be -1 or > 0 regardless of encoding */
3010 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
3011 "Invalid length %d passed to proto_tree_add_item_ret_varint",
3014 if (encoding & ENC_STRING) {
3015 REPORT_DISSECTOR_BUG("wrong encoding");
3018 length = tvb_get_varint(tvb, start, (length == -1) ? FT_VARINT_MAX_LEN : length, &value);
3022 if (hfinfo->bitmask) {
3023 /* Mask out irrelevant portions */
3024 *retval &= hfinfo->bitmask;
3026 *retval >>= hfinfo_bitshift(hfinfo);
3031 *lenretval = length;
3034 CHECK_FOR_NULL_TREE(tree);
3036 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3038 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3040 proto_tree_set_uint64(new_fi, value);
3042 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3043 if (encoding & ENC_VARINT_PROTOBUF) {
3044 new_fi->flags |= FI_VARINT;
3047 return proto_tree_add_node(tree, new_fi);
3052 proto_tree_add_item_ret_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3053 const gint start, gint length,
3054 const guint encoding, gboolean *retval)
3056 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3058 guint64 value, bitval;
3060 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3062 if (hfinfo->type != FT_BOOLEAN) {
3063 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
3064 "field %s is not of type FT_BOOLEAN", hfinfo->abbrev));
3067 /* length validation for native number encoding caught by get_uint64_value() */
3068 /* length has to be -1 or > 0 regardless of encoding */
3069 if (length < -1 || length == 0)
3070 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
3071 "Invalid length %d passed to proto_tree_add_item_ret_uint",
3074 if (encoding & ENC_STRING) {
3075 REPORT_DISSECTOR_BUG("wrong encoding");
3077 /* I believe it's ok if this is called with a NULL tree */
3078 value = get_uint64_value(tree, tvb, start, length, encoding);
3082 if (hfinfo->bitmask) {
3083 /* Mask out irrelevant portions */
3084 bitval &= hfinfo->bitmask;
3086 *retval = (bitval != 0);
3089 CHECK_FOR_NULL_TREE(tree);
3091 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3093 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3095 proto_tree_set_boolean(new_fi, value);
3097 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3099 return proto_tree_add_node(tree, new_fi);
3103 proto_tree_add_item_ret_string_and_length(proto_tree *tree, int hfindex,
3105 const gint start, gint length,
3106 const guint encoding,
3107 wmem_allocator_t *scope,
3108 const guint8 **retval,
3111 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
3113 const guint8 *value;
3115 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3117 switch (hfinfo->type){
3119 value = get_string_value(scope, tvb, start, length, lenretval, encoding);
3122 value = get_stringz_value(scope, tree, tvb, start, length, lenretval, encoding);
3124 case FT_UINT_STRING:
3125 value = get_uint_string_value(scope, tree, tvb, start, length, lenretval, encoding);
3128 value = get_stringzpad_value(scope, tvb, start, length, lenretval, encoding);
3131 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
3132 "field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, or FT_STRINGZPAD",
3139 CHECK_FOR_NULL_TREE(tree);
3141 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3143 new_fi = new_field_info(tree, hfinfo, tvb, start, *lenretval);
3145 proto_tree_set_string(new_fi, value);
3147 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
3149 return proto_tree_add_node(tree, new_fi);
3153 proto_tree_add_item_ret_string(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3154 const gint start, gint length,
3155 const guint encoding, wmem_allocator_t *scope,
3156 const guint8 **retval)
3158 return proto_tree_add_item_ret_string_and_length(tree, hfindex,
3159 tvb, start, length, encoding, scope, retval, &length);
3163 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
3164 and returns proto_item* */
3166 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
3167 const guint encoding)
3170 header_field_info *hfinfo;
3174 offset = ptvc->offset;
3175 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3176 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length, encoding);
3177 test_length(hfinfo, ptvc->tvb, offset, item_length, encoding);
3179 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
3180 item_length, encoding);
3182 CHECK_FOR_NULL_TREE(ptvc->tree);
3184 /* Coast clear. Try and fake it */
3185 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
3187 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
3189 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
3190 offset, length, encoding);
3193 /* Add an item to a proto_tree, using the text label registered to that item;
3194 the item is extracted from the tvbuff handed to it. */
3196 proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3197 const gint start, gint length, const guint encoding)
3202 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3204 get_hfi_length(hfinfo, tvb, start, &length, &item_length, encoding);
3205 test_length(hfinfo, tvb, start, item_length, encoding);
3207 CHECK_FOR_NULL_TREE(tree);
3209 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3211 new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
3213 return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
3217 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3218 const gint start, gint length, const guint encoding)
3220 register header_field_info *hfinfo;
3222 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3223 return proto_tree_add_item_new(tree, hfinfo, tvb, start, length, encoding);
3226 /* Add an item to a proto_tree, using the text label registered to that item;
3227 the item is extracted from the tvbuff handed to it.
3229 Return the length of the item through the pointer. */
3231 proto_tree_add_item_new_ret_length(proto_tree *tree, header_field_info *hfinfo,
3232 tvbuff_t *tvb, const gint start,
3233 gint length, const guint encoding,
3240 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3242 get_hfi_length(hfinfo, tvb, start, &length, &item_length, encoding);
3243 test_length(hfinfo, tvb, start, item_length, encoding);
3247 * We need to get the correct item length here.
3248 * That's normally done by proto_tree_new_item(),
3249 * but we won't be calling it.
3251 *lenretval = get_full_length(hfinfo, tvb, start, length,
3252 item_length, encoding);
3256 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfinfo->id, hfinfo, {
3258 * Even if the tree item is not referenced (and thus faked),
3259 * the caller must still be informed of the actual length.
3261 *lenretval = get_full_length(hfinfo, tvb, start, length,
3262 item_length, encoding);
3265 new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
3267 item = proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
3268 *lenretval = new_fi->length;
3273 proto_tree_add_item_ret_length(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3274 const gint start, gint length,
3275 const guint encoding, gint *lenretval)
3277 register header_field_info *hfinfo;
3279 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3280 return proto_tree_add_item_new_ret_length(tree, hfinfo, tvb, start, length, encoding, lenretval);
3283 /* which FT_ types can use proto_tree_add_bytes_item() */
3284 static inline gboolean
3285 validate_proto_tree_add_bytes_ftype(const enum ftenum type)
3287 return (type == FT_BYTES ||
3288 type == FT_UINT_BYTES ||
3290 type == FT_REL_OID ||
3291 type == FT_SYSTEM_ID );
3294 /* Note: this does no validation that the byte array of an FT_OID or
3295 FT_REL_OID is actually valid; and neither does proto_tree_add_item(),
3296 so I think it's ok to continue not validating it?
3299 proto_tree_add_bytes_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3300 const gint start, gint length, const guint encoding,
3301 GByteArray *retval, gint *endoff, gint *err)
3304 GByteArray *bytes = retval;
3305 GByteArray *created_bytes = NULL;
3308 header_field_info *hfinfo;
3309 gboolean generate = (bytes || tree) ? TRUE : FALSE;
3311 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3313 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3315 DISSECTOR_ASSERT_HINT(validate_proto_tree_add_bytes_ftype(hfinfo->type),
3316 "Called proto_tree_add_bytes_item but not a bytes-based FT_XXX type");
3318 /* length has to be -1 or > 0 regardless of encoding */
3319 /* invalid FT_UINT_BYTES length is caught in get_uint_value() */
3320 if (length < -1 || length == 0) {
3321 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
3322 "Invalid length %d passed to proto_tree_add_bytes_item for %s",
3323 length, ftype_name(hfinfo->type)));
3326 if (encoding & ENC_STR_NUM) {
3327 REPORT_DISSECTOR_BUG("Decoding number strings for byte arrays is not supported");
3330 if (generate && (encoding & ENC_STR_HEX)) {
3331 if (hfinfo->type == FT_UINT_BYTES) {
3332 /* can't decode FT_UINT_BYTES from strings */
3333 REPORT_DISSECTOR_BUG("proto_tree_add_bytes_item called for "
3334 "FT_UINT_BYTES type, but as ENC_STR_HEX");
3338 /* caller doesn't care about return value, but we need it to
3339 call tvb_get_string_bytes() and set the tree later */
3340 bytes = created_bytes = g_byte_array_new();
3343 /* bytes might be NULL after this, but can't add expert error until later */
3344 bytes = tvb_get_string_bytes(tvb, start, length, encoding, bytes, endoff);
3346 /* grab the errno now before it gets overwritten */
3349 else if (generate) {
3350 tvb_ensure_bytes_exist(tvb, start, length);
3353 /* caller doesn't care about return value, but we need it to
3354 call tvb_get_string_bytes() and set the tree later */
3355 bytes = created_bytes = g_byte_array_new();
3358 if (hfinfo->type == FT_UINT_BYTES) {
3359 n = length; /* n is now the "header" length */
3360 length = get_uint_value(tree, tvb, start, n, encoding);
3361 /* length is now the value's length; only store the value in the array */
3362 g_byte_array_append(bytes, tvb_get_ptr(tvb, start + n, length), length);
3364 else if (length > 0) {
3365 g_byte_array_append(bytes, tvb_get_ptr(tvb, start, length), length);
3369 *endoff = start + n + length;
3372 if (err) *err = saved_err;
3374 CHECK_FOR_NULL_TREE_AND_FREE(tree,
3377 g_byte_array_free(created_bytes, TRUE);
3378 created_bytes = NULL;
3382 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfinfo->id, hfinfo,
3385 g_byte_array_free(created_bytes, TRUE);
3386 created_bytes = NULL;
3390 /* n will be zero except when it's a FT_UINT_BYTES */
3391 new_fi = new_field_info(tree, hfinfo, tvb, start, n + length);
3393 if (encoding & ENC_STRING) {
3394 if (saved_err == ERANGE)
3395 expert_add_info(NULL, tree, &ei_number_string_decoding_erange_error);
3396 else if (!bytes || saved_err != 0)
3397 expert_add_info(NULL, tree, &ei_number_string_decoding_failed_error);
3400 proto_tree_set_bytes_gbytearray(new_fi, bytes);
3402 proto_tree_set_bytes(new_fi, NULL, 0);
3405 g_byte_array_free(created_bytes, TRUE);
3408 /* n will be zero except when it's a FT_UINT_BYTES */
3409 proto_tree_set_bytes_tvb(new_fi, tvb, start + n, length);
3412 (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
3415 return proto_tree_add_node(tree, new_fi);
3420 proto_tree_add_time_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3421 const gint start, gint length, const guint encoding,
3422 nstime_t *retval, gint *endoff, gint *err)
3425 nstime_t time_stamp;
3427 header_field_info *hfinfo;
3429 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3431 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3433 DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo);
3435 /* length has to be -1 or > 0 regardless of encoding */
3436 if (length < -1 || length == 0) {
3437 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
3438 "Invalid length %d passed to proto_tree_add_time_item", length));
3441 time_stamp.secs = 0;
3442 time_stamp.nsecs = 0;
3444 if (encoding & ENC_STR_TIME_MASK) {
3445 tvb_get_string_time(tvb, start, length, encoding, &time_stamp, endoff);
3446 /* grab the errno now before it gets overwritten */
3450 const gboolean is_relative = (hfinfo->type == FT_RELATIVE_TIME) ? TRUE : FALSE;
3451 const gboolean length_error = length < 4 ? TRUE : FALSE;
3453 if (length > 8 || length < 4) {
3455 report_type_length_mismatch(tree, "a relative time value", length, length_error);
3457 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
3460 tvb_ensure_bytes_exist(tvb, start, length);
3461 get_time_value(tree, tvb, start, length, encoding, &time_stamp, is_relative);
3462 if (endoff) *endoff = length;
3465 if (err) *err = saved_err;
3468 retval->secs = time_stamp.secs;
3469 retval->nsecs = time_stamp.nsecs;
3472 CHECK_FOR_NULL_TREE(tree);
3474 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3476 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3478 proto_tree_set_time(new_fi, &time_stamp);
3480 if (encoding & ENC_STRING) {
3481 if (saved_err == ERANGE)
3482 expert_add_info(NULL, tree, &ei_number_string_decoding_erange_error);
3483 else if (saved_err == EDOM)
3484 expert_add_info(NULL, tree, &ei_number_string_decoding_failed_error);
3488 (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
3491 return proto_tree_add_node(tree, new_fi);
3494 /* Add a FT_NONE to a proto_tree */
3496 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
3497 const gint start, gint length, const char *format,
3502 header_field_info *hfinfo;
3504 CHECK_FOR_NULL_TREE(tree);
3506 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3508 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_NONE);
3510 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3512 TRY_TO_FAKE_THIS_REPR(pi);
3514 va_start(ap, format);
3515 proto_tree_set_representation(pi, format, ap);
3518 /* no value to set for FT_NONE */
3522 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
3523 * offset, and returns proto_item* */
3525 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
3526 const guint encoding)
3530 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
3536 /* Advance the ptvcursor's offset within its tvbuff without
3537 * adding anything to the proto_tree. */
3539 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
3541 ptvc->offset += length;
3546 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb, const char* field_data)
3548 fvalue_set_protocol(&fi->value, tvb, field_data);
3551 /* Add a FT_PROTOCOL to a proto_tree */
3553 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3554 gint start, gint length, const char *format, ...)
3558 header_field_info *hfinfo;
3559 gchar* protocol_rep;
3561 CHECK_FOR_NULL_TREE(tree);
3563 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3565 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_PROTOCOL);
3567 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3569 va_start(ap, format);
3570 protocol_rep = g_strdup_vprintf(format, ap);
3571 proto_tree_set_protocol_tvb(PNODE_FINFO(pi), (start == 0 ? tvb : tvb_new_subset_length(tvb, start, length)), protocol_rep);
3572 g_free(protocol_rep);
3575 TRY_TO_FAKE_THIS_REPR(pi);
3577 va_start(ap, format);
3578 proto_tree_set_representation(pi, format, ap);
3584 /* Add a FT_BYTES to a proto_tree */
3586 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3587 gint length, const guint8 *start_ptr)
3590 header_field_info *hfinfo;
3593 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3594 get_hfi_length(hfinfo, tvb, start, &length, &item_length, ENC_NA);
3595 test_length(hfinfo, tvb, start, item_length, ENC_NA);
3597 CHECK_FOR_NULL_TREE(tree);
3599 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3601 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BYTES);
3603 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3604 proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, length);
3609 /* Add a FT_BYTES to a proto_tree */
3611 proto_tree_add_bytes_with_length(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3612 gint tvbuff_length, const guint8 *start_ptr, gint ptr_length)
3615 header_field_info *hfinfo;
3618 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3619 get_hfi_length(hfinfo, tvb, start, &tvbuff_length, &item_length, ENC_NA);
3620 test_length(hfinfo, tvb, start, item_length, ENC_NA);
3622 CHECK_FOR_NULL_TREE(tree);
3624 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3626 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BYTES);
3628 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &tvbuff_length);
3629 proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, ptr_length);
3635 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3636 gint start, gint length,
3637 const guint8 *start_ptr,
3638 const char *format, ...)
3643 if (start_ptr == NULL)
3644 start_ptr = tvb_get_ptr(tvb, start, length);
3646 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
3648 TRY_TO_FAKE_THIS_REPR_NESTED(pi);
3650 va_start(ap, format);
3651 proto_tree_set_representation_value(pi, format, ap);
3658 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3659 gint start, gint length, const guint8 *start_ptr,
3660 const char *format, ...)
3665 if (start_ptr == NULL)
3666 start_ptr = tvb_get_ptr(tvb, start, length);
3668 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
3670 TRY_TO_FAKE_THIS_REPR_NESTED(pi);
3672 va_start(ap, format);
3673 proto_tree_set_representation(pi, format, ap);
3680 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
3684 DISSECTOR_ASSERT(start_ptr != NULL || length == 0);
3686 bytes = g_byte_array_new();
3688 g_byte_array_append(bytes, start_ptr, length);
3690 fvalue_set_byte_array(&fi->value, bytes);
3695 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
3697 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
3701 proto_tree_set_bytes_gbytearray(field_info *fi, const GByteArray *value)
3705 DISSECTOR_ASSERT(value != NULL);
3707 bytes = byte_array_dup(value);
3709 fvalue_set_byte_array(&fi->value, bytes);
3712 /* Add a FT_*TIME to a proto_tree */
3714 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3715 gint length, const nstime_t *value_ptr)
3718 header_field_info *hfinfo;
3720 CHECK_FOR_NULL_TREE(tree);
3722 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3724 DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo);
3726 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3727 proto_tree_set_time(PNODE_FINFO(pi), value_ptr);
3733 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3734 gint start, gint length, nstime_t *value_ptr,
3735 const char *format, ...)
3740 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
3742 va_start(ap, format);
3743 proto_tree_set_representation_value(pi, format, ap);
3751 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3752 gint start, gint length, nstime_t *value_ptr,
3753 const char *format, ...)
3758 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
3760 TRY_TO_FAKE_THIS_REPR(pi);
3762 va_start(ap, format);
3763 proto_tree_set_representation(pi, format, ap);
3770 /* Set the FT_*TIME value */
3772 proto_tree_set_time(field_info *fi, const nstime_t *value_ptr)
3774 DISSECTOR_ASSERT(value_ptr != NULL);
3776 fvalue_set_time(&fi->value, value_ptr);
3779 /* Add a FT_IPXNET to a proto_tree */
3781 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3782 gint length, guint32 value)
3785 header_field_info *hfinfo;
3787 CHECK_FOR_NULL_TREE(tree);
3789 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3791 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPXNET);
3793 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3794 proto_tree_set_ipxnet(PNODE_FINFO(pi), value);
3800 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3801 gint start, gint length, guint32 value,
3802 const char *format, ...)
3807 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
3809 va_start(ap, format);
3810 proto_tree_set_representation_value(pi, format, ap);
3818 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3819 gint start, gint length, guint32 value,
3820 const char *format, ...)
3825 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
3827 TRY_TO_FAKE_THIS_REPR(pi);
3829 va_start(ap, format);
3830 proto_tree_set_representation(pi, format, ap);
3837 /* Set the FT_IPXNET value */
3839 proto_tree_set_ipxnet(field_info *fi, guint32 value)
3841 fvalue_set_uinteger(&fi->value, value);
3844 /* Add a FT_IPv4 to a proto_tree */
3846 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3847 gint length, guint32 value)
3850 header_field_info *hfinfo;
3852 CHECK_FOR_NULL_TREE(tree);
3854 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3856 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPv4);
3858 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3859 proto_tree_set_ipv4(PNODE_FINFO(pi), value);
3865 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3866 gint start, gint length, guint32 value,
3867 const char *format, ...)
3872 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
3874 va_start(ap, format);
3875 proto_tree_set_representation_value(pi, format, ap);
3883 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3884 gint start, gint length, guint32 value,
3885 const char *format, ...)
3890 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
3892 TRY_TO_FAKE_THIS_REPR(pi);
3894 va_start(ap, format);
3895 proto_tree_set_representation(pi, format, ap);
3902 /* Set the FT_IPv4 value */
3904 proto_tree_set_ipv4(field_info *fi, guint32 value)
3906 fvalue_set_uinteger(&fi->value, value);
3909 /* Add a FT_IPv6 to a proto_tree */
3911 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3912 gint length, const ws_in6_addr *value_ptr)
3915 header_field_info *hfinfo;
3917 CHECK_FOR_NULL_TREE(tree);
3919 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3921 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPv6);
3923 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3924 proto_tree_set_ipv6(PNODE_FINFO(pi), value_ptr->bytes);
3930 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3931 gint start, gint length,
3932 const ws_in6_addr *value_ptr,
3933 const char *format, ...)
3938 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
3940 va_start(ap, format);
3941 proto_tree_set_representation_value(pi, format, ap);
3949 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3950 gint start, gint length,
3951 const ws_in6_addr *value_ptr,
3952 const char *format, ...)
3957 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
3959 TRY_TO_FAKE_THIS_REPR(pi);
3961 va_start(ap, format);
3962 proto_tree_set_representation(pi, format, ap);
3969 /* Set the FT_IPv6 value */
3971 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
3973 DISSECTOR_ASSERT(value_ptr != NULL);
3974 fvalue_set_bytes(&fi->value, value_ptr);
3978 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
3980 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
3983 /* Set the FT_FCWWN value */
3985 proto_tree_set_fcwwn(field_info *fi, const guint8* value_ptr)
3987 DISSECTOR_ASSERT(value_ptr != NULL);
3988 fvalue_set_bytes(&fi->value, value_ptr);
3992 proto_tree_set_fcwwn_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
3994 proto_tree_set_fcwwn(fi, tvb_get_ptr(tvb, start, length));
3997 /* Add a FT_GUID to a proto_tree */
3999 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4000 gint length, const e_guid_t *value_ptr)
4003 header_field_info *hfinfo;
4005 CHECK_FOR_NULL_TREE(tree);
4007 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4009 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_GUID);
4011 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4012 proto_tree_set_guid(PNODE_FINFO(pi), value_ptr);
4018 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4019 gint start, gint length,
4020 const e_guid_t *value_ptr,
4021 const char *format, ...)
4026 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
4028 va_start(ap, format);
4029 proto_tree_set_representation_value(pi, format, ap);
4037 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4038 gint start, gint length, const e_guid_t *value_ptr,
4039 const char *format, ...)
4044 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
4046 TRY_TO_FAKE_THIS_REPR(pi);
4048 va_start(ap, format);
4049 proto_tree_set_representation(pi, format, ap);
4056 /* Set the FT_GUID value */
4058 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
4060 DISSECTOR_ASSERT(value_ptr != NULL);
4061 fvalue_set_guid(&fi->value, value_ptr);
4065 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
4066 const guint encoding)
4070 tvb_get_guid(tvb, start, &guid, encoding);
4071 proto_tree_set_guid(fi, &guid);
4074 /* Add a FT_OID to a proto_tree */
4076 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4077 gint length, const guint8* value_ptr)
4080 header_field_info *hfinfo;
4082 CHECK_FOR_NULL_TREE(tree);
4084 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4086 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_OID);
4088 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4089 proto_tree_set_oid(PNODE_FINFO(pi), value_ptr, length);
4095 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4096 gint start, gint length,
4097 const guint8* value_ptr,
4098 const char *format, ...)
4103 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
4105 va_start(ap, format);
4106 proto_tree_set_representation_value(pi, format, ap);
4114 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4115 gint start, gint length, const guint8* value_ptr,
4116 const char *format, ...)
4121 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
4123 TRY_TO_FAKE_THIS_REPR(pi);
4125 va_start(ap, format);
4126 proto_tree_set_representation(pi, format, ap);
4133 /* Set the FT_OID value */
4135 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
4139 DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
4141 bytes = g_byte_array_new();
4143 g_byte_array_append(bytes, value_ptr, length);
4145 fvalue_set_byte_array(&fi->value, bytes);
4149 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
4151 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
4154 /* Set the FT_SYSTEM_ID value */
4156 proto_tree_set_system_id(field_info *fi, const guint8* value_ptr, gint length)
4160 DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
4162 bytes = g_byte_array_new();
4164 g_byte_array_append(bytes, value_ptr, length);
4166 fvalue_set_byte_array(&fi->value, bytes);
4170 proto_tree_set_system_id_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
4172 proto_tree_set_system_id(fi, tvb_get_ptr(tvb, start, length), length);
4175 /* Add a FT_STRING, FT_STRINGZ, or FT_STRINGZPAD to a proto_tree. Creates
4176 * own copy of string, and frees it when the proto_tree is destroyed. */
4178 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4179 gint length, const char* value)
4182 header_field_info *hfinfo;
4184 CHECK_FOR_NULL_TREE(tree);
4186 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4188 DISSECTOR_ASSERT_FIELD_TYPE_IS_STRING(hfinfo);
4190 if (hfinfo->display == STR_UNICODE) {
4191 DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL));
4194 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4195 DISSECTOR_ASSERT(length >= 0);
4196 proto_tree_set_string(PNODE_FINFO(pi), value);
4202 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4203 gint start, gint length, const char* value,
4210 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
4212 va_start(ap, format);
4213 proto_tree_set_representation_value(pi, format, ap);
4221 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4222 gint start, gint length, const char* value,
4223 const char *format, ...)
4228 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
4230 TRY_TO_FAKE_THIS_REPR(pi);
4232 va_start(ap, format);
4233 proto_tree_set_representation(pi, format, ap);
4240 /* Set the FT_STRING value */
4242 proto_tree_set_string(field_info *fi, const char* value)
4245 fvalue_set_string(&fi->value, value);
4247 fvalue_set_string(&fi->value, "[ Null ]");
4251 /* Set the FT_AX25 value */
4253 proto_tree_set_ax25(field_info *fi, const guint8* value)
4255 fvalue_set_bytes(&fi->value, value);
4259 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
4261 proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
4264 /* Set the FT_VINES value */
4266 proto_tree_set_vines(field_info *fi, const guint8* value)
4268 fvalue_set_bytes(&fi->value, value);
4272 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start)
4274 proto_tree_set_vines(fi, tvb_get_ptr(tvb, start, FT_VINES_ADDR_LEN));
4277 /* Add a FT_ETHER to a proto_tree */
4279 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4280 gint length, const guint8* value)
4283 header_field_info *hfinfo;
4285 CHECK_FOR_NULL_TREE(tree);
4287 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4289 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_ETHER);
4291 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4292 proto_tree_set_ether(PNODE_FINFO(pi), value);
4298 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4299 gint start, gint length, const guint8* value,
4300 const char *format, ...)
4305 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
4307 va_start(ap, format);
4308 proto_tree_set_representation_value(pi, format, ap);
4316 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4317 gint start, gint length, const guint8* value,
4318 const char *format, ...)
4323 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
4325 TRY_TO_FAKE_THIS_REPR(pi);
4327 va_start(ap, format);
4328 proto_tree_set_representation(pi, format, ap);
4335 /* Set the FT_ETHER value */
4337 proto_tree_set_ether(field_info *fi, const guint8* value)
4339 fvalue_set_bytes(&fi->value, value);
4343 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
4345 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
4348 /* Add a FT_BOOLEAN to a proto_tree */
4350 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4351 gint length, guint32 value)
4354 header_field_info *hfinfo;
4356 CHECK_FOR_NULL_TREE(tree);
4358 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4360 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BOOLEAN);
4362 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4363 proto_tree_set_boolean(PNODE_FINFO(pi), value);
4369 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
4370 tvbuff_t *tvb, gint start, gint length,
4371 guint32 value, const char *format, ...)
4376 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
4378 va_start(ap, format);
4379 proto_tree_set_representation_value(pi, format, ap);
4387 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4388 gint start, gint length, guint32 value,
4389 const char *format, ...)
4394 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
4396 TRY_TO_FAKE_THIS_REPR(pi);
4398 va_start(ap, format);
4399 proto_tree_set_representation(pi, format, ap);
4407 proto_tree_add_boolean64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4408 gint length, guint64 value)
4411 header_field_info *hfinfo;
4413 CHECK_FOR_NULL_TREE(tree);
4415 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4417 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BOOLEAN);
4419 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4420 proto_tree_set_boolean(PNODE_FINFO(pi), value);
4425 /* Set the FT_BOOLEAN value */
4427 proto_tree_set_boolean(field_info *fi, guint64 value)
4429 proto_tree_set_uint64(fi, value);
4432 /* Generate, into "buf", a string showing the bits of a bitfield.
4433 Return a pointer to the character after that string. */
4434 /*XXX this needs a buf_len check */
4436 other_decode_bitfield_value(char *buf, const guint64 val, const guint64 mask, const int width)
4444 bit = G_GUINT64_CONSTANT(1) << (width - 1);
4447 /* This bit is part of the field. Show its value. */
4453 /* This bit is not part of the field. */
4468 decode_bitfield_value(char *buf, const guint64 val, const guint64 mask, const int width)
4472 p = other_decode_bitfield_value(buf, val, mask, width);
4473 p = g_stpcpy(p, " = ");
4479 other_decode_bitfield_varint_value(char *buf, guint64 val, guint64 mask, const int width)
4486 bit = G_GUINT64_CONSTANT(1) << (width - 1);
4488 if (((8-(i % 8)) != 8) && /* MSB is never used for value. */
4490 /* This bit is part of the field. Show its value. */
4496 /* This bit is not part of the field. */
4512 decode_bitfield_varint_value(char *buf, const guint64 val, const guint64 mask, const int width)
4516 p = other_decode_bitfield_varint_value(buf, val, mask, width);
4517 p = g_stpcpy(p, " = ");
4522 /* Add a FT_FLOAT to a proto_tree */
4524 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4525 gint length, float value)
4528 header_field_info *hfinfo;
4530 CHECK_FOR_NULL_TREE(tree);
4532 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4534 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_FLOAT);
4536 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4537 proto_tree_set_float(PNODE_FINFO(pi), value);
4543 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4544 gint start, gint length, float value,
4545 const char *format, ...)
4550 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
4552 va_start(ap, format);
4553 proto_tree_set_representation_value(pi, format, ap);
4561 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4562 gint start, gint length, float value,
4563 const char *format, ...)
4568 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
4570 TRY_TO_FAKE_THIS_REPR(pi);
4572 va_start(ap, format);
4573 proto_tree_set_representation(pi, format, ap);
4580 /* Set the FT_FLOAT value */
4582 proto_tree_set_float(field_info *fi, float value)
4584 fvalue_set_floating(&fi->value, value);
4587 /* Add a FT_DOUBLE to a proto_tree */
4589 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4590 gint length, double value)
4593 header_field_info *hfinfo;
4595 CHECK_FOR_NULL_TREE(tree);
4597 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4599 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_DOUBLE);
4601 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4602 proto_tree_set_double(PNODE_FINFO(pi), value);
4608 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4609 gint start, gint length, double value,
4610 const char *format, ...)
4615 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
4617 va_start(ap, format);
4618 proto_tree_set_representation_value(pi, format, ap);
4626 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4627 gint start, gint length, double value,
4628 const char *format, ...)
4633 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
4635 TRY_TO_FAKE_THIS_REPR(pi);
4637 va_start(ap, format);
4638 proto_tree_set_representation(pi, format, ap);
4645 /* Set the FT_DOUBLE value */
4647 proto_tree_set_double(field_info *fi, double value)
4649 fvalue_set_floating(&fi->value, value);
4652 /* Add FT_CHAR or FT_UINT{8,16,24,32} to a proto_tree */
4654 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4655 gint length, guint32 value)
4657 proto_item *pi = NULL;
4658 header_field_info *hfinfo;
4660 CHECK_FOR_NULL_TREE(tree);
4662 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4664 switch (hfinfo->type) {
4671 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4672 proto_tree_set_uint(PNODE_FINFO(pi), value);
4676 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
4677 "field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, FT_UINT32, or FT_FRAMENUM",
4685 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4686 gint start, gint length, guint32 value,
4687 const char *format, ...)
4692 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
4694 va_start(ap, format);
4695 proto_tree_set_representation_value(pi, format, ap);
4703 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4704 gint start, gint length, guint32 value,
4705 const char *format, ...)
4710 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
4712 TRY_TO_FAKE_THIS_REPR(pi);
4714 va_start(ap, format);
4715 proto_tree_set_representation(pi, format, ap);
4722 /* Set the FT_UINT{8,16,24,32} value */
4724 proto_tree_set_uint(field_info *fi, guint32 value)
4726 header_field_info *hfinfo;
4729 hfinfo = fi->hfinfo;
4732 if (hfinfo->bitmask) {
4733 /* Mask out irrelevant portions */
4734 integer &= (guint32)(hfinfo->bitmask);
4737 integer >>= hfinfo_bitshift(hfinfo);
4740 fvalue_set_uinteger(&fi->value, integer);
4743 /* Add FT_UINT{40,48,56,64} to a proto_tree */
4745 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4746 gint length, guint64 value)
4748 proto_item *pi = NULL;
4749 header_field_info *hfinfo;
4751 CHECK_FOR_NULL_TREE(tree);
4753 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4755 switch (hfinfo->type) {
4761 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4762 proto_tree_set_uint64(PNODE_FINFO(pi), value);
4766 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
4767 "field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, FT_UINT64, or FT_FRAMENUM",
4775 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4776 gint start, gint length, guint64 value,
4777 const char *format, ...)
4782 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
4784 va_start(ap, format);
4785 proto_tree_set_representation_value(pi, format, ap);
4793 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4794 gint start, gint length, guint64 value,
4795 const char *format, ...)
4800 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
4802 TRY_TO_FAKE_THIS_REPR(pi);
4804 va_start(ap, format);
4805 proto_tree_set_representation(pi, format, ap);
4812 /* Set the FT_UINT{40,48,56,64} value */
4814 proto_tree_set_uint64(field_info *fi, guint64 value)
4816 header_field_info *hfinfo;
4819 hfinfo = fi->hfinfo;
4822 if (hfinfo->bitmask) {
4823 /* Mask out irrelevant portions */
4824 integer &= hfinfo->bitmask;
4827 integer >>= hfinfo_bitshift(hfinfo);
4830 fvalue_set_uinteger64(&fi->value, integer);
4833 /* Add FT_INT{8,16,24,32} to a proto_tree */
4835 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4836 gint length, gint32 value)
4838 proto_item *pi = NULL;
4839 header_field_info *hfinfo;
4841 CHECK_FOR_NULL_TREE(tree);
4843 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4845 switch (hfinfo->type) {
4850 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4851 proto_tree_set_int(PNODE_FINFO(pi), value);
4855 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
4856 "field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
4864 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4865 gint start, gint length, gint32 value,
4866 const char *format, ...)
4871 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
4873 va_start(ap, format);
4874 proto_tree_set_representation_value(pi, format, ap);
4882 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4883 gint start, gint length, gint32 value,
4884 const char *format, ...)
4889 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
4891 TRY_TO_FAKE_THIS_REPR(pi);
4893 va_start(ap, format);
4894 proto_tree_set_representation(pi, format, ap);
4901 /* Set the FT_INT{8,16,24,32} value */
4903 proto_tree_set_int(field_info *fi, gint32 value)
4905 header_field_info *hfinfo;
4909 hfinfo = fi->hfinfo;
4910 integer = (guint32) value;
4912 if (hfinfo->bitmask) {
4913 /* Mask out irrelevant portions */
4914 integer &= (guint32)(hfinfo->bitmask);
4917 integer >>= hfinfo_bitshift(hfinfo);
4919 no_of_bits = ws_count_ones(hfinfo->bitmask);
4920 integer = ws_sign_ext32(integer, no_of_bits);
4923 fvalue_set_sinteger(&fi->value, integer);
4926 /* Add FT_INT{40,48,56,64} to a proto_tree */
4928 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4929 gint length, gint64 value)
4931 proto_item *pi = NULL;
4932 header_field_info *hfinfo;
4934 CHECK_FOR_NULL_TREE(tree);
4936 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4938 switch (hfinfo->type) {
4943 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4944 proto_tree_set_int64(PNODE_FINFO(pi), value);
4948 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
4949 "field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
4957 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4958 gint start, gint length, gint64 value,
4959 const char *format, ...)
4964 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
4966 va_start(ap, format);
4967 proto_tree_set_representation_value(pi, format, ap);
4974 /* Set the FT_INT{40,48,56,64} value */
4976 proto_tree_set_int64(field_info *fi, gint64 value)
4978 header_field_info *hfinfo;
4982 hfinfo = fi->hfinfo;
4985 if (hfinfo->bitmask) {
4986 /* Mask out irrelevant portions */
4987 integer &= hfinfo->bitmask;
4990 integer >>= hfinfo_bitshift(hfinfo);
4992 no_of_bits = ws_count_ones(hfinfo->bitmask);
4993 integer = ws_sign_ext64(integer, no_of_bits);
4996 fvalue_set_sinteger64(&fi->value, integer);
5000 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5001 gint start, gint length, gint64 value,
5002 const char *format, ...)
5007 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
5009 TRY_TO_FAKE_THIS_REPR(pi);
5011 va_start(ap, format);
5012 proto_tree_set_representation(pi, format, ap);
5019 /* Add a FT_EUI64 to a proto_tree */
5021 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
5022 gint length, const guint64 value)
5025 header_field_info *hfinfo;
5027 CHECK_FOR_NULL_TREE(tree);
5029 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
5031 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_EUI64);
5033 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
5034 proto_tree_set_eui64(PNODE_FINFO(pi), value);
5040 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5041 gint start, gint length, const guint64 value,
5042 const char *format, ...)
5047 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
5049 va_start(ap, format);
5050 proto_tree_set_representation_value(pi, format, ap);
5058 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
5059 gint start, gint length, const guint64 value,
5060 const char *format, ...)
5065 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
5067 TRY_TO_FAKE_THIS_REPR(pi);
5069 va_start(ap, format);
5070 proto_tree_set_representation(pi, format, ap);
5077 /* Set the FT_EUI64 value */
5079 proto_tree_set_eui64(field_info *fi, const guint64 value)
5081 fvalue_set_uinteger64(&fi->value, value);
5084 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding)
5088 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
5090 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
5094 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
5096 proto_tree_add_node(proto_tree *tree, field_info *fi)
5098 proto_node *pnode, *tnode, *sibling;
5103 * Restrict our depth. proto_tree_traverse_pre_order and
5104 * proto_tree_traverse_post_order (and possibly others) are recursive
5105 * so we need to be mindful of our stack size.
5107 if (tree->first_child == NULL) {
5108 for (tnode = tree; tnode != NULL; tnode = tnode->parent) {
5110 if (G_UNLIKELY(depth > MAX_TREE_LEVELS)) {
5111 THROW_MESSAGE(DissectorError, wmem_strdup_printf(wmem_packet_scope(),
5112 "Maximum tree depth %d exceeded for \"%s\" - \"%s\" (%s:%u)",
5114 fi->hfinfo->name, fi->hfinfo->abbrev, G_STRFUNC, __LINE__));
5120 * Make sure "tree" is ready to have subtrees under it, by
5121 * checking whether it's been given an ett_ value.
5123 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
5124 * node of the protocol tree. That node is not displayed,
5125 * so it doesn't need an ett_ value to remember whether it
5129 tfi = PNODE_FINFO(tnode);
5130 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
5131 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
5132 "\"%s\" - \"%s\" tfi->tree_type: %d invalid (%s:%u)",
5133 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
5134 /* XXX - is it safe to continue here? */
5137 pnode = wmem_new(PNODE_POOL(tree), proto_node);
5138 PROTO_NODE_INIT(pnode);
5139 pnode->parent = tnode;
5140 PNODE_FINFO(pnode) = fi;
5141 pnode->tree_data = PTREE_DATA(tree);
5143 if (tnode->last_child != NULL) {
5144 sibling = tnode->last_child;
5145 DISSECTOR_ASSERT(sibling->next == NULL);
5146 sibling->next = pnode;
5148 tnode->first_child = pnode;
5149 tnode->last_child = pnode;
5151 tree_data_add_maybe_interesting_field(pnode->tree_data, fi);
5153 return (proto_item *)pnode;
5157 /* Generic way to allocate field_info and add to proto_tree.
5158 * Sets *pfi to address of newly-allocated field_info struct */
5160 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, gint start,
5167 get_hfi_length(hfinfo, tvb, start, length, &item_length, ENC_NA);
5168 fi = new_field_info(tree, hfinfo, tvb, start, item_length);
5169 pi = proto_tree_add_node(tree, fi);
5176 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
5177 gint *item_length, const guint encoding)
5179 gint length_remaining;
5182 * We only allow a null tvbuff if the item has a zero length,
5183 * i.e. if there's no data backing it.
5185 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
5188 * XXX - in some protocols, there are 32-bit unsigned length
5189 * fields, so lengths in protocol tree and tvbuff routines
5190 * should really be unsigned. We should have, for those
5191 * field types for which "to the end of the tvbuff" makes sense,
5192 * additional routines that take no length argument and
5193 * add fields that run to the end of the tvbuff.
5195 if (*length == -1) {
5197 * For FT_NONE, FT_PROTOCOL, FT_BYTES, FT_STRING, and
5198 * FT_STRINGZPAD fields, a length of -1 means "set the
5199 * length to what remains in the tvbuff".
5201 * The assumption is either that
5203 * 1) the length of the item can only be determined
5204 * by dissection (typically true of items with
5205 * subitems, which are probably FT_NONE or
5210 * 2) if the tvbuff is "short" (either due to a short
5211 * snapshot length or due to lack of reassembly of
5212 * fragments/segments/whatever), we want to display
5213 * what's available in the field (probably FT_BYTES
5214 * or FT_STRING) and then throw an exception later
5218 * 3) the field is defined to be "what's left in the
5221 * so we set the length to what remains in the tvbuff so
5222 * that, if we throw an exception while dissecting, it
5223 * has what is probably the right value.
5225 * For FT_STRINGZ, it means "the string is null-terminated,
5226 * not null-padded; set the length to the actual length
5227 * of the string", and if the tvbuff if short, we just
5228 * throw an exception.
5230 * For ENC_VARINT_PROTOBUF, it means "find the end of the string",
5231 * and if the tvbuff if short, we just throw an exception.
5233 * It's not valid for any other type of field. For those
5234 * fields, we treat -1 the same way we treat other
5235 * negative values - we assume the length is a Really
5236 * Big Positive Number, and throw a ReportedBoundsError
5237 * exception, under the assumption that the Really Big
5238 * Length would run past the end of the packet.
5240 if ((IS_FT_INT(hfinfo->type)) || (IS_FT_UINT(hfinfo->type))) {
5241 if (encoding & ENC_VARINT_PROTOBUF) {
5243 * Leave the length as -1, so our caller knows
5246 *item_length = *length;
5251 switch (hfinfo->type) {
5259 * We allow FT_PROTOCOLs to be zero-length -
5260 * for example, an ONC RPC NULL procedure has
5261 * neither arguments nor reply, so the
5262 * payload for that protocol is empty.
5264 * We also allow the others to be zero-length -
5265 * because that's the way the code has been for a
5268 * However, we want to ensure that the start
5269 * offset is not *past* the byte past the end
5270 * of the tvbuff: we throw an exception in that
5273 *length = tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
5274 DISSECTOR_ASSERT(*length >= 0);
5279 * Leave the length as -1, so our caller knows
5285 THROW(ReportedBoundsError);
5286 DISSECTOR_ASSERT_NOT_REACHED();
5288 *item_length = *length;
5290 *item_length = *length;
5291 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
5293 * These types are for interior nodes of the
5294 * tree, and don't have data associated with
5295 * them; if the length is negative (XXX - see
5296 * above) or goes past the end of the tvbuff,
5297 * cut it short at the end of the tvbuff.
5298 * That way, if this field is selected in
5299 * Wireshark, we don't highlight stuff past
5300 * the end of the data.
5302 /* XXX - what to do, if we don't have a tvb? */
5304 length_remaining = tvb_captured_length_remaining(tvb, start);
5305 if (*item_length < 0 ||
5306 (*item_length > 0 &&
5307 (length_remaining < *item_length)))
5308 *item_length = length_remaining;
5311 if (*item_length < 0) {
5312 THROW(ReportedBoundsError);
5318 get_full_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
5319 gint length, guint item_length, const gint encoding)
5324 * We need to get the correct item length here.
5325 * That's normally done by proto_tree_new_item(),
5326 * but we won't be calling it.
5328 switch (hfinfo->type) {
5334 * The length is the specified length.
5340 * Map all non-zero values to little-endian for
5341 * backwards compatibility.
5343 n = get_uint_value(NULL, tvb, start, length,
5344 encoding ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN);
5348 /* XXX - make these just FT_UINT? */
5357 /* XXX - make these just FT_INT? */
5366 if (encoding & ENC_VARINT_PROTOBUF) {
5368 report_type_length_mismatch(NULL, "a FT_[U]INT", length, TRUE);
5372 /* This can throw an exception */
5373 /* XXX - do this without fetching the varint? */
5374 length = tvb_get_varint(tvb, start, FT_VARINT_MAX_LEN, &dummy);
5376 THROW(ReportedBoundsError);
5379 item_length = length;
5384 * The length is the specified length.
5406 * The length is the specified length.
5412 report_type_length_mismatch(NULL, "a string", length, TRUE);
5415 /* This can throw an exception */
5416 /* XXX - do this without fetching the string? */
5417 tvb_get_stringz_enc(wmem_packet_scope(), tvb, start, &length, encoding);
5419 item_length = length;
5422 case FT_UINT_STRING:
5423 n = get_uint_value(NULL, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
5428 case FT_ABSOLUTE_TIME:
5429 case FT_RELATIVE_TIME:
5430 case FT_IEEE_11073_SFLOAT:
5431 case FT_IEEE_11073_FLOAT:
5433 * The length is the specified length.
5438 g_error("hfinfo->type %d (%s) not handled\n",
5440 ftype_name(hfinfo->type));
5441 DISSECTOR_ASSERT_NOT_REACHED();
5448 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
5449 const gint start, const gint item_length)
5453 FIELD_INFO_NEW(PNODE_POOL(tree), fi);
5455 fi->hfinfo = hfinfo;
5457 fi->start += (tvb)?tvb_raw_offset(tvb):0;
5458 fi->length = item_length;
5461 if (!PTREE_DATA(tree)->visible)
5462 FI_SET_FLAG(fi, FI_HIDDEN);
5463 fvalue_init(&fi->value, fi->hfinfo->type);
5466 /* add the data source tvbuff */
5467 fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
5469 fi->appendix_start = 0;
5470 fi->appendix_length = 0;
5475 /* If the protocol tree is to be visible, set the representation of a
5476 proto_tree entry with the name of the field for the item and with
5477 the value formatted with the supplied printf-style format and
5480 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
5484 /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
5485 * items string representation */
5486 if (PTREE_DATA(pi)->visible && !PROTO_ITEM_IS_HIDDEN(pi)) {
5488 field_info *fi = PITEM_FINFO(pi);
5489 header_field_info *hf;
5491 DISSECTOR_ASSERT(fi);
5495 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
5496 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
5500 if (IS_FT_UINT32(hf->type))
5501 val = fvalue_get_uinteger(&fi->value);
5503 val = fvalue_get_uinteger64(&fi->value);
5505 val <<= hfinfo_bitshift(hf);
5507 p = decode_bitfield_value(fi->rep->representation, val, hf->bitmask, hfinfo_container_bitwidth(hf));
5508 ret = (int) (p - fi->rep->representation);
5511 /* put in the hf name */
5512 ret += g_snprintf(fi->rep->representation + ret, ITEM_LABEL_LENGTH - ret, "%s: ", hf->name);
5514 /* If possible, Put in the value of the string */
5515 if (ret < ITEM_LABEL_LENGTH) {
5516 ret += g_vsnprintf(fi->rep->representation + ret,
5517 ITEM_LABEL_LENGTH - ret, format, ap);
5519 if (ret >= ITEM_LABEL_LENGTH) {
5520 /* Uh oh, we don't have enough room. Tell the user
5521 * that the field is truncated.
5523 LABEL_MARK_TRUNCATED_START(fi->rep->representation);
5528 /* If the protocol tree is to be visible, set the representation of a
5529 proto_tree entry with the representation formatted with the supplied
5530 printf-style format and argument list. */
5532 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
5534 int ret; /*tmp return value */
5535 field_info *fi = PITEM_FINFO(pi);
5537 DISSECTOR_ASSERT(fi);
5539 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
5540 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
5541 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
5543 if (ret >= ITEM_LABEL_LENGTH) {
5544 /* Uh oh, we don't have enough room. Tell the user
5545 * that the field is truncated.
5547 LABEL_MARK_TRUNCATED_START(fi->rep->representation);
5553 hfinfo_format_text(const header_field_info *hfinfo, const guchar *string)
5555 switch (hfinfo->display) {
5557 return format_text(NULL, string, strlen(string));
5560 return format_text_wsp(string, strlen(string));
5563 /* XXX, format_unicode_text() */
5564 return wmem_strdup(NULL, string);
5567 return format_text(NULL, string, strlen(string));
5571 protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
5573 gsize res = g_strlcpy(dest, src, dest_size);
5575 if (res > dest_size)
5580 static header_field_info *
5581 hfinfo_same_name_get_prev(const header_field_info *hfinfo)
5583 header_field_info *dup_hfinfo;
5585 if (hfinfo->same_name_prev_id == -1)
5587 PROTO_REGISTRAR_GET_NTH(hfinfo->same_name_prev_id, dup_hfinfo);
5592 hfinfo_remove_from_gpa_name_map(const header_field_info *hfinfo)
5594 g_free(last_field_name);
5595 last_field_name = NULL;
5597 if (!hfinfo->same_name_next && hfinfo->same_name_prev_id == -1) {
5598 /* No hfinfo with the same name */
5599 g_hash_table_steal(gpa_name_map, hfinfo->abbrev);
5603 if (hfinfo->same_name_next) {
5604 hfinfo->same_name_next->same_name_prev_id = hfinfo->same_name_prev_id;
5607 if (hfinfo->same_name_prev_id != -1) {
5608 header_field_info *same_name_prev = hfinfo_same_name_get_prev(hfinfo);
5609 same_name_prev->same_name_next = hfinfo->same_name_next;
5610 if (!hfinfo->same_name_next) {
5611 /* It's always the latest added hfinfo which is stored in gpa_name_map */
5612 g_hash_table_insert(gpa_name_map, (gpointer) (same_name_prev->abbrev), same_name_prev);
5617 /* -------------------------- */
5619 proto_custom_set(proto_tree* tree, GSList *field_ids, gint occurrence,
5620 gchar *result, gchar *expr, const int size)
5625 ipv4_addr_and_mask *ipv4;
5628 guint32 n_addr; /* network-order IPv4 address */
5630 const true_false_string *tfstring;
5632 int len, prev_len = 0, last, i, offset_r = 0, offset_e = 0;
5634 field_info *finfo = NULL;
5635 header_field_info* hfinfo;
5636 const gchar *abbrev = NULL;
5638 const char *hf_str_val;
5639 char number_buf[48];
5640 const char *number_out;
5646 g_assert(field_ids != NULL);
5647 while ((field_idx = (int *) g_slist_nth_data(field_ids, ii++))) {
5648 field_id = *field_idx;
5649 PROTO_REGISTRAR_GET_NTH((guint)field_id, hfinfo);
5651 /* do we need to rewind ? */
5655 if (occurrence < 0) {
5656 /* Search other direction */
5657 while (hfinfo->same_name_prev_id != -1) {
5658 PROTO_REGISTRAR_GET_NTH(hfinfo->same_name_prev_id, hfinfo);
5663 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
5665 if (!finfos || !(len = g_ptr_array_len(finfos))) {
5666 if (occurrence < 0) {
5667 hfinfo = hfinfo->same_name_next;
5669 hfinfo = hfinfo_same_name_get_prev(hfinfo);
5674 /* Are there enough occurrences of the field? */
5675 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
5676 if (occurrence < 0) {
5677 hfinfo = hfinfo->same_name_next;
5679 hfinfo = hfinfo_same_name_get_prev(hfinfo);
5685 /* Calculate single index or set outer bounderies */
5686 if (occurrence < 0) {
5687 i = occurrence + len + prev_len;
5689 } else if (occurrence > 0) {
5690 i = occurrence - 1 - prev_len;
5697 prev_len += len; /* Count handled occurrences */
5700 finfo = (field_info *)g_ptr_array_index(finfos, i);
5702 if (offset_r && (offset_r < (size - 2)))
5703 result[offset_r++] = ',';
5705 if (offset_e && (offset_e < (size - 2)))
5706 expr[offset_e++] = ',';
5708 switch (hfinfo->type) {
5710 case FT_NONE: /* Nothing to add */
5711 if (offset_r == 0) {
5713 } else if (result[offset_r-1] == ',') {
5714 result[offset_r-1] = '\0';
5719 /* prevent multiple "yes" entries by setting result directly */
5720 g_strlcpy(result, "Yes", size);
5725 bytes = (guint8 *)fvalue_get(&finfo->value);
5727 switch(hfinfo->display)
5730 str = bytestring_to_str(NULL, bytes, fvalue_length(&finfo->value), '.');
5733 str = bytestring_to_str(NULL, bytes, fvalue_length(&finfo->value), '-');
5736 str = bytestring_to_str(NULL, bytes, fvalue_length(&finfo->value), ':');
5739 str = bytestring_to_str(NULL, bytes, fvalue_length(&finfo->value), ' ');
5743 if (prefs.display_byte_fields_with_spaces)
5745 str = bytestring_to_str(NULL, bytes, fvalue_length(&finfo->value), ' ');
5749 str = bytes_to_str(NULL, bytes, fvalue_length(&finfo->value));
5753 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5754 wmem_free(NULL, str);
5757 if (hfinfo->display & BASE_ALLOW_ZERO) {
5758 offset_r += protoo_strlcpy(result+offset_r, "<none>", size-offset_r);
5760 offset_r += protoo_strlcpy(result+offset_r, "<MISSING>", size-offset_r);
5765 case FT_ABSOLUTE_TIME:
5766 tmpbuf = abs_time_to_str(NULL, (const nstime_t *)fvalue_get(&finfo->value), (absolute_time_display_e)hfinfo->display, TRUE);
5767 offset_r += protoo_strlcpy(result+offset_r,
5770 wmem_free(NULL, tmpbuf);
5773 case FT_RELATIVE_TIME:
5774 tmpbuf = rel_time_to_secs_str(NULL, (const nstime_t *)fvalue_get(&finfo->value));
5775 offset_r += protoo_strlcpy(result+offset_r,
5778 wmem_free(NULL, tmpbuf);
5782 number64 = fvalue_get_uinteger64(&finfo->value);
5783 tfstring = (const true_false_string *)&tfs_true_false;
5784 if (hfinfo->strings) {
5785 tfstring = (const struct true_false_string*) hfinfo->strings;
5787 offset_r += protoo_strlcpy(result+offset_r,
5789 tfstring->true_string :
5790 tfstring->false_string, size-offset_r);
5792 offset_e += protoo_strlcpy(expr+offset_e,
5793 number64 ? "1" : "0", size-offset_e);
5798 number = fvalue_get_uinteger(&finfo->value);
5800 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) {
5801 gchar tmp[ITEM_LABEL_LENGTH];
5802 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5804 DISSECTOR_ASSERT(fmtfunc);
5805 fmtfunc(tmp, number);
5807 offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
5809 } else if (hfinfo->strings) {
5810 number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
5813 number_out = hfinfo_char_value_format_display(BASE_HEX, number_buf, number);
5815 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5818 number_out = hfinfo_char_value_format(hfinfo, number_buf, number);
5820 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5823 if (hf_str_val && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
5824 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
5826 number_out = hfinfo_char_value_format(hfinfo, number_buf, number);
5828 g_strlcpy(expr+offset_e, number_out, size-offset_e);
5831 offset_e = (int)strlen(expr);
5834 /* XXX - make these just FT_NUMBER? */
5845 number = IS_FT_INT(hfinfo->type) ?
5846 (guint32) fvalue_get_sinteger(&finfo->value) :
5847 fvalue_get_uinteger(&finfo->value);
5849 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) {
5850 gchar tmp[ITEM_LABEL_LENGTH];
5851 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5853 DISSECTOR_ASSERT(fmtfunc);
5854 fmtfunc(tmp, number);
5856 offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
5858 } else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) {
5859 if (hfinfo->display & BASE_UNIT_STRING) {
5860 number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
5861 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5862 hf_str_val = hf_try_val_to_str(number, hfinfo);
5863 offset_r += protoo_strlcpy(result+offset_r, hf_str_val, size-offset_r);
5865 number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
5868 number_out = hfinfo_number_value_format_display(hfinfo, hfinfo->display, number_buf, number);
5870 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5873 number_out = hfinfo_number_value_format(hfinfo, number_buf, number);
5875 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5878 if (hf_str_val && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
5879 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
5881 number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
5883 g_strlcpy(expr+offset_e, number_out, size-offset_e);
5886 offset_e = (int)strlen(expr);
5898 number64 = IS_FT_INT(hfinfo->type) ?
5899 (guint64) fvalue_get_sinteger64(&finfo->value) :
5900 fvalue_get_uinteger64(&finfo->value);
5902 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) {
5903 gchar tmp[ITEM_LABEL_LENGTH];
5904 custom_fmt_func_64_t fmtfunc64 = (custom_fmt_func_64_t)hfinfo->strings;
5906 DISSECTOR_ASSERT(fmtfunc64);
5907 fmtfunc64(tmp, number64);
5908 offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
5909 } else if (hfinfo->strings) {
5910 if (hfinfo->display & BASE_UNIT_STRING) {
5911 number_out = hfinfo_numeric_value_format64(hfinfo, number_buf, number64);
5912 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5913 hf_str_val = hf_try_val64_to_str(number64, hfinfo);
5914 offset_r += protoo_strlcpy(result+offset_r, hf_str_val, size-offset_r);
5916 number_out = hf_str_val = hf_try_val64_to_str(number64, hfinfo);
5919 number_out = hfinfo_number_value_format_display64(hfinfo, hfinfo->display, number_buf, number64);
5921 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5924 number_out = hfinfo_number_value_format64(hfinfo, number_buf, number64);
5926 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5929 if (hf_str_val && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
5930 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
5932 number_out = hfinfo_numeric_value_format64(hfinfo, number_buf, number64);
5934 g_strlcpy(expr+offset_e, number_out, size-offset_e);
5937 offset_e = (int)strlen(expr);
5941 str = eui64_to_str(NULL, fvalue_get_uinteger64(&finfo->value));
5942 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5943 wmem_free(NULL, str);
5947 ipv4 = (ipv4_addr_and_mask *)fvalue_get(&finfo->value);
5948 n_addr = ipv4_get_net_order_addr(ipv4);
5949 set_address (&addr, AT_IPv4, 4, &n_addr);
5950 address_to_str_buf(&addr, result+offset_r, size-offset_r);
5951 offset_r = (int)strlen(result);
5955 ipv6 = (ws_in6_addr *)fvalue_get(&finfo->value);
5956 set_address (&addr, AT_IPv6, sizeof(ws_in6_addr), ipv6);
5957 address_to_str_buf(&addr, result+offset_r, size-offset_r);
5958 offset_r = (int)strlen(result);
5962 set_address (&addr, AT_FCWWN, FCWWN_ADDR_LEN, fvalue_get(&finfo->value));
5963 address_to_str_buf(&addr, result+offset_r, size-offset_r);
5964 offset_r = (int)strlen(result);
5968 set_address (&addr, AT_ETHER, FT_ETHER_LEN, fvalue_get(&finfo->value));
5969 address_to_str_buf(&addr, result+offset_r, size-offset_r);
5970 offset_r = (int)strlen(result);
5974 str = guid_to_str(NULL, (e_guid_t *)fvalue_get(&finfo->value));
5975 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5976 wmem_free(NULL, str);
5980 bytes = (guint8 *)fvalue_get(&finfo->value);
5981 str = rel_oid_resolved_from_encoded(NULL, bytes, fvalue_length(&finfo->value));
5982 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5983 wmem_free(NULL, str);
5985 str = rel_oid_encoded2string(NULL, bytes, fvalue_length(&finfo->value));
5986 offset_e += protoo_strlcpy(expr+offset_e, str, size-offset_e);
5987 wmem_free(NULL, str);
5991 bytes = (guint8 *)fvalue_get(&finfo->value);
5992 str = oid_resolved_from_encoded(NULL, bytes, fvalue_length(&finfo->value));
5993 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5994 wmem_free(NULL, str);
5996 str = oid_encoded2string(NULL, bytes, fvalue_length(&finfo->value));
5997 offset_e += protoo_strlcpy(expr+offset_e, str, size-offset_e);
5998 wmem_free(NULL, str);
6002 bytes = (guint8 *)fvalue_get(&finfo->value);
6003 str = print_system_id(NULL, bytes, fvalue_length(&finfo->value));
6004 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
6005 offset_e += protoo_strlcpy(expr+offset_e, str, size-offset_e);
6006 wmem_free(NULL, str);
6010 if (hfinfo->display & BASE_UNIT_STRING) {
6011 double d_value = fvalue_get_floating(&finfo->value);
6012 g_snprintf(result+offset_r, size-offset_r,
6013 "%." G_STRINGIFY(FLT_DIG) "g%s", d_value,
6014 unit_name_string_get_double(d_value, (unit_name_string*)hfinfo->strings));
6016 g_snprintf(result+offset_r, size-offset_r,
6017 "%." G_STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
6019 offset_r = (int)strlen(result);
6023 if (hfinfo->display & BASE_UNIT_STRING) {
6024 double d_value = fvalue_get_floating(&finfo->value);
6025 g_snprintf(result+offset_r, size-offset_r,
6026 "%." G_STRINGIFY(DBL_DIG) "g%s", d_value,
6027 unit_name_string_get_double(d_value, (unit_name_string*)hfinfo->strings));
6029 g_snprintf(result+offset_r, size-offset_r,
6030 "%." G_STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
6032 offset_r = (int)strlen(result);
6037 case FT_UINT_STRING:
6039 bytes = (guint8 *)fvalue_get(&finfo->value);
6040 str = hfinfo_format_text(hfinfo, bytes);
6041 offset_r += protoo_strlcpy(result+offset_r,
6042 str, size-offset_r);
6043 wmem_free(NULL, str);
6046 case FT_IEEE_11073_SFLOAT:
6047 str = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DISPLAY, hfinfo->display);
6048 g_snprintf(result+offset_r, size-offset_r,
6051 wmem_free(NULL, str);
6052 offset_r = (int)strlen(result);
6055 case FT_IEEE_11073_FLOAT:
6056 str = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DISPLAY, hfinfo->display);
6057 g_snprintf(result+offset_r, size-offset_r,
6060 offset_r = (int)strlen(result);
6061 wmem_free(NULL, str);
6064 case FT_IPXNET: /*XXX really No column custom ?*/
6067 g_error("hfinfo->type %d (%s) not handled\n",
6069 ftype_name(hfinfo->type));
6070 DISSECTOR_ASSERT_NOT_REACHED();
6076 switch (hfinfo->type) {
6100 /* for these types, "expr" is filled in the loop above */
6104 /* for all others, just copy "result" to "expr" */
6105 g_strlcpy(expr, result, size);
6110 /* Store abbrev for return value */
6111 abbrev = hfinfo->abbrev;
6114 if (occurrence == 0) {
6115 /* Fetch next hfinfo with same name (abbrev) */
6116 hfinfo = hfinfo_same_name_get_prev(hfinfo);
6123 return abbrev ? abbrev : "";
6127 /* Set text of proto_item after having already been created. */
6129 proto_item_set_text(proto_item *pi, const char *format, ...)
6131 field_info *fi = NULL;
6134 TRY_TO_FAKE_THIS_REPR_VOID(pi);
6136 fi = PITEM_FINFO(pi);
6141 ITEM_LABEL_FREE(PNODE_POOL(pi), fi->rep);
6145 va_start(ap, format);
6146 proto_tree_set_representation(pi, format, ap);
6150 /* Append to text of proto_item after having already been created. */
6152 proto_item_append_text(proto_item *pi, const char *format, ...)
6154 field_info *fi = NULL;
6158 TRY_TO_FAKE_THIS_REPR_VOID(pi);
6160 fi = PITEM_FINFO(pi);
6165 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
6167 * If we don't already have a representation,
6168 * generate the default representation.
6170 if (fi->rep == NULL) {
6171 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
6172 proto_item_fill_label(fi, fi->rep->representation);
6175 curlen = strlen(fi->rep->representation);
6176 if (ITEM_LABEL_LENGTH > curlen) {
6177 va_start(ap, format);
6178 g_vsnprintf(fi->rep->representation + curlen,
6179 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
6185 /* Prepend to text of proto_item after having already been created. */
6187 proto_item_prepend_text(proto_item *pi, const char *format, ...)
6189 field_info *fi = NULL;
6190 char representation[ITEM_LABEL_LENGTH];
6193 TRY_TO_FAKE_THIS_REPR_VOID(pi);
6195 fi = PITEM_FINFO(pi);
6200 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
6202 * If we don't already have a representation,
6203 * generate the default representation.
6205 if (fi->rep == NULL) {
6206 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
6207 proto_item_fill_label(fi, representation);
6209 g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
6211 va_start(ap, format);
6212 g_vsnprintf(fi->rep->representation,
6213 ITEM_LABEL_LENGTH, format, ap);
6215 g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
6220 finfo_set_len(field_info *fi, const gint length)
6222 DISSECTOR_ASSERT(length >= 0);
6223 fi->length = length;
6226 * You cannot just make the "len" field of a GByteArray
6227 * larger, if there's no data to back that length;
6228 * you can only make it smaller.
6230 if (fi->value.ftype->ftype == FT_BYTES && length <= (gint)fi->value.value.bytes->len)
6231 fi->value.value.bytes->len = length;
6235 proto_item_set_len(proto_item *pi, const gint length)
6239 TRY_TO_FAKE_THIS_REPR_VOID(pi);
6241 fi = PITEM_FINFO(pi);
6245 finfo_set_len(fi, length);
6249 * Sets the length of the item based on its start and on the specified
6250 * offset, which is the offset past the end of the item; as the start
6251 * in the item is relative to the beginning of the data source tvbuff,
6252 * we need to pass in a tvbuff - the end offset is relative to the beginning
6256 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
6261 TRY_TO_FAKE_THIS_REPR_VOID(pi);
6263 fi = PITEM_FINFO(pi);
6267 end += tvb_raw_offset(tvb);
6268 DISSECTOR_ASSERT(end >= fi->start);
6269 length = end - fi->start;
6271 finfo_set_len(fi, length);
6275 proto_item_get_len(const proto_item *pi)
6277 field_info *fi = PITEM_FINFO(pi);
6278 return fi ? fi->length : -1;
6282 proto_tree_create_root(packet_info *pinfo)
6286 /* Initialize the proto_node */
6287 pnode = g_slice_new(proto_tree);
6288 PROTO_NODE_INIT(pnode);
6289 pnode->parent = NULL;
6290 PNODE_FINFO(pnode) = NULL;
6291 pnode->tree_data = g_slice_new(tree_data_t);
6293 /* Make sure we can access pinfo everywhere */
6294 pnode->tree_data->pinfo = pinfo;
6296 /* Don't initialize the tree_data_t. Wait until we know we need it */
6297 pnode->tree_data->interesting_hfids = NULL;
6299 /* Set the default to FALSE so it's easier to
6300 * find errors; if we expect to see the protocol tree
6301 * but for some reason the default 'visible' is not
6302 * changed, then we'll find out very quickly. */
6303 pnode->tree_data->visible = FALSE;
6305 /* Make sure that we fake protocols (if possible) */
6306 pnode->tree_data->fake_protocols = TRUE;
6308 /* Keep track of the number of children */
6309 pnode->tree_data->count = 0;
6311 return (proto_tree *)pnode;
6315 /* "prime" a proto_tree with a single hfid that a dfilter
6316 * is interested in. */
6318 proto_tree_prime_with_hfid(proto_tree *tree _U_, const gint hfid)
6320 header_field_info *hfinfo;
6322 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
6323 /* this field is referenced by a filter so increase the refcount.
6324 also increase the refcount for the parent, i.e the protocol.
6326 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
6327 /* only increase the refcount if there is a parent.
6328 if this is a protocol and not a field then parent will be -1
6329 and there is no parent to add any refcounting for.
6331 if (hfinfo->parent != -1) {
6332 header_field_info *parent_hfinfo;
6333 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
6335 /* Mark parent as indirectly referenced unless it is already directly
6336 * referenced, i.e. the user has specified the parent in a filter.
6338 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
6339 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
6344 proto_item_add_subtree(proto_item *pi, const gint idx) {
6350 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
6352 fi = PITEM_FINFO(pi);
6354 return (proto_tree *)pi;
6356 fi->tree_type = idx;
6358 return (proto_tree *)pi;
6362 proto_item_get_subtree(proto_item *pi) {
6367 fi = PITEM_FINFO(pi);
6368 if ( (!fi) || (fi->tree_type == -1) )
6370 return (proto_tree *)pi;
6374 proto_item_get_parent(const proto_item *ti) {
6381 proto_item_get_parent_nth(proto_item *ti, int gen) {
6394 proto_tree_get_parent(proto_tree *tree) {
6397 return (proto_item *)tree;
6401 proto_tree_get_parent_tree(proto_tree *tree) {
6405 /* we're the root tree, there's no parent
6406 return ourselves so the caller has at least a tree to attach to */
6410 return (proto_tree *)tree->parent;
6414 proto_tree_get_root(proto_tree *tree) {
6417 while (tree->parent) {
6418 tree = tree->parent;
6424 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
6425 proto_item *item_to_move)
6428 /* Revert part of: https://code.wireshark.org/review/gitweb?p=wireshark.git;a=commit;h=00c05ed3fdfa9287422e6e1fc9bd6ea8b31ca4ee
6429 * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5500
6431 /* This function doesn't generate any values. It only reorganizes the prococol tree
6432 * so we can bail out immediately if it isn't visible. */
6433 if (!tree || !PTREE_DATA(tree)->visible)
6436 DISSECTOR_ASSERT(item_to_move->parent == tree);
6437 DISSECTOR_ASSERT(fixed_item->parent == tree);
6439 /*** cut item_to_move out ***/
6441 /* is item_to_move the first? */
6442 if (tree->first_child == item_to_move) {
6443 /* simply change first child to next */
6444 tree->first_child = item_to_move->next;
6446 DISSECTOR_ASSERT(tree->last_child != item_to_move);
6448 proto_item *curr_item;
6449 /* find previous and change it's next */
6450 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
6451 if (curr_item->next == item_to_move) {
6456 DISSECTOR_ASSERT(curr_item);
6458 curr_item->next = item_to_move->next;
6460 /* fix last_child if required */
6461 if (tree->last_child == item_to_move) {
6462 tree->last_child = curr_item;
6466 /*** insert to_move after fixed ***/
6467 item_to_move->next = fixed_item->next;
6468 fixed_item->next = item_to_move;
6469 if (tree->last_child == fixed_item) {
6470 tree->last_child = item_to_move;
6475 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
6483 fi = PTREE_FINFO(tree);
6487 start += tvb_raw_offset(tvb);
6488 DISSECTOR_ASSERT(start >= 0);
6489 DISSECTOR_ASSERT(length >= 0);
6491 fi->appendix_start = start;
6492 fi->appendix_length = length;
6496 proto_register_protocol(const char *name, const char *short_name,
6497 const char *filter_name)
6499 protocol_t *protocol;
6500 const protocol_t *existing_protocol = NULL;
6501 header_field_info *hfinfo;
6503 const char *existing_name;
6507 gboolean found_invalid;
6510 * Make sure there's not already a protocol with any of those
6511 * names. Crash if there is, as that's an error in the code
6512 * or an inappropriate plugin.
6513 * This situation has to be fixed to not register more than one
6514 * protocol with the same name.
6516 * This is done by reducing the number of strcmp (and alike) calls
6517 * as much as possible, as this significally slows down startup time.
6519 * Drawback: As a hash value is used to reduce insert time,
6520 * this might lead to a hash collision.
6521 * However, although we have somewhat over 1000 protocols, we're using
6522 * a 32 bit int so this is very, very unlikely.
6525 key = (gint *)g_malloc (sizeof(gint));
6526 *key = wrs_str_hash(name);
6528 existing_name = (const char *)g_hash_table_lookup(proto_names, key);
6529 if (existing_name != NULL) {
6530 /* g_error will terminate the program */
6531 g_error("Duplicate protocol name \"%s\"!"
6532 " This might be caused by an inappropriate plugin or a development error.", name);
6534 g_hash_table_insert(proto_names, key, (gpointer)name);
6536 existing_protocol = (const protocol_t *)g_hash_table_lookup(proto_short_names, short_name);
6537 if (existing_protocol != NULL) {
6538 g_error("Duplicate protocol short_name \"%s\"!"
6539 " This might be caused by an inappropriate plugin or a development error.", short_name);
6542 found_invalid = FALSE;
6543 for (i = 0; filter_name[i]; i++) {
6545 if (!(g_ascii_islower(c) || g_ascii_isdigit(c) || c == '-' || c == '_' || c == '.')) {
6546 found_invalid = TRUE;
6549 if (found_invalid) {
6550 g_error("Protocol filter name \"%s\" has one or more invalid characters."
6551 " Allowed are lower characters, digits, '-', '_' and '.'."
6552 " This might be caused by an inappropriate plugin or a development error.", filter_name);
6554 existing_protocol = (const protocol_t *)g_hash_table_lookup(proto_filter_names, filter_name);
6555 if (existing_protocol != NULL) {
6556 g_error("Duplicate protocol filter_name \"%s\"!"
6557 " This might be caused by an inappropriate plugin or a development error.", filter_name);
6560 /* Add this protocol to the list of known protocols; the list
6561 is sorted by protocol short name. */
6562 protocol = g_new(protocol_t, 1);
6563 protocol->name = name;
6564 protocol->short_name = short_name;
6565 protocol->filter_name = filter_name;
6566 /*protocol->fields = g_ptr_array_new();*/
6567 /* Delegate until actually needed and use g_ptr_array_sized_new*/
6568 protocol->fields = NULL;
6569 protocol->is_enabled = TRUE; /* protocol is enabled by default */
6570 protocol->enabled_by_default = TRUE; /* see previous comment */
6571 protocol->can_toggle = TRUE;
6572 protocol->parent_proto_id = -1;
6573 protocol->heur_list = NULL;
6574 /* list will be sorted later by name, when all protocols completed registering */
6575 protocols = g_list_prepend(protocols, protocol);
6576 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, protocol);
6577 g_hash_table_insert(proto_short_names, (gpointer)short_name, protocol);
6579 /* Here we allocate a new header_field_info struct */
6580 hfinfo = g_slice_new(header_field_info);
6581 hfinfo->name = name;
6582 hfinfo->abbrev = filter_name;
6583 hfinfo->type = FT_PROTOCOL;
6584 hfinfo->display = BASE_NONE;
6585 hfinfo->strings = protocol;
6586 hfinfo->bitmask = 0;
6587 hfinfo->ref_type = HF_REF_TYPE_NONE;
6588 hfinfo->blurb = NULL;
6589 hfinfo->parent = -1; /* this field differentiates protos and fields */
6591 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
6592 protocol->proto_id = proto_id;
6597 proto_register_protocol_in_name_only(const char *name, const char *short_name, const char *filter_name, int parent_proto, enum ftenum field_type)
6599 protocol_t *protocol;
6600 header_field_info *hfinfo;
6603 gboolean found_invalid = FALSE;
6606 * Helper protocols don't need the strict rules as a "regular" protocol
6607 * Just register it in a list and make a hf_ field from it
6609 if ((field_type != FT_PROTOCOL) && (field_type != FT_BYTES)) {
6610 g_error("Pino \"%s\" must be of type FT_PROTOCOL or FT_BYTES.", name);
6613 if (parent_proto < 0) {
6614 g_error("Must have a valid parent protocol for helper protocol \"%s\"!"
6615 " This might be caused by an inappropriate plugin or a development error.", name);
6618 for (i = 0; filter_name[i]; i++) {
6620 if (!(g_ascii_islower(c) || g_ascii_isdigit(c) || c == '-' || c == '_' || c == '.')) {
6621 found_invalid = TRUE;
6624 if (found_invalid) {
6625 g_error("Protocol filter name \"%s\" has one or more invalid characters."
6626 " Allowed are lower characters, digits, '-', '_' and '.'."
6627 " This might be caused by an inappropriate plugin or a development error.", filter_name);
6630 /* Add this protocol to the list of helper protocols (just so it can be properly freed) */
6631 protocol = g_new(protocol_t, 1);
6632 protocol->name = name;
6633 protocol->short_name = short_name;
6634 protocol->filter_name = filter_name;
6635 protocol->fields = NULL;
6637 /* Enabling and toggling is really determined by parent protocol,
6638 but provide default values here */
6639 protocol->is_enabled = TRUE;
6640 protocol->enabled_by_default = TRUE;
6641 protocol->can_toggle = TRUE;
6643 protocol->parent_proto_id = parent_proto;
6644 protocol->heur_list = NULL;
6645 /* list will be sorted later by name, when all protocols completed registering */
6646 pino_protocols = g_list_prepend(pino_protocols, protocol);
6648 /* Here we allocate a new header_field_info struct */
6649 hfinfo = g_slice_new(header_field_info);
6650 hfinfo->name = name;
6651 hfinfo->abbrev = filter_name;
6652 hfinfo->type = field_type;
6653 hfinfo->display = BASE_NONE;
6654 if (field_type == FT_BYTES) {
6655 hfinfo->display |= (BASE_NO_DISPLAY_VALUE|BASE_PROTOCOL_INFO);
6657 hfinfo->strings = protocol;
6658 hfinfo->bitmask = 0;
6659 hfinfo->ref_type = HF_REF_TYPE_NONE;
6660 hfinfo->blurb = NULL;
6661 hfinfo->parent = -1; /* this field differentiates protos and fields */
6663 protocol->proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
6664 return protocol->proto_id;
6668 proto_deregister_protocol(const char *short_name)
6670 protocol_t *protocol;
6671 header_field_info *hfinfo;
6676 proto_id = proto_get_id_by_short_name(short_name);
6677 protocol = find_protocol_by_id(proto_id);
6678 if (protocol == NULL)
6681 key = wrs_str_hash(protocol->name);
6682 g_hash_table_remove(proto_names, &key);
6684 g_hash_table_remove(proto_short_names, (gpointer)short_name);
6685 g_hash_table_remove(proto_filter_names, (gpointer)protocol->filter_name);
6687 if (protocol->fields) {
6688 for (i = 0; i < protocol->fields->len; i++) {
6689 hfinfo = (header_field_info *)g_ptr_array_index(protocol->fields, i);
6690 hfinfo_remove_from_gpa_name_map(hfinfo);
6691 expert_deregister_expertinfo(hfinfo->abbrev);
6692 g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[hfinfo->id]);
6694 g_ptr_array_free(protocol->fields, TRUE);
6695 protocol->fields = NULL;
6698 /* Remove this protocol from the list of known protocols */
6699 protocols = g_list_remove(protocols, protocol);
6701 g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[proto_id]);
6702 g_hash_table_steal(gpa_name_map, protocol->filter_name);
6704 g_free(last_field_name);
6705 last_field_name = NULL;
6711 * Routines to use to iterate over the protocols.
6712 * The argument passed to the iterator routines is an opaque cookie to
6713 * their callers; it's the GList pointer for the current element in
6715 * The ID of the protocol is returned, or -1 if there is no protocol.
6718 proto_get_first_protocol(void **cookie)
6720 protocol_t *protocol;
6722 if (protocols == NULL)
6724 *cookie = protocols;
6725 protocol = (protocol_t *)protocols->data;
6726 return protocol->proto_id;
6730 proto_get_data_protocol(void *cookie)
6732 GList *list_item = (GList *)cookie;
6734 protocol_t *protocol = (protocol_t *)list_item->data;
6735 return protocol->proto_id;
6739 proto_get_next_protocol(void **cookie)
6741 GList *list_item = (GList *)*cookie;
6742 protocol_t *protocol;
6744 list_item = g_list_next(list_item);
6745 if (list_item == NULL)
6747 *cookie = list_item;
6748 protocol = (protocol_t *)list_item->data;
6749 return protocol->proto_id;
6752 /* XXX: Unfortunately certain functions in proto_hier_tree_model.c
6753 assume that the cookie stored by
6754 proto_get_(first|next)_protocol_field() will never have a
6755 value of NULL. So, to preserve this semantic, the cookie value
6756 below is adjusted so that the cookie value stored is 1 + the
6757 current (zero-based) array index.
6760 proto_get_first_protocol_field(const int proto_id, void **cookie)
6762 protocol_t *protocol = find_protocol_by_id(proto_id);
6764 if ((protocol == NULL) || (protocol->fields == NULL) || (protocol->fields->len == 0))
6767 *cookie = GUINT_TO_POINTER(0 + 1);
6768 return (header_field_info *)g_ptr_array_index(protocol->fields, 0);
6772 proto_get_next_protocol_field(const int proto_id, void **cookie)
6774 protocol_t *protocol = find_protocol_by_id(proto_id);
6775 guint i = GPOINTER_TO_UINT(*cookie) - 1;
6779 if ((protocol->fields == NULL) || (i >= protocol->fields->len))
6782 *cookie = GUINT_TO_POINTER(i + 1);
6783 return (header_field_info *)g_ptr_array_index(protocol->fields, i);
6787 find_protocol_by_id(const int proto_id)
6789 header_field_info *hfinfo;
6794 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
6795 if (hfinfo->type != FT_PROTOCOL) {
6796 DISSECTOR_ASSERT(hfinfo->display & BASE_PROTOCOL_INFO);
6798 return (protocol_t *)hfinfo->strings;
6802 proto_get_id(const protocol_t *protocol)
6804 return protocol->proto_id;
6808 proto_name_already_registered(const gchar *name)
6812 DISSECTOR_ASSERT_HINT(name, "No name present");
6814 key = wrs_str_hash(name);
6815 if (g_hash_table_lookup(proto_names, &key) != NULL)
6821 proto_get_id_by_filter_name(const gchar *filter_name)
6823 const protocol_t *protocol = NULL;
6825 DISSECTOR_ASSERT_HINT(filter_name, "No filter name present");
6827 protocol = (const protocol_t *)g_hash_table_lookup(proto_filter_names, filter_name);
6829 if (protocol == NULL)
6831 return protocol->proto_id;
6835 proto_get_id_by_short_name(const gchar *short_name)
6837 const protocol_t *protocol = NULL;
6839 DISSECTOR_ASSERT_HINT(short_name, "No short name present");
6841 protocol = (const protocol_t *)g_hash_table_lookup(proto_short_names, short_name);
6843 if (protocol == NULL)
6845 return protocol->proto_id;
6849 proto_get_protocol_name(const int proto_id)
6851 protocol_t *protocol;
6853 protocol = find_protocol_by_id(proto_id);
6855 if (protocol == NULL)
6857 return protocol->name;
6861 proto_get_protocol_short_name(const protocol_t *protocol)
6863 if (protocol == NULL)
6865 return protocol->short_name;
6869 proto_get_protocol_long_name(const protocol_t *protocol)
6871 if (protocol == NULL)
6873 return protocol->name;
6877 proto_get_protocol_filter_name(const int proto_id)
6879 protocol_t *protocol;
6881 protocol = find_protocol_by_id(proto_id);
6882 if (protocol == NULL)
6884 return protocol->filter_name;
6887 void proto_add_heuristic_dissector(protocol_t *protocol, const char *short_name)
6889 heur_dtbl_entry_t* heuristic_dissector;
6891 if (protocol == NULL)
6894 heuristic_dissector = find_heur_dissector_by_unique_short_name(short_name);
6895 if (heuristic_dissector != NULL)
6897 protocol->heur_list = g_list_prepend (protocol->heur_list, heuristic_dissector);
6901 void proto_heuristic_dissector_foreach(const protocol_t *protocol, GFunc func, gpointer user_data)
6903 if (protocol == NULL)
6906 g_list_foreach(protocol->heur_list, func, user_data);
6910 proto_get_frame_protocols(const wmem_list_t *layers, gboolean *is_ip,
6911 gboolean *is_tcp, gboolean *is_udp,
6912 gboolean *is_sctp, gboolean *is_ssl,
6914 gboolean *is_lte_rlc)
6916 wmem_list_frame_t *protos = wmem_list_head(layers);
6918 const char *proto_name;
6920 /* Walk the list of a available protocols in the packet and
6921 find "major" ones. */
6922 /* It might make more sense to assemble and return a bitfield. */
6923 while (protos != NULL)
6925 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
6926 proto_name = proto_get_protocol_filter_name(proto_id);
6928 if (is_ip && ((!strcmp(proto_name, "ip")) ||
6929 (!strcmp(proto_name, "ipv6")))) {
6931 } else if (is_tcp && !strcmp(proto_name, "tcp")) {
6933 } else if (is_udp && !strcmp(proto_name, "udp")) {
6935 } else if (is_sctp && !strcmp(proto_name, "sctp")) {
6937 } else if (is_ssl && !strcmp(proto_name, "ssl")) {
6939 } else if (is_rtp && !strcmp(proto_name, "rtp")) {
6941 } else if (is_lte_rlc && !strcmp(proto_name, "rlc-lte")) {
6945 protos = wmem_list_frame_next(protos);
6950 proto_is_frame_protocol(const wmem_list_t *layers, const char* proto_name)
6952 wmem_list_frame_t *protos = wmem_list_head(layers);
6956 /* Walk the list of a available protocols in the packet and
6957 find "major" ones. */
6958 /* It might make more sense to assemble and return a bitfield. */
6959 while (protos != NULL)
6961 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
6962 name = proto_get_protocol_filter_name(proto_id);
6964 if (!strcmp(name, proto_name))
6969 protos = wmem_list_frame_next(protos);
6976 proto_is_pino(const protocol_t *protocol)
6978 return (protocol->parent_proto_id != -1);
6982 proto_is_protocol_enabled(const protocol_t *protocol)
6984 //parent protocol determines enable/disable for helper dissectors
6985 if (proto_is_pino(protocol))
6986 return proto_is_protocol_enabled(find_protocol_by_id(protocol->parent_proto_id));
6988 return protocol->is_enabled;
6992 proto_is_protocol_enabled_by_default(const protocol_t *protocol)
6994 //parent protocol determines enable/disable for helper dissectors
6995 if (proto_is_pino(protocol))
6996 return proto_is_protocol_enabled_by_default(find_protocol_by_id(protocol->parent_proto_id));
6998 return protocol->enabled_by_default;
7002 proto_can_toggle_protocol(const int proto_id)
7004 protocol_t *protocol;
7006 protocol = find_protocol_by_id(proto_id);
7007 //parent protocol determines toggling for helper dissectors
7008 if (proto_is_pino(protocol))
7009 return proto_can_toggle_protocol(protocol->parent_proto_id);
7011 return protocol->can_toggle;
7015 proto_disable_by_default(const int proto_id)
7017 protocol_t *protocol;
7019 protocol = find_protocol_by_id(proto_id);
7020 DISSECTOR_ASSERT(protocol->can_toggle);
7021 DISSECTOR_ASSERT(proto_is_pino(protocol) == FALSE);
7022 protocol->is_enabled = FALSE;
7023 protocol->enabled_by_default = FALSE;
7027 proto_set_decoding(const int proto_id, const gboolean enabled)
7029 protocol_t *protocol;
7031 protocol = find_protocol_by_id(proto_id);
7032 DISSECTOR_ASSERT(protocol->can_toggle);
7033 DISSECTOR_ASSERT(proto_is_pino(protocol) == FALSE);
7034 protocol->is_enabled = enabled;
7038 proto_reenable_all(void)
7040 protocol_t *protocol;
7041 GList *list_item = protocols;
7043 if (protocols == NULL)
7047 protocol = (protocol_t *)list_item->data;
7048 if (protocol->can_toggle && protocol->enabled_by_default)
7049 protocol->is_enabled = TRUE;
7050 list_item = g_list_next(list_item);
7055 proto_set_cant_toggle(const int proto_id)
7057 protocol_t *protocol;
7059 protocol = find_protocol_by_id(proto_id);
7060 protocol->can_toggle = FALSE;
7064 proto_register_field_common(protocol_t *proto, header_field_info *hfi, const int parent)
7066 if (proto != NULL) {
7067 g_ptr_array_add(proto->fields, hfi);
7070 return proto_register_field_init(hfi, parent);
7073 /* for use with static arrays only, since we don't allocate our own copies
7074 of the header_field_info struct contained within the hf_register_info struct */
7076 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
7078 hf_register_info *ptr = hf;
7082 proto = find_protocol_by_id(parent);
7084 if (proto->fields == NULL) {
7085 proto->fields = g_ptr_array_sized_new(num_records);
7088 for (i = 0; i < num_records; i++, ptr++) {
7090 * Make sure we haven't registered this yet.
7091 * Most fields have variables associated with them
7092 * that are initialized to -1; some have array elements,
7093 * or possibly uninitialized variables, so we also allow
7094 * 0 (which is unlikely to be the field ID we get back
7095 * from "proto_register_field_init()").
7097 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
7099 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
7100 ptr->hfinfo.abbrev);
7104 *ptr->p_id = proto_register_field_common(proto, &ptr->hfinfo, parent);
7109 proto_register_fields_section(const int parent, header_field_info *hfi, const int num_records)
7114 proto = find_protocol_by_id(parent);
7116 if (proto->fields == NULL) {
7117 proto->fields = g_ptr_array_sized_new(num_records);
7120 for (i = 0; i < num_records; i++) {
7122 * Make sure we haven't registered this yet.
7124 if (hfi[i].id != -1) {
7126 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
7131 proto_register_field_common(proto, &hfi[i], parent);
7136 proto_register_fields_manual(const int parent, header_field_info **hfi, const int num_records)
7141 proto = find_protocol_by_id(parent);
7143 if (proto->fields == NULL) {
7144 proto->fields = g_ptr_array_sized_new(num_records);
7148 for (i = 0; i < num_records; i++) {
7150 * Make sure we haven't registered this yet.
7152 if (hfi[i]->id != -1) {
7154 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
7159 proto_register_field_common(proto, hfi[i], parent);
7163 /* deregister already registered fields */
7165 proto_deregister_field (const int parent, gint hf_id)
7167 header_field_info *hfi;
7171 g_free(last_field_name);
7172 last_field_name = NULL;
7174 if (hf_id == -1 || hf_id == 0)
7177 proto = find_protocol_by_id (parent);
7178 if (!proto || proto->fields == NULL) {
7182 for (i = 0; i < proto->fields->len; i++) {
7183 hfi = (header_field_info *)g_ptr_array_index(proto->fields, i);
7184 if (hfi->id == hf_id) {
7185 /* Found the hf_id in this protocol */
7186 g_hash_table_steal(gpa_name_map, hfi->abbrev);
7187 g_ptr_array_remove_index_fast(proto->fields, i);
7188 g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[hf_id]);
7195 proto_add_deregistered_data (void *data)
7197 g_ptr_array_add(deregistered_data, data);
7201 free_deregistered_field (gpointer data, gpointer user_data _U_)
7203 header_field_info *hfi = (header_field_info *) data;
7204 gint hf_id = hfi->id;
7206 g_free((char *)hfi->name);
7207 g_free((char *)hfi->abbrev);
7208 g_free((char *)hfi->blurb);
7211 switch (hfi->type) {
7213 /* This is just an integer represented as a pointer */
7216 protocol_t *protocol = (protocol_t *)hfi->strings;
7217 g_free((gchar *)protocol->short_name);
7221 true_false_string *tf = (true_false_string *)hfi->strings;
7222 g_free ((gchar *)tf->true_string);
7223 g_free ((gchar *)tf->false_string);
7228 if (hfi->display & BASE_UNIT_STRING) {
7229 unit_name_string *unit = (unit_name_string*)hfi->strings;
7230 g_free ((gchar *)unit->singular);
7231 g_free ((gchar *)unit->plural);
7233 val64_string *vs64 = (val64_string *)hfi->strings;
7234 while (vs64->strptr) {
7235 g_free((gchar *)vs64->strptr);
7242 /* Other Integer types */
7243 if (hfi->display & BASE_UNIT_STRING) {
7244 unit_name_string *unit = (unit_name_string*)hfi->strings;
7245 g_free ((gchar *)unit->singular);
7246 g_free ((gchar *)unit->plural);
7248 value_string *vs = (value_string *)hfi->strings;
7249 while (vs->strptr) {
7250 g_free((gchar *)vs->strptr);
7257 if (hfi->type != FT_FRAMENUM) {
7258 g_free((void *)hfi->strings);
7262 if (hfi->parent == -1)
7263 g_slice_free(header_field_info, hfi);
7265 gpa_hfinfo.hfi[hf_id] = NULL; /* Invalidate this hf_id / proto_id */
7269 free_deregistered_data (gpointer data, gpointer user_data _U_)
7274 /* free deregistered fields and data */
7276 proto_free_deregistered_fields (void)
7278 expert_free_deregistered_expertinfos();
7280 g_ptr_array_foreach(deregistered_fields, free_deregistered_field, NULL);
7281 g_ptr_array_free(deregistered_fields, TRUE);
7282 deregistered_fields = g_ptr_array_new();
7284 g_ptr_array_foreach(deregistered_data, free_deregistered_data, NULL);
7285 g_ptr_array_free(deregistered_data, TRUE);
7286 deregistered_data = g_ptr_array_new();
7289 /* chars allowed in field abbrev */
7291 const guint8 fld_abbrev_chars[256] = {
7292 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
7293 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
7294 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
7295 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
7296 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
7297 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
7298 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
7299 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
7300 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
7301 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
7302 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
7303 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
7304 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
7305 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
7306 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
7307 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
7310 static const value_string hf_display[] = {
7311 { BASE_NONE, "BASE_NONE" },
7312 { BASE_DEC, "BASE_DEC" },
7313 { BASE_HEX, "BASE_HEX" },
7314 { BASE_OCT, "BASE_OCT" },
7315 { BASE_DEC_HEX, "BASE_DEC_HEX" },
7316 { BASE_HEX_DEC, "BASE_HEX_DEC" },
7317 { BASE_CUSTOM, "BASE_CUSTOM" },
7318 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
7319 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
7320 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
7321 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
7322 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
7323 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
7324 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
7325 { BASE_NONE|BASE_VAL64_STRING, "BASE_NONE|BASE_VAL64_STRING" },
7326 { BASE_DEC|BASE_VAL64_STRING, "BASE_DEC|BASE_VAL64_STRING" },
7327 { BASE_HEX|BASE_VAL64_STRING, "BASE_HEX|BASE_VAL64_STRING" },
7328 { BASE_OCT|BASE_VAL64_STRING, "BASE_OCT|BASE_VAL64_STRING" },
7329 { BASE_DEC_HEX|BASE_VAL64_STRING, "BASE_DEC_HEX|BASE_VAL64_STRING" },
7330 { BASE_HEX_DEC|BASE_VAL64_STRING, "BASE_HEX_DEC|BASE_VAL64_STRING" },
7331 { BASE_CUSTOM|BASE_VAL64_STRING, "BASE_CUSTOM|BASE_VAL64_STRING" },
7332 /* Alias: BASE_NONE { BASE_FLOAT, "BASE_FLOAT" }, */
7333 /* Alias: BASE_NONE { STR_ASCII, "STR_ASCII" }, */
7334 { STR_UNICODE, "STR_UNICODE" },
7335 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
7336 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_UTC" },
7337 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_DOY_UTC" },
7338 { BASE_PT_UDP, "BASE_PT_UDP" },
7339 { BASE_PT_TCP, "BASE_PT_TCP" },
7340 { BASE_PT_DCCP, "BASE_PT_DCCP" },
7341 { BASE_PT_SCTP, "BASE_PT_SCTP" },
7342 { BASE_OUI, "BASE_OUI" },
7345 const char* proto_field_display_to_string(int field_display)
7347 return val_to_str_const(field_display, hf_display, "Unknown");
7350 static inline port_type
7351 display_to_port_type(field_display_e e)
7368 /* temporary function containing assert part for easier profiling */
7370 tmp_fld_check_assert(header_field_info *hfinfo)
7374 /* The field must have a name (with length > 0) */
7375 if (!hfinfo->name || !hfinfo->name[0]) {
7377 /* Try to identify the field */
7378 g_error("Field (abbrev='%s') does not have a name\n",
7382 g_error("Field does not have a name (nor an abbreviation)\n");
7385 /* fields with an empty string for an abbreviation aren't filterable */
7386 if (!hfinfo->abbrev || !hfinfo->abbrev[0])
7387 g_error("Field '%s' does not have an abbreviation\n", hfinfo->name);
7389 /* These types of fields are allowed to have value_strings,
7390 * true_false_strings or a protocol_t struct
7392 if (hfinfo->strings != NULL) {
7393 switch(hfinfo->type) {
7417 //allowed to support string if its a unit decsription
7418 if (hfinfo->display & BASE_UNIT_STRING)
7423 //allowed to support string if its a protocol (for pinos)
7424 if (hfinfo->display & BASE_PROTOCOL_INFO)
7429 g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
7430 " (which is not allowed to have strings)\n",
7431 hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type));
7435 /* TODO: This check may slow down startup, and output quite a few warnings.
7436 It would be good to be able to enable this (and possibly other checks?)
7437 in non-release builds. */
7439 /* Check for duplicate value_string values.
7440 There are lots that have the same value *and* string, so for now only
7441 report those that have same value but different string. */
7442 if ((hfinfo->strings != NULL) &&
7443 !(hfinfo->display & BASE_RANGE_STRING) &&
7444 !((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) &&
7446 (hfinfo->type == FT_CHAR) ||
7447 (hfinfo->type == FT_UINT8) ||
7448 (hfinfo->type == FT_UINT16) ||
7449 (hfinfo->type == FT_UINT24) ||
7450 (hfinfo->type == FT_UINT32) ||
7451 (hfinfo->type == FT_INT8) ||
7452 (hfinfo->type == FT_INT16) ||
7453 (hfinfo->type == FT_INT24) ||
7454 (hfinfo->type == FT_INT32) ||
7455 (hfinfo->type == FT_FRAMENUM) )) {
7458 const value_string *start_values;
7459 const value_string *current;
7461 if (hfinfo->display & BASE_EXT_STRING)
7462 start_values = VALUE_STRING_EXT_VS_P(((const value_string_ext*)hfinfo->strings));
7464 start_values = (const value_string*)hfinfo->strings;
7465 current = start_values;
7467 for (n=0; current; n++, current++) {
7468 /* Drop out if we reached the end. */
7469 if ((current->value == 0) && (current->strptr == NULL)) {
7473 /* Check value against all previous */
7474 for (m=0; m < n; m++) {
7475 /* There are lots of duplicates with the same string,
7476 so only report if different... */
7477 if ((start_values[m].value == current->value) &&
7478 (strcmp(start_values[m].strptr, current->strptr) != 0)) {
7479 ws_g_warning("Field '%s' (%s) has a conflicting entry in its"
7480 " value_string: %u is at indices %u (%s) and %u (%s))\n",
7481 hfinfo->name, hfinfo->abbrev,
7482 current->value, m, start_values[m].strptr, n, current->strptr);
7490 switch (hfinfo->type) {
7493 /* Require the char type to have BASE_HEX, BASE_OCT,
7494 * BASE_CUSTOM, or BASE_NONE as its base.
7496 * If the display value is BASE_NONE and there is a
7497 * strings conversion then the dissector writer is
7498 * telling us that the field's numerical value is
7499 * meaningless; we'll avoid showing the value to the
7502 switch (FIELD_DISPLAY(hfinfo->display)) {
7505 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
7508 if (hfinfo->strings == NULL)
7509 g_error("Field '%s' (%s) is an integral value (%s)"
7510 " but is being displayed as BASE_NONE but"
7511 " without a strings conversion",
7512 hfinfo->name, hfinfo->abbrev,
7513 ftype_name(hfinfo->type));
7516 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
7517 g_error("Field '%s' (%s) is a character value (%s)"
7518 " but is being displayed as %s\n",
7519 hfinfo->name, hfinfo->abbrev,
7520 ftype_name(hfinfo->type), tmp_str);
7521 wmem_free(NULL, tmp_str);
7523 if (hfinfo->display & BASE_UNIT_STRING) {
7524 g_error("Field '%s' (%s) is a character value (%s) but has a unit string\n",
7525 hfinfo->name, hfinfo->abbrev,
7526 ftype_name(hfinfo->type));
7537 /* Hexadecimal and octal are, in printf() and everywhere
7538 * else, unsigned so don't allow dissectors to register a
7539 * signed field to be displayed unsigned. (Else how would
7540 * we display negative values?)
7542 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
7547 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7548 g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
7549 hfinfo->name, hfinfo->abbrev,
7550 ftype_name(hfinfo->type), tmp_str);
7551 wmem_free(NULL, tmp_str);
7562 if (IS_BASE_PORT(hfinfo->display)) {
7563 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
7564 if (hfinfo->type != FT_UINT16) {
7565 g_error("Field '%s' (%s) has 'display' value %s but it can only be used with FT_UINT16, not %s\n",
7566 hfinfo->name, hfinfo->abbrev,
7567 tmp_str, ftype_name(hfinfo->type));
7569 if (hfinfo->strings != NULL) {
7570 g_error("Field '%s' (%s) is an %s (%s) but has a strings value\n",
7571 hfinfo->name, hfinfo->abbrev,
7572 ftype_name(hfinfo->type), tmp_str);
7574 if (hfinfo->bitmask != 0) {
7575 g_error("Field '%s' (%s) is an %s (%s) but has a bitmask\n",
7576 hfinfo->name, hfinfo->abbrev,
7577 ftype_name(hfinfo->type), tmp_str);
7579 wmem_free(NULL, tmp_str);
7583 if (hfinfo->display == BASE_OUI) {
7584 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
7585 if (hfinfo->type != FT_UINT24) {
7586 g_error("Field '%s' (%s) has 'display' value %s but it can only be used with FT_UINT24, not %s\n",
7587 hfinfo->name, hfinfo->abbrev,
7588 tmp_str, ftype_name(hfinfo->type));
7590 if (hfinfo->strings != NULL) {
7591 g_error("Field '%s' (%s) is an %s (%s) but has a strings value\n",
7592 hfinfo->name, hfinfo->abbrev,
7593 ftype_name(hfinfo->type), tmp_str);
7595 if (hfinfo->bitmask != 0) {
7596 g_error("Field '%s' (%s) is an %s (%s) but has a bitmask\n",
7597 hfinfo->name, hfinfo->abbrev,
7598 ftype_name(hfinfo->type), tmp_str);
7600 wmem_free(NULL, tmp_str);
7604 /* Require integral types (other than frame number,
7605 * which is always displayed in decimal) to have a
7608 * If the display value is BASE_NONE and there is a
7609 * strings conversion then the dissector writer is
7610 * telling us that the field's numerical value is
7611 * meaningless; we'll avoid showing the value to the
7614 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
7620 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
7623 if (hfinfo->strings == NULL) {
7624 g_error("Field '%s' (%s) is an integral value (%s)"
7625 " but is being displayed as BASE_NONE but"
7626 " without a strings conversion",
7627 hfinfo->name, hfinfo->abbrev,
7628 ftype_name(hfinfo->type));
7630 if (hfinfo->display & BASE_SPECIAL_VALS) {
7631 g_error("Field '%s' (%s) is an integral value (%s)"
7632 " that is being displayed as BASE_NONE but"
7633 " with BASE_SPECIAL_VALS",
7634 hfinfo->name, hfinfo->abbrev,
7635 ftype_name(hfinfo->type));
7640 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
7641 g_error("Field '%s' (%s) is an integral value (%s)"
7642 " but is being displayed as %s\n",
7643 hfinfo->name, hfinfo->abbrev,
7644 ftype_name(hfinfo->type), tmp_str);
7645 wmem_free(NULL, tmp_str);
7650 /* Require bytes to have a "display type" that could
7651 * add a character between displayed bytes.
7653 switch (FIELD_DISPLAY(hfinfo->display)) {
7661 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7662 g_error("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\n",
7663 hfinfo->name, hfinfo->abbrev, tmp_str);
7664 wmem_free(NULL, tmp_str);
7666 if (hfinfo->bitmask != 0)
7667 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7668 hfinfo->name, hfinfo->abbrev,
7669 ftype_name(hfinfo->type));
7670 //allowed to support string if its a protocol (for pinos)
7671 if ((hfinfo->strings != NULL) && (!(hfinfo->display & BASE_PROTOCOL_INFO)))
7672 g_error("Field '%s' (%s) is an %s but has a strings value\n",
7673 hfinfo->name, hfinfo->abbrev,
7674 ftype_name(hfinfo->type));
7679 if (hfinfo->display != BASE_NONE) {
7680 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7681 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
7682 hfinfo->name, hfinfo->abbrev,
7683 ftype_name(hfinfo->type), tmp_str);
7684 wmem_free(NULL, tmp_str);
7686 if (hfinfo->bitmask != 0)
7687 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7688 hfinfo->name, hfinfo->abbrev,
7689 ftype_name(hfinfo->type));
7695 case FT_ABSOLUTE_TIME:
7696 if (!(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
7697 hfinfo->display == ABSOLUTE_TIME_UTC ||
7698 hfinfo->display == ABSOLUTE_TIME_DOY_UTC)) {
7699 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7700 g_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
7701 hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type), tmp_str);
7702 wmem_free(NULL, tmp_str);
7704 if (hfinfo->bitmask != 0)
7705 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7706 hfinfo->name, hfinfo->abbrev,
7707 ftype_name(hfinfo->type));
7712 case FT_UINT_STRING:
7714 switch (hfinfo->display) {
7720 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
7721 g_error("Field '%s' (%s) is an string value (%s)"
7722 " but is being displayed as %s\n",
7723 hfinfo->name, hfinfo->abbrev,
7724 ftype_name(hfinfo->type), tmp_str);
7725 wmem_free(NULL, tmp_str);
7728 if (hfinfo->bitmask != 0)
7729 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7730 hfinfo->name, hfinfo->abbrev,
7731 ftype_name(hfinfo->type));
7732 if (hfinfo->strings != NULL)
7733 g_error("Field '%s' (%s) is an %s but has a strings value\n",
7734 hfinfo->name, hfinfo->abbrev,
7735 ftype_name(hfinfo->type));
7739 switch (hfinfo->display) {
7745 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
7746 g_error("Field '%s' (%s) is an IPv4 value (%s)"
7747 " but is being displayed as %s\n",
7748 hfinfo->name, hfinfo->abbrev,
7749 ftype_name(hfinfo->type), tmp_str);
7750 wmem_free(NULL, tmp_str);
7756 if (FIELD_DISPLAY(hfinfo->display) != BASE_NONE) {
7757 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7758 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
7759 hfinfo->name, hfinfo->abbrev,
7760 ftype_name(hfinfo->type),
7762 wmem_free(NULL, tmp_str);
7764 if (hfinfo->bitmask != 0)
7765 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7766 hfinfo->name, hfinfo->abbrev,
7767 ftype_name(hfinfo->type));
7768 if ((hfinfo->strings != NULL) && (!(hfinfo->display & BASE_UNIT_STRING)))
7769 g_error("Field '%s' (%s) is an %s but has a strings value\n",
7770 hfinfo->name, hfinfo->abbrev,
7771 ftype_name(hfinfo->type));
7774 if (hfinfo->display != BASE_NONE) {
7775 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7776 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
7777 hfinfo->name, hfinfo->abbrev,
7778 ftype_name(hfinfo->type),
7780 wmem_free(NULL, tmp_str);
7782 if (hfinfo->bitmask != 0)
7783 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7784 hfinfo->name, hfinfo->abbrev,
7785 ftype_name(hfinfo->type));
7786 if (hfinfo->strings != NULL)
7787 g_error("Field '%s' (%s) is an %s but has a strings value\n",
7788 hfinfo->name, hfinfo->abbrev,
7789 ftype_name(hfinfo->type));
7794 #ifdef ENABLE_CHECK_FILTER
7796 _ftype_common(enum ftenum type)
7820 case FT_UINT_STRING:
7833 case FT_ABSOLUTE_TIME:
7834 case FT_RELATIVE_TIME:
7835 return FT_ABSOLUTE_TIME;
7844 register_type_length_mismatch(void)
7846 static ei_register_info ei[] = {
7847 { &ei_type_length_mismatch_error, { "_ws.type_length.mismatch", PI_MALFORMED, PI_ERROR, "Trying to fetch X with length Y", EXPFILL }},
7848 { &ei_type_length_mismatch_warn, { "_ws.type_length.mismatch", PI_MALFORMED, PI_WARN, "Trying to fetch X with length Y", EXPFILL }},
7851 expert_module_t* expert_type_length_mismatch;
7853 proto_type_length_mismatch = proto_register_protocol("Type Length Mismatch", "Type length mismatch", "_ws.type_length");
7855 expert_type_length_mismatch = expert_register_protocol(proto_type_length_mismatch);
7856 expert_register_field_array(expert_type_length_mismatch, ei, array_length(ei));
7858 /* "Type Length Mismatch" isn't really a protocol, it's an error indication;
7859 disabling them makes no sense. */
7860 proto_set_cant_toggle(proto_type_length_mismatch);
7864 register_number_string_decoding_error(void)
7866 static ei_register_info ei[] = {
7867 { &ei_number_string_decoding_failed_error,
7868 { "_ws.number_string.decoding_error.failed", PI_MALFORMED, PI_ERROR,
7869 "Failed to decode number from string", EXPFILL
7872 { &ei_number_string_decoding_erange_error,
7873 { "_ws.number_string.decoding_error.erange", PI_MALFORMED, PI_ERROR,
7874 "Decoded number from string is out of valid range", EXPFILL
7879 expert_module_t* expert_number_string_decoding_error;
7881 proto_number_string_decoding_error =
7882 proto_register_protocol("Number-String Decoding Error",
7883 "Number-string decoding error",
7884 "_ws.number_string.decoding_error");
7886 expert_number_string_decoding_error =
7887 expert_register_protocol(proto_number_string_decoding_error);
7888 expert_register_field_array(expert_number_string_decoding_error, ei, array_length(ei));
7890 /* "Number-String Decoding Error" isn't really a protocol, it's an error indication;
7891 disabling them makes no sense. */
7892 proto_set_cant_toggle(proto_number_string_decoding_error);
7895 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM (188000+PRE_ALLOC_EXPERT_FIELDS_MEM)
7897 proto_register_field_init(header_field_info *hfinfo, const int parent)
7900 tmp_fld_check_assert(hfinfo);
7902 hfinfo->parent = parent;
7903 hfinfo->same_name_next = NULL;
7904 hfinfo->same_name_prev_id = -1;
7906 /* if we always add and never delete, then id == len - 1 is correct */
7907 if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
7908 if (!gpa_hfinfo.hfi) {
7909 gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
7910 gpa_hfinfo.hfi = (header_field_info **)g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
7912 gpa_hfinfo.allocated_len += 1000;
7913 gpa_hfinfo.hfi = (header_field_info **)g_realloc(gpa_hfinfo.hfi,
7914 sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
7915 /*g_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
7918 gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
7920 hfinfo->id = gpa_hfinfo.len - 1;
7922 /* if we have real names, enter this field in the name tree */
7923 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
7925 header_field_info *same_name_next_hfinfo;
7928 /* Check that the filter name (abbreviation) is legal;
7929 * it must contain only alphanumerics, '-', "_", and ".". */
7930 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
7932 if (g_ascii_isprint(c))
7933 fprintf(stderr, "Invalid character '%c' in filter name '%s'\n", c, hfinfo->abbrev);
7935 fprintf(stderr, "Invalid byte \\%03o in filter name '%s'\n", c, hfinfo->abbrev);
7936 DISSECTOR_ASSERT_NOT_REACHED();
7939 /* We allow multiple hfinfo's to be registered under the same
7940 * abbreviation. This was done for X.25, as, depending
7941 * on whether it's modulo-8 or modulo-128 operation,
7942 * some bitfield fields may be in different bits of
7943 * a byte, and we want to be able to refer to that field
7944 * with one name regardless of whether the packets
7945 * are modulo-8 or modulo-128 packets. */
7947 same_name_hfinfo = NULL;
7949 g_hash_table_insert(gpa_name_map, (gpointer) (hfinfo->abbrev), hfinfo);
7950 /* GLIB 2.x - if it is already present
7951 * the previous hfinfo with the same name is saved
7952 * to same_name_hfinfo by value destroy callback */
7953 if (same_name_hfinfo) {
7954 /* There's already a field with this name.
7955 * Put the current field *before* that field
7956 * in the list of fields with this name, Thus,
7957 * we end up with an effectively
7958 * doubly-linked-list of same-named hfinfo's,
7959 * with the head of the list (stored in the
7960 * hash) being the last seen hfinfo.
7962 same_name_next_hfinfo =
7963 same_name_hfinfo->same_name_next;
7965 hfinfo->same_name_next = same_name_next_hfinfo;
7966 if (same_name_next_hfinfo)
7967 same_name_next_hfinfo->same_name_prev_id = hfinfo->id;
7969 same_name_hfinfo->same_name_next = hfinfo;
7970 hfinfo->same_name_prev_id = same_name_hfinfo->id;
7971 #ifdef ENABLE_CHECK_FILTER
7972 while (same_name_hfinfo) {
7973 if (_ftype_common(hfinfo->type) != _ftype_common(same_name_hfinfo->type))
7974 fprintf(stderr, "'%s' exists multiple times with NOT compatible types: %s and %s\n", hfinfo->abbrev, ftype_name(hfinfo->type), ftype_name(same_name_hfinfo->type));
7975 same_name_hfinfo = same_name_hfinfo->same_name_next;
7985 proto_register_subtree_array(gint *const *indices, const int num_indices)
7988 gint *const *ptr = indices;
7991 * If we've already allocated the array of tree types, expand
7992 * it; this lets plugins such as mate add tree types after
7993 * the initial startup. (If we haven't already allocated it,
7994 * we don't allocate it; on the first pass, we just assign
7995 * ett values and keep track of how many we've assigned, and
7996 * when we're finished registering all dissectors we allocate
7997 * the array, so that we do only one allocation rather than
7998 * wasting CPU time and memory by growing the array for each
7999 * dissector that registers ett values.)
8001 if (tree_is_expanded != NULL) {
8002 tree_is_expanded = (guint32 *)g_realloc(tree_is_expanded, (1+((num_tree_types + num_indices)/32)) * sizeof(guint32));
8004 /* set new items to 0 */
8005 /* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of guint32 to 0) */
8006 for (i = num_tree_types; i < num_tree_types + num_indices; i++)
8007 tree_is_expanded[i >> 5] &= ~(1U << (i & 31));
8011 * Assign "num_indices" subtree numbers starting at "num_tree_types",
8012 * returning the indices through the pointers in the array whose
8013 * first element is pointed to by "indices", and update
8014 * "num_tree_types" appropriately.
8016 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
8018 /* g_error will terminate the program */
8019 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
8020 " This is a development error:"
8021 " Either the subtree item type has already been assigned or"
8022 " was not initialized to -1.");
8024 **ptr = num_tree_types;
8029 label_concat(char *label_str, gsize pos, const char *str)
8031 if (pos < ITEM_LABEL_LENGTH)
8032 pos += g_strlcpy(label_str + pos, str, ITEM_LABEL_LENGTH - pos);
8038 label_mark_truncated(char *label_str, gsize name_pos)
8040 static const char trunc_str[] = " [truncated]";
8041 const size_t trunc_len = sizeof(trunc_str)-1;
8044 /* ..... field_name: dataaaaaaaaaaaaa
8048 * ..... field_name [truncated]: dataaaaaaaaaaaaa
8050 * name_pos==0 means that we have only data or only a field_name
8053 if (name_pos < ITEM_LABEL_LENGTH - trunc_len) {
8054 memmove(label_str + name_pos + trunc_len, label_str + name_pos, ITEM_LABEL_LENGTH - name_pos - trunc_len);
8055 memcpy(label_str + name_pos, trunc_str, trunc_len);
8057 /* in general, label_str is UTF-8
8058 we can truncate it only at the beginning of a new character
8059 we go backwards from the byte right after our buffer and
8060 find the next starting byte of a UTF-8 character, this is
8062 there's no need to use g_utf8_find_prev_char(), the search
8063 will always succeed since we copied trunc_str into the
8065 last_char = g_utf8_prev_char(&label_str[ITEM_LABEL_LENGTH]);
8068 } else if (name_pos < ITEM_LABEL_LENGTH)
8069 g_strlcpy(label_str + name_pos, trunc_str, ITEM_LABEL_LENGTH - name_pos);
8073 label_fill(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text)
8077 /* "%s: %s", hfinfo->name, text */
8078 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
8079 if (!(hfinfo->display & BASE_NO_DISPLAY_VALUE)) {
8080 pos = label_concat(label_str, pos, ": ");
8081 pos = label_concat(label_str, pos, text ? text : "(null)");
8084 if (pos >= ITEM_LABEL_LENGTH) {
8085 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
8086 label_mark_truncated(label_str, name_pos);
8093 label_fill_descr(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text, const char *descr)
8097 /* "%s: %s (%s)", hfinfo->name, text, descr */
8098 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
8099 if (!(hfinfo->display & BASE_NO_DISPLAY_VALUE)) {
8100 pos = label_concat(label_str, pos, ": ");
8101 if (hfinfo->display & BASE_UNIT_STRING) {
8102 pos = label_concat(label_str, pos, descr ? descr : "(null)");
8103 pos = label_concat(label_str, pos, text ? text : "(null)");
8105 pos = label_concat(label_str, pos, text ? text : "(null)");
8106 pos = label_concat(label_str, pos, " (");
8107 pos = label_concat(label_str, pos, descr ? descr : "(null)");
8108 pos = label_concat(label_str, pos, ")");
8112 if (pos >= ITEM_LABEL_LENGTH) {
8113 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
8114 label_mark_truncated(label_str, name_pos);
8121 proto_item_fill_label(field_info *fi, gchar *label_str)
8123 header_field_info *hfinfo;
8127 ipv4_addr_and_mask *ipv4;
8129 guint32 n_addr; /* network-order IPv4 address */
8138 /* XXX: Check validity of hfinfo->type */
8142 hfinfo = fi->hfinfo;
8144 switch (hfinfo->type) {
8147 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
8151 fill_label_boolean(fi, label_str);
8156 bytes = (guint8 *)fvalue_get(&fi->value);
8159 switch(hfinfo->display)
8162 str = bytestring_to_str(NULL, bytes, fvalue_length(&fi->value), '.');
8165 str = bytestring_to_str(NULL, bytes, fvalue_length(&fi->value), '-');
8168 str = bytestring_to_str(NULL, bytes, fvalue_length(&fi->value), ':');
8171 str = bytestring_to_str(NULL, bytes, fvalue_length(&fi->value), ' ');
8175 if (prefs.display_byte_fields_with_spaces)
8177 str = bytestring_to_str(NULL, bytes, fvalue_length(&fi->value), ' ');
8181 str = bytes_to_str(NULL, bytes, fvalue_length(&fi->value));
8185 label_fill(label_str, 0, hfinfo, str);
8186 wmem_free(NULL, str);
8188 if (hfinfo->display & BASE_ALLOW_ZERO) {
8189 label_fill(label_str, 0, hfinfo, "<none>");
8191 label_fill(label_str, 0, hfinfo, "<MISSING>");
8197 if (hfinfo->bitmask) {
8198 fill_label_bitfield_char(fi, label_str);
8200 fill_label_char(fi, label_str);
8204 /* Four types of integers to take care of:
8205 * Bitfield, with val_string
8206 * Bitfield, w/o val_string
8207 * Non-bitfield, with val_string
8208 * Non-bitfield, w/o val_string
8214 if (hfinfo->bitmask) {
8215 if (fi->flags & FI_VARINT) {
8216 fill_label_bitfield_varint(fi, label_str, FALSE);
8218 fill_label_bitfield(fi, label_str, FALSE);
8221 fill_label_number(fi, label_str, FALSE);
8226 fill_label_number(fi, label_str, FALSE);
8233 if (hfinfo->bitmask) {
8234 if (fi->flags & FI_VARINT) {
8235 fill_label_bitfield_varint64(fi, label_str, FALSE);
8237 fill_label_bitfield64(fi, label_str, FALSE);
8240 fill_label_number64(fi, label_str, FALSE);
8248 if (hfinfo->bitmask) {
8249 if (fi->flags & FI_VARINT) {
8250 fill_label_bitfield_varint(fi, label_str, TRUE);
8252 fill_label_bitfield(fi, label_str, TRUE);
8255 fill_label_number(fi, label_str, TRUE);
8263 if (hfinfo->bitmask) {
8264 if (fi->flags & FI_VARINT) {
8265 fill_label_bitfield_varint64(fi, label_str, TRUE);
8267 fill_label_bitfield64(fi, label_str, TRUE);
8270 fill_label_number64(fi, label_str, TRUE);
8275 double d_value = fvalue_get_floating(&fi->value);
8276 if (hfinfo->display & BASE_UNIT_STRING) {
8277 g_snprintf(label_str, ITEM_LABEL_LENGTH,
8278 "%s: %." G_STRINGIFY(FLT_DIG) "g%s",
8279 hfinfo->name, d_value,
8280 unit_name_string_get_double(d_value, (unit_name_string*)hfinfo->strings));
8282 g_snprintf(label_str, ITEM_LABEL_LENGTH,
8283 "%s: %." G_STRINGIFY(FLT_DIG) "g",
8284 hfinfo->name, d_value);
8290 double d_value = fvalue_get_floating(&fi->value);
8291 if (hfinfo->display & BASE_UNIT_STRING) {
8292 g_snprintf(label_str, ITEM_LABEL_LENGTH,
8293 "%s: %." G_STRINGIFY(DBL_DIG) "g%s",
8294 hfinfo->name, d_value,
8295 unit_name_string_get_double(d_value, (unit_name_string*)hfinfo->strings));
8297 g_snprintf(label_str, ITEM_LABEL_LENGTH,
8298 "%s: %." G_STRINGIFY(DBL_DIG) "g",
8299 hfinfo->name, d_value);
8304 case FT_ABSOLUTE_TIME:
8305 tmp = abs_time_to_str(NULL, (const nstime_t *)fvalue_get(&fi->value), (absolute_time_display_e)hfinfo->display, TRUE);
8306 label_fill(label_str, 0, hfinfo, tmp);
8307 wmem_free(NULL, tmp);
8310 case FT_RELATIVE_TIME:
8311 tmp = rel_time_to_secs_str(NULL, (const nstime_t *)fvalue_get(&fi->value));
8312 g_snprintf(label_str, ITEM_LABEL_LENGTH,
8313 "%s: %s seconds", hfinfo->name, tmp);
8314 wmem_free(NULL, tmp);
8318 integer = fvalue_get_uinteger(&fi->value);
8319 tmp = get_ipxnet_name(NULL, integer);
8320 g_snprintf(label_str, ITEM_LABEL_LENGTH,
8321 "%s: %s (0x%08X)", hfinfo->name,
8323 wmem_free(NULL, tmp);
8327 addr.type = AT_AX25;
8328 addr.len = AX25_ADDR_LEN;
8329 addr.data = (guint8 *)fvalue_get(&fi->value);
8331 addr_str = (char*)address_to_str(NULL, &addr);
8332 g_snprintf(label_str, ITEM_LABEL_LENGTH,
8333 "%s: %s", hfinfo->name, addr_str);
8334 wmem_free(NULL, addr_str);
8338 addr.type = vines_address_type;
8339 addr.len = VINES_ADDR_LEN;
8340 addr.data = (guint8 *)fvalue_get(&fi->value);
8342 addr_str = (char*)address_to_str(NULL, &addr);
8343 g_snprintf(label_str, ITEM_LABEL_LENGTH,
8344 "%s: %s", hfinfo->name, addr_str);
8345 wmem_free(NULL, addr_str);
8349 bytes = (guint8 *)fvalue_get(&fi->value);
8351 addr.type = AT_ETHER;
8355 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
8356 g_snprintf(label_str, ITEM_LABEL_LENGTH,
8357 "%s: %s", hfinfo->name, addr_str);
8358 wmem_free(NULL, addr_str);
8362 ipv4 = (ipv4_addr_and_mask *)fvalue_get(&fi->value);
8363 n_addr = ipv4_get_net_order_addr(ipv4);
8365 addr.type = AT_IPv4;
8367 addr.data = &n_addr;
8369 if (hfinfo->display == BASE_NETMASK)
8371 addr_str = (char*)address_to_str(NULL, &addr);
8375 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
8377 g_snprintf(label_str, ITEM_LABEL_LENGTH,
8378 "%s: %s", hfinfo->name, addr_str);
8379 wmem_free(NULL, addr_str);
8383 bytes = (guint8 *)fvalue_get(&fi->value);
8385 addr.type = AT_IPv6;
8389 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
8390 g_snprintf(label_str, ITEM_LABEL_LENGTH,
8391 "%s: %s", hfinfo->name, addr_str);
8392 wmem_free(NULL, addr_str);
8396 addr.type = AT_FCWWN;
8397 addr.len = FCWWN_ADDR_LEN;
8398 addr.data = (guint8 *)fvalue_get(&fi->value);
8400 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
8401 g_snprintf(label_str, ITEM_LABEL_LENGTH,
8402 "%s: %s", hfinfo->name, addr_str);
8403 wmem_free(NULL, addr_str);
8407 guid = (e_guid_t *)fvalue_get(&fi->value);
8408 tmp = guid_to_str(NULL, guid);
8409 label_fill(label_str, 0, hfinfo, tmp);
8410 wmem_free(NULL, tmp);
8414 bytes = (guint8 *)fvalue_get(&fi->value);
8415 name = oid_resolved_from_encoded(NULL, bytes, fvalue_length(&fi->value));
8416 tmp = oid_encoded2string(NULL, bytes, fvalue_length(&fi->value));
8418 label_fill_descr(label_str, 0, hfinfo, tmp, name);
8419 wmem_free(NULL, name);
8421 label_fill(label_str, 0, hfinfo, tmp);
8423 wmem_free(NULL, tmp);
8427 bytes = (guint8 *)fvalue_get(&fi->value);
8428 name = rel_oid_resolved_from_encoded(NULL, bytes, fvalue_length(&fi->value));
8429 tmp = rel_oid_encoded2string(NULL, bytes, fvalue_length(&fi->value));
8431 label_fill_descr(label_str, 0, hfinfo, tmp, name);
8432 wmem_free(NULL, name);
8434 label_fill(label_str, 0, hfinfo, tmp);
8436 wmem_free(NULL, tmp);
8440 bytes = (guint8 *)fvalue_get(&fi->value);
8441 tmp = print_system_id(NULL, bytes, fvalue_length(&fi->value));
8442 label_fill(label_str, 0, hfinfo, tmp);
8443 wmem_free(NULL, tmp);
8447 integer64 = fvalue_get_uinteger64(&fi->value);
8448 addr_str = eui64_to_str(NULL, integer64);
8449 tmp = (char*)eui64_to_display(NULL, integer64);
8450 label_fill_descr(label_str, 0, hfinfo, tmp, addr_str);
8451 wmem_free(NULL, tmp);
8452 wmem_free(NULL, addr_str);
8456 case FT_UINT_STRING:
8458 bytes = (guint8 *)fvalue_get(&fi->value);
8459 tmp = hfinfo_format_text(hfinfo, bytes);
8460 label_fill(label_str, 0, hfinfo, tmp);
8461 wmem_free(NULL, tmp);
8464 case FT_IEEE_11073_SFLOAT:
8465 tmp = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, hfinfo->display);
8466 g_snprintf(label_str, ITEM_LABEL_LENGTH,
8469 wmem_free(NULL, tmp);
8471 case FT_IEEE_11073_FLOAT:
8472 tmp = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, hfinfo->display);
8473 g_snprintf(label_str, ITEM_LABEL_LENGTH,
8476 wmem_free(NULL, tmp);
8480 g_error("hfinfo->type %d (%s) not handled\n",
8481 hfinfo->type, ftype_name(hfinfo->type));
8482 DISSECTOR_ASSERT_NOT_REACHED();
8488 fill_label_boolean(field_info *fi, gchar *label_str)
8490 char *p = label_str;
8491 int bitfield_byte_length = 0, bitwidth;
8492 guint64 unshifted_value;
8495 header_field_info *hfinfo = fi->hfinfo;
8496 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
8498 if (hfinfo->strings) {
8499 tfstring = (const struct true_false_string*) hfinfo->strings;
8502 value = fvalue_get_uinteger64(&fi->value);
8503 if (hfinfo->bitmask) {
8504 /* Figure out the bit width */
8505 bitwidth = hfinfo_container_bitwidth(hfinfo);
8508 unshifted_value = value;
8509 unshifted_value <<= hfinfo_bitshift(hfinfo);
8511 /* Create the bitfield first */
8512 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
8513 bitfield_byte_length = (int) (p - label_str);
8516 /* Fill in the textual info */
8517 label_fill(label_str, bitfield_byte_length, hfinfo, value ? tfstring->true_string : tfstring->false_string);
8521 hf_try_val_to_str(guint32 value, const header_field_info *hfinfo)
8523 if (hfinfo->display & BASE_RANGE_STRING)
8524 return try_rval_to_str(value, (const range_string *) hfinfo->strings);
8526 if (hfinfo->display & BASE_EXT_STRING)
8527 return try_val_to_str_ext(value, (value_string_ext *) hfinfo->strings);
8529 if (hfinfo->display & BASE_VAL64_STRING)
8530 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
8532 if (hfinfo->display & BASE_UNIT_STRING)
8533 return unit_name_string_get_value(value, (struct unit_name_string*) hfinfo->strings);
8535 return try_val_to_str(value, (const value_string *) hfinfo->strings);
8539 hf_try_val64_to_str(guint64 value, const header_field_info *hfinfo)
8541 if (hfinfo->display & BASE_VAL64_STRING)
8542 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
8544 if (hfinfo->display & BASE_RANGE_STRING)
8545 return try_rval64_to_str(value, (const range_string *) hfinfo->strings);
8547 if (hfinfo->display & BASE_UNIT_STRING)
8548 return unit_name_string_get_value64(value, (struct unit_name_string*) hfinfo->strings);
8550 /* If this is reached somebody registered a 64-bit field with a 32-bit
8551 * value-string, which isn't right. */
8552 DISSECTOR_ASSERT_NOT_REACHED();
8554 /* This is necessary to squelch MSVC errors; is there
8555 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
8561 hf_try_val_to_str_const(guint32 value, const header_field_info *hfinfo, const char *unknown_str)
8563 const char *str = hf_try_val_to_str(value, hfinfo);
8565 return (str) ? str : unknown_str;
8569 hf_try_val64_to_str_const(guint64 value, const header_field_info *hfinfo, const char *unknown_str)
8571 const char *str = hf_try_val64_to_str(value, hfinfo);
8573 return (str) ? str : unknown_str;
8576 /* Fills data for bitfield chars with val_strings */
8578 fill_label_bitfield_char(field_info *fi, gchar *label_str)
8581 int bitfield_byte_length, bitwidth;
8582 guint32 unshifted_value;
8588 header_field_info *hfinfo = fi->hfinfo;
8590 /* Figure out the bit width */
8591 bitwidth = hfinfo_container_bitwidth(hfinfo);
8594 value = fvalue_get_uinteger(&fi->value);
8596 unshifted_value = value;
8597 if (hfinfo->bitmask) {
8598 unshifted_value <<= hfinfo_bitshift(hfinfo);
8601 /* Create the bitfield first */
8602 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
8603 bitfield_byte_length = (int) (p - label_str);
8605 /* Fill in the textual info using stored (shifted) value */
8606 if (hfinfo->display == BASE_CUSTOM) {
8607 gchar tmp[ITEM_LABEL_LENGTH];
8608 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
8610 DISSECTOR_ASSERT(fmtfunc);
8611 fmtfunc(tmp, value);
8612 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
8614 else if (hfinfo->strings) {
8615 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
8617 out = hfinfo_char_vals_format(hfinfo, buf, value);
8618 if (out == NULL) /* BASE_NONE so don't put integer in descr */
8619 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
8621 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
8624 out = hfinfo_char_value_format(hfinfo, buf, value);
8626 label_fill(label_str, bitfield_byte_length, hfinfo, out);
8630 /* Fills data for bitfield ints with val_strings */
8632 fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed)
8635 int bitfield_byte_length, bitwidth;
8636 guint32 unshifted_value;
8642 header_field_info *hfinfo = fi->hfinfo;
8644 /* Figure out the bit width */
8645 bitwidth = hfinfo_container_bitwidth(hfinfo);
8649 value = fvalue_get_sinteger(&fi->value);
8651 value = fvalue_get_uinteger(&fi->value);
8653 unshifted_value = value;
8654 if (hfinfo->bitmask) {
8655 unshifted_value <<= hfinfo_bitshift(hfinfo);
8658 /* Create the bitfield first */
8659 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
8660 bitfield_byte_length = (int) (p - label_str);
8662 /* Fill in the textual info using stored (shifted) value */
8663 if (hfinfo->display == BASE_CUSTOM) {
8664 gchar tmp[ITEM_LABEL_LENGTH];
8665 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
8667 DISSECTOR_ASSERT(fmtfunc);
8668 fmtfunc(tmp, value);
8669 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
8671 else if (hfinfo->strings) {
8672 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
8674 out = hfinfo_number_vals_format(hfinfo, buf, value);
8675 if (out == NULL) /* BASE_NONE so don't put integer in descr */
8676 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
8678 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
8681 out = hfinfo_number_value_format(hfinfo, buf, value);
8683 label_fill(label_str, bitfield_byte_length, hfinfo, out);
8688 fill_label_bitfield64(field_info *fi, gchar *label_str, gboolean is_signed)
8691 int bitfield_byte_length, bitwidth;
8692 guint64 unshifted_value;
8698 header_field_info *hfinfo = fi->hfinfo;
8700 /* Figure out the bit width */
8701 bitwidth = hfinfo_container_bitwidth(hfinfo);
8705 value = fvalue_get_sinteger64(&fi->value);
8707 value = fvalue_get_uinteger64(&fi->value);
8709 unshifted_value = value;
8710 if (hfinfo->bitmask) {
8711 unshifted_value <<= hfinfo_bitshift(hfinfo);
8714 /* Create the bitfield first */
8715 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
8716 bitfield_byte_length = (int) (p - label_str);
8718 /* Fill in the textual info using stored (shifted) value */
8719 if (hfinfo->display == BASE_CUSTOM) {
8720 gchar tmp[ITEM_LABEL_LENGTH];
8721 const custom_fmt_func_64_t fmtfunc64 = (const custom_fmt_func_64_t)hfinfo->strings;
8723 DISSECTOR_ASSERT(fmtfunc64);
8724 fmtfunc64(tmp, value);
8725 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
8727 else if (hfinfo->strings) {
8728 const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
8730 out = hfinfo_number_vals_format64(hfinfo, buf, value);
8731 if (out == NULL) /* BASE_NONE so don't put integer in descr */
8732 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
8734 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
8737 out = hfinfo_number_value_format64(hfinfo, buf, value);
8739 label_fill(label_str, bitfield_byte_length, hfinfo, out);
8744 fill_label_bitfield_varint(field_info *fi, gchar *label_str, gboolean is_signed)
8747 int bitfield_byte_length;
8748 guint32 value, unshifted_value;
8752 header_field_info *hfinfo = fi->hfinfo;
8756 value = fvalue_get_sinteger(&fi->value);
8758 value = fvalue_get_uinteger(&fi->value);
8760 unshifted_value = value;
8761 if (hfinfo->bitmask) {
8762 unshifted_value <<= hfinfo_bitshift(hfinfo);
8765 /* Create the bitfield first */
8766 p = decode_bitfield_varint_value(label_str, unshifted_value, hfinfo->bitmask, fi->length*8);
8767 bitfield_byte_length = (int) (p - label_str);
8769 /* Fill in the textual info using stored (shifted) value */
8770 if (hfinfo->display == BASE_CUSTOM) {
8771 gchar tmp[ITEM_LABEL_LENGTH];
8772 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
8774 DISSECTOR_ASSERT(fmtfunc);
8775 fmtfunc(tmp, value);
8776 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
8778 else if (hfinfo->strings) {
8779 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
8781 out = hfinfo_number_vals_format(hfinfo, buf, value);
8782 if (out == NULL) /* BASE_NONE so don't put integer in descr */
8783 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
8785 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
8788 out = hfinfo_number_value_format(hfinfo, buf, value);
8790 label_fill(label_str, bitfield_byte_length, hfinfo, out);
8795 fill_label_bitfield_varint64(field_info *fi, gchar *label_str, gboolean is_signed)
8798 int bitfield_byte_length;
8799 guint64 unshifted_value;
8805 header_field_info *hfinfo = fi->hfinfo;
8809 value = fvalue_get_sinteger64(&fi->value);
8811 value = fvalue_get_uinteger64(&fi->value);
8813 unshifted_value = value;
8814 if (hfinfo->bitmask) {
8815 unshifted_value <<= hfinfo_bitshift(hfinfo);
8818 /* Create the bitfield first */
8819 p = decode_bitfield_varint_value(label_str, unshifted_value, hfinfo->bitmask, fi->length*8);
8820 bitfield_byte_length = (int) (p - label_str);
8822 /* Fill in the textual info using stored (shifted) value */
8823 if (hfinfo->display == BASE_CUSTOM) {
8824 gchar tmp[ITEM_LABEL_LENGTH];
8825 const custom_fmt_func_64_t fmtfunc64 = (const custom_fmt_func_64_t)hfinfo->strings;
8827 DISSECTOR_ASSERT(fmtfunc64);
8828 fmtfunc64(tmp, value);
8829 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
8831 else if (hfinfo->strings) {
8832 const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
8834 out = hfinfo_number_vals_format64(hfinfo, buf, value);
8835 if (out == NULL) /* BASE_NONE so don't put integer in descr */
8836 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
8838 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
8841 out = hfinfo_number_value_format64(hfinfo, buf, value);
8843 label_fill(label_str, bitfield_byte_length, hfinfo, out);
8848 fill_label_char(field_info *fi, gchar *label_str)
8850 header_field_info *hfinfo = fi->hfinfo;
8856 value = fvalue_get_uinteger(&fi->value);
8858 /* Fill in the textual info */
8859 if (hfinfo->display == BASE_CUSTOM) {
8860 gchar tmp[ITEM_LABEL_LENGTH];
8861 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
8863 DISSECTOR_ASSERT(fmtfunc);
8864 fmtfunc(tmp, value);
8865 label_fill(label_str, 0, hfinfo, tmp);
8867 else if (hfinfo->strings) {
8868 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
8870 out = hfinfo_char_vals_format(hfinfo, buf, value);
8871 label_fill_descr(label_str, 0, hfinfo, val_str, out);
8874 out = hfinfo_char_value_format(hfinfo, buf, value);
8876 label_fill(label_str, 0, hfinfo, out);
8881 fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
8883 header_field_info *hfinfo = fi->hfinfo;
8890 value = fvalue_get_sinteger(&fi->value);
8892 value = fvalue_get_uinteger(&fi->value);
8894 /* Fill in the textual info */
8895 if (hfinfo->display == BASE_CUSTOM) {
8896 gchar tmp[ITEM_LABEL_LENGTH];
8897 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
8899 DISSECTOR_ASSERT(fmtfunc);
8900 fmtfunc(tmp, value);
8901 label_fill(label_str, 0, hfinfo, tmp);
8903 else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) {
8905 * It makes no sense to have a value-string table for a
8906 * frame-number field - they're just integers giving
8907 * the ordinal frame number.
8909 const char *val_str = hf_try_val_to_str(value, hfinfo);
8911 out = hfinfo_number_vals_format(hfinfo, buf, value);
8912 if (hfinfo->display & BASE_SPECIAL_VALS) {
8914 * Unique values only display value_string string
8915 * if there is a match. Otherwise it's just a number
8918 label_fill_descr(label_str, 0, hfinfo, val_str, out);
8920 label_fill(label_str, 0, hfinfo, out);
8923 if (val_str == NULL)
8924 val_str = "Unknown";
8926 if (out == NULL) /* BASE_NONE so don't put integer in descr */
8927 label_fill(label_str, 0, hfinfo, val_str);
8929 label_fill_descr(label_str, 0, hfinfo, val_str, out);
8932 else if (IS_BASE_PORT(hfinfo->display)) {
8933 gchar tmp[ITEM_LABEL_LENGTH];
8935 port_with_resolution_to_str_buf(tmp, sizeof(tmp),
8936 display_to_port_type((field_display_e)hfinfo->display), value);
8937 label_fill(label_str, 0, hfinfo, tmp);
8940 out = hfinfo_number_value_format(hfinfo, buf, value);
8942 label_fill(label_str, 0, hfinfo, out);
8947 fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed)
8949 header_field_info *hfinfo = fi->hfinfo;
8956 value = fvalue_get_sinteger64(&fi->value);
8958 value = fvalue_get_uinteger64(&fi->value);
8960 /* Fill in the textual info */
8961 if (hfinfo->display == BASE_CUSTOM) {
8962 gchar tmp[ITEM_LABEL_LENGTH];
8963 const custom_fmt_func_64_t fmtfunc64 = (const custom_fmt_func_64_t)hfinfo->strings;
8965 DISSECTOR_ASSERT(fmtfunc64);
8966 fmtfunc64(tmp, value);
8967 label_fill(label_str, 0, hfinfo, tmp);
8969 else if (hfinfo->strings) {
8970 const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
8972 out = hfinfo_number_vals_format64(hfinfo, buf, value);
8973 if (out == NULL) /* BASE_NONE so don't put integer in descr */
8974 label_fill(label_str, 0, hfinfo, val_str);
8976 label_fill_descr(label_str, 0, hfinfo, val_str, out);
8979 out = hfinfo_number_value_format64(hfinfo, buf, value);
8981 label_fill(label_str, 0, hfinfo, out);
8986 hfinfo_bitshift(const header_field_info *hfinfo)
8988 return ws_ctz(hfinfo->bitmask);
8992 hfinfo_mask_bitwidth(const header_field_info *hfinfo)
8994 if (!hfinfo->bitmask) {
8998 /* ilog2 = first set bit, ctz = last set bit */
8999 return ws_ilog2(hfinfo->bitmask) - ws_ctz(hfinfo->bitmask) + 1;
9003 hfinfo_type_bitwidth(enum ftenum type)
9042 DISSECTOR_ASSERT_NOT_REACHED();
9050 hfinfo_container_bitwidth(const header_field_info *hfinfo)
9052 if (!hfinfo->bitmask) {
9056 if (hfinfo->type == FT_BOOLEAN) {
9057 return hfinfo->display; /* hacky? :) */
9060 return hfinfo_type_bitwidth(hfinfo->type);
9064 hfinfo_hex_digits(const header_field_info *hfinfo)
9068 /* If we have a bitmask, hfinfo->type is the width of the container, so not
9069 * appropriate to determine the number of hex digits for the field.
9070 * So instead, we compute it from the bitmask.
9072 if (hfinfo->bitmask != 0) {
9073 bitwidth = hfinfo_mask_bitwidth(hfinfo);
9075 bitwidth = hfinfo_type_bitwidth(hfinfo->type);
9078 /* Divide by 4, rounding up, to get number of hex digits. */
9079 return (bitwidth + 3) / 4;
9083 hfinfo_char_value_format_display(int display, char buf[7], guint32 value)
9085 char *ptr = &buf[6];
9086 static const gchar hex_digits[16] =
9087 { '0', '1', '2', '3', '4', '5', '6', '7',
9088 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
9092 /* Properly format value */
9093 if (g_ascii_isprint(value)) {
9095 * Printable, so just show the character, and, if it needs
9096 * to be escaped, escape it.
9099 if (value == '\\' || value == '\'')
9103 * Non-printable; show it as an escape sequence.
9109 * Show a NUL with only one digit.
9143 switch (display & FIELD_DISPLAY_E_MASK) {
9146 *(--ptr) = (value & 0x7) + '0';
9148 *(--ptr) = (value & 0x7) + '0';
9150 *(--ptr) = (value & 0x7) + '0';
9154 *(--ptr) = hex_digits[value & 0x0F];
9156 *(--ptr) = hex_digits[value & 0x0F];
9161 g_assert_not_reached();
9171 hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value)
9173 char *ptr = &buf[31];
9174 gboolean isint = IS_FT_INT(hfinfo->type);
9177 /* Properly format value */
9178 switch (display & FIELD_DISPLAY_E_MASK) {
9180 return isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
9184 ptr = hex_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
9187 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
9191 return oct_to_str_back(ptr, value);
9194 return hex_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
9198 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
9201 ptr = hex_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
9208 port_with_resolution_to_str_buf(buf, 32,
9209 display_to_port_type((field_display_e)display), value);
9214 const gchar *manuf_name;
9216 p_oui[0] = value >> 16 & 0xFF;
9217 p_oui[1] = value >> 8 & 0xFF;
9218 p_oui[2] = value & 0xFF;
9220 /* Attempt an OUI lookup. */
9221 manuf_name = uint_get_manuf_name_if_known(value);
9222 if (manuf_name == NULL) {
9223 /* Could not find an OUI. */
9224 g_snprintf(buf, 32, "%02x:%02x:%02x", p_oui[0], p_oui[1], p_oui[2]);
9227 /* Found an address string. */
9228 g_snprintf(buf, 32, "%02x:%02x:%02x (%s)", p_oui[0], p_oui[1], p_oui[2], manuf_name);
9234 g_assert_not_reached();
9240 hfinfo_number_value_format_display64(const header_field_info *hfinfo, int display, char buf[48], guint64 value)
9242 char *ptr = &buf[47];
9243 gboolean isint = IS_FT_INT(hfinfo->type);
9246 /* Properly format value */
9249 return isint ? int64_to_str_back(ptr, (gint64) value) : uint64_to_str_back(ptr, value);
9253 ptr = hex64_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
9256 ptr = isint ? int64_to_str_back(ptr, (gint64) value) : uint64_to_str_back(ptr, value);
9260 return oct64_to_str_back(ptr, value);
9263 return hex64_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
9267 ptr = isint ? int64_to_str_back(ptr, (gint64) value) : uint64_to_str_back(ptr, value);
9270 ptr = hex64_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
9274 g_assert_not_reached();
9280 hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
9282 int display = hfinfo->display;
9284 if (hfinfo->type == FT_FRAMENUM) {
9286 * Frame numbers are always displayed in decimal.
9291 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
9295 hfinfo_number_value_format64(const header_field_info *hfinfo, char buf[64], guint64 value)
9297 int display = hfinfo->display;
9299 if (hfinfo->type == FT_FRAMENUM) {
9301 * Frame numbers are always displayed in decimal.
9306 return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
9310 hfinfo_char_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
9312 /* Get the underlying BASE_ value */
9313 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
9315 return hfinfo_char_value_format_display(display, buf, value);
9319 hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
9321 /* Get the underlying BASE_ value */
9322 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
9324 if (hfinfo->type == FT_FRAMENUM) {
9326 * Frame numbers are always displayed in decimal.
9331 if (IS_BASE_PORT(display)) {
9333 } else if (display == BASE_OUI) {
9339 /* case BASE_DEC: */
9341 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
9346 /* case BASE_HEX: */
9352 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
9356 hfinfo_numeric_value_format64(const header_field_info *hfinfo, char buf[64], guint64 value)
9358 /* Get the underlying BASE_ value */
9359 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
9361 if (hfinfo->type == FT_FRAMENUM) {
9363 * Frame numbers are always displayed in decimal.
9370 /* case BASE_DEC: */
9372 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
9377 /* case BASE_HEX: */
9383 return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
9387 hfinfo_char_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
9389 /* Get the underlying BASE_ value */
9390 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
9392 return hfinfo_char_value_format_display(display, buf, value);
9396 hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
9398 /* Get the underlying BASE_ value */
9399 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
9401 if (display == BASE_NONE)
9404 if (display == BASE_DEC_HEX)
9406 if (display == BASE_HEX_DEC)
9409 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
9413 hfinfo_number_vals_format64(const header_field_info *hfinfo, char buf[64], guint64 value)
9415 /* Get the underlying BASE_ value */
9416 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
9418 if (display == BASE_NONE)
9421 if (display == BASE_DEC_HEX)
9423 if (display == BASE_HEX_DEC)
9426 return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
9430 proto_registrar_get_name(const int n)
9432 header_field_info *hfinfo;
9434 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
9435 return hfinfo->name;
9439 proto_registrar_get_abbrev(const int n)
9441 header_field_info *hfinfo;
9443 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
9444 return hfinfo->abbrev;
9448 proto_registrar_get_ftype(const int n)
9450 header_field_info *hfinfo;
9452 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
9453 return hfinfo->type;
9457 proto_registrar_get_parent(const int n)
9459 header_field_info *hfinfo;
9461 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
9462 return hfinfo->parent;
9466 proto_registrar_is_protocol(const int n)
9468 header_field_info *hfinfo;
9470 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
9471 return (((hfinfo->id != hf_text_only) && (hfinfo->parent == -1)) ? TRUE : FALSE);
9474 /* Returns length of field in packet (not necessarily the length
9475 * in our internal representation, as in the case of IPv4).
9476 * 0 means undeterminable at time of registration
9477 * -1 means the field is not registered. */
9479 proto_registrar_get_length(const int n)
9481 header_field_info *hfinfo;
9483 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
9484 return ftype_length(hfinfo->type);
9487 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
9488 * it exists anywhere, or FALSE if it exists nowhere. */
9490 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
9492 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
9494 if (g_ptr_array_len(ptrs) > 0) {
9502 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
9503 * This only works if the hfindex was "primed" before the dissection
9504 * took place, as we just pass back the already-created GPtrArray*.
9505 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
9508 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
9513 if (PTREE_DATA(tree)->interesting_hfids != NULL)
9514 return (GPtrArray *)g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
9515 GINT_TO_POINTER(id));
9521 proto_tracking_interesting_fields(const proto_tree *tree)
9523 GHashTable *interesting_hfids;
9528 interesting_hfids = PTREE_DATA(tree)->interesting_hfids;
9530 return (interesting_hfids != NULL) && g_hash_table_size(interesting_hfids);
9533 /* Helper struct for proto_find_info() and proto_all_finfos() */
9539 /* Helper function for proto_find_info() */
9541 find_finfo(proto_node *node, gpointer data)
9543 field_info *fi = PNODE_FINFO(node);
9544 if (fi && fi->hfinfo) {
9545 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
9546 g_ptr_array_add(((ffdata_t*)data)->array, fi);
9550 /* Don't stop traversing. */
9554 /* Helper function for proto_find_first_info() */
9556 find_first_finfo(proto_node *node, gpointer data)
9558 field_info *fi = PNODE_FINFO(node);
9559 if (fi && fi->hfinfo) {
9560 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
9561 g_ptr_array_add(((ffdata_t*)data)->array, fi);
9563 /* Stop traversing. */
9568 /* Continue traversing. */
9572 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
9573 * This works on any proto_tree, primed or unprimed, but actually searches
9574 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
9575 * The caller does need to free the returned GPtrArray with
9576 * g_ptr_array_free(<array>, TRUE).
9579 proto_find_finfo(proto_tree *tree, const int id)
9583 ffdata.array = g_ptr_array_new();
9586 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
9588 return ffdata.array;
9591 /* Return GPtrArray* of first field_info pointers for the searched hfindex that appear in a tree.
9592 * This works on any proto_tree, primed or unprimed, but actually searches
9593 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
9594 * The caller does need to free the returned GPtrArray with
9595 * g_ptr_array_free(<array>, TRUE).
9598 proto_find_first_finfo(proto_tree *tree, const int id)
9602 ffdata.array = g_ptr_array_new();
9605 proto_tree_traverse_pre_order(tree, find_first_finfo, &ffdata);
9607 return ffdata.array;
9610 /* Helper function for proto_all_finfos() */
9612 every_finfo(proto_node *node, gpointer data)
9614 field_info *fi = PNODE_FINFO(node);
9615 if (fi && fi->hfinfo) {
9616 g_ptr_array_add(((ffdata_t*)data)->array, fi);
9619 /* Don't stop traversing. */
9623 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
9625 proto_all_finfos(proto_tree *tree)
9629 /* Pre allocate enough space to hold all fields in most cases */
9630 ffdata.array = g_ptr_array_sized_new(512);
9633 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
9635 return ffdata.array;
9646 check_for_offset(proto_node *node, gpointer data)
9648 field_info *fi = PNODE_FINFO(node);
9649 offset_search_t *offsearch = (offset_search_t *)data;
9651 /* !fi == the top most container node which holds nothing */
9652 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && !PROTO_ITEM_IS_GENERATED(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
9653 if (offsearch->offset >= (guint) fi->start &&
9654 offsearch->offset < (guint) (fi->start + fi->length)) {
9656 offsearch->finfo = fi;
9657 return FALSE; /* keep traversing */
9660 return FALSE; /* keep traversing */
9663 /* Search a proto_tree backwards (from leaves to root) looking for the field
9664 * whose start/length occupies 'offset' */
9665 /* XXX - I couldn't find an easy way to search backwards, so I search
9666 * forwards, w/o stopping. Therefore, the last finfo I find will the be
9667 * the one I want to return to the user. This algorithm is inefficient
9668 * and could be re-done, but I'd have to handle all the children and
9669 * siblings of each node myself. When I have more time I'll do that.
9672 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
9674 offset_search_t offsearch;
9676 offsearch.offset = offset;
9677 offsearch.finfo = NULL;
9678 offsearch.tvb = tvb;
9680 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
9682 return offsearch.finfo;
9691 check_for_undecoded(proto_node *node, gpointer data)
9693 field_info *fi = PNODE_FINFO(node);
9694 decoded_data_t* decoded = (decoded_data_t*)data;
9699 if (fi && fi->hfinfo->type != FT_PROTOCOL) {
9700 for (i = fi->start; i < fi->start + fi->length && i < decoded->length; i++) {
9703 decoded->buf[byte] |= (1 << bit);
9711 proto_find_undecoded_data(proto_tree *tree, guint length)
9713 decoded_data_t decoded;
9714 decoded.length = length;
9715 decoded.buf = (gchar*)wmem_alloc0(wmem_packet_scope(), length / 8 + 1);
9717 proto_tree_traverse_pre_order(tree, check_for_undecoded, &decoded);
9721 /* Dumps the protocols in the registration database to stdout. An independent
9722 * program can take this output and format it into nice tables or HTML or
9725 * There is one record per line. The fields are tab-delimited.
9727 * Field 1 = protocol name
9728 * Field 2 = protocol short name
9729 * Field 3 = protocol filter name
9732 proto_registrar_dump_protocols(void)
9734 protocol_t *protocol;
9736 void *cookie = NULL;
9739 i = proto_get_first_protocol(&cookie);
9741 protocol = find_protocol_by_id(i);
9742 ws_debug_printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
9743 protocol->filter_name);
9744 i = proto_get_next_protocol(&cookie);
9748 /* Dumps the value_strings, extended value string headers, range_strings
9749 * or true/false strings for fields that have them.
9750 * There is one record per line. Fields are tab-delimited.
9751 * There are four types of records: Value String, Extended Value String Header,
9752 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
9753 * the type of record.
9755 * Note that a record will be generated only if the value_string,... is referenced
9756 * in a registered hfinfo entry.
9762 * Field 2 = Field abbreviation to which this value string corresponds
9763 * Field 3 = Integer value
9766 * Extended Value String Headers
9767 * -----------------------------
9769 * Field 2 = Field abbreviation to which this extended value string header corresponds
9770 * Field 3 = Extended Value String "Name"
9771 * Field 4 = Number of entries in the associated value_string array
9772 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
9777 * Field 2 = Field abbreviation to which this range string corresponds
9778 * Field 3 = Integer value: lower bound
9779 * Field 4 = Integer value: upper bound
9782 * True/False Strings
9783 * ------------------
9785 * Field 2 = Field abbreviation to which this true/false string corresponds
9786 * Field 3 = True String
9787 * Field 4 = False String
9790 proto_registrar_dump_values(void)
9792 header_field_info *hfinfo;
9794 const value_string *vals;
9795 const val64_string *vals64;
9796 const range_string *range;
9797 const true_false_string *tfs;
9798 const unit_name_string *units;
9800 len = gpa_hfinfo.len;
9801 for (i = 0; i < len ; i++) {
9802 if (gpa_hfinfo.hfi[i] == NULL)
9803 continue; /* This is a deregistered protocol or field */
9805 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
9807 if (hfinfo->id == hf_text_only) {
9811 /* ignore protocols */
9812 if (proto_registrar_is_protocol(i)) {
9815 /* process header fields */
9816 #if 0 /* XXX: We apparently allow fields with the same name but with differing "strings" content */
9818 * If this field isn't at the head of the list of
9819 * fields with this name, skip this field - all
9820 * fields with the same name are really just versions
9821 * of the same field stored in different bits, and
9822 * should have the same type/radix/value list, and
9823 * just differ in their bit masks. (If a field isn't
9824 * a bitfield, but can be, say, 1 or 2 bytes long,
9825 * it can just be made FT_UINT16, meaning the
9826 * *maximum* length is 2 bytes, and be used
9829 if (hfinfo->same_name_prev_id != -1)
9838 if (hfinfo->strings != NULL) {
9839 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) != BASE_CUSTOM &&
9840 (hfinfo->type == FT_CHAR ||
9841 hfinfo->type == FT_UINT8 ||
9842 hfinfo->type == FT_UINT16 ||
9843 hfinfo->type == FT_UINT24 ||
9844 hfinfo->type == FT_UINT32 ||
9845 hfinfo->type == FT_UINT40 ||
9846 hfinfo->type == FT_UINT48 ||
9847 hfinfo->type == FT_UINT56 ||
9848 hfinfo->type == FT_UINT64 ||
9849 hfinfo->type == FT_INT8 ||
9850 hfinfo->type == FT_INT16 ||
9851 hfinfo->type == FT_INT24 ||
9852 hfinfo->type == FT_INT32 ||
9853 hfinfo->type == FT_INT40 ||
9854 hfinfo->type == FT_INT48 ||
9855 hfinfo->type == FT_INT56 ||
9856 hfinfo->type == FT_INT64)) {
9858 if (hfinfo->display & BASE_RANGE_STRING) {
9859 range = (const range_string *)hfinfo->strings;
9860 } else if (hfinfo->display & BASE_EXT_STRING) {
9861 vals = VALUE_STRING_EXT_VS_P((value_string_ext *)hfinfo->strings);
9862 } else if (hfinfo->display & BASE_VAL64_STRING) {
9863 vals64 = (const val64_string *)hfinfo->strings;
9864 } else if (hfinfo->display & BASE_UNIT_STRING) {
9865 units = (const unit_name_string *)hfinfo->strings;
9867 vals = (const value_string *)hfinfo->strings;
9870 else if (hfinfo->type == FT_BOOLEAN) {
9871 tfs = (const struct true_false_string *)hfinfo->strings;
9875 /* Print value strings? */
9877 if (hfinfo->display & BASE_EXT_STRING) {
9878 value_string_ext *vse_p = (value_string_ext *)hfinfo->strings;
9879 if (!value_string_ext_validate(vse_p)) {
9880 ws_g_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
9883 try_val_to_str_ext(0, vse_p); /* "prime" the extended value_string */
9884 ws_debug_printf("E\t%s\t%u\t%s\t%s\n",
9886 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
9887 VALUE_STRING_EXT_VS_NAME(vse_p),
9888 value_string_ext_match_type_str(vse_p));
9891 while (vals[vi].strptr) {
9892 /* Print in the proper base */
9893 if (hfinfo->type == FT_CHAR) {
9894 if (g_ascii_isprint(vals[vi].value)) {
9895 ws_debug_printf("V\t%s\t'%c'\t%s\n",
9900 if (hfinfo->display == BASE_HEX) {
9901 ws_debug_printf("V\t%s\t'\\x%02x'\t%s\n",
9907 ws_debug_printf("V\t%s\t'\\%03o'\t%s\n",
9914 if (hfinfo->display == BASE_HEX) {
9915 ws_debug_printf("V\t%s\t0x%x\t%s\n",
9921 ws_debug_printf("V\t%s\t%u\t%s\n",
9932 while (vals64[vi].strptr) {
9933 ws_debug_printf("V64\t%s\t%" G_GINT64_MODIFIER "u\t%s\n",
9941 /* print range strings? */
9944 while (range[vi].strptr) {
9945 /* Print in the proper base */
9946 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_HEX) {
9947 ws_debug_printf("R\t%s\t0x%x\t0x%x\t%s\n",
9949 range[vi].value_min,
9950 range[vi].value_max,
9954 ws_debug_printf("R\t%s\t%u\t%u\t%s\n",
9956 range[vi].value_min,
9957 range[vi].value_max,
9964 /* Print true/false strings? */
9966 ws_debug_printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
9967 tfs->true_string, tfs->false_string);
9969 /* Print unit strings? */
9971 ws_debug_printf("U\t%s\t%s\t%s\n", hfinfo->abbrev,
9972 units->singular, units->plural ? units->plural : "(no plural)");
9977 /* Prints the number of registered fields.
9978 * Useful for determining an appropriate value for
9979 * PROTO_PRE_ALLOC_HF_FIELDS_MEM.
9981 * Returns FALSE if PROTO_PRE_ALLOC_HF_FIELDS_MEM is larger than or equal to
9982 * the number of fields, TRUE otherwise.
9985 proto_registrar_dump_fieldcount(void)
9988 header_field_info *hfinfo;
9989 guint32 deregistered_count = 0;
9990 guint32 same_name_count = 0;
9991 guint32 protocol_count = 0;
9993 for (i = 0; i < gpa_hfinfo.len; i++) {
9994 if (gpa_hfinfo.hfi[i] == NULL) {
9995 deregistered_count++;
9996 continue; /* This is a deregistered protocol or header field */
9999 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
10001 if (proto_registrar_is_protocol(i))
10004 if (hfinfo->same_name_prev_id != -1)
10008 ws_debug_printf("There are %u header fields registered, of which:\n"
10009 "\t%u are deregistered\n"
10010 "\t%u are protocols\n"
10011 "\t%u have the same name as another field\n\n",
10012 gpa_hfinfo.len, deregistered_count, protocol_count,
10015 ws_debug_printf("%d fields were pre-allocated.\n%s", PROTO_PRE_ALLOC_HF_FIELDS_MEM,
10016 (gpa_hfinfo.allocated_len > PROTO_PRE_ALLOC_HF_FIELDS_MEM) ?
10017 "* * Please increase PROTO_PRE_ALLOC_HF_FIELDS_MEM (in epan/proto.c)! * *\n\n" :
10020 ws_debug_printf("The header field table consumes %u KiB of memory.\n",
10021 (unsigned int)(gpa_hfinfo.allocated_len * sizeof(header_field_info *) / 1024));
10022 ws_debug_printf("The fields themselves consume %u KiB of memory.\n",
10023 (unsigned int)(gpa_hfinfo.len * sizeof(header_field_info) / 1024));
10025 return (gpa_hfinfo.allocated_len > PROTO_PRE_ALLOC_HF_FIELDS_MEM);
10029 /* Dumps the contents of the registration database to stdout. An independent
10030 * program can take this output and format it into nice tables or HTML or
10033 * There is one record per line. Each record is either a protocol or a header
10034 * field, differentiated by the first field. The fields are tab-delimited.
10039 * Field 2 = descriptive protocol name
10040 * Field 3 = protocol abbreviation
10045 * Field 2 = descriptive field name
10046 * Field 3 = field abbreviation
10047 * Field 4 = type ( textual representation of the the ftenum type )
10048 * Field 5 = parent protocol abbreviation
10049 * Field 6 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
10050 * Field 7 = bitmask: format: hex: 0x....
10051 * Field 8 = blurb describing field
10054 proto_registrar_dump_fields(void)
10056 header_field_info *hfinfo, *parent_hfinfo;
10058 const char *enum_name;
10059 const char *base_name;
10063 len = gpa_hfinfo.len;
10064 for (i = 0; i < len ; i++) {
10065 if (gpa_hfinfo.hfi[i] == NULL)
10066 continue; /* This is a deregistered protocol or header field */
10068 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
10071 * Skip the pseudo-field for "proto_tree_add_text()" since
10072 * we don't want it in the list of filterable fields.
10074 if (hfinfo->id == hf_text_only)
10077 /* format for protocols */
10078 if (proto_registrar_is_protocol(i)) {
10079 ws_debug_printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
10081 /* format for header fields */
10084 * If this field isn't at the head of the list of
10085 * fields with this name, skip this field - all
10086 * fields with the same name are really just versions
10087 * of the same field stored in different bits, and
10088 * should have the same type/radix/value list, and
10089 * just differ in their bit masks. (If a field isn't
10090 * a bitfield, but can be, say, 1 or 2 bytes long,
10091 * it can just be made FT_UINT16, meaning the
10092 * *maximum* length is 2 bytes, and be used
10093 * for all lengths.)
10095 if (hfinfo->same_name_prev_id != -1)
10098 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
10100 enum_name = ftype_name(hfinfo->type);
10103 if (hfinfo->type == FT_CHAR ||
10104 hfinfo->type == FT_UINT8 ||
10105 hfinfo->type == FT_UINT16 ||
10106 hfinfo->type == FT_UINT24 ||
10107 hfinfo->type == FT_UINT32 ||
10108 hfinfo->type == FT_UINT40 ||
10109 hfinfo->type == FT_UINT48 ||
10110 hfinfo->type == FT_UINT56 ||
10111 hfinfo->type == FT_UINT64 ||
10112 hfinfo->type == FT_INT8 ||
10113 hfinfo->type == FT_INT16 ||
10114 hfinfo->type == FT_INT24 ||
10115 hfinfo->type == FT_INT32 ||
10116 hfinfo->type == FT_INT40 ||
10117 hfinfo->type == FT_INT48 ||
10118 hfinfo->type == FT_INT56 ||
10119 hfinfo->type == FT_INT64) {
10121 switch (FIELD_DISPLAY(hfinfo->display)) {
10134 base_name = val_to_str_const(FIELD_DISPLAY(hfinfo->display), hf_display, "????");
10137 base_name = "????";
10140 } else if (hfinfo->type == FT_BOOLEAN) {
10141 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
10142 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
10146 blurb = hfinfo->blurb;
10149 else if (strlen(blurb) == 0)
10152 ws_debug_printf("F\t%s\t%s\t%s\t%s\t%s\t0x%" G_GINT64_MODIFIER "x\t%s\n",
10153 hfinfo->name, hfinfo->abbrev, enum_name,
10154 parent_hfinfo->abbrev, base_name,
10155 hfinfo->bitmask, blurb);
10160 /* Dumps field types and descriptive names to stdout. An independent
10161 * program can take this output and format it into nice tables or HTML or
10164 * There is one record per line. The fields are tab-delimited.
10166 * Field 1 = field type name, e.g. FT_UINT8
10167 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
10170 proto_registrar_dump_ftypes(void)
10174 for (fte = 0; fte < FT_NUM_TYPES; fte++) {
10175 ws_debug_printf("%s\t%s\n", ftype_name((ftenum_t)fte), ftype_pretty_name((ftenum_t)fte));
10179 /* This function indicates whether it's possible to construct a
10180 * "match selected" display filter string for the specified field,
10181 * returns an indication of whether it's possible, and, if it's
10182 * possible and "filter" is non-null, constructs the filter and
10183 * sets "*filter" to point to it.
10184 * You do not need to [g_]free() this string since it will be automatically
10185 * freed once the next packet is dissected.
10188 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
10191 header_field_info *hfinfo;
10195 int dfilter_len, i;
10196 gint start, length, length_remaining;
10198 gchar is_signed_num = FALSE;
10203 hfinfo = finfo->hfinfo;
10204 DISSECTOR_ASSERT(hfinfo);
10205 abbrev_len = (int) strlen(hfinfo->abbrev);
10207 if (hfinfo->strings && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
10208 const gchar *str = NULL;
10210 switch (hfinfo->type) {
10216 str = hf_try_val_to_str(fvalue_get_sinteger(&finfo->value), hfinfo);
10224 str = hf_try_val_to_str(fvalue_get_uinteger(&finfo->value), hfinfo);
10231 if (str != NULL && filter != NULL) {
10232 *filter = wmem_strdup_printf(NULL, "%s == \"%s\"", hfinfo->abbrev, str);
10238 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
10239 * functions for FT_UINT and FT_INT types, as we choose the base in
10240 * the string expression based on the display base of the field.
10242 * Note that the base does matter, as this is also used for
10243 * the protocolinfo tap.
10245 * It might be nice to use them in "proto_item_fill_label()"
10246 * as well, although, there, you'd have to deal with the base
10247 * *and* with resolved values for addresses.
10249 * Perhaps we need two different val_to_string routines, one
10250 * to generate items for display filters and one to generate
10251 * strings for display, and pass to both of them the
10252 * "display" and "strings" values in the header_field_info
10253 * structure for the field, so they can get the base and,
10254 * if the field is Boolean or an enumerated integer type,
10255 * the tables used to generate human-readable values.
10257 switch (hfinfo->type) {
10260 if (filter != NULL) {
10266 number = fvalue_get_uinteger(&finfo->value);
10268 out = hfinfo_char_value_format(hfinfo, buf, number);
10270 *filter = wmem_strdup_printf(NULL, "%s == %s", hfinfo->abbrev, out);
10278 is_signed_num = TRUE;
10285 if (filter != NULL) {
10292 number = fvalue_get_sinteger(&finfo->value);
10294 number = fvalue_get_uinteger(&finfo->value);
10296 out = hfinfo_numeric_value_format(hfinfo, buf, number);
10298 *filter = wmem_strdup_printf(NULL, "%s == %s", hfinfo->abbrev, out);
10306 is_signed_num = TRUE;
10312 if (filter != NULL) {
10319 number = fvalue_get_sinteger64(&finfo->value);
10321 number = fvalue_get_uinteger64(&finfo->value);
10323 out = hfinfo_numeric_value_format64(hfinfo, buf, number);
10325 *filter = wmem_strdup_printf(NULL, "%s == %s", hfinfo->abbrev, out);
10330 if (filter != NULL)
10331 *filter = wmem_strdup(NULL, finfo->hfinfo->abbrev);
10336 * If the length is 0, just match the name of the
10339 * (Also check for negative values, just in case,
10340 * as we'll cast it to an unsigned value later.)
10342 length = finfo->length;
10344 if (filter != NULL)
10345 *filter = wmem_strdup(NULL, finfo->hfinfo->abbrev);
10352 * This doesn't have a value, so we'd match
10353 * on the raw bytes at this address.
10355 * Should we be allowed to access to the raw bytes?
10356 * If "edt" is NULL, the answer is "no".
10362 * Is this field part of the raw frame tvbuff?
10363 * If not, we can't use "frame[N:M]" to match
10366 * XXX - should this be frame-relative, or
10367 * protocol-relative?
10369 * XXX - does this fallback for non-registered
10370 * fields even make sense?
10372 if (finfo->ds_tvb != edt->tvb)
10373 return FALSE; /* you lose */
10376 * Don't go past the end of that tvbuff.
10378 length_remaining = tvb_captured_length_remaining(finfo->ds_tvb, finfo->start);
10379 if (length > length_remaining)
10380 length = length_remaining;
10384 if (filter != NULL) {
10385 start = finfo->start;
10386 buf_len = 32 + length * 3;
10387 *filter = (char *)wmem_alloc0(NULL, buf_len);
10390 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
10391 "frame[%d:%d] == ", finfo->start, length);
10392 for (i=0; i<length; i++) {
10393 c = tvb_get_guint8(finfo->ds_tvb, start);
10396 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
10399 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
10406 /* FT_PCRE never appears as a type for a registered field. It is
10407 * only used internally. */
10408 DISSECTOR_ASSERT_NOT_REACHED();
10411 /* By default, use the fvalue's "to_string_repr" method. */
10413 /* Figure out the string length needed.
10414 * The ft_repr length.
10415 * 4 bytes for " == ".
10416 * 1 byte for trailing NUL.
10418 if (filter != NULL) {
10420 dfilter_len = fvalue_string_repr_len(&finfo->value,
10421 FTREPR_DFILTER, finfo->hfinfo->display);
10422 dfilter_len += abbrev_len + 4 + 1;
10423 *filter = (char *)wmem_alloc0(NULL, dfilter_len);
10425 /* Create the string */
10426 str = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DFILTER, finfo->hfinfo->display);
10427 g_snprintf(*filter, dfilter_len, "%s == %s", hfinfo->abbrev, str);
10428 wmem_free(NULL, str);
10437 * Returns TRUE if we can do a "match selected" on the field, FALSE
10441 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
10443 return construct_match_selected_string(finfo, edt, NULL);
10446 /* This function attempts to construct a "match selected" display filter
10447 * string for the specified field; if it can do so, it returns a pointer
10448 * to the string, otherwise it returns NULL.
10450 * The string is allocated with packet lifetime scope.
10451 * You do not need to [g_]free() this string since it will be automatically
10452 * freed once the next packet is dissected.
10455 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
10457 char *filter = NULL;
10459 if (!construct_match_selected_string(finfo, edt, &filter))
10461 wmem_free(NULL, filter);
10467 /* This function is common code for all proto_tree_add_bitmask... functions.
10471 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
10472 const int len, const gint ett, const int **fields,
10473 const int flags, gboolean first,
10474 gboolean use_parent_tree,
10475 proto_tree* tree, guint64 value)
10478 guint64 available_bits = 0;
10480 header_field_info *hf;
10484 if (len < 0 || len > 8)
10485 g_assert_not_reached();
10486 bitshift = (8 - (guint)len)*8;
10487 available_bits = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF) >> bitshift;
10489 if (use_parent_tree == FALSE)
10490 tree = proto_item_add_subtree(item, ett);
10493 guint64 present_bits;
10494 PROTO_REGISTRAR_GET_NTH(**fields,hf);
10495 DISSECTOR_ASSERT_HINT(hf->bitmask != 0, hf->abbrev);
10497 /* Skip fields that aren't fully present */
10498 present_bits = available_bits & hf->bitmask;
10499 if (present_bits != hf->bitmask) {
10504 switch (hf->type) {
10510 proto_tree_add_uint(tree, **fields, tvb, offset, len, (guint32)value);
10517 proto_tree_add_int(tree, **fields, tvb, offset, len, (gint32)value);
10524 proto_tree_add_uint64(tree, **fields, tvb, offset, len, value);
10531 proto_tree_add_int64(tree, **fields, tvb, offset, len, (gint64)value);
10535 proto_tree_add_boolean64(tree, **fields, tvb, offset, len, value);
10539 DISSECTOR_ASSERT_NOT_REACHED();
10542 if (flags & BMT_NO_APPEND) {
10546 tmpval = (value & hf->bitmask) >> hfinfo_bitshift(hf);
10548 switch (hf->type) {
10550 if (hf->display == BASE_CUSTOM) {
10551 gchar lbl[ITEM_LABEL_LENGTH];
10552 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
10554 DISSECTOR_ASSERT(fmtfunc);
10555 fmtfunc(lbl, (guint32) tmpval);
10556 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10560 else if (hf->strings) {
10561 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10562 hf->name, hf_try_val_to_str_const((guint32) tmpval, hf, "Unknown"));
10565 else if (!(flags & BMT_NO_INT)) {
10570 proto_item_append_text(item, ", ");
10573 out = hfinfo_char_value_format(hf, buf, (guint32) tmpval);
10574 proto_item_append_text(item, "%s: %s", hf->name, out);
10584 if (hf->display == BASE_CUSTOM) {
10585 gchar lbl[ITEM_LABEL_LENGTH];
10586 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
10588 DISSECTOR_ASSERT(fmtfunc);
10589 fmtfunc(lbl, (guint32) tmpval);
10590 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10594 else if ((hf->strings) &&(!(hf->display & BASE_UNIT_STRING))) {
10595 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10596 hf->name, hf_try_val_to_str_const((guint32) tmpval, hf, "Unknown"));
10599 else if (!(flags & BMT_NO_INT)) {
10604 proto_item_append_text(item, ", ");
10607 out = hfinfo_number_value_format(hf, buf, (guint32) tmpval);
10608 if (hf->display & BASE_UNIT_STRING) {
10609 proto_item_append_text(item, "%s: %s%s", hf->name, out, unit_name_string_get_value((guint32) tmpval, (unit_name_string*)hf->strings));
10611 proto_item_append_text(item, "%s: %s", hf->name, out);
10622 integer32 = (guint32) tmpval;
10624 no_of_bits = ws_count_ones(hf->bitmask);
10625 integer32 = ws_sign_ext32(integer32, no_of_bits);
10627 if (hf->display == BASE_CUSTOM) {
10628 gchar lbl[ITEM_LABEL_LENGTH];
10629 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
10631 DISSECTOR_ASSERT(fmtfunc);
10632 fmtfunc(lbl, (gint32) integer32);
10633 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10637 else if ((hf->strings) &&(!(hf->display & BASE_UNIT_STRING))) {
10638 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10639 hf->name, hf_try_val_to_str_const((gint32) integer32, hf, "Unknown"));
10642 else if (!(flags & BMT_NO_INT)) {
10647 proto_item_append_text(item, ", ");
10650 out = hfinfo_number_value_format(hf, buf, (gint32) integer32);
10651 if ((hf->strings) &&(!(hf->display & BASE_UNIT_STRING))) {
10652 proto_item_append_text(item, "%s: %s%s", hf->name, out, unit_name_string_get_value((guint32) tmpval, (unit_name_string*)hf->strings));
10654 proto_item_append_text(item, "%s: %s", hf->name, out);
10665 if (hf->display == BASE_CUSTOM) {
10666 gchar lbl[ITEM_LABEL_LENGTH];
10667 const custom_fmt_func_64_t fmtfunc = (const custom_fmt_func_64_t)hf->strings;
10669 DISSECTOR_ASSERT(fmtfunc);
10670 fmtfunc(lbl, tmpval);
10671 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10675 else if (hf->strings) {
10676 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10677 hf->name, hf_try_val64_to_str_const(tmpval, hf, "Unknown"));
10680 else if (!(flags & BMT_NO_INT)) {
10685 proto_item_append_text(item, ", ");
10688 out = hfinfo_number_value_format64(hf, buf, tmpval);
10689 proto_item_append_text(item, "%s: %s", hf->name, out);
10700 no_of_bits = ws_count_ones(hf->bitmask);
10701 tmpval = ws_sign_ext64(tmpval, no_of_bits);
10703 if (hf->display == BASE_CUSTOM) {
10704 gchar lbl[ITEM_LABEL_LENGTH];
10705 const custom_fmt_func_64_t fmtfunc = (const custom_fmt_func_64_t)hf->strings;
10707 DISSECTOR_ASSERT(fmtfunc);
10708 fmtfunc(lbl, (gint64) tmpval);
10709 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10713 else if (hf->strings) {
10714 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10715 hf->name, hf_try_val64_to_str_const((gint64) tmpval, hf, "Unknown"));
10718 else if (!(flags & BMT_NO_INT)) {
10723 proto_item_append_text(item, ", ");
10726 out = hfinfo_number_value_format64(hf, buf, (gint64) tmpval);
10727 proto_item_append_text(item, "%s: %s", hf->name, out);
10734 if (hf->strings && !(flags & BMT_NO_TFS)) {
10735 /* If we have true/false strings, emit full - otherwise messages
10736 might look weird */
10737 const struct true_false_string *tfs =
10738 (const struct true_false_string *)hf->strings;
10741 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10742 hf->name, tfs->true_string);
10744 } else if (!(flags & BMT_NO_FALSE)) {
10745 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10746 hf->name, tfs->false_string);
10749 } else if (hf->bitmask & value) {
10750 /* If the flag is set, show the name */
10751 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
10756 DISSECTOR_ASSERT_NOT_REACHED();
10766 /* This function will dissect a sequence of bytes that describe a
10767 * bitmask and supply the value of that sequence through a pointer.
10768 * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
10770 * This field will form an expansion under which the individual fields of the
10771 * bitmask is dissected and displayed.
10772 * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
10774 * fields is an array of pointers to int that lists all the fields of the
10775 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
10776 * or another integer of the same type/size as hf_hdr with a mask specified.
10777 * This array is terminated by a NULL entry.
10779 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
10780 * FT_integer fields that have a value_string attached will have the
10781 * matched string displayed on the expansion line.
10784 proto_tree_add_bitmask_ret_uint64(proto_tree *parent_tree, tvbuff_t *tvb,
10785 const guint offset, const int hf_hdr,
10786 const gint ett, const int **fields,
10787 const guint encoding, guint64 *retval)
10789 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);
10792 /* This function will dissect a sequence of bytes that describe a
10794 * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
10796 * This field will form an expansion under which the individual fields of the
10797 * bitmask is dissected and displayed.
10798 * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
10800 * fields is an array of pointers to int that lists all the fields of the
10801 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
10802 * or another integer of the same type/size as hf_hdr with a mask specified.
10803 * This array is terminated by a NULL entry.
10805 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
10806 * FT_integer fields that have a value_string attached will have the
10807 * matched string displayed on the expansion line.
10810 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
10811 const guint offset, const int hf_hdr,
10812 const gint ett, const int **fields,
10813 const guint encoding)
10815 return proto_tree_add_bitmask_with_flags(parent_tree, tvb, offset, hf_hdr, ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS);
10818 /* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
10819 * what data is appended to the header.
10822 proto_tree_add_bitmask_with_flags_ret_uint64(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
10823 const int hf_hdr, const gint ett, const int **fields, const guint encoding, const int flags,
10826 proto_item *item = NULL;
10827 header_field_info *hf;
10831 PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
10832 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
10833 len = ftype_length(hf->type);
10834 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
10837 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
10838 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
10839 flags, FALSE, FALSE, NULL, value);
10844 /* Mask out irrelevant portions */
10845 *retval &= hf->bitmask;
10847 *retval >>= hfinfo_bitshift(hf);
10853 /* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
10854 * what data is appended to the header.
10857 proto_tree_add_bitmask_with_flags(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
10858 const int hf_hdr, const gint ett, const int **fields, const guint encoding, const int flags)
10860 proto_item *item = NULL;
10861 header_field_info *hf;
10865 PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
10866 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
10869 len = ftype_length(hf->type);
10870 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
10871 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
10872 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
10873 flags, FALSE, FALSE, NULL, value);
10879 /* Similar to proto_tree_add_bitmask(), but with a passed in value (presumably because it
10880 can't be retrieved directly from tvb) */
10882 proto_tree_add_bitmask_value(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
10883 const int hf_hdr, const gint ett, const int **fields, const guint64 value)
10885 return proto_tree_add_bitmask_value_with_flags(parent_tree, tvb, offset,
10886 hf_hdr, ett, fields, value, BMT_NO_INT|BMT_NO_TFS);
10889 /* Similar to proto_tree_add_bitmask_value(), but with control of flag values */
10890 WS_DLL_PUBLIC proto_item *
10891 proto_tree_add_bitmask_value_with_flags(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
10892 const int hf_hdr, const gint ett, const int **fields, const guint64 value, const int flags)
10894 proto_item *item = NULL;
10895 header_field_info *hf;
10898 PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
10899 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
10900 /* the proto_tree_add_uint/_uint64() calls below
10901 will fail if tvb==NULL and len!=0 */
10902 len = tvb ? ftype_length(hf->type) : 0;
10906 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len, (guint32)value);
10908 item = proto_tree_add_uint64(parent_tree, hf_hdr, tvb, offset, len, value);
10910 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
10911 flags, FALSE, FALSE, NULL, value);
10917 /* Similar to proto_tree_add_bitmask(), but with no "header" item to group all of the fields */
10919 proto_tree_add_bitmask_list(proto_tree *tree, tvbuff_t *tvb, const guint offset,
10920 const int len, const int **fields, const guint encoding)
10925 value = get_uint64_value(tree, tvb, offset, len, encoding);
10926 proto_item_add_bitmask_tree(NULL, tvb, offset, len, -1, fields,
10927 BMT_NO_APPEND, FALSE, TRUE, tree, value);
10932 proto_tree_add_bitmask_list_value(proto_tree *tree, tvbuff_t *tvb, const guint offset,
10933 const int len, const int **fields, const guint64 value)
10936 proto_item_add_bitmask_tree(NULL, tvb, offset, len, -1, fields,
10937 BMT_NO_APPEND, FALSE, TRUE, tree, value);
10942 /* The same as proto_tree_add_bitmask(), but using a caller-supplied length.
10943 * This is intended to support bitmask fields whose lengths can vary, perhaps
10944 * as the underlying standard evolves over time.
10945 * With this API there is the possibility of being called to display more or
10946 * less data than the dissector was coded to support.
10947 * In such cases, it is assumed that bitmasks are extended on the MSb end.
10948 * Thus when presented with "too much" or "too little" data, MSbits will be
10949 * ignored or MSfields sacrificed.
10951 * Only fields for which all defined bits are available are displayed.
10954 proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb,
10955 const guint offset, const guint len, const int hf_hdr,
10956 const gint ett, const int **fields, struct expert_field* exp,
10957 const guint encoding)
10959 proto_item *item = NULL;
10960 header_field_info *hf;
10961 guint decodable_len;
10962 guint decodable_offset;
10963 guint32 decodable_value;
10966 PROTO_REGISTRAR_GET_NTH(hf_hdr, hf);
10967 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
10969 decodable_offset = offset;
10970 decodable_len = MIN(len, (guint) ftype_length(hf->type));
10972 /* If we are ftype_length-limited,
10973 * make sure we decode as many LSBs as possible.
10975 if (encoding == ENC_BIG_ENDIAN) {
10976 decodable_offset += (len - decodable_len);
10980 decodable_value = get_uint_value(parent_tree, tvb, decodable_offset,
10981 decodable_len, encoding);
10983 /* The root item covers all the bytes even if we can't decode them all */
10984 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len,
10988 if (decodable_len < len) {
10989 /* Dissector likely requires updating for new protocol revision */
10990 expert_add_info_format(NULL, item, exp,
10991 "Only least-significant %d of %d bytes decoded",
10992 decodable_len, len);
10996 value = get_uint64_value(parent_tree, tvb, decodable_offset, decodable_len, encoding);
10997 proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len,
10998 ett, fields, BMT_NO_INT|BMT_NO_TFS, FALSE, FALSE, NULL, value);
11004 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
11006 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
11007 const guint offset, const guint len,
11008 const char *name, const char *fallback,
11009 const gint ett, const int **fields,
11010 const guint encoding, const int flags)
11012 proto_item *item = NULL;
11016 item = proto_tree_add_text_internal(parent_tree, tvb, offset, len, "%s", name ? name : "");
11017 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
11018 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
11019 flags, TRUE, FALSE, NULL, value) && fallback) {
11020 /* Still at first item - append 'fallback' text if any */
11021 proto_item_append_text(item, "%s", fallback);
11029 proto_tree_add_bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
11030 const guint bit_offset, const gint no_of_bits,
11031 const guint encoding)
11033 header_field_info *hfinfo;
11037 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
11039 octet_length = (no_of_bits + 7) >> 3;
11040 octet_offset = bit_offset >> 3;
11041 test_length(hfinfo, tvb, octet_offset, octet_length, encoding);
11043 /* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
11044 * but only after doing a bunch more work (which we can, in the common
11045 * case, shortcut here).
11047 CHECK_FOR_NULL_TREE(tree);
11048 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
11050 return proto_tree_add_bits_ret_val(tree, hfindex, tvb, bit_offset, no_of_bits, NULL, encoding);
11054 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
11055 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
11056 * Offset should be given in bits from the start of the tvb.
11059 static proto_item *
11060 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
11061 const guint bit_offset, const gint no_of_bits,
11062 guint64 *return_value, const guint encoding)
11066 guint8 tot_no_bits;
11068 char lbl_str[ITEM_LABEL_LENGTH];
11072 header_field_info *hf_field;
11074 const true_false_string *tfstring;
11076 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
11077 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
11079 if (hf_field->bitmask != 0) {
11080 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
11081 "Incompatible use of proto_tree_add_bits_ret_val"
11082 " with field '%s' (%s) with bitmask != 0",
11083 hf_field->abbrev, hf_field->name));
11086 DISSECTOR_ASSERT(no_of_bits > 0);
11088 /* Byte align offset */
11089 offset = bit_offset>>3;
11092 * Calculate the number of octets used to hold the bits
11094 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
11095 length = (tot_no_bits + 7) >> 3;
11097 if (no_of_bits < 65) {
11098 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
11100 DISSECTOR_ASSERT_NOT_REACHED();
11104 /* Sign extend for signed types */
11105 switch (hf_field->type) {
11114 value = ws_sign_ext64(value, no_of_bits);
11121 if (return_value) {
11122 *return_value = value;
11125 /* Coast clear. Try and fake it */
11126 CHECK_FOR_NULL_TREE(tree);
11127 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11129 bf_str = decode_bits_in_field(bit_offset, no_of_bits, value);
11131 switch (hf_field->type) {
11133 /* Boolean field */
11134 tfstring = (const true_false_string *) &tfs_true_false;
11135 if (hf_field->strings)
11136 tfstring = (const true_false_string *)hf_field->strings;
11137 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, (guint32)value,
11139 bf_str, hf_field->name,
11140 (guint64)value ? tfstring->true_string : tfstring->false_string);
11144 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
11145 fill_label_char(PITEM_FINFO(pi), lbl_str);
11152 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
11153 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
11160 pi = proto_tree_add_int(tree, hfindex, tvb, offset, length, (gint32)value);
11161 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
11168 pi = proto_tree_add_uint64(tree, hfindex, tvb, offset, length, value);
11169 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
11176 pi = proto_tree_add_int64(tree, hfindex, tvb, offset, length, (gint64)value);
11177 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
11181 DISSECTOR_ASSERT_NOT_REACHED();
11186 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
11191 proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
11192 const guint bit_offset, const crumb_spec_t *crumb_spec,
11193 guint64 *return_value)
11198 guint mask_initial_bit_offset;
11199 guint mask_greatest_bit_offset;
11200 guint octet_length;
11203 char lbl_str[ITEM_LABEL_LENGTH];
11205 guint64 composite_bitmask;
11206 guint64 composite_bitmap;
11208 header_field_info *hf_field;
11209 const true_false_string *tfstring;
11211 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
11212 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
11214 if (hf_field->bitmask != 0) {
11215 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
11216 "Incompatible use of proto_tree_add_split_bits_item_ret_val"
11217 " with field '%s' (%s) with bitmask != 0",
11218 hf_field->abbrev, hf_field->name));
11221 mask_initial_bit_offset = bit_offset % 8;
11226 mask_greatest_bit_offset = 0;
11227 composite_bitmask = 0;
11228 composite_bitmap = 0;
11230 while (crumb_spec[i].crumb_bit_length != 0) {
11231 guint64 crumb_mask, crumb_value;
11232 guint8 crumb_end_bit_offset;
11234 DISSECTOR_ASSERT(i < 64);
11235 crumb_value = tvb_get_bits64(tvb,
11236 bit_offset + crumb_spec[i].crumb_bit_offset,
11237 crumb_spec[i].crumb_bit_length,
11239 value += crumb_value;
11240 no_of_bits += crumb_spec[i].crumb_bit_length;
11242 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
11243 octet containing the initial offset.
11244 If the mask is beyond 32 bits, then give up on bit map display.
11245 This could be improved in future, probably showing a table
11246 of 32 or 64 bits per row */
11247 if (mask_greatest_bit_offset < 32) {
11248 crumb_end_bit_offset = mask_initial_bit_offset
11249 + crumb_spec[i].crumb_bit_offset
11250 + crumb_spec[i].crumb_bit_length;
11251 crumb_mask = (G_GUINT64_CONSTANT(1) << crumb_spec[i].crumb_bit_length) - 1;
11253 if (crumb_end_bit_offset > mask_greatest_bit_offset) {
11254 mask_greatest_bit_offset = crumb_end_bit_offset;
11256 composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset));
11257 composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset));
11259 /* Shift left for the next segment */
11260 value <<= crumb_spec[++i].crumb_bit_length;
11263 /* Sign extend for signed types */
11264 switch (hf_field->type) {
11273 value = ws_sign_ext64(value, no_of_bits);
11279 if (return_value) {
11280 *return_value = value;
11283 /* Coast clear. Try and fake it */
11284 CHECK_FOR_NULL_TREE(tree);
11285 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11287 /* initialise the format string */
11290 octet_offset = bit_offset >> 3;
11292 /* Round up mask length to nearest octet */
11293 octet_length = ((mask_greatest_bit_offset + 7) >> 3);
11294 mask_greatest_bit_offset = octet_length << 3;
11296 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
11297 It would be a useful enhancement to eliminate this restriction. */
11298 if (mask_greatest_bit_offset > 0 && mask_greatest_bit_offset <= 32) {
11299 other_decode_bitfield_value(bf_str,
11300 (guint32)(composite_bitmap >> (64 - mask_greatest_bit_offset)),
11301 (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
11302 mask_greatest_bit_offset);
11305 switch (hf_field->type) {
11306 case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
11307 /* Boolean field */
11308 tfstring = (const true_false_string *) &tfs_true_false;
11309 if (hf_field->strings)
11310 tfstring = (const true_false_string *) hf_field->strings;
11311 return proto_tree_add_boolean_format(tree, hfindex,
11312 tvb, octet_offset, octet_length, (guint32)value,
11314 bf_str, hf_field->name,
11315 (guint64)value ? tfstring->true_string : tfstring->false_string);
11319 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
11320 fill_label_char(PITEM_FINFO(pi), lbl_str);
11327 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
11328 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
11335 pi = proto_tree_add_int(tree, hfindex, tvb, octet_offset, octet_length, (gint32)value);
11336 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
11343 pi = proto_tree_add_uint64(tree, hfindex, tvb, octet_offset, octet_length, value);
11344 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
11351 pi = proto_tree_add_int64(tree, hfindex, tvb, octet_offset, octet_length, (gint64)value);
11352 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
11356 DISSECTOR_ASSERT_NOT_REACHED();
11360 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
11365 proto_tree_add_split_bits_crumb(proto_tree *tree, const int hfindex, tvbuff_t *tvb, const guint bit_offset,
11366 const crumb_spec_t *crumb_spec, guint16 crumb_index)
11368 header_field_info *hfinfo;
11370 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
11371 proto_tree_add_text_internal(tree, tvb,
11373 ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1,
11374 "%s crumb %d of %s (decoded above)",
11375 decode_bits_in_field(bit_offset, crumb_spec[crumb_index].crumb_bit_length,
11378 crumb_spec[crumb_index].crumb_bit_length,
11385 proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
11386 const guint bit_offset, const gint no_of_bits,
11387 guint64 *return_value, const guint encoding)
11391 if ((item = _proto_tree_add_bits_ret_val(tree, hfindex, tvb,
11392 bit_offset, no_of_bits,
11393 return_value, encoding))) {
11394 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
11395 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
11400 static proto_item *
11401 _proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
11402 tvbuff_t *tvb, const guint bit_offset,
11403 const gint no_of_bits, void *value_ptr,
11408 guint8 tot_no_bits;
11411 header_field_info *hf_field;
11413 /* We do not have to return a value, try to fake it as soon as possible */
11414 CHECK_FOR_NULL_TREE(tree);
11415 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11417 if (hf_field->bitmask != 0) {
11418 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
11419 "Incompatible use of proto_tree_add_bits_format_value"
11420 " with field '%s' (%s) with bitmask != 0",
11421 hf_field->abbrev, hf_field->name));
11424 DISSECTOR_ASSERT(no_of_bits > 0);
11426 /* Byte align offset */
11427 offset = bit_offset>>3;
11430 * Calculate the number of octets used to hold the bits
11432 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
11433 length = tot_no_bits>>3;
11434 /* If we are using part of the next octet, increase length by 1 */
11435 if (tot_no_bits & 0x07)
11438 if (no_of_bits < 65) {
11439 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
11441 DISSECTOR_ASSERT_NOT_REACHED();
11445 str = decode_bits_in_field(bit_offset, no_of_bits, value);
11447 g_strlcat(str, " = ", 256+64);
11448 g_strlcat(str, hf_field->name, 256+64);
11451 * This function does not receive an actual value but a dimensionless pointer to that value.
11452 * For this reason, the type of the header field is examined in order to determine
11453 * what kind of value we should read from this address.
11454 * The caller of this function must make sure that for the specific header field type the address of
11455 * a compatible value is provided.
11457 switch (hf_field->type) {
11459 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
11460 "%s: %s", str, value_str);
11468 return proto_tree_add_uint_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
11469 "%s: %s", str, value_str);
11476 return proto_tree_add_uint64_format(tree, hfindex, tvb, offset, length, *(guint64 *)value_ptr,
11477 "%s: %s", str, value_str);
11484 return proto_tree_add_int_format(tree, hfindex, tvb, offset, length, *(gint32 *)value_ptr,
11485 "%s: %s", str, value_str);
11492 return proto_tree_add_int64_format(tree, hfindex, tvb, offset, length, *(gint64 *)value_ptr,
11493 "%s: %s", str, value_str);
11497 return proto_tree_add_float_format(tree, hfindex, tvb, offset, length, *(float *)value_ptr,
11498 "%s: %s", str, value_str);
11502 DISSECTOR_ASSERT_NOT_REACHED();
11508 static proto_item *
11509 proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
11510 tvbuff_t *tvb, const guint bit_offset,
11511 const gint no_of_bits, void *value_ptr,
11516 if ((item = _proto_tree_add_bits_format_value(tree, hfindex,
11517 tvb, bit_offset, no_of_bits,
11518 value_ptr, value_str))) {
11519 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
11520 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
11525 #define CREATE_VALUE_STRING(dst,format,ap) \
11526 va_start(ap, format); \
11527 dst = wmem_strdup_vprintf(wmem_packet_scope(), format, ap); \
11531 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hfindex,
11532 tvbuff_t *tvb, const guint bit_offset,
11533 const gint no_of_bits, guint32 value,
11534 const char *format, ...)
11538 header_field_info *hf_field;
11540 CHECK_FOR_NULL_TREE(tree);
11542 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11544 switch (hf_field->type) {
11552 DISSECTOR_ASSERT_NOT_REACHED();
11557 CREATE_VALUE_STRING(dst, format, ap);
11559 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11563 proto_tree_add_uint64_bits_format_value(proto_tree *tree, const int hfindex,
11564 tvbuff_t *tvb, const guint bit_offset,
11565 const gint no_of_bits, guint64 value,
11566 const char *format, ...)
11570 header_field_info *hf_field;
11572 CHECK_FOR_NULL_TREE(tree);
11574 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11576 switch (hf_field->type) {
11584 DISSECTOR_ASSERT_NOT_REACHED();
11589 CREATE_VALUE_STRING(dst, format, ap);
11591 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11595 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hfindex,
11596 tvbuff_t *tvb, const guint bit_offset,
11597 const gint no_of_bits, float value,
11598 const char *format, ...)
11602 header_field_info *hf_field;
11604 CHECK_FOR_NULL_TREE(tree);
11606 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11608 DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_FLOAT);
11610 CREATE_VALUE_STRING(dst, format, ap);
11612 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11616 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hfindex,
11617 tvbuff_t *tvb, const guint bit_offset,
11618 const gint no_of_bits, gint32 value,
11619 const char *format, ...)
11623 header_field_info *hf_field;
11625 CHECK_FOR_NULL_TREE(tree);
11627 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11629 switch (hf_field->type) {
11637 DISSECTOR_ASSERT_NOT_REACHED();
11642 CREATE_VALUE_STRING(dst, format, ap);
11644 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11648 proto_tree_add_int64_bits_format_value(proto_tree *tree, const int hfindex,
11649 tvbuff_t *tvb, const guint bit_offset,
11650 const gint no_of_bits, gint64 value,
11651 const char *format, ...)
11655 header_field_info *hf_field;
11657 CHECK_FOR_NULL_TREE(tree);
11659 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11661 switch (hf_field->type) {
11669 DISSECTOR_ASSERT_NOT_REACHED();
11674 CREATE_VALUE_STRING(dst, format, ap);
11676 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11680 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hfindex,
11681 tvbuff_t *tvb, const guint bit_offset,
11682 const gint no_of_bits, guint32 value,
11683 const char *format, ...)
11687 header_field_info *hf_field;
11689 CHECK_FOR_NULL_TREE(tree);
11691 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11693 DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_BOOLEAN);
11695 CREATE_VALUE_STRING(dst, format, ap);
11697 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11701 proto_tree_add_boolean_bits_format_value64(proto_tree *tree, const int hfindex,
11702 tvbuff_t *tvb, const guint bit_offset,
11703 const gint no_of_bits, guint64 value,
11704 const char *format, ...)
11708 header_field_info *hf_field;
11710 CHECK_FOR_NULL_TREE(tree);
11712 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11714 DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_BOOLEAN);
11716 CREATE_VALUE_STRING(dst, format, ap);
11718 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11722 proto_tree_add_ts_23_038_7bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
11723 const guint bit_offset, const gint no_of_chars)
11726 header_field_info *hfinfo;
11731 CHECK_FOR_NULL_TREE(tree);
11733 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
11735 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_STRING);
11737 byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3;
11738 byte_offset = bit_offset >> 3;
11740 string = tvb_get_ts_23_038_7bits_string(wmem_packet_scope(), tvb, bit_offset, no_of_chars);
11742 if (hfinfo->display == STR_UNICODE) {
11743 DISSECTOR_ASSERT(g_utf8_validate(string, -1, NULL));
11746 pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length);
11747 DISSECTOR_ASSERT(byte_length >= 0);
11748 proto_tree_set_string(PNODE_FINFO(pi), string);
11754 proto_tree_add_ascii_7bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
11755 const guint bit_offset, const gint no_of_chars)
11758 header_field_info *hfinfo;
11763 CHECK_FOR_NULL_TREE(tree);
11765 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
11767 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_STRING);
11769 byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3;
11770 byte_offset = bit_offset >> 3;
11772 string = tvb_get_ascii_7bits_string(wmem_packet_scope(), tvb, bit_offset, no_of_chars);
11774 if (hfinfo->display == STR_UNICODE) {
11775 DISSECTOR_ASSERT(g_utf8_validate(string, -1, NULL));
11778 pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length);
11779 DISSECTOR_ASSERT(byte_length >= 0);
11780 proto_tree_set_string(PNODE_FINFO(pi), string);
11785 const value_string proto_checksum_vals[] = {
11786 { PROTO_CHECKSUM_E_BAD, "Bad" },
11787 { PROTO_CHECKSUM_E_GOOD, "Good" },
11788 { PROTO_CHECKSUM_E_UNVERIFIED, "Unverified" },
11789 { PROTO_CHECKSUM_E_NOT_PRESENT, "Not present" },
11795 proto_tree_add_checksum(proto_tree *tree, tvbuff_t *tvb, const guint offset,
11796 const int hf_checksum, const int hf_checksum_status, struct expert_field* bad_checksum_expert,
11797 packet_info *pinfo, guint32 computed_checksum, const guint encoding, const guint flags)
11799 header_field_info *hfinfo = proto_registrar_get_nth(hf_checksum);
11802 proto_item* ti = NULL;
11804 gboolean incorrect_checksum = TRUE;
11806 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
11808 if (flags & PROTO_CHECKSUM_NOT_PRESENT) {
11809 ti = proto_tree_add_uint_format_value(tree, hf_checksum, tvb, offset, 0, 0, "[missing]");
11810 PROTO_ITEM_SET_GENERATED(ti);
11811 if (hf_checksum_status != -1) {
11812 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_NOT_PRESENT);
11813 PROTO_ITEM_SET_GENERATED(ti2);
11818 switch (hfinfo->type){
11832 DISSECTOR_ASSERT_NOT_REACHED();
11835 if (flags & PROTO_CHECKSUM_GENERATED) {
11836 ti = proto_tree_add_uint(tree, hf_checksum, tvb, offset, 0, computed_checksum);
11837 PROTO_ITEM_SET_GENERATED(ti);
11839 ti = proto_tree_add_item_ret_uint(tree, hf_checksum, tvb, offset, len, encoding, &checksum);
11840 if (flags & PROTO_CHECKSUM_VERIFY) {
11841 if (flags & (PROTO_CHECKSUM_IN_CKSUM|PROTO_CHECKSUM_ZERO)) {
11842 if (computed_checksum == 0) {
11843 proto_item_append_text(ti, " [correct]");
11844 if (hf_checksum_status != -1) {
11845 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
11846 PROTO_ITEM_SET_GENERATED(ti2);
11848 incorrect_checksum = FALSE;
11849 } else if (flags & PROTO_CHECKSUM_IN_CKSUM) {
11850 computed_checksum = in_cksum_shouldbe(checksum, computed_checksum);
11853 if (checksum == computed_checksum) {
11854 proto_item_append_text(ti, " [correct]");
11855 if (hf_checksum_status != -1) {
11856 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
11857 PROTO_ITEM_SET_GENERATED(ti2);
11859 incorrect_checksum = FALSE;
11863 if (incorrect_checksum) {
11864 if (hf_checksum_status != -1) {
11865 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_BAD);
11866 PROTO_ITEM_SET_GENERATED(ti2);
11868 if (flags & PROTO_CHECKSUM_ZERO) {
11869 proto_item_append_text(ti, " [incorrect]");
11870 if (bad_checksum_expert != NULL)
11871 expert_add_info_format(pinfo, ti, bad_checksum_expert, "Bad checksum");
11873 proto_item_append_text(ti, " incorrect, should be 0x%0*x", len*2, computed_checksum);
11874 if (bad_checksum_expert != NULL)
11875 expert_add_info_format(pinfo, ti, bad_checksum_expert, "Bad checksum [should be 0x%0*x]", len*2, computed_checksum);
11879 if (hf_checksum_status != -1) {
11880 proto_item_append_text(ti, " [unverified]");
11881 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_UNVERIFIED);
11882 PROTO_ITEM_SET_GENERATED(ti2);
11891 proto_check_field_name(const gchar *field_name)
11893 return wrs_check_charset(fld_abbrev_chars, field_name);
11897 tree_expanded(int tree_type)
11899 g_assert(tree_type >= 0 && tree_type < num_tree_types);
11900 return tree_is_expanded[tree_type >> 5] & (1U << (tree_type & 31));
11904 tree_expanded_set(int tree_type, gboolean value)
11906 g_assert(tree_type >= 0 && tree_type < num_tree_types);
11909 tree_is_expanded[tree_type >> 5] |= (1U << (tree_type & 31));
11911 tree_is_expanded[tree_type >> 5] &= ~(1U << (tree_type & 31));
11915 * Editor modelines - http://www.wireshark.org/tools/modelines.html
11918 * c-basic-offset: 8
11920 * indent-tabs-mode: t
11923 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
11924 * :indentSize=8:tabSize=8:noTabs=false: