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_char(field_info *fi, gchar *label_str);
193 static void fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed);
194 static void fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed);
196 static const char *hfinfo_char_value_format_display(int display, char buf[7], guint32 value);
197 static const char *hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value);
198 static const char *hfinfo_number_value_format_display64(const header_field_info *hfinfo, int display, char buf[48], guint64 value);
199 static const char *hfinfo_char_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
200 static const char *hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
201 static const char *hfinfo_number_vals_format64(const header_field_info *hfinfo, char buf[48], guint64 value);
202 static const char *hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
203 static const char *hfinfo_number_value_format64(const header_field_info *hfinfo, char buf[48], guint64 value);
204 static const char *hfinfo_char_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
205 static const char *hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
206 static const char *hfinfo_numeric_value_format64(const header_field_info *hfinfo, char buf[48], guint64 value);
208 static void proto_cleanup_base(void);
211 proto_tree_add_node(proto_tree *tree, field_info *fi);
214 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
218 get_full_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
219 gint length, guint item_length, const gint encoding);
222 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
223 const gint start, const gint item_length);
226 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
227 gint start, gint *length);
230 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
232 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
235 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb, const char* field_data);
237 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
239 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
241 proto_tree_set_bytes_gbytearray(field_info *fi, const GByteArray *value);
243 proto_tree_set_time(field_info *fi, const nstime_t *value_ptr);
245 proto_tree_set_string(field_info *fi, const char* value);
247 proto_tree_set_ax25(field_info *fi, const guint8* value);
249 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start);
251 proto_tree_set_vines(field_info *fi, const guint8* value);
253 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start);
255 proto_tree_set_ether(field_info *fi, const guint8* value);
257 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
259 proto_tree_set_ipxnet(field_info *fi, guint32 value);
261 proto_tree_set_ipv4(field_info *fi, guint32 value);
263 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
265 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
267 proto_tree_set_fcwwn_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
269 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
271 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
273 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
275 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
277 proto_tree_set_system_id(field_info *fi, const guint8* value_ptr, gint length);
279 proto_tree_set_system_id_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
281 proto_tree_set_boolean(field_info *fi, guint64 value);
283 proto_tree_set_float(field_info *fi, float value);
285 proto_tree_set_double(field_info *fi, double value);
287 proto_tree_set_uint(field_info *fi, guint32 value);
289 proto_tree_set_int(field_info *fi, gint32 value);
291 proto_tree_set_uint64(field_info *fi, guint64 value);
293 proto_tree_set_int64(field_info *fi, gint64 value);
295 proto_tree_set_eui64(field_info *fi, const guint64 value);
297 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
299 /* Handle type length mismatch (now filterable) expert info */
300 static int proto_type_length_mismatch = -1;
301 static expert_field ei_type_length_mismatch_error = EI_INIT;
302 static expert_field ei_type_length_mismatch_warn = EI_INIT;
303 static void register_type_length_mismatch(void);
305 /* Handle number string decoding errors with expert info */
306 static int proto_number_string_decoding_error = -1;
307 static expert_field ei_number_string_decoding_failed_error = EI_INIT;
308 static expert_field ei_number_string_decoding_erange_error = EI_INIT;
309 static void register_number_string_decoding_error(void);
311 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
313 /* special-case header field used within proto.c */
314 static header_field_info hfi_text_only =
315 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
316 int hf_text_only = -1;
318 /* Structure for information about a protocol */
320 const char *name; /* long description */
321 const char *short_name; /* short description */
322 const char *filter_name; /* name of this protocol in filters */
323 GPtrArray *fields; /* fields for this protocol */
324 int proto_id; /* field ID for this protocol */
325 gboolean is_enabled; /* TRUE if protocol is enabled */
326 gboolean enabled_by_default; /* TRUE if protocol is enabled by default */
327 gboolean can_toggle; /* TRUE if is_enabled can be changed */
328 int parent_proto_id; /* Used to identify "pino"s (Protocol In Name Only).
329 For dissectors that need a protocol name so they
330 can be added to a dissector table, but use the
331 parent_proto_id for things like enable/disable */
332 GList *heur_list; /* Heuristic dissectors associated with this protocol */
335 /* List of all protocols */
336 static GList *protocols = NULL;
337 static GList *pino_protocols = NULL;
339 /* Deregistered fields */
340 static GPtrArray *deregistered_fields = NULL;
341 static GPtrArray *deregistered_data = NULL;
343 /* indexed by prefix, contains initializers */
344 static GHashTable* prefixes = NULL;
346 /* Contains information about a field when a dissector calls
347 * proto_tree_add_item. */
348 #define FIELD_INFO_NEW(pool, fi) fi = wmem_new(pool, field_info)
349 #define FIELD_INFO_FREE(pool, fi) wmem_free(pool, fi)
351 /* Contains the space for proto_nodes. */
352 #define PROTO_NODE_INIT(node) \
353 node->first_child = NULL; \
354 node->last_child = NULL; \
357 #define PROTO_NODE_FREE(pool, node) \
358 wmem_free(pool, node)
360 /* String space for protocol and field items for the GUI */
361 #define ITEM_LABEL_NEW(pool, il) \
362 il = wmem_new(pool, item_label_t);
363 #define ITEM_LABEL_FREE(pool, il) \
366 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
367 if((guint)hfindex >= gpa_hfinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG")) \
368 g_error("Unregistered hf! index=%d", hfindex); \
369 DISSECTOR_ASSERT_HINT((guint)hfindex < gpa_hfinfo.len, "Unregistered hf!"); \
370 DISSECTOR_ASSERT_HINT(gpa_hfinfo.hfi[hfindex] != NULL, "Unregistered hf!"); \
371 hfinfo = gpa_hfinfo.hfi[hfindex];
373 /* List which stores protocols and fields that have been registered */
374 typedef struct _gpa_hfinfo_t {
376 guint32 allocated_len;
377 header_field_info **hfi;
380 static gpa_hfinfo_t gpa_hfinfo;
382 /* Hash table of abbreviations and IDs */
383 static GHashTable *gpa_name_map = NULL;
384 static header_field_info *same_name_hfinfo;
386 * We're called repeatedly with the same field name when sorting a column.
387 * Cache our last gpa_name_map hit for faster lookups.
389 static char *last_field_name = NULL;
390 static header_field_info *last_hfinfo;
392 static void save_same_name_hfinfo(gpointer data)
394 same_name_hfinfo = (header_field_info*)data;
397 /* Cached value for VINES address type (used for FT_VINES) */
398 static int vines_address_type = -1;
400 /* Points to the first element of an array of bits, indexed by
401 a subtree item type; that array element is TRUE if subtrees of
402 an item of that type are to be expanded. */
403 static guint32 *tree_is_expanded;
405 /* Number of elements in that array. */
408 /* Name hashtables for fast detection of duplicate names */
409 static GHashTable* proto_names = NULL;
410 static GHashTable* proto_short_names = NULL;
411 static GHashTable* proto_filter_names = NULL;
414 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
416 const protocol_t *p1 = (const protocol_t *)p1_arg;
417 const protocol_t *p2 = (const protocol_t *)p2_arg;
419 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
424 * List of dissector plugins.
427 void (*register_protoinfo)(void); /* routine to call to register protocol information */
428 void (*reg_handoff)(void); /* routine to call to register dissector handoff */
431 static GSList *dissector_plugins = NULL;
434 * Callback for each plugin found.
437 check_for_dissector_plugin(GModule *handle)
440 void (*register_protoinfo)(void);
441 void (*reg_handoff)(void);
442 dissector_plugin *plugin;
445 * Do we have a register routine?
447 if (g_module_symbol(handle, "plugin_register", &gp)) {
449 register_protoinfo = (void (*)(void))gp;
453 register_protoinfo = NULL;
457 * Do we have a reg_handoff routine?
459 if (g_module_symbol(handle, "plugin_reg_handoff", &gp)) {
461 reg_handoff = (void (*)(void))gp;
469 * If we have neither, we're not a dissector plugin.
471 if (register_protoinfo == NULL && reg_handoff == NULL)
475 * Add this one to the list of dissector plugins.
477 plugin = (dissector_plugin *)g_malloc(sizeof (dissector_plugin));
478 plugin->register_protoinfo = register_protoinfo;
479 plugin->reg_handoff = reg_handoff;
480 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 /* If we're fetching until the end of the TVB, only validate
1245 * that the offset is within range.
1249 tvb_ensure_bytes_exist(tvb, start, length);
1251 CHECK_FOR_NULL_TREE(tree);
1253 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1255 pi = proto_tree_add_text_node(tree, tvb, start, length);
1257 TRY_TO_FAKE_THIS_REPR(pi);
1259 va_start(ap, format);
1260 proto_tree_set_representation(pi, format, ap);
1266 /* (INTERNAL USE ONLY) Add a text-only node to the proto_tree (va_list version) */
1268 proto_tree_add_text_valist_internal(proto_tree *tree, tvbuff_t *tvb, gint start,
1269 gint length, const char *format, va_list ap)
1272 header_field_info *hfinfo;
1275 /* If we're fetching until the end of the TVB, only validate
1276 * that the offset is within range.
1280 tvb_ensure_bytes_exist(tvb, start, length);
1282 CHECK_FOR_NULL_TREE(tree);
1284 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1286 pi = proto_tree_add_text_node(tree, tvb, start, length);
1288 TRY_TO_FAKE_THIS_REPR(pi);
1290 proto_tree_set_representation(pi, format, ap);
1295 /* Add a text-only node that creates a subtree underneath.
1298 proto_tree_add_subtree(proto_tree *tree, tvbuff_t *tvb, gint start, gint length, gint idx, proto_item **tree_item, const char *text)
1300 return proto_tree_add_subtree_format(tree, tvb, start, length, idx, tree_item, "%s", text);
1303 /* Add a text-only node that creates a subtree underneath.
1306 proto_tree_add_subtree_format(proto_tree *tree, tvbuff_t *tvb, gint start, gint length, gint idx, proto_item **tree_item, const char *format, ...)
1312 va_start(ap, format);
1313 pi = proto_tree_add_text_valist_internal(tree, tvb, start, length, format, ap);
1316 if (tree_item != NULL)
1319 pt = proto_item_add_subtree(pi, idx);
1324 /* Add a text-only node for debugging purposes. The caller doesn't need
1325 * to worry about tvbuff, start, or length. Debug message gets sent to
1328 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1333 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1336 va_start(ap, format);
1337 proto_tree_set_representation(pi, format, ap);
1340 va_start(ap, format);
1341 vprintf(format, ap);
1343 ws_debug_printf("\n");
1349 proto_tree_add_format_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1352 header_field_info *hfinfo;
1354 CHECK_FOR_NULL_TREE(tree);
1356 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1358 pi = proto_tree_add_text_node(tree, tvb, start, length);
1360 TRY_TO_FAKE_THIS_REPR(pi);
1362 proto_item_set_text(pi, "%s", tvb_format_text(tvb, start, length));
1368 proto_tree_add_format_wsp_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1371 header_field_info *hfinfo;
1374 CHECK_FOR_NULL_TREE(tree);
1376 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1378 pi = proto_tree_add_text_node(tree, tvb, start, length);
1380 TRY_TO_FAKE_THIS_REPR(pi);
1382 str = tvb_format_text_wsp(NULL, tvb, start, length);
1383 proto_item_set_text(pi, "%s", str);
1384 wmem_free(NULL, str);
1389 void proto_report_dissector_bug(const char *message)
1391 if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
1394 THROW_MESSAGE(DissectorError, message);
1397 /* We could probably get away with changing is_error to a minimum length value. */
1399 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
1402 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_error, "Trying to fetch %s with length %d", descr, length);
1404 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_warn, "Trying to fetch %s with length %d", descr, length);
1408 THROW(ReportedBoundsError);
1413 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1416 gboolean length_error;
1421 value = tvb_get_guint8(tvb, offset);
1425 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1426 : tvb_get_ntohs(tvb, offset);
1430 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1431 : tvb_get_ntoh24(tvb, offset);
1435 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1436 : tvb_get_ntohl(tvb, offset);
1441 length_error = TRUE;
1444 length_error = FALSE;
1445 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1446 : tvb_get_ntohl(tvb, offset);
1448 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1454 static inline guint64
1455 get_uint64_value(proto_tree *tree, tvbuff_t *tvb, gint offset, guint length, const guint encoding)
1458 gboolean length_error;
1463 value = tvb_get_guint8(tvb, offset);
1467 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1468 : tvb_get_ntohs(tvb, offset);
1472 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1473 : tvb_get_ntoh24(tvb, offset);
1477 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1478 : tvb_get_ntohl(tvb, offset);
1482 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh40(tvb, offset)
1483 : tvb_get_ntoh40(tvb, offset);
1487 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh48(tvb, offset)
1488 : tvb_get_ntoh48(tvb, offset);
1492 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh56(tvb, offset)
1493 : tvb_get_ntoh56(tvb, offset);
1497 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh64(tvb, offset)
1498 : tvb_get_ntoh64(tvb, offset);
1503 length_error = TRUE;
1506 length_error = FALSE;
1507 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh64(tvb, offset)
1508 : tvb_get_ntoh64(tvb, offset);
1510 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1517 get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1520 gboolean length_error;
1525 value = (gint8)tvb_get_guint8(tvb, offset);
1529 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1530 : tvb_get_ntohs(tvb, offset));
1534 value = encoding ? tvb_get_letoh24(tvb, offset)
1535 : tvb_get_ntoh24(tvb, offset);
1536 if (value & 0x00800000) {
1537 /* Sign bit is set; sign-extend it. */
1538 value |= 0xFF000000;
1543 value = encoding ? tvb_get_letohl(tvb, offset)
1544 : tvb_get_ntohl(tvb, offset);
1549 length_error = TRUE;
1552 length_error = FALSE;
1553 value = encoding ? tvb_get_letohl(tvb, offset)
1554 : tvb_get_ntohl(tvb, offset);
1556 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1562 /* Note: this returns an unsigned int64, but with the appropriate bit(s) set to
1563 * be cast-able as a gint64. This is weird, but what the code has always done.
1565 static inline guint64
1566 get_int64_value(proto_tree *tree, tvbuff_t *tvb, gint start, guint length, const guint encoding)
1568 guint64 value = get_uint64_value(tree, tvb, start, length, encoding);
1573 value = ws_sign_ext64(value, 56);
1576 value = ws_sign_ext64(value, 48);
1579 value = ws_sign_ext64(value, 40);
1582 value = ws_sign_ext64(value, 32);
1585 value = ws_sign_ext64(value, 24);
1588 value = ws_sign_ext64(value, 16);
1591 value = ws_sign_ext64(value, 8);
1599 static inline const guint8 *
1600 get_string_value(wmem_allocator_t *scope, tvbuff_t *tvb, gint start,
1601 gint length, gint *ret_length, const guint encoding)
1604 length = tvb_ensure_captured_length_remaining(tvb, start);
1606 *ret_length = length;
1607 return tvb_get_string_enc(scope, tvb, start, length, encoding);
1610 /* For FT_STRINGZ */
1611 static inline const guint8 *
1612 get_stringz_value(wmem_allocator_t *scope, proto_tree *tree, tvbuff_t *tvb,
1613 gint start, gint length, gint *ret_length, const guint encoding)
1615 const guint8 *value;
1618 report_type_length_mismatch(tree, "a string", length, TRUE);
1621 /* This can throw an exception */
1622 value = tvb_get_stringz_enc(scope, tvb, start, &length, encoding);
1623 } else if (length == 0) {
1626 /* In this case, length signifies the length of the string.
1628 * This could either be a null-padded string, which doesn't
1629 * necessarily have a '\0' at the end, or a null-terminated
1630 * string, with a trailing '\0'. (Yes, there are cases
1631 * where you have a string that's both counted and null-
1634 * In the first case, we must allocate a buffer of length
1635 * "length+1", to make room for a trailing '\0'.
1637 * In the second case, we don't assume that there is a
1638 * trailing '\0' there, as the packet might be malformed.
1639 * (XXX - should we throw an exception if there's no
1640 * trailing '\0'?) Therefore, we allocate a buffer of
1641 * length "length+1", and put in a trailing '\0', just to
1644 * (XXX - this would change if we made string values counted
1645 * rather than null-terminated.)
1647 value = tvb_get_string_enc(scope, tvb, start, length, encoding);
1649 *ret_length = length;
1653 /* For FT_UINT_STRING */
1654 static inline const guint8 *
1655 get_uint_string_value(wmem_allocator_t *scope, proto_tree *tree,
1656 tvbuff_t *tvb, gint start, gint length, gint *ret_length,
1657 const guint encoding)
1660 const guint8 *value;
1662 /* I believe it's ok if this is called with a NULL tree */
1663 n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1664 value = tvb_get_string_enc(scope, tvb, start + length, n, encoding);
1666 *ret_length = length;
1670 /* For FT_STRINGZPAD */
1671 static inline const guint8 *
1672 get_stringzpad_value(wmem_allocator_t *scope, tvbuff_t *tvb, gint start,
1673 gint length, gint *ret_length, const guint encoding)
1676 * XXX - currently, string values are null-
1677 * terminated, so a "zero-padded" string
1678 * isn't special. If we represent string
1679 * values as something that includes a counted
1680 * array of bytes, we'll need to strip
1684 length = tvb_ensure_captured_length_remaining(tvb, start);
1686 *ret_length = length;
1687 return tvb_get_string_enc(scope, tvb, start, length, encoding);
1691 * Epochs for various non-UN*X time stamp formats.
1693 #define NTP_BASETIME G_GUINT64_CONSTANT(2208988800) /* NTP */
1694 #define TOD_BASETIME G_GUINT64_CONSTANT(2208988800) /* System/3x0 and z/Architecture TOD clock */
1696 /* this can be called when there is no tree, so tree may be null */
1698 get_time_value(proto_tree *tree, tvbuff_t *tvb, const gint start,
1699 const gint length, const guint encoding, nstime_t *time_stamp,
1700 const gboolean is_relative)
1707 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1709 * 4-byte seconds, followed by 4-byte fractional
1710 * time in nanoseconds, both big-endian.
1711 * For absolute times, the seconds are seconds
1712 * since the UN*X epoch.
1714 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
1716 time_stamp->nsecs = tvb_get_ntohl(tvb, start+4);
1717 else if (length == 4) {
1719 * Backwards compatibility.
1721 time_stamp->nsecs = 0;
1723 report_type_length_mismatch(tree, "a timespec", length, TRUE);
1726 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1728 * 4-byte UNIX epoch, possibly followed by
1729 * 4-byte fractional time in nanoseconds,
1730 * both little-endian.
1731 * For absolute times, the seconds are seconds
1732 * since the UN*X epoch.
1734 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
1736 time_stamp->nsecs = tvb_get_letohl(tvb, start+4);
1737 else if (length == 4) {
1739 * Backwards compatibility.
1741 time_stamp->nsecs = 0;
1743 report_type_length_mismatch(tree, "a timespec", length, TRUE);
1746 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1748 * NTP time stamp, big-endian.
1749 * Only supported for absolute times.
1751 DISSECTOR_ASSERT(!is_relative);
1753 /* We need a temporary variable here so the unsigned math
1754 * works correctly (for years > 2036 according to RFC 2030
1757 tmpsecs = tvb_get_ntohl(tvb, start);
1759 time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
1761 time_stamp->secs = tmpsecs; /* 0 */
1765 * Convert 1/2^32s of a second to nanoseconds.
1767 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1768 } else if (length == 4) {
1770 * Backwards compatibility.
1772 time_stamp->nsecs = 0;
1774 report_type_length_mismatch(tree, "an NTP time stamp", length, TRUE);
1777 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1779 * NTP time stamp, little-endian.
1780 * Only supported for absolute times.
1782 DISSECTOR_ASSERT(!is_relative);
1784 tmpsecs = tvb_get_letohl(tvb, start);
1786 time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
1788 time_stamp->secs = tmpsecs; /* 0 */
1792 * Convert 1/2^32s of a second to nanoseconds.
1794 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1795 } else if (length == 4) {
1797 * Backwards compatibility.
1799 time_stamp->nsecs = 0;
1801 report_type_length_mismatch(tree, "an NTP time stamp", length, TRUE);
1804 case ENC_TIME_TOD|ENC_BIG_ENDIAN:
1806 * S/3x0 and z/Architecture TOD clock time stamp,
1808 * Only supported for absolute times.
1810 DISSECTOR_ASSERT(!is_relative);
1811 DISSECTOR_ASSERT(length == 8);
1814 todsecs = tvb_get_ntoh64(tvb, start) >> 12;
1815 time_stamp->secs = (time_t)((todsecs / 1000000) - TOD_BASETIME);
1816 time_stamp->nsecs = (int)((todsecs % 1000000) * 1000);
1818 report_type_length_mismatch(tree, "a TOD clock time stamp", length, TRUE);
1821 case ENC_TIME_TOD|ENC_LITTLE_ENDIAN:
1823 * S/3x0 and z/Architecture TOD clock time stamp,
1825 * Only supported for absolute times.
1827 DISSECTOR_ASSERT(!is_relative);
1830 todsecs = tvb_get_letoh64(tvb, start) >> 12 ;
1831 time_stamp->secs = (time_t)((todsecs / 1000000) - TOD_BASETIME);
1832 time_stamp->nsecs = (int)((todsecs % 1000000) * 1000);
1834 report_type_length_mismatch(tree, "a TOD clock time stamp", length, TRUE);
1837 case ENC_TIME_RTPS|ENC_BIG_ENDIAN:
1839 * Time stamp using the same seconds/fraction format
1840 * as NTP, but with the origin of the time stamp being
1841 * the UNIX epoch rather than the NTP epoch; big-
1844 * Only supported for absolute times.
1846 DISSECTOR_ASSERT(!is_relative);
1849 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
1851 * Convert 1/2^32s of a second to nanoseconds.
1853 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1855 report_type_length_mismatch(tree, "an RTPS time stamp", length, TRUE);
1858 case ENC_TIME_RTPS|ENC_LITTLE_ENDIAN:
1860 * Time stamp using the same seconds/fraction format
1861 * as NTP, but with the origin of the time stamp being
1862 * the UNIX epoch rather than the NTP epoch; little-
1865 * Only supported for absolute times.
1867 DISSECTOR_ASSERT(!is_relative);
1870 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
1872 * Convert 1/2^32s of a second to nanoseconds.
1874 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1876 report_type_length_mismatch(tree, "an RTPS time stamp", length, TRUE);
1879 case ENC_TIME_TIMEVAL|ENC_BIG_ENDIAN:
1881 * 4-byte seconds, followed by 4-byte fractional
1882 * time in microseconds, both big-endian.
1883 * For absolute times, the seconds are seconds
1884 * since the UN*X epoch.
1887 time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start);
1888 time_stamp->nsecs = tvb_get_ntohl(tvb, start+4)*1000;
1890 report_type_length_mismatch(tree, "a timeval", length, TRUE);
1893 case ENC_TIME_TIMEVAL|ENC_LITTLE_ENDIAN:
1895 * 4-byte seconds, followed by 4-byte fractional
1896 * time in microseconds, both little-endian.
1897 * For absolute times, the seconds are seconds
1898 * since the UN*X epoch.
1901 time_stamp->secs = (time_t)tvb_get_letohl(tvb, start);
1902 time_stamp->nsecs = tvb_get_letohl(tvb, start+4)*1000;
1904 report_type_length_mismatch(tree, "a timeval", length, TRUE);
1907 case ENC_TIME_SECS|ENC_BIG_ENDIAN:
1908 case ENC_TIME_SECS|ENC_LITTLE_ENDIAN:
1910 * Seconds, 1 to 8 bytes.
1911 * For absolute times, it's seconds since the
1914 if (length >= 1 && length <= 8) {
1915 time_stamp->secs = (time_t)get_uint64_value(tree, tvb, start, length, encoding);
1916 time_stamp->nsecs = 0;
1918 report_type_length_mismatch(tree, "a time-in-seconds time stamp", length, TRUE);
1921 case ENC_TIME_MSECS|ENC_BIG_ENDIAN:
1923 * Milliseconds, 1 to 8 bytes.
1924 * For absolute times, it's milliseconds since the
1927 if (length >= 1 && length <= 8) {
1930 msecs = get_uint64_value(tree, tvb, start, length, encoding);
1931 time_stamp->secs = (time_t)(msecs / 1000);
1932 time_stamp->nsecs = (int)(msecs % 1000)*1000000;
1934 report_type_length_mismatch(tree, "a time-in-milliseconds time stamp", length, TRUE);
1937 case ENC_TIME_RFC_3971|ENC_BIG_ENDIAN:
1939 * 1/64ths of a second since the UN*X epoch,
1942 * Only supported for absolute times.
1944 DISSECTOR_ASSERT(!is_relative);
1948 * The upper 48 bits are seconds since the
1951 time_stamp->secs = tvb_get_ntoh48(tvb, start);
1953 * The lower 16 bits are 1/2^16s of a second;
1954 * convert them to nanoseconds.
1956 * XXX - this may give the impression of higher
1957 * precision than you actually get.
1959 time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohs(tvb, start+6)/65536.0));
1961 report_type_length_mismatch(tree, "an RFC 3971-style time stamp", length, TRUE);
1964 case ENC_TIME_RFC_3971|ENC_LITTLE_ENDIAN:
1966 * 1/64ths of a second since the UN*X epoch,
1969 * Only supported for absolute times.
1971 DISSECTOR_ASSERT(!is_relative);
1975 * XXX - this is assuming that, if anybody
1976 * were ever to use this format - RFC 3971
1977 * doesn't, because that's an Internet
1978 * protocol, and those use network byte
1979 * order, i.e. big-endian - they'd treat it
1980 * as a 64-bit count of 1/2^16s of a second,
1981 * putting the upper 48 bits at the end.
1983 * The lower 48 bits are seconds since the
1986 time_stamp->secs = tvb_get_letoh48(tvb, start+2);
1988 * The upper 16 bits are 1/2^16s of a second;
1989 * convert them to nanoseconds.
1991 * XXX - this may give the impression of higher
1992 * precision than you actually get.
1994 time_stamp->nsecs = (int)(1000000000*(tvb_get_letohs(tvb, start)/65536.0));
1996 report_type_length_mismatch(tree, "an RFC 3971-style time stamp", length, TRUE);
1999 case ENC_TIME_SECS_NTP|ENC_BIG_ENDIAN:
2001 * NTP time stamp, with 1-second resolution (i.e.,
2002 * seconds since the NTP epoch), big-endian.
2003 * Only supported for absolute times.
2005 DISSECTOR_ASSERT(!is_relative);
2009 * We need a temporary variable here so the
2010 * unsigned math works correctly (for
2011 * years > 2036 according to RFC 2030
2014 tmpsecs = tvb_get_ntohl(tvb, start);
2016 time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
2018 time_stamp->secs = tmpsecs; /* 0 */
2019 time_stamp->nsecs = 0;
2021 report_type_length_mismatch(tree, "an NTP seconds-only time stamp", length, TRUE);
2024 case ENC_TIME_SECS_NTP|ENC_LITTLE_ENDIAN:
2026 * NTP time stamp, with 1-second resolution (i.e.,
2027 * seconds since the NTP epoch), little-endian.
2028 * Only supported for absolute times.
2030 DISSECTOR_ASSERT(!is_relative);
2033 tmpsecs = tvb_get_letohl(tvb, start);
2035 time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
2037 time_stamp->secs = tmpsecs; /* 0 */
2038 time_stamp->nsecs = 0;
2040 report_type_length_mismatch(tree, "an NTP seconds-only time stamp", length, TRUE);
2042 case ENC_TIME_MSEC_NTP | ENC_BIG_ENDIAN:
2044 * Milliseconds, 1 to 8 bytes.
2045 * For absolute times, it's milliseconds since the
2048 if (length >= 1 && length <= 8) {
2051 msecs = get_uint64_value(tree, tvb, start, length, encoding);
2052 tmpsecs = (guint32)(msecs / 1000);
2053 time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME);
2054 time_stamp->nsecs = (int)(msecs % 1000)*1000000;
2057 report_type_length_mismatch(tree, "a time-in-milliseconds NTP time stamp", length, TRUE);
2060 DISSECTOR_ASSERT_NOT_REACHED();
2066 tree_data_add_maybe_interesting_field(tree_data_t *tree_data, field_info *fi)
2068 const header_field_info *hfinfo = fi->hfinfo;
2070 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
2071 GPtrArray *ptrs = NULL;
2073 if (tree_data->interesting_hfids == NULL) {
2074 /* Initialize the hash because we now know that it is needed */
2075 tree_data->interesting_hfids =
2076 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
2077 } else if (g_hash_table_size(tree_data->interesting_hfids)) {
2078 ptrs = (GPtrArray *)g_hash_table_lookup(tree_data->interesting_hfids,
2079 GINT_TO_POINTER(hfinfo->id));
2083 /* First element triggers the creation of pointer array */
2084 ptrs = g_ptr_array_new();
2085 g_hash_table_insert(tree_data->interesting_hfids,
2086 GINT_TO_POINTER(hfinfo->id), ptrs);
2089 g_ptr_array_add(ptrs, fi);
2093 /* Add an item to a proto_tree, using the text label registered to that item;
2094 the item is extracted from the tvbuff handed to it. */
2096 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
2097 tvbuff_t *tvb, gint start, gint length,
2104 const char *stringval;
2105 nstime_t time_stamp;
2106 gboolean length_error;
2108 switch (new_fi->hfinfo->type) {
2110 /* no value to set for FT_NONE */
2114 proto_tree_set_protocol_tvb(new_fi, tvb, new_fi->hfinfo->name);
2118 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
2123 * Map all non-zero values to little-endian for
2124 * backwards compatibility.
2127 encoding = ENC_LITTLE_ENDIAN;
2128 n = get_uint_value(tree, tvb, start, length, encoding);
2129 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
2131 /* Instead of calling proto_item_set_len(), since we don't yet
2132 * have a proto_item, we set the field_info's length ourselves. */
2133 new_fi->length = n + length;
2138 * Map all non-zero values to little-endian for
2139 * backwards compatibility.
2142 encoding = ENC_LITTLE_ENDIAN;
2143 proto_tree_set_boolean(new_fi,
2144 get_uint64_value(tree, tvb, start, length, encoding));
2148 /* XXX - make these just FT_UINT? */
2154 * Map all non-zero values to little-endian for
2155 * backwards compatibility.
2158 encoding = ENC_LITTLE_ENDIAN;
2159 proto_tree_set_uint(new_fi,
2160 get_uint_value(tree, tvb, start, length, encoding));
2168 * Map all non-zero values to little-endian for
2169 * backwards compatibility.
2172 encoding = ENC_LITTLE_ENDIAN;
2173 proto_tree_set_uint64(new_fi,
2174 get_uint64_value(tree, tvb, start, length, encoding));
2177 /* XXX - make these just FT_INT? */
2183 * Map all non-zero values to little-endian for
2184 * backwards compatibility.
2187 encoding = ENC_LITTLE_ENDIAN;
2188 proto_tree_set_int(new_fi,
2189 get_int_value(tree, tvb, start, length, encoding));
2197 * Map all non-zero values to little-endian for
2198 * backwards compatibility.
2201 encoding = ENC_LITTLE_ENDIAN;
2202 proto_tree_set_int64(new_fi,
2203 get_int64_value(tree, tvb, start, length, encoding));
2208 * Map all non-zero values to little-endian for
2209 * backwards compatibility.
2212 encoding = ENC_LITTLE_ENDIAN;
2213 if (length != FT_IPv4_LEN) {
2214 length_error = length < FT_IPv4_LEN ? TRUE : FALSE;
2215 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
2217 value = tvb_get_ipv4(tvb, start);
2219 * NOTE: to support code written when
2220 * proto_tree_add_item() took a gboolean as its
2221 * last argument, with FALSE meaning "big-endian"
2222 * and TRUE meaning "little-endian", we treat any
2223 * non-zero value of "encoding" as meaning
2226 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
2230 if (length != FT_IPXNET_LEN) {
2231 length_error = length < FT_IPXNET_LEN ? TRUE : FALSE;
2232 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
2234 proto_tree_set_ipxnet(new_fi,
2235 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, ENC_BIG_ENDIAN));
2239 if (length != FT_IPv6_LEN) {
2240 length_error = length < FT_IPv6_LEN ? TRUE : FALSE;
2241 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
2243 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
2247 if (length != FT_FCWWN_LEN) {
2248 length_error = length < FT_FCWWN_LEN ? TRUE : FALSE;
2249 report_type_length_mismatch(tree, "an FCWWN address", length, length_error);
2251 proto_tree_set_fcwwn_tvb(new_fi, tvb, start, length);
2256 length_error = length < 7 ? TRUE : FALSE;
2257 report_type_length_mismatch(tree, "an AX.25 address", length, length_error);
2259 proto_tree_set_ax25_tvb(new_fi, tvb, start);
2263 if (length != VINES_ADDR_LEN) {
2264 length_error = length < VINES_ADDR_LEN ? TRUE : FALSE;
2265 report_type_length_mismatch(tree, "a Vines address", length, length_error);
2267 proto_tree_set_vines_tvb(new_fi, tvb, start);
2271 if (length != FT_ETHER_LEN) {
2272 length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
2273 report_type_length_mismatch(tree, "a MAC address", length, length_error);
2275 proto_tree_set_ether_tvb(new_fi, tvb, start);
2280 * Map all non-zero values to little-endian for
2281 * backwards compatibility.
2284 encoding = ENC_LITTLE_ENDIAN;
2285 if (length != FT_EUI64_LEN) {
2286 length_error = length < FT_EUI64_LEN ? TRUE : FALSE;
2287 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
2289 proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
2293 * Map all non-zero values to little-endian for
2294 * backwards compatibility.
2297 encoding = ENC_LITTLE_ENDIAN;
2298 if (length != FT_GUID_LEN) {
2299 length_error = length < FT_GUID_LEN ? TRUE : FALSE;
2300 report_type_length_mismatch(tree, "a GUID", length, length_error);
2302 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
2307 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
2311 proto_tree_set_system_id_tvb(new_fi, tvb, start, length);
2316 * NOTE: to support code written when
2317 * proto_tree_add_item() took a gboolean as its
2318 * last argument, with FALSE meaning "big-endian"
2319 * and TRUE meaning "little-endian", we treat any
2320 * non-zero value of "encoding" as meaning
2323 * At some point in the future, we might
2324 * support non-IEEE-binary floating-point
2325 * formats in the encoding as well
2326 * (IEEE decimal, System/3x0, VAX).
2329 encoding = ENC_LITTLE_ENDIAN;
2331 length_error = length < 4 ? TRUE : FALSE;
2332 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
2335 floatval = tvb_get_letohieee_float(tvb, start);
2337 floatval = tvb_get_ntohieee_float(tvb, start);
2338 proto_tree_set_float(new_fi, floatval);
2343 * NOTE: to support code written when
2344 * proto_tree_add_item() took a gboolean as its
2345 * last argument, with FALSE meaning "big-endian"
2346 * and TRUE meaning "little-endian", we treat any
2347 * non-zero value of "encoding" as meaning
2350 * At some point in the future, we might
2351 * support non-IEEE-binary floating-point
2352 * formats in the encoding as well
2353 * (IEEE decimal, System/3x0, VAX).
2355 if (encoding == TRUE)
2356 encoding = ENC_LITTLE_ENDIAN;
2358 length_error = length < 8 ? TRUE : FALSE;
2359 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
2362 doubleval = tvb_get_letohieee_double(tvb, start);
2364 doubleval = tvb_get_ntohieee_double(tvb, start);
2365 proto_tree_set_double(new_fi, doubleval);
2369 stringval = get_string_value(wmem_packet_scope(),
2370 tvb, start, length, &length, encoding);
2371 proto_tree_set_string(new_fi, stringval);
2373 /* Instead of calling proto_item_set_len(), since we
2374 * don't yet have a proto_item, we set the
2375 * field_info's length ourselves.
2377 * XXX - our caller can't use that length to
2378 * advance an offset unless they arrange that
2379 * there always be a protocol tree into which
2380 * we're putting this item.
2382 new_fi->length = length;
2386 stringval = get_stringz_value(wmem_packet_scope(),
2387 tree, tvb, start, length, &length, encoding);
2388 proto_tree_set_string(new_fi, stringval);
2390 /* Instead of calling proto_item_set_len(),
2391 * since we don't yet have a proto_item, we
2392 * set the field_info's length ourselves.
2394 * XXX - our caller can't use that length to
2395 * advance an offset unless they arrange that
2396 * there always be a protocol tree into which
2397 * we're putting this item.
2399 new_fi->length = length;
2402 case FT_UINT_STRING:
2404 * NOTE: to support code written when
2405 * proto_tree_add_item() took a gboolean as its
2406 * last argument, with FALSE meaning "big-endian"
2407 * and TRUE meaning "little-endian", if the
2408 * encoding value is TRUE, treat that as
2409 * ASCII with a little-endian length.
2411 * This won't work for code that passes
2412 * arbitrary non-zero values; that code
2413 * will need to be fixed.
2415 if (encoding == TRUE)
2416 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
2417 stringval = get_uint_string_value(wmem_packet_scope(),
2418 tree, tvb, start, length, &length, encoding);
2419 proto_tree_set_string(new_fi, stringval);
2421 /* Instead of calling proto_item_set_len(), since we
2422 * don't yet have a proto_item, we set the
2423 * field_info's length ourselves.
2425 * XXX - our caller can't use that length to
2426 * advance an offset unless they arrange that
2427 * there always be a protocol tree into which
2428 * we're putting this item.
2430 new_fi->length = length;
2434 stringval = get_stringzpad_value(wmem_packet_scope(),
2435 tvb, start, length, &length, encoding);
2436 proto_tree_set_string(new_fi, stringval);
2438 /* Instead of calling proto_item_set_len(), since we
2439 * don't yet have a proto_item, we set the
2440 * field_info's length ourselves.
2442 * XXX - our caller can't use that length to
2443 * advance an offset unless they arrange that
2444 * there always be a protocol tree into which
2445 * we're putting this item.
2447 new_fi->length = length;
2450 case FT_ABSOLUTE_TIME:
2452 * Absolute times can be in any of a number of
2453 * formats, and they can be big-endian or
2456 * Historically FT_TIMEs were only timespecs;
2457 * the only question was whether they were stored
2458 * in big- or little-endian format.
2460 * For backwards compatibility, we interpret an
2461 * encoding of 1 as meaning "little-endian timespec",
2462 * so that passing TRUE is interpreted as that.
2464 if (encoding == TRUE)
2465 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
2467 if (length > 8 || length < 4) {
2468 length_error = length < 4 ? TRUE : FALSE;
2469 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
2472 get_time_value(tree, tvb, start, length, encoding, &time_stamp, FALSE);
2474 proto_tree_set_time(new_fi, &time_stamp);
2477 case FT_RELATIVE_TIME:
2479 * Relative times can be in any of a number of
2480 * formats, and they can be big-endian or
2483 * Historically FT_TIMEs were only timespecs;
2484 * the only question was whether they were stored
2485 * in big- or little-endian format.
2487 * For backwards compatibility, we interpret an
2488 * encoding of 1 as meaning "little-endian timespec",
2489 * so that passing TRUE is interpreted as that.
2491 if (encoding == TRUE)
2492 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
2494 if (length != 8 && length != 4) {
2495 length_error = length < 4 ? TRUE : FALSE;
2496 report_type_length_mismatch(tree, "a relative time value", length, length_error);
2499 get_time_value(tree, tvb, start, length, encoding, &time_stamp, TRUE);
2501 proto_tree_set_time(new_fi, &time_stamp);
2503 case FT_IEEE_11073_SFLOAT:
2505 encoding = ENC_LITTLE_ENDIAN;
2507 length_error = length < 2 ? TRUE : FALSE;
2508 report_type_length_mismatch(tree, "a IEEE 11073 SFLOAT", length, length_error);
2511 fvalue_set_uinteger(&new_fi->value, tvb_get_guint16(tvb, start, encoding));
2514 case FT_IEEE_11073_FLOAT:
2516 encoding = ENC_LITTLE_ENDIAN;
2518 length_error = length < 4 ? TRUE : FALSE;
2519 report_type_length_mismatch(tree, "a IEEE 11073 FLOAT", length, length_error);
2524 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
2525 new_fi->hfinfo->type,
2526 ftype_name(new_fi->hfinfo->type));
2527 DISSECTOR_ASSERT_NOT_REACHED();
2530 FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
2532 /* Don't add new node to proto_tree until now so that any exceptions
2533 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
2534 /* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
2535 * to know which item caused exception? */
2536 pi = proto_tree_add_node(tree, new_fi);
2542 proto_tree_add_item_ret_int(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2543 const gint start, gint length,
2544 const guint encoding, gint32 *retval)
2546 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
2550 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2552 switch (hfinfo->type){
2559 DISSECTOR_ASSERT_NOT_REACHED();
2562 /* length validation for native number encoding caught by get_uint_value() */
2563 /* length has to be -1 or > 0 regardless of encoding */
2564 if (length < -1 || length == 0)
2565 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2566 "Invalid length %d passed to proto_tree_add_item_ret_int",
2569 if (encoding & ENC_STRING) {
2570 REPORT_DISSECTOR_BUG("wrong encoding");
2572 /* I believe it's ok if this is called with a NULL tree */
2573 value = get_int_value(tree, tvb, start, length, encoding);
2578 if (hfinfo->bitmask) {
2579 /* Mask out irrelevant portions */
2580 *retval &= (guint32)(hfinfo->bitmask);
2582 *retval >>= hfinfo_bitshift(hfinfo);
2584 no_of_bits = ws_count_ones(hfinfo->bitmask);
2585 *retval = ws_sign_ext32(*retval, no_of_bits);
2588 CHECK_FOR_NULL_TREE(tree);
2590 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2592 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
2594 proto_tree_set_int(new_fi, value);
2596 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
2598 return proto_tree_add_node(tree, new_fi);
2602 proto_tree_add_item_ret_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2603 const gint start, gint length,
2604 const guint encoding, guint32 *retval)
2606 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
2610 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2612 switch (hfinfo->type){
2620 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2621 "field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, or FT_UINT32",
2625 /* length validation for native number encoding caught by get_uint_value() */
2626 /* length has to be -1 or > 0 regardless of encoding */
2627 if (length < -1 || length == 0)
2628 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2629 "Invalid length %d passed to proto_tree_add_item_ret_uint",
2632 if (encoding & ENC_STRING) {
2633 REPORT_DISSECTOR_BUG("wrong encoding");
2635 /* I believe it's ok if this is called with a NULL tree */
2636 /* XXX - modify if we ever support EBCDIC FT_CHAR */
2637 value = get_uint_value(tree, tvb, start, length, encoding);
2641 if (hfinfo->bitmask) {
2642 /* Mask out irrelevant portions */
2643 *retval &= (guint32)(hfinfo->bitmask);
2645 *retval >>= hfinfo_bitshift(hfinfo);
2649 CHECK_FOR_NULL_TREE(tree);
2651 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2653 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
2655 proto_tree_set_uint(new_fi, value);
2657 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
2659 return proto_tree_add_node(tree, new_fi);
2663 proto_tree_add_item_ret_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2664 const gint start, gint length, const guint encoding, guint64 *retval)
2666 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
2670 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2672 if (hfinfo->type != FT_UINT64) {
2673 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2674 "field %s is not of type FT_UINT64", hfinfo->abbrev));
2677 /* length validation for native number encoding caught by get_uint64_value() */
2678 /* length has to be -1 or > 0 regardless of encoding */
2679 if (length < -1 || length == 0)
2680 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2681 "Invalid length %d passed to proto_tree_add_item_ret_uint",
2684 if (encoding & ENC_STRING) {
2685 REPORT_DISSECTOR_BUG("wrong encoding");
2687 /* I believe it's ok if this is called with a NULL tree */
2688 value = get_uint64_value(tree, tvb, start, length, encoding);
2692 if (hfinfo->bitmask) {
2693 /* Mask out irrelevant portions */
2694 *retval &= hfinfo->bitmask;
2696 *retval >>= hfinfo_bitshift(hfinfo);
2700 CHECK_FOR_NULL_TREE(tree);
2702 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2704 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
2706 proto_tree_set_uint64(new_fi, value);
2708 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
2710 return proto_tree_add_node(tree, new_fi);
2714 proto_tree_add_item_ret_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2715 const gint start, gint length,
2716 const guint encoding, gboolean *retval)
2718 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
2720 guint64 value, bitval;
2722 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2724 if (hfinfo->type != FT_BOOLEAN) {
2725 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2726 "field %s is not of type FT_BOOLEAN", hfinfo->abbrev));
2729 /* length validation for native number encoding caught by get_uint64_value() */
2730 /* length has to be -1 or > 0 regardless of encoding */
2731 if (length < -1 || length == 0)
2732 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2733 "Invalid length %d passed to proto_tree_add_item_ret_uint",
2736 if (encoding & ENC_STRING) {
2737 REPORT_DISSECTOR_BUG("wrong encoding");
2739 /* I believe it's ok if this is called with a NULL tree */
2740 value = get_uint64_value(tree, tvb, start, length, encoding);
2744 if (hfinfo->bitmask) {
2745 /* Mask out irrelevant portions */
2746 bitval &= hfinfo->bitmask;
2748 *retval = (bitval != 0);
2751 CHECK_FOR_NULL_TREE(tree);
2753 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2755 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
2757 proto_tree_set_boolean(new_fi, value);
2759 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
2761 return proto_tree_add_node(tree, new_fi);
2765 proto_tree_add_item_ret_string_and_length(proto_tree *tree, int hfindex,
2767 const gint start, gint length,
2768 const guint encoding,
2769 wmem_allocator_t *scope,
2770 const guint8 **retval,
2773 header_field_info *hfinfo = proto_registrar_get_nth(hfindex);
2775 const guint8 *value;
2777 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2779 switch (hfinfo->type){
2781 value = get_string_value(scope, tvb, start, length, lenretval, encoding);
2784 value = get_stringz_value(scope, tree, tvb, start, length, lenretval, encoding);
2786 case FT_UINT_STRING:
2787 value = get_uint_string_value(scope, tree, tvb, start, length, lenretval, encoding);
2790 value = get_stringzpad_value(scope, tvb, start, length, lenretval, encoding);
2793 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
2794 "field %s is not of type FT_STRING, FT_STRINGZ, FT_UINT_STRING, or FT_STRINGZPAD",
2801 CHECK_FOR_NULL_TREE(tree);
2803 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2805 new_fi = new_field_info(tree, hfinfo, tvb, start, *lenretval);
2807 proto_tree_set_string(new_fi, value);
2809 new_fi->flags |= (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN;
2811 return proto_tree_add_node(tree, new_fi);
2815 proto_tree_add_item_ret_string(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2816 const gint start, gint length,
2817 const guint encoding, wmem_allocator_t *scope,
2818 const guint8 **retval)
2820 return proto_tree_add_item_ret_string_and_length(tree, hfindex,
2821 tvb, start, length, encoding, scope, retval, &length);
2825 * Validates that field length bytes are available starting from
2826 * start (pos/neg). Throws an exception if they aren't.
2829 test_length(header_field_info *hfinfo, tvbuff_t *tvb,
2830 gint start, gint length)
2837 if (hfinfo->type == FT_STRINGZ) {
2838 /* If we're fetching until the end of the TVB, only validate
2839 * that the offset is within range.
2845 tvb_ensure_bytes_exist(tvb, start, size);
2848 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
2849 and returns proto_item* */
2851 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
2852 const guint encoding)
2855 header_field_info *hfinfo;
2859 offset = ptvc->offset;
2860 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2861 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length);
2862 test_length(hfinfo, ptvc->tvb, offset, item_length);
2864 ptvc->offset += get_full_length(hfinfo, ptvc->tvb, offset, length,
2865 item_length, encoding);
2867 CHECK_FOR_NULL_TREE(ptvc->tree);
2869 /* Coast clear. Try and fake it */
2870 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
2872 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
2874 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
2875 offset, length, encoding);
2878 /* Add an item to a proto_tree, using the text label registered to that item;
2879 the item is extracted from the tvbuff handed to it. */
2881 proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
2882 const gint start, gint length, const guint encoding)
2887 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2889 get_hfi_length(hfinfo, tvb, start, &length, &item_length);
2890 test_length(hfinfo, tvb, start, item_length);
2892 CHECK_FOR_NULL_TREE(tree);
2894 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
2896 new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
2898 return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
2902 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2903 const gint start, gint length, const guint encoding)
2905 register header_field_info *hfinfo;
2907 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2908 return proto_tree_add_item_new(tree, hfinfo, tvb, start, length, encoding);
2911 /* Add an item to a proto_tree, using the text label registered to that item;
2912 the item is extracted from the tvbuff handed to it.
2914 Return the length of the item through the pointer. */
2916 proto_tree_add_item_new_ret_length(proto_tree *tree, header_field_info *hfinfo,
2917 tvbuff_t *tvb, const gint start,
2918 gint length, const guint encoding,
2925 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
2927 get_hfi_length(hfinfo, tvb, start, &length, &item_length);
2928 test_length(hfinfo, tvb, start, item_length);
2932 * We need to get the correct item length here.
2933 * That's normally done by proto_tree_new_item(),
2934 * but we won't be calling it.
2936 *lenretval = get_full_length(hfinfo, tvb, start, length,
2937 item_length, encoding);
2941 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfinfo->id, hfinfo, {
2943 * Even if the tree item is not referenced (and thus faked),
2944 * the caller must still be informed of the actual length.
2946 *lenretval = get_full_length(hfinfo, tvb, start, length,
2947 item_length, encoding);
2950 new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
2952 item = proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
2953 *lenretval = new_fi->length;
2958 proto_tree_add_item_ret_length(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2959 const gint start, gint length,
2960 const guint encoding, gint *lenretval)
2962 register header_field_info *hfinfo;
2964 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2965 return proto_tree_add_item_new_ret_length(tree, hfinfo, tvb, start, length, encoding, lenretval);
2968 /* which FT_ types can use proto_tree_add_bytes_item() */
2969 static inline gboolean
2970 validate_proto_tree_add_bytes_ftype(const enum ftenum type)
2972 return (type == FT_BYTES ||
2973 type == FT_UINT_BYTES ||
2975 type == FT_REL_OID ||
2976 type == FT_SYSTEM_ID );
2979 /* Note: this does no validation that the byte array of an FT_OID or
2980 FT_REL_OID is actually valid; and neither does proto_tree_add_item(),
2981 so I think it's ok to continue not validating it?
2984 proto_tree_add_bytes_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2985 const gint start, gint length, const guint encoding,
2986 GByteArray *retval, gint *endoff, gint *err)
2989 GByteArray *bytes = retval;
2990 GByteArray *created_bytes = NULL;
2993 header_field_info *hfinfo;
2994 gboolean generate = (bytes || tree) ? TRUE : FALSE;
2996 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
2998 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3000 DISSECTOR_ASSERT_HINT(validate_proto_tree_add_bytes_ftype(hfinfo->type),
3001 "Called proto_tree_add_bytes_item but not a bytes-based FT_XXX type");
3003 /* length has to be -1 or > 0 regardless of encoding */
3004 /* invalid FT_UINT_BYTES length is caught in get_uint_value() */
3005 if (length < -1 || length == 0) {
3006 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
3007 "Invalid length %d passed to proto_tree_add_bytes_item for %s",
3008 length, ftype_name(hfinfo->type)));
3011 if (encoding & ENC_STR_NUM) {
3012 REPORT_DISSECTOR_BUG("Decoding number strings for byte arrays is not supported");
3015 if (generate && (encoding & ENC_STR_HEX)) {
3016 if (hfinfo->type == FT_UINT_BYTES) {
3017 /* can't decode FT_UINT_BYTES from strings */
3018 REPORT_DISSECTOR_BUG("proto_tree_add_bytes_item called for "
3019 "FT_UINT_BYTES type, but as ENC_STR_HEX");
3023 /* caller doesn't care about return value, but we need it to
3024 call tvb_get_string_bytes() and set the tree later */
3025 bytes = created_bytes = g_byte_array_new();
3028 /* bytes might be NULL after this, but can't add expert error until later */
3029 bytes = tvb_get_string_bytes(tvb, start, length, encoding, bytes, endoff);
3031 /* grab the errno now before it gets overwritten */
3034 else if (generate) {
3035 tvb_ensure_bytes_exist(tvb, start, length);
3038 /* caller doesn't care about return value, but we need it to
3039 call tvb_get_string_bytes() and set the tree later */
3040 bytes = created_bytes = g_byte_array_new();
3043 if (hfinfo->type == FT_UINT_BYTES) {
3044 n = length; /* n is now the "header" length */
3045 length = get_uint_value(tree, tvb, start, n, encoding);
3046 /* length is now the value's length; only store the value in the array */
3047 g_byte_array_append(bytes, tvb_get_ptr(tvb, start + n, length), length);
3049 else if (length > 0) {
3050 g_byte_array_append(bytes, tvb_get_ptr(tvb, start, length), length);
3054 *endoff = start + n + length;
3057 if (err) *err = saved_err;
3059 CHECK_FOR_NULL_TREE_AND_FREE(tree,
3062 g_byte_array_free(created_bytes, TRUE);
3063 created_bytes = NULL;
3067 TRY_TO_FAKE_THIS_ITEM_OR_FREE(tree, hfinfo->id, hfinfo,
3070 g_byte_array_free(created_bytes, TRUE);
3071 created_bytes = NULL;
3075 /* n will be zero except when it's a FT_UINT_BYTES */
3076 new_fi = new_field_info(tree, hfinfo, tvb, start, n + length);
3078 if (encoding & ENC_STRING) {
3079 if (saved_err == ERANGE)
3080 expert_add_info(NULL, tree, &ei_number_string_decoding_erange_error);
3081 else if (!bytes || saved_err != 0)
3082 expert_add_info(NULL, tree, &ei_number_string_decoding_failed_error);
3085 proto_tree_set_bytes_gbytearray(new_fi, bytes);
3087 proto_tree_set_bytes(new_fi, NULL, 0);
3090 g_byte_array_free(created_bytes, TRUE);
3093 /* n will be zero except when it's a FT_UINT_BYTES */
3094 proto_tree_set_bytes_tvb(new_fi, tvb, start + n, length);
3097 (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
3100 return proto_tree_add_node(tree, new_fi);
3105 proto_tree_add_time_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3106 const gint start, gint length, const guint encoding,
3107 nstime_t *retval, gint *endoff, gint *err)
3110 nstime_t time_stamp;
3112 header_field_info *hfinfo;
3114 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3116 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3118 DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo);
3120 /* length has to be -1 or > 0 regardless of encoding */
3121 if (length < -1 || length == 0) {
3122 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
3123 "Invalid length %d passed to proto_tree_add_time_item", length));
3126 time_stamp.secs = 0;
3127 time_stamp.nsecs = 0;
3129 if (encoding & ENC_STR_TIME_MASK) {
3130 tvb_get_string_time(tvb, start, length, encoding, &time_stamp, endoff);
3131 /* grab the errno now before it gets overwritten */
3135 const gboolean is_relative = (hfinfo->type == FT_RELATIVE_TIME) ? TRUE : FALSE;
3136 const gboolean length_error = length < 4 ? TRUE : FALSE;
3138 if (length > 8 || length < 4) {
3140 report_type_length_mismatch(tree, "a relative time value", length, length_error);
3142 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
3145 tvb_ensure_bytes_exist(tvb, start, length);
3146 get_time_value(tree, tvb, start, length, encoding, &time_stamp, is_relative);
3147 if (endoff) *endoff = length;
3150 if (err) *err = saved_err;
3153 retval->secs = time_stamp.secs;
3154 retval->nsecs = time_stamp.nsecs;
3157 CHECK_FOR_NULL_TREE(tree);
3159 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
3161 new_fi = new_field_info(tree, hfinfo, tvb, start, length);
3163 proto_tree_set_time(new_fi, &time_stamp);
3165 if (encoding & ENC_STRING) {
3166 if (saved_err == ERANGE)
3167 expert_add_info(NULL, tree, &ei_number_string_decoding_erange_error);
3168 else if (saved_err == EDOM)
3169 expert_add_info(NULL, tree, &ei_number_string_decoding_failed_error);
3173 (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
3176 return proto_tree_add_node(tree, new_fi);
3179 /* Add a FT_NONE to a proto_tree */
3181 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
3182 const gint start, gint length, const char *format,
3187 header_field_info *hfinfo;
3189 CHECK_FOR_NULL_TREE(tree);
3191 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3193 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_NONE);
3195 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3197 TRY_TO_FAKE_THIS_REPR(pi);
3199 va_start(ap, format);
3200 proto_tree_set_representation(pi, format, ap);
3203 /* no value to set for FT_NONE */
3207 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
3208 * offset, and returns proto_item* */
3210 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
3211 const guint encoding)
3215 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
3221 /* Advance the ptvcursor's offset within its tvbuff without
3222 * adding anything to the proto_tree. */
3224 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
3226 ptvc->offset += length;
3231 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb, const char* field_data)
3233 fvalue_set_protocol(&fi->value, tvb, field_data);
3236 /* Add a FT_PROTOCOL to a proto_tree */
3238 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3239 gint start, gint length, const char *format, ...)
3243 header_field_info *hfinfo;
3244 gchar* protocol_rep;
3246 CHECK_FOR_NULL_TREE(tree);
3248 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3250 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_PROTOCOL);
3252 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3254 va_start(ap, format);
3255 protocol_rep = g_strdup_vprintf(format, ap);
3256 proto_tree_set_protocol_tvb(PNODE_FINFO(pi), (start == 0 ? tvb : tvb_new_subset_length(tvb, start, length)), protocol_rep);
3257 g_free(protocol_rep);
3260 TRY_TO_FAKE_THIS_REPR(pi);
3262 va_start(ap, format);
3263 proto_tree_set_representation(pi, format, ap);
3269 /* Add a FT_BYTES to a proto_tree */
3271 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3272 gint length, const guint8 *start_ptr)
3275 header_field_info *hfinfo;
3278 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3279 get_hfi_length(hfinfo, tvb, start, &length, &item_length);
3280 test_length(hfinfo, tvb, start, item_length);
3282 CHECK_FOR_NULL_TREE(tree);
3284 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3286 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BYTES);
3288 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3289 proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, length);
3294 /* Add a FT_BYTES to a proto_tree */
3296 proto_tree_add_bytes_with_length(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3297 gint tvbuff_length, const guint8 *start_ptr, gint ptr_length)
3300 header_field_info *hfinfo;
3303 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
3304 get_hfi_length(hfinfo, tvb, start, &tvbuff_length, &item_length);
3305 test_length(hfinfo, tvb, start, item_length);
3307 CHECK_FOR_NULL_TREE(tree);
3309 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3311 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BYTES);
3313 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &tvbuff_length);
3314 proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, ptr_length);
3320 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3321 gint start, gint length,
3322 const guint8 *start_ptr,
3323 const char *format, ...)
3328 if (start_ptr == NULL)
3329 start_ptr = tvb_get_ptr(tvb, start, length);
3331 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
3333 TRY_TO_FAKE_THIS_REPR_NESTED(pi);
3335 va_start(ap, format);
3336 proto_tree_set_representation_value(pi, format, ap);
3343 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3344 gint start, gint length, const guint8 *start_ptr,
3345 const char *format, ...)
3350 if (start_ptr == NULL)
3351 start_ptr = tvb_get_ptr(tvb, start, length);
3353 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length, start_ptr);
3355 TRY_TO_FAKE_THIS_REPR_NESTED(pi);
3357 va_start(ap, format);
3358 proto_tree_set_representation(pi, format, ap);
3365 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
3369 DISSECTOR_ASSERT(start_ptr != NULL || length == 0);
3371 bytes = g_byte_array_new();
3373 g_byte_array_append(bytes, start_ptr, length);
3375 fvalue_set_byte_array(&fi->value, bytes);
3380 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
3382 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
3386 proto_tree_set_bytes_gbytearray(field_info *fi, const GByteArray *value)
3390 DISSECTOR_ASSERT(value != NULL);
3392 bytes = byte_array_dup(value);
3394 fvalue_set_byte_array(&fi->value, bytes);
3397 /* Add a FT_*TIME to a proto_tree */
3399 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3400 gint length, const nstime_t *value_ptr)
3403 header_field_info *hfinfo;
3405 CHECK_FOR_NULL_TREE(tree);
3407 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3409 DISSECTOR_ASSERT_FIELD_TYPE_IS_TIME(hfinfo);
3411 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3412 proto_tree_set_time(PNODE_FINFO(pi), value_ptr);
3418 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3419 gint start, gint length, nstime_t *value_ptr,
3420 const char *format, ...)
3425 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
3427 va_start(ap, format);
3428 proto_tree_set_representation_value(pi, format, ap);
3436 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3437 gint start, gint length, nstime_t *value_ptr,
3438 const char *format, ...)
3443 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
3445 TRY_TO_FAKE_THIS_REPR(pi);
3447 va_start(ap, format);
3448 proto_tree_set_representation(pi, format, ap);
3455 /* Set the FT_*TIME value */
3457 proto_tree_set_time(field_info *fi, const nstime_t *value_ptr)
3459 DISSECTOR_ASSERT(value_ptr != NULL);
3461 fvalue_set_time(&fi->value, value_ptr);
3464 /* Add a FT_IPXNET to a proto_tree */
3466 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3467 gint length, guint32 value)
3470 header_field_info *hfinfo;
3472 CHECK_FOR_NULL_TREE(tree);
3474 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3476 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPXNET);
3478 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3479 proto_tree_set_ipxnet(PNODE_FINFO(pi), value);
3485 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3486 gint start, gint length, guint32 value,
3487 const char *format, ...)
3492 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
3494 va_start(ap, format);
3495 proto_tree_set_representation_value(pi, format, ap);
3503 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3504 gint start, gint length, guint32 value,
3505 const char *format, ...)
3510 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
3512 TRY_TO_FAKE_THIS_REPR(pi);
3514 va_start(ap, format);
3515 proto_tree_set_representation(pi, format, ap);
3522 /* Set the FT_IPXNET value */
3524 proto_tree_set_ipxnet(field_info *fi, guint32 value)
3526 fvalue_set_uinteger(&fi->value, value);
3529 /* Add a FT_IPv4 to a proto_tree */
3531 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3532 gint length, guint32 value)
3535 header_field_info *hfinfo;
3537 CHECK_FOR_NULL_TREE(tree);
3539 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3541 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPv4);
3543 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3544 proto_tree_set_ipv4(PNODE_FINFO(pi), value);
3550 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3551 gint start, gint length, guint32 value,
3552 const char *format, ...)
3557 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
3559 va_start(ap, format);
3560 proto_tree_set_representation_value(pi, format, ap);
3568 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3569 gint start, gint length, guint32 value,
3570 const char *format, ...)
3575 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
3577 TRY_TO_FAKE_THIS_REPR(pi);
3579 va_start(ap, format);
3580 proto_tree_set_representation(pi, format, ap);
3587 /* Set the FT_IPv4 value */
3589 proto_tree_set_ipv4(field_info *fi, guint32 value)
3591 fvalue_set_uinteger(&fi->value, value);
3594 /* Add a FT_IPv6 to a proto_tree */
3596 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3597 gint length, const struct e_in6_addr *value_ptr)
3600 header_field_info *hfinfo;
3602 CHECK_FOR_NULL_TREE(tree);
3604 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3606 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_IPv6);
3608 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3609 proto_tree_set_ipv6(PNODE_FINFO(pi), value_ptr->bytes);
3615 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3616 gint start, gint length,
3617 const struct e_in6_addr *value_ptr,
3618 const char *format, ...)
3623 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
3625 va_start(ap, format);
3626 proto_tree_set_representation_value(pi, format, ap);
3634 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3635 gint start, gint length,
3636 const struct e_in6_addr *value_ptr,
3637 const char *format, ...)
3642 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
3644 TRY_TO_FAKE_THIS_REPR(pi);
3646 va_start(ap, format);
3647 proto_tree_set_representation(pi, format, ap);
3654 /* Set the FT_IPv6 value */
3656 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
3658 DISSECTOR_ASSERT(value_ptr != NULL);
3659 fvalue_set_bytes(&fi->value, value_ptr);
3663 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
3665 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
3668 /* Set the FT_FCWWN value */
3670 proto_tree_set_fcwwn(field_info *fi, const guint8* value_ptr)
3672 DISSECTOR_ASSERT(value_ptr != NULL);
3673 fvalue_set_bytes(&fi->value, value_ptr);
3677 proto_tree_set_fcwwn_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
3679 proto_tree_set_fcwwn(fi, tvb_get_ptr(tvb, start, length));
3682 /* Add a FT_GUID to a proto_tree */
3684 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3685 gint length, const e_guid_t *value_ptr)
3688 header_field_info *hfinfo;
3690 CHECK_FOR_NULL_TREE(tree);
3692 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3694 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_GUID);
3696 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3697 proto_tree_set_guid(PNODE_FINFO(pi), value_ptr);
3703 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3704 gint start, gint length,
3705 const e_guid_t *value_ptr,
3706 const char *format, ...)
3711 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
3713 va_start(ap, format);
3714 proto_tree_set_representation_value(pi, format, ap);
3722 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3723 gint start, gint length, const e_guid_t *value_ptr,
3724 const char *format, ...)
3729 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
3731 TRY_TO_FAKE_THIS_REPR(pi);
3733 va_start(ap, format);
3734 proto_tree_set_representation(pi, format, ap);
3741 /* Set the FT_GUID value */
3743 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
3745 DISSECTOR_ASSERT(value_ptr != NULL);
3746 fvalue_set_guid(&fi->value, value_ptr);
3750 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
3751 const guint encoding)
3755 tvb_get_guid(tvb, start, &guid, encoding);
3756 proto_tree_set_guid(fi, &guid);
3759 /* Add a FT_OID to a proto_tree */
3761 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3762 gint length, const guint8* value_ptr)
3765 header_field_info *hfinfo;
3767 CHECK_FOR_NULL_TREE(tree);
3769 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3771 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_OID);
3773 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3774 proto_tree_set_oid(PNODE_FINFO(pi), value_ptr, length);
3780 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3781 gint start, gint length,
3782 const guint8* value_ptr,
3783 const char *format, ...)
3788 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
3790 va_start(ap, format);
3791 proto_tree_set_representation_value(pi, format, ap);
3799 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3800 gint start, gint length, const guint8* value_ptr,
3801 const char *format, ...)
3806 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
3808 TRY_TO_FAKE_THIS_REPR(pi);
3810 va_start(ap, format);
3811 proto_tree_set_representation(pi, format, ap);
3818 /* Set the FT_OID value */
3820 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
3824 DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
3826 bytes = g_byte_array_new();
3828 g_byte_array_append(bytes, value_ptr, length);
3830 fvalue_set_byte_array(&fi->value, bytes);
3834 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
3836 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
3839 /* Set the FT_SYSTEM_ID value */
3841 proto_tree_set_system_id(field_info *fi, const guint8* value_ptr, gint length)
3845 DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
3847 bytes = g_byte_array_new();
3849 g_byte_array_append(bytes, value_ptr, length);
3851 fvalue_set_byte_array(&fi->value, bytes);
3855 proto_tree_set_system_id_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
3857 proto_tree_set_system_id(fi, tvb_get_ptr(tvb, start, length), length);
3860 /* Add a FT_STRING, FT_STRINGZ, or FT_STRINGZPAD to a proto_tree. Creates
3861 * own copy of string, and frees it when the proto_tree is destroyed. */
3863 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3864 gint length, const char* value)
3867 header_field_info *hfinfo;
3869 CHECK_FOR_NULL_TREE(tree);
3871 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3873 DISSECTOR_ASSERT_FIELD_TYPE_IS_STRING(hfinfo);
3875 if (hfinfo->display == STR_UNICODE) {
3876 DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL));
3879 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3880 DISSECTOR_ASSERT(length >= 0);
3881 proto_tree_set_string(PNODE_FINFO(pi), value);
3887 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3888 gint start, gint length, const char* value,
3895 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
3897 va_start(ap, format);
3898 proto_tree_set_representation_value(pi, format, ap);
3906 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3907 gint start, gint length, const char* value,
3908 const char *format, ...)
3913 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
3915 TRY_TO_FAKE_THIS_REPR(pi);
3917 va_start(ap, format);
3918 proto_tree_set_representation(pi, format, ap);
3925 /* Set the FT_STRING value */
3927 proto_tree_set_string(field_info *fi, const char* value)
3930 fvalue_set_string(&fi->value, value);
3932 fvalue_set_string(&fi->value, "[ Null ]");
3936 /* Set the FT_AX25 value */
3938 proto_tree_set_ax25(field_info *fi, const guint8* value)
3940 fvalue_set_bytes(&fi->value, value);
3944 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
3946 proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
3949 /* Set the FT_VINES value */
3951 proto_tree_set_vines(field_info *fi, const guint8* value)
3953 fvalue_set_bytes(&fi->value, value);
3957 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start)
3959 proto_tree_set_vines(fi, tvb_get_ptr(tvb, start, FT_VINES_ADDR_LEN));
3962 /* Add a FT_ETHER to a proto_tree */
3964 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3965 gint length, const guint8* value)
3968 header_field_info *hfinfo;
3970 CHECK_FOR_NULL_TREE(tree);
3972 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3974 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_ETHER);
3976 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3977 proto_tree_set_ether(PNODE_FINFO(pi), value);
3983 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3984 gint start, gint length, const guint8* value,
3985 const char *format, ...)
3990 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
3992 va_start(ap, format);
3993 proto_tree_set_representation_value(pi, format, ap);
4001 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4002 gint start, gint length, const guint8* value,
4003 const char *format, ...)
4008 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
4010 TRY_TO_FAKE_THIS_REPR(pi);
4012 va_start(ap, format);
4013 proto_tree_set_representation(pi, format, ap);
4020 /* Set the FT_ETHER value */
4022 proto_tree_set_ether(field_info *fi, const guint8* value)
4024 fvalue_set_bytes(&fi->value, value);
4028 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
4030 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
4033 /* Add a FT_BOOLEAN to a proto_tree */
4035 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4036 gint length, guint32 value)
4039 header_field_info *hfinfo;
4041 CHECK_FOR_NULL_TREE(tree);
4043 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4045 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BOOLEAN);
4047 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4048 proto_tree_set_boolean(PNODE_FINFO(pi), value);
4054 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
4055 tvbuff_t *tvb, gint start, gint length,
4056 guint32 value, const char *format, ...)
4061 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
4063 va_start(ap, format);
4064 proto_tree_set_representation_value(pi, format, ap);
4072 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4073 gint start, gint length, guint32 value,
4074 const char *format, ...)
4079 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
4081 TRY_TO_FAKE_THIS_REPR(pi);
4083 va_start(ap, format);
4084 proto_tree_set_representation(pi, format, ap);
4092 proto_tree_add_boolean64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4093 gint length, guint64 value)
4096 header_field_info *hfinfo;
4098 CHECK_FOR_NULL_TREE(tree);
4100 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4102 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_BOOLEAN);
4104 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4105 proto_tree_set_boolean(PNODE_FINFO(pi), value);
4110 /* Set the FT_BOOLEAN value */
4112 proto_tree_set_boolean(field_info *fi, guint64 value)
4114 proto_tree_set_uint64(fi, value);
4117 /* Generate, into "buf", a string showing the bits of a bitfield.
4118 Return a pointer to the character after that string. */
4119 /*XXX this needs a buf_len check */
4121 other_decode_bitfield_value(char *buf, const guint64 val, const guint64 mask, const int width)
4129 bit = G_GUINT64_CONSTANT(1) << (width - 1);
4132 /* This bit is part of the field. Show its value. */
4138 /* This bit is not part of the field. */
4153 decode_bitfield_value(char *buf, const guint64 val, const guint64 mask, const int width)
4157 p = other_decode_bitfield_value(buf, val, mask, width);
4158 p = g_stpcpy(p, " = ");
4163 /* Add a FT_FLOAT to a proto_tree */
4165 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4166 gint length, float value)
4169 header_field_info *hfinfo;
4171 CHECK_FOR_NULL_TREE(tree);
4173 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4175 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_FLOAT);
4177 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4178 proto_tree_set_float(PNODE_FINFO(pi), value);
4184 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4185 gint start, gint length, float value,
4186 const char *format, ...)
4191 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
4193 va_start(ap, format);
4194 proto_tree_set_representation_value(pi, format, ap);
4202 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4203 gint start, gint length, float value,
4204 const char *format, ...)
4209 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
4211 TRY_TO_FAKE_THIS_REPR(pi);
4213 va_start(ap, format);
4214 proto_tree_set_representation(pi, format, ap);
4221 /* Set the FT_FLOAT value */
4223 proto_tree_set_float(field_info *fi, float value)
4225 fvalue_set_floating(&fi->value, value);
4228 /* Add a FT_DOUBLE to a proto_tree */
4230 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4231 gint length, double value)
4234 header_field_info *hfinfo;
4236 CHECK_FOR_NULL_TREE(tree);
4238 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4240 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_DOUBLE);
4242 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4243 proto_tree_set_double(PNODE_FINFO(pi), value);
4249 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4250 gint start, gint length, double value,
4251 const char *format, ...)
4256 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
4258 va_start(ap, format);
4259 proto_tree_set_representation_value(pi, format, ap);
4267 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4268 gint start, gint length, double value,
4269 const char *format, ...)
4274 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
4276 TRY_TO_FAKE_THIS_REPR(pi);
4278 va_start(ap, format);
4279 proto_tree_set_representation(pi, format, ap);
4286 /* Set the FT_DOUBLE value */
4288 proto_tree_set_double(field_info *fi, double value)
4290 fvalue_set_floating(&fi->value, value);
4293 /* Add FT_CHAR or FT_UINT{8,16,24,32} to a proto_tree */
4295 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4296 gint length, guint32 value)
4298 proto_item *pi = NULL;
4299 header_field_info *hfinfo;
4301 CHECK_FOR_NULL_TREE(tree);
4303 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4305 switch (hfinfo->type) {
4312 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4313 proto_tree_set_uint(PNODE_FINFO(pi), value);
4317 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
4318 "field %s is not of type FT_CHAR, FT_UINT8, FT_UINT16, FT_UINT24, FT_UINT32, or FT_FRAMENUM",
4326 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4327 gint start, gint length, guint32 value,
4328 const char *format, ...)
4333 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
4335 va_start(ap, format);
4336 proto_tree_set_representation_value(pi, format, ap);
4344 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4345 gint start, gint length, guint32 value,
4346 const char *format, ...)
4351 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
4353 TRY_TO_FAKE_THIS_REPR(pi);
4355 va_start(ap, format);
4356 proto_tree_set_representation(pi, format, ap);
4363 /* Set the FT_UINT{8,16,24,32} value */
4365 proto_tree_set_uint(field_info *fi, guint32 value)
4367 header_field_info *hfinfo;
4370 hfinfo = fi->hfinfo;
4373 if (hfinfo->bitmask) {
4374 /* Mask out irrelevant portions */
4375 integer &= (guint32)(hfinfo->bitmask);
4378 integer >>= hfinfo_bitshift(hfinfo);
4381 fvalue_set_uinteger(&fi->value, integer);
4384 /* Add FT_UINT{40,48,56,64} to a proto_tree */
4386 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4387 gint length, guint64 value)
4389 proto_item *pi = NULL;
4390 header_field_info *hfinfo;
4392 CHECK_FOR_NULL_TREE(tree);
4394 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4396 switch (hfinfo->type) {
4402 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4403 proto_tree_set_uint64(PNODE_FINFO(pi), value);
4407 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
4408 "field %s is not of type FT_UINT40, FT_UINT48, FT_UINT56, FT_UINT64, or FT_FRAMENUM",
4416 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4417 gint start, gint length, guint64 value,
4418 const char *format, ...)
4423 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
4425 va_start(ap, format);
4426 proto_tree_set_representation_value(pi, format, ap);
4434 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4435 gint start, gint length, guint64 value,
4436 const char *format, ...)
4441 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
4443 TRY_TO_FAKE_THIS_REPR(pi);
4445 va_start(ap, format);
4446 proto_tree_set_representation(pi, format, ap);
4453 /* Set the FT_UINT{40,48,56,64} value */
4455 proto_tree_set_uint64(field_info *fi, guint64 value)
4457 header_field_info *hfinfo;
4460 hfinfo = fi->hfinfo;
4463 if (hfinfo->bitmask) {
4464 /* Mask out irrelevant portions */
4465 integer &= hfinfo->bitmask;
4468 integer >>= hfinfo_bitshift(hfinfo);
4471 fvalue_set_uinteger64(&fi->value, integer);
4474 /* Add FT_INT{8,16,24,32} to a proto_tree */
4476 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4477 gint length, gint32 value)
4479 proto_item *pi = NULL;
4480 header_field_info *hfinfo;
4482 CHECK_FOR_NULL_TREE(tree);
4484 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4486 switch (hfinfo->type) {
4491 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4492 proto_tree_set_int(PNODE_FINFO(pi), value);
4496 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
4497 "field %s is not of type FT_INT8, FT_INT16, FT_INT24, or FT_INT32",
4505 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4506 gint start, gint length, gint32 value,
4507 const char *format, ...)
4512 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
4514 va_start(ap, format);
4515 proto_tree_set_representation_value(pi, format, ap);
4523 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4524 gint start, gint length, gint32 value,
4525 const char *format, ...)
4530 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
4532 TRY_TO_FAKE_THIS_REPR(pi);
4534 va_start(ap, format);
4535 proto_tree_set_representation(pi, format, ap);
4542 /* Set the FT_INT{8,16,24,32} value */
4544 proto_tree_set_int(field_info *fi, gint32 value)
4546 header_field_info *hfinfo;
4550 hfinfo = fi->hfinfo;
4551 integer = (guint32) value;
4553 if (hfinfo->bitmask) {
4554 /* Mask out irrelevant portions */
4555 integer &= (guint32)(hfinfo->bitmask);
4558 integer >>= hfinfo_bitshift(hfinfo);
4560 no_of_bits = ws_count_ones(hfinfo->bitmask);
4561 integer = ws_sign_ext32(integer, no_of_bits);
4564 fvalue_set_sinteger(&fi->value, integer);
4567 /* Add FT_INT{40,48,56,64} to a proto_tree */
4569 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4570 gint length, gint64 value)
4572 proto_item *pi = NULL;
4573 header_field_info *hfinfo;
4575 CHECK_FOR_NULL_TREE(tree);
4577 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4579 switch (hfinfo->type) {
4584 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4585 proto_tree_set_int64(PNODE_FINFO(pi), value);
4589 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
4590 "field %s is not of type FT_INT40, FT_INT48, FT_INT56, or FT_INT64",
4598 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4599 gint start, gint length, gint64 value,
4600 const char *format, ...)
4605 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
4607 va_start(ap, format);
4608 proto_tree_set_representation_value(pi, format, ap);
4615 /* Set the FT_INT{40,48,56,64} value */
4617 proto_tree_set_int64(field_info *fi, gint64 value)
4619 header_field_info *hfinfo;
4623 hfinfo = fi->hfinfo;
4626 if (hfinfo->bitmask) {
4627 /* Mask out irrelevant portions */
4628 integer &= hfinfo->bitmask;
4631 integer >>= hfinfo_bitshift(hfinfo);
4633 no_of_bits = ws_count_ones(hfinfo->bitmask);
4634 integer = ws_sign_ext64(integer, no_of_bits);
4637 fvalue_set_sinteger64(&fi->value, integer);
4641 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4642 gint start, gint length, gint64 value,
4643 const char *format, ...)
4648 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
4650 TRY_TO_FAKE_THIS_REPR(pi);
4652 va_start(ap, format);
4653 proto_tree_set_representation(pi, format, ap);
4660 /* Add a FT_EUI64 to a proto_tree */
4662 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
4663 gint length, const guint64 value)
4666 header_field_info *hfinfo;
4668 CHECK_FOR_NULL_TREE(tree);
4670 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
4672 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_EUI64);
4674 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
4675 proto_tree_set_eui64(PNODE_FINFO(pi), value);
4681 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4682 gint start, gint length, const guint64 value,
4683 const char *format, ...)
4688 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
4690 va_start(ap, format);
4691 proto_tree_set_representation_value(pi, format, ap);
4699 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
4700 gint start, gint length, const guint64 value,
4701 const char *format, ...)
4706 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
4708 TRY_TO_FAKE_THIS_REPR(pi);
4710 va_start(ap, format);
4711 proto_tree_set_representation(pi, format, ap);
4718 /* Set the FT_EUI64 value */
4720 proto_tree_set_eui64(field_info *fi, const guint64 value)
4722 fvalue_set_uinteger64(&fi->value, value);
4725 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding)
4729 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
4731 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
4735 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
4737 proto_tree_add_node(proto_tree *tree, field_info *fi)
4739 proto_node *pnode, *tnode, *sibling;
4744 * Restrict our depth. proto_tree_traverse_pre_order and
4745 * proto_tree_traverse_post_order (and possibly others) are recursive
4746 * so we need to be mindful of our stack size.
4748 if (tree->first_child == NULL) {
4749 for (tnode = tree; tnode != NULL; tnode = tnode->parent) {
4751 if (G_UNLIKELY(depth > MAX_TREE_LEVELS)) {
4752 THROW_MESSAGE(DissectorError, wmem_strdup_printf(wmem_packet_scope(),
4753 "Maximum tree depth %d exceeded for \"%s\" - \"%s\" (%s:%u)",
4755 fi->hfinfo->name, fi->hfinfo->abbrev, G_STRFUNC, __LINE__));
4761 * Make sure "tree" is ready to have subtrees under it, by
4762 * checking whether it's been given an ett_ value.
4764 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
4765 * node of the protocol tree. That node is not displayed,
4766 * so it doesn't need an ett_ value to remember whether it
4770 tfi = PNODE_FINFO(tnode);
4771 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
4772 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
4773 "\"%s\" - \"%s\" tfi->tree_type: %d invalid (%s:%u)",
4774 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
4775 /* XXX - is it safe to continue here? */
4778 pnode = wmem_new(PNODE_POOL(tree), proto_node);
4779 PROTO_NODE_INIT(pnode);
4780 pnode->parent = tnode;
4781 PNODE_FINFO(pnode) = fi;
4782 pnode->tree_data = PTREE_DATA(tree);
4784 if (tnode->last_child != NULL) {
4785 sibling = tnode->last_child;
4786 DISSECTOR_ASSERT(sibling->next == NULL);
4787 sibling->next = pnode;
4789 tnode->first_child = pnode;
4790 tnode->last_child = pnode;
4792 tree_data_add_maybe_interesting_field(pnode->tree_data, fi);
4794 return (proto_item *)pnode;
4798 /* Generic way to allocate field_info and add to proto_tree.
4799 * Sets *pfi to address of newly-allocated field_info struct */
4801 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, gint start,
4808 get_hfi_length(hfinfo, tvb, start, length, &item_length);
4809 fi = new_field_info(tree, hfinfo, tvb, start, item_length);
4810 pi = proto_tree_add_node(tree, fi);
4817 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
4820 gint length_remaining;
4823 * We only allow a null tvbuff if the item has a zero length,
4824 * i.e. if there's no data backing it.
4826 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
4829 * XXX - in some protocols, there are 32-bit unsigned length
4830 * fields, so lengths in protocol tree and tvbuff routines
4831 * should really be unsigned. We should have, for those
4832 * field types for which "to the end of the tvbuff" makes sense,
4833 * additional routines that take no length argument and
4834 * add fields that run to the end of the tvbuff.
4836 if (*length == -1) {
4838 * For FT_NONE, FT_PROTOCOL, FT_BYTES, FT_STRING, and
4839 * FT_STRINGZPAD fields, a length of -1 means "set the
4840 * length to what remains in the tvbuff".
4842 * The assumption is either that
4844 * 1) the length of the item can only be determined
4845 * by dissection (typically true of items with
4846 * subitems, which are probably FT_NONE or
4851 * 2) if the tvbuff is "short" (either due to a short
4852 * snapshot length or due to lack of reassembly of
4853 * fragments/segments/whatever), we want to display
4854 * what's available in the field (probably FT_BYTES
4855 * or FT_STRING) and then throw an exception later
4859 * 3) the field is defined to be "what's left in the
4862 * so we set the length to what remains in the tvbuff so
4863 * that, if we throw an exception while dissecting, it
4864 * has what is probably the right value.
4866 * For FT_STRINGZ, it means "the string is null-terminated,
4867 * not null-padded; set the length to the actual length
4868 * of the string", and if the tvbuff if short, we just
4869 * throw an exception.
4871 * It's not valid for any other type of field. For those
4872 * fields, we treat -1 the same way we treat other
4873 * negative values - we assume the length is a Really
4874 * Big Positive Number, and throw a ReportedBoundsError
4875 * exception, under the assumption that the Really Big
4876 * Length would run past the end of the packet.
4878 switch (hfinfo->type) {
4886 * We allow FT_PROTOCOLs to be zero-length -
4887 * for example, an ONC RPC NULL procedure has
4888 * neither arguments nor reply, so the
4889 * payload for that protocol is empty.
4891 * We also allow the others to be zero-length -
4892 * because that's the way the code has been for a
4895 * However, we want to ensure that the start
4896 * offset is not *past* the byte past the end
4897 * of the tvbuff: we throw an exception in that
4900 *length = tvb_captured_length(tvb) ? tvb_ensure_captured_length_remaining(tvb, start) : 0;
4901 DISSECTOR_ASSERT(*length >= 0);
4906 * Leave the length as -1, so our caller knows
4912 THROW(ReportedBoundsError);
4913 DISSECTOR_ASSERT_NOT_REACHED();
4915 *item_length = *length;
4917 *item_length = *length;
4918 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
4920 * These types are for interior nodes of the
4921 * tree, and don't have data associated with
4922 * them; if the length is negative (XXX - see
4923 * above) or goes past the end of the tvbuff,
4924 * cut it short at the end of the tvbuff.
4925 * That way, if this field is selected in
4926 * Wireshark, we don't highlight stuff past
4927 * the end of the data.
4929 /* XXX - what to do, if we don't have a tvb? */
4931 length_remaining = tvb_captured_length_remaining(tvb, start);
4932 if (*item_length < 0 ||
4933 (*item_length > 0 &&
4934 (length_remaining < *item_length)))
4935 *item_length = length_remaining;
4938 if (*item_length < 0) {
4939 THROW(ReportedBoundsError);
4945 get_full_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
4946 gint length, guint item_length, const gint encoding)
4951 * We need to get the correct item length here.
4952 * That's normally done by proto_tree_new_item(),
4953 * but we won't be calling it.
4955 switch (hfinfo->type) {
4961 * The length is the specified length.
4967 * Map all non-zero values to little-endian for
4968 * backwards compatibility.
4970 n = get_uint_value(NULL, tvb, start, length,
4971 encoding ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN);
4977 /* XXX - make these just FT_UINT? */
4986 /* XXX - make these just FT_INT? */
5011 * The length is the specified length.
5017 report_type_length_mismatch(NULL, "a string", length, TRUE);
5020 /* This can throw an exception */
5021 /* XXX - do this without fetching the string? */
5022 tvb_get_stringz_enc(wmem_packet_scope(), tvb, start, &length, encoding);
5024 item_length = length;
5027 case FT_UINT_STRING:
5028 n = get_uint_value(NULL, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
5033 case FT_ABSOLUTE_TIME:
5034 case FT_RELATIVE_TIME:
5035 case FT_IEEE_11073_SFLOAT:
5036 case FT_IEEE_11073_FLOAT:
5038 * The length is the specified length.
5043 g_error("hfinfo->type %d (%s) not handled\n",
5045 ftype_name(hfinfo->type));
5046 DISSECTOR_ASSERT_NOT_REACHED();
5053 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
5054 const gint start, const gint item_length)
5058 FIELD_INFO_NEW(PNODE_POOL(tree), fi);
5060 fi->hfinfo = hfinfo;
5062 fi->start += (tvb)?tvb_raw_offset(tvb):0;
5063 fi->length = item_length;
5066 if (!PTREE_DATA(tree)->visible)
5067 FI_SET_FLAG(fi, FI_HIDDEN);
5068 fvalue_init(&fi->value, fi->hfinfo->type);
5071 /* add the data source tvbuff */
5072 fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
5074 fi->appendix_start = 0;
5075 fi->appendix_length = 0;
5080 /* If the protocol tree is to be visible, set the representation of a
5081 proto_tree entry with the name of the field for the item and with
5082 the value formatted with the supplied printf-style format and
5085 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
5089 /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
5090 * items string representation */
5091 if (PTREE_DATA(pi)->visible && !PROTO_ITEM_IS_HIDDEN(pi)) {
5093 field_info *fi = PITEM_FINFO(pi);
5094 header_field_info *hf;
5096 DISSECTOR_ASSERT(fi);
5100 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
5101 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
5105 if (IS_FT_UINT(hf->type))
5106 val = fvalue_get_uinteger(&fi->value);
5108 val = fvalue_get_uinteger64(&fi->value);
5110 val <<= hfinfo_bitshift(hf);
5112 p = decode_bitfield_value(fi->rep->representation, val, hf->bitmask, hfinfo_container_bitwidth(hf));
5113 ret = (int) (p - fi->rep->representation);
5116 /* put in the hf name */
5117 ret += g_snprintf(fi->rep->representation + ret, ITEM_LABEL_LENGTH - ret, "%s: ", hf->name);
5119 /* If possible, Put in the value of the string */
5120 if (ret < ITEM_LABEL_LENGTH) {
5121 ret += g_vsnprintf(fi->rep->representation + ret,
5122 ITEM_LABEL_LENGTH - ret, format, ap);
5124 if (ret >= ITEM_LABEL_LENGTH) {
5125 /* Uh oh, we don't have enough room. Tell the user
5126 * that the field is truncated.
5128 LABEL_MARK_TRUNCATED_START(fi->rep->representation);
5133 /* If the protocol tree is to be visible, set the representation of a
5134 proto_tree entry with the representation formatted with the supplied
5135 printf-style format and argument list. */
5137 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
5139 int ret; /*tmp return value */
5140 field_info *fi = PITEM_FINFO(pi);
5142 DISSECTOR_ASSERT(fi);
5144 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
5145 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
5146 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
5148 if (ret >= ITEM_LABEL_LENGTH) {
5149 /* Uh oh, we don't have enough room. Tell the user
5150 * that the field is truncated.
5152 LABEL_MARK_TRUNCATED_START(fi->rep->representation);
5158 hfinfo_format_text(const header_field_info *hfinfo, const guchar *string)
5160 switch (hfinfo->display) {
5162 return format_text(NULL, string, strlen(string));
5165 return format_text_wsp(string, strlen(string));
5168 /* XXX, format_unicode_text() */
5169 return wmem_strdup(NULL, string);
5172 return format_text(NULL, string, strlen(string));
5176 protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
5178 gsize res = g_strlcpy(dest, src, dest_size);
5180 if (res > dest_size)
5185 static header_field_info *
5186 hfinfo_same_name_get_prev(const header_field_info *hfinfo)
5188 header_field_info *dup_hfinfo;
5190 if (hfinfo->same_name_prev_id == -1)
5192 PROTO_REGISTRAR_GET_NTH(hfinfo->same_name_prev_id, dup_hfinfo);
5197 hfinfo_remove_from_gpa_name_map(const header_field_info *hfinfo)
5199 g_free(last_field_name);
5200 last_field_name = NULL;
5202 if (!hfinfo->same_name_next && hfinfo->same_name_prev_id == -1) {
5203 /* No hfinfo with the same name */
5204 g_hash_table_steal(gpa_name_map, hfinfo->abbrev);
5208 if (hfinfo->same_name_next) {
5209 hfinfo->same_name_next->same_name_prev_id = hfinfo->same_name_prev_id;
5212 if (hfinfo->same_name_prev_id != -1) {
5213 header_field_info *same_name_prev = hfinfo_same_name_get_prev(hfinfo);
5214 same_name_prev->same_name_next = hfinfo->same_name_next;
5215 if (!hfinfo->same_name_next) {
5216 /* It's always the latest added hfinfo which is stored in gpa_name_map */
5217 g_hash_table_insert(gpa_name_map, (gpointer) (same_name_prev->abbrev), same_name_prev);
5222 /* -------------------------- */
5224 proto_custom_set(proto_tree* tree, GSList *field_ids, gint occurrence,
5225 gchar *result, gchar *expr, const int size)
5230 ipv4_addr_and_mask *ipv4;
5231 struct e_in6_addr *ipv6;
5233 guint32 n_addr; /* network-order IPv4 address */
5235 const true_false_string *tfstring;
5237 int len, prev_len = 0, last, i, offset_r = 0, offset_e = 0;
5239 field_info *finfo = NULL;
5240 header_field_info* hfinfo;
5241 const gchar *abbrev = NULL;
5243 const char *hf_str_val;
5244 char number_buf[48];
5245 const char *number_out;
5251 g_assert(field_ids != NULL);
5252 while ((field_idx = (int *) g_slist_nth_data(field_ids, ii++))) {
5253 field_id = *field_idx;
5254 PROTO_REGISTRAR_GET_NTH((guint)field_id, hfinfo);
5256 /* do we need to rewind ? */
5260 if (occurrence < 0) {
5261 /* Search other direction */
5262 while (hfinfo->same_name_prev_id != -1) {
5263 PROTO_REGISTRAR_GET_NTH(hfinfo->same_name_prev_id, hfinfo);
5268 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
5270 if (!finfos || !(len = g_ptr_array_len(finfos))) {
5271 if (occurrence < 0) {
5272 hfinfo = hfinfo->same_name_next;
5274 hfinfo = hfinfo_same_name_get_prev(hfinfo);
5279 /* Are there enough occurrences of the field? */
5280 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
5281 if (occurrence < 0) {
5282 hfinfo = hfinfo->same_name_next;
5284 hfinfo = hfinfo_same_name_get_prev(hfinfo);
5290 /* Calculate single index or set outer bounderies */
5291 if (occurrence < 0) {
5292 i = occurrence + len + prev_len;
5294 } else if (occurrence > 0) {
5295 i = occurrence - 1 - prev_len;
5302 prev_len += len; /* Count handled occurrences */
5305 finfo = (field_info *)g_ptr_array_index(finfos, i);
5307 if (offset_r && (offset_r < (size - 2)))
5308 result[offset_r++] = ',';
5310 if (offset_e && (offset_e < (size - 2)))
5311 expr[offset_e++] = ',';
5313 switch (hfinfo->type) {
5315 case FT_NONE: /* Nothing to add */
5316 if (offset_r == 0) {
5318 } else if (result[offset_r-1] == ',') {
5319 result[offset_r-1] = '\0';
5324 /* prevent multiple "yes" entries by setting result directly */
5325 g_strlcpy(result, "Yes", size);
5330 bytes = (guint8 *)fvalue_get(&finfo->value);
5332 switch(hfinfo->display)
5335 str = bytestring_to_str(NULL, bytes, fvalue_length(&finfo->value), '.');
5338 str = bytestring_to_str(NULL, bytes, fvalue_length(&finfo->value), '-');
5341 str = bytestring_to_str(NULL, bytes, fvalue_length(&finfo->value), ':');
5344 str = bytestring_to_str(NULL, bytes, fvalue_length(&finfo->value), ' ');
5348 if (prefs.display_byte_fields_with_spaces)
5350 str = bytestring_to_str(NULL, bytes, fvalue_length(&finfo->value), ' ');
5354 str = bytes_to_str(NULL, bytes, fvalue_length(&finfo->value));
5358 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5359 wmem_free(NULL, str);
5362 if (hfinfo->display & BASE_ALLOW_ZERO) {
5363 offset_r += protoo_strlcpy(result+offset_r, "<none>", size-offset_r);
5365 offset_r += protoo_strlcpy(result+offset_r, "<MISSING>", size-offset_r);
5370 case FT_ABSOLUTE_TIME:
5371 tmpbuf = abs_time_to_str(NULL, (const nstime_t *)fvalue_get(&finfo->value), (absolute_time_display_e)hfinfo->display, TRUE);
5372 offset_r += protoo_strlcpy(result+offset_r,
5375 wmem_free(NULL, tmpbuf);
5378 case FT_RELATIVE_TIME:
5379 tmpbuf = rel_time_to_secs_str(NULL, (const nstime_t *)fvalue_get(&finfo->value));
5380 offset_r += protoo_strlcpy(result+offset_r,
5383 wmem_free(NULL, tmpbuf);
5387 number64 = fvalue_get_uinteger64(&finfo->value);
5388 tfstring = (const true_false_string *)&tfs_true_false;
5389 if (hfinfo->strings) {
5390 tfstring = (const struct true_false_string*) hfinfo->strings;
5392 offset_r += protoo_strlcpy(result+offset_r,
5394 tfstring->true_string :
5395 tfstring->false_string, size-offset_r);
5397 offset_e += protoo_strlcpy(expr+offset_e,
5398 number64 ? "1" : "0", size-offset_e);
5403 number = fvalue_get_uinteger(&finfo->value);
5405 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) {
5406 gchar tmp[ITEM_LABEL_LENGTH];
5407 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5409 DISSECTOR_ASSERT(fmtfunc);
5410 fmtfunc(tmp, number);
5412 offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
5414 } else if (hfinfo->strings) {
5415 number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
5418 number_out = hfinfo_char_value_format_display(BASE_HEX, number_buf, number);
5420 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5423 number_out = hfinfo_char_value_format(hfinfo, number_buf, number);
5425 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5428 if (hf_str_val && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
5429 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
5431 number_out = hfinfo_char_value_format(hfinfo, number_buf, number);
5433 g_strlcpy(expr+offset_e, number_out, size-offset_e);
5436 offset_e = (int)strlen(expr);
5439 /* XXX - make these just FT_NUMBER? */
5450 number = IS_FT_INT(hfinfo->type) ?
5451 (guint32) fvalue_get_sinteger(&finfo->value) :
5452 fvalue_get_uinteger(&finfo->value);
5454 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) {
5455 gchar tmp[ITEM_LABEL_LENGTH];
5456 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
5458 DISSECTOR_ASSERT(fmtfunc);
5459 fmtfunc(tmp, number);
5461 offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
5463 } else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) {
5464 if (hfinfo->display & BASE_UNIT_STRING) {
5465 number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
5466 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5467 hf_str_val = hf_try_val_to_str(number, hfinfo);
5468 offset_r += protoo_strlcpy(result+offset_r, hf_str_val, size-offset_r);
5470 number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
5473 number_out = hfinfo_number_value_format_display(hfinfo, hfinfo->display, number_buf, number);
5475 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5478 number_out = hfinfo_number_value_format(hfinfo, number_buf, number);
5480 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5483 if (hf_str_val && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
5484 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
5486 number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
5488 g_strlcpy(expr+offset_e, number_out, size-offset_e);
5491 offset_e = (int)strlen(expr);
5503 number64 = IS_FT_INT(hfinfo->type) ?
5504 (guint64) fvalue_get_sinteger64(&finfo->value) :
5505 fvalue_get_uinteger64(&finfo->value);
5507 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) {
5508 gchar tmp[ITEM_LABEL_LENGTH];
5509 custom_fmt_func_64_t fmtfunc64 = (custom_fmt_func_64_t)hfinfo->strings;
5511 DISSECTOR_ASSERT(fmtfunc64);
5512 fmtfunc64(tmp, number64);
5513 offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
5514 } else if (hfinfo->strings) {
5515 if (hfinfo->display & BASE_UNIT_STRING) {
5516 number_out = hfinfo_numeric_value_format64(hfinfo, number_buf, number64);
5517 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5518 hf_str_val = hf_try_val64_to_str(number64, hfinfo);
5519 offset_r += protoo_strlcpy(result+offset_r, hf_str_val, size-offset_r);
5521 number_out = hf_str_val = hf_try_val64_to_str(number64, hfinfo);
5524 number_out = hfinfo_number_value_format_display64(hfinfo, hfinfo->display, number_buf, number64);
5526 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5529 number_out = hfinfo_number_value_format64(hfinfo, number_buf, number64);
5531 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
5534 if (hf_str_val && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
5535 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
5537 number_out = hfinfo_numeric_value_format64(hfinfo, number_buf, number64);
5539 g_strlcpy(expr+offset_e, number_out, size-offset_e);
5542 offset_e = (int)strlen(expr);
5546 str = eui64_to_str(NULL, fvalue_get_uinteger64(&finfo->value));
5547 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5548 wmem_free(NULL, str);
5552 ipv4 = (ipv4_addr_and_mask *)fvalue_get(&finfo->value);
5553 n_addr = ipv4_get_net_order_addr(ipv4);
5554 set_address (&addr, AT_IPv4, 4, &n_addr);
5555 address_to_str_buf(&addr, result+offset_r, size-offset_r);
5556 offset_r = (int)strlen(result);
5560 ipv6 = (struct e_in6_addr *)fvalue_get(&finfo->value);
5561 set_address (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
5562 address_to_str_buf(&addr, result+offset_r, size-offset_r);
5563 offset_r = (int)strlen(result);
5567 set_address (&addr, AT_FCWWN, FCWWN_ADDR_LEN, fvalue_get(&finfo->value));
5568 address_to_str_buf(&addr, result+offset_r, size-offset_r);
5569 offset_r = (int)strlen(result);
5573 set_address (&addr, AT_ETHER, FT_ETHER_LEN, fvalue_get(&finfo->value));
5574 address_to_str_buf(&addr, result+offset_r, size-offset_r);
5575 offset_r = (int)strlen(result);
5579 str = guid_to_str(NULL, (e_guid_t *)fvalue_get(&finfo->value));
5580 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5581 wmem_free(NULL, str);
5585 bytes = (guint8 *)fvalue_get(&finfo->value);
5586 str = rel_oid_resolved_from_encoded(NULL, bytes, fvalue_length(&finfo->value));
5587 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5588 wmem_free(NULL, str);
5590 str = rel_oid_encoded2string(NULL, bytes, fvalue_length(&finfo->value));
5591 offset_e += protoo_strlcpy(expr+offset_e, str, size-offset_e);
5592 wmem_free(NULL, str);
5596 bytes = (guint8 *)fvalue_get(&finfo->value);
5597 str = oid_resolved_from_encoded(NULL, bytes, fvalue_length(&finfo->value));
5598 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5599 wmem_free(NULL, str);
5601 str = oid_encoded2string(NULL, bytes, fvalue_length(&finfo->value));
5602 offset_e += protoo_strlcpy(expr+offset_e, str, size-offset_e);
5603 wmem_free(NULL, str);
5607 bytes = (guint8 *)fvalue_get(&finfo->value);
5608 str = print_system_id(NULL, bytes, fvalue_length(&finfo->value));
5609 offset_r += protoo_strlcpy(result+offset_r, str, size-offset_r);
5610 offset_e += protoo_strlcpy(expr+offset_e, str, size-offset_e);
5611 wmem_free(NULL, str);
5615 if (hfinfo->display & BASE_UNIT_STRING) {
5616 double d_value = fvalue_get_floating(&finfo->value);
5617 g_snprintf(result+offset_r, size-offset_r,
5618 "%." G_STRINGIFY(FLT_DIG) "g%s", d_value,
5619 unit_name_string_get_double(d_value, (unit_name_string*)hfinfo->strings));
5621 g_snprintf(result+offset_r, size-offset_r,
5622 "%." G_STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
5624 offset_r = (int)strlen(result);
5628 if (hfinfo->display & BASE_UNIT_STRING) {
5629 double d_value = fvalue_get_floating(&finfo->value);
5630 g_snprintf(result+offset_r, size-offset_r,
5631 "%." G_STRINGIFY(DBL_DIG) "g%s", d_value,
5632 unit_name_string_get_double(d_value, (unit_name_string*)hfinfo->strings));
5634 g_snprintf(result+offset_r, size-offset_r,
5635 "%." G_STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
5637 offset_r = (int)strlen(result);
5642 case FT_UINT_STRING:
5644 bytes = (guint8 *)fvalue_get(&finfo->value);
5645 str = hfinfo_format_text(hfinfo, bytes);
5646 offset_r += protoo_strlcpy(result+offset_r,
5647 str, size-offset_r);
5648 wmem_free(NULL, str);
5651 case FT_IEEE_11073_SFLOAT:
5652 str = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DISPLAY, hfinfo->display);
5653 g_snprintf(result+offset_r, size-offset_r,
5656 wmem_free(NULL, str);
5657 offset_r = (int)strlen(result);
5660 case FT_IEEE_11073_FLOAT:
5661 str = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DISPLAY, hfinfo->display);
5662 g_snprintf(result+offset_r, size-offset_r,
5665 offset_r = (int)strlen(result);
5666 wmem_free(NULL, str);
5669 case FT_IPXNET: /*XXX really No column custom ?*/
5672 g_error("hfinfo->type %d (%s) not handled\n",
5674 ftype_name(hfinfo->type));
5675 DISSECTOR_ASSERT_NOT_REACHED();
5681 switch (hfinfo->type) {
5705 /* for these types, "expr" is filled in the loop above */
5709 /* for all others, just copy "result" to "expr" */
5710 g_strlcpy(expr, result, size);
5715 /* Store abbrev for return value */
5716 abbrev = hfinfo->abbrev;
5719 if (occurrence == 0) {
5720 /* Fetch next hfinfo with same name (abbrev) */
5721 hfinfo = hfinfo_same_name_get_prev(hfinfo);
5728 return abbrev ? abbrev : "";
5732 /* Set text of proto_item after having already been created. */
5734 proto_item_set_text(proto_item *pi, const char *format, ...)
5736 field_info *fi = NULL;
5739 TRY_TO_FAKE_THIS_REPR_VOID(pi);
5741 fi = PITEM_FINFO(pi);
5746 ITEM_LABEL_FREE(PNODE_POOL(pi), fi->rep);
5750 va_start(ap, format);
5751 proto_tree_set_representation(pi, format, ap);
5755 /* Append to text of proto_item after having already been created. */
5757 proto_item_append_text(proto_item *pi, const char *format, ...)
5759 field_info *fi = NULL;
5763 TRY_TO_FAKE_THIS_REPR_VOID(pi);
5765 fi = PITEM_FINFO(pi);
5770 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
5772 * If we don't already have a representation,
5773 * generate the default representation.
5775 if (fi->rep == NULL) {
5776 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
5777 proto_item_fill_label(fi, fi->rep->representation);
5780 curlen = strlen(fi->rep->representation);
5781 if (ITEM_LABEL_LENGTH > curlen) {
5782 va_start(ap, format);
5783 g_vsnprintf(fi->rep->representation + curlen,
5784 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
5790 /* Prepend to text of proto_item after having already been created. */
5792 proto_item_prepend_text(proto_item *pi, const char *format, ...)
5794 field_info *fi = NULL;
5795 char representation[ITEM_LABEL_LENGTH];
5798 TRY_TO_FAKE_THIS_REPR_VOID(pi);
5800 fi = PITEM_FINFO(pi);
5805 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
5807 * If we don't already have a representation,
5808 * generate the default representation.
5810 if (fi->rep == NULL) {
5811 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
5812 proto_item_fill_label(fi, representation);
5814 g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
5816 va_start(ap, format);
5817 g_vsnprintf(fi->rep->representation,
5818 ITEM_LABEL_LENGTH, format, ap);
5820 g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
5825 finfo_set_len(field_info *fi, const gint length)
5827 DISSECTOR_ASSERT(length >= 0);
5828 fi->length = length;
5831 * You cannot just make the "len" field of a GByteArray
5832 * larger, if there's no data to back that length;
5833 * you can only make it smaller.
5835 if (fi->value.ftype->ftype == FT_BYTES && length <= (gint)fi->value.value.bytes->len)
5836 fi->value.value.bytes->len = length;
5840 proto_item_set_len(proto_item *pi, const gint length)
5844 TRY_TO_FAKE_THIS_REPR_VOID(pi);
5846 fi = PITEM_FINFO(pi);
5850 finfo_set_len(fi, length);
5854 * Sets the length of the item based on its start and on the specified
5855 * offset, which is the offset past the end of the item; as the start
5856 * in the item is relative to the beginning of the data source tvbuff,
5857 * we need to pass in a tvbuff - the end offset is relative to the beginning
5861 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
5866 TRY_TO_FAKE_THIS_REPR_VOID(pi);
5868 fi = PITEM_FINFO(pi);
5872 end += tvb_raw_offset(tvb);
5873 DISSECTOR_ASSERT(end >= fi->start);
5874 length = end - fi->start;
5876 finfo_set_len(fi, length);
5880 proto_item_get_len(const proto_item *pi)
5882 field_info *fi = PITEM_FINFO(pi);
5883 return fi ? fi->length : -1;
5887 proto_tree_create_root(packet_info *pinfo)
5891 /* Initialize the proto_node */
5892 pnode = g_slice_new(proto_tree);
5893 PROTO_NODE_INIT(pnode);
5894 pnode->parent = NULL;
5895 PNODE_FINFO(pnode) = NULL;
5896 pnode->tree_data = g_slice_new(tree_data_t);
5898 /* Make sure we can access pinfo everywhere */
5899 pnode->tree_data->pinfo = pinfo;
5901 /* Don't initialize the tree_data_t. Wait until we know we need it */
5902 pnode->tree_data->interesting_hfids = NULL;
5904 /* Set the default to FALSE so it's easier to
5905 * find errors; if we expect to see the protocol tree
5906 * but for some reason the default 'visible' is not
5907 * changed, then we'll find out very quickly. */
5908 pnode->tree_data->visible = FALSE;
5910 /* Make sure that we fake protocols (if possible) */
5911 pnode->tree_data->fake_protocols = TRUE;
5913 /* Keep track of the number of children */
5914 pnode->tree_data->count = 0;
5916 return (proto_tree *)pnode;
5920 /* "prime" a proto_tree with a single hfid that a dfilter
5921 * is interested in. */
5923 proto_tree_prime_with_hfid(proto_tree *tree _U_, const gint hfid)
5925 header_field_info *hfinfo;
5927 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
5928 /* this field is referenced by a filter so increase the refcount.
5929 also increase the refcount for the parent, i.e the protocol.
5931 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
5932 /* only increase the refcount if there is a parent.
5933 if this is a protocol and not a field then parent will be -1
5934 and there is no parent to add any refcounting for.
5936 if (hfinfo->parent != -1) {
5937 header_field_info *parent_hfinfo;
5938 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
5940 /* Mark parent as indirectly referenced unless it is already directly
5941 * referenced, i.e. the user has specified the parent in a filter.
5943 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
5944 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
5949 proto_item_add_subtree(proto_item *pi, const gint idx) {
5955 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
5957 fi = PITEM_FINFO(pi);
5959 return (proto_tree *)pi;
5961 fi->tree_type = idx;
5963 return (proto_tree *)pi;
5967 proto_item_get_subtree(proto_item *pi) {
5972 fi = PITEM_FINFO(pi);
5973 if ( (!fi) || (fi->tree_type == -1) )
5975 return (proto_tree *)pi;
5979 proto_item_get_parent(const proto_item *ti) {
5986 proto_item_get_parent_nth(proto_item *ti, int gen) {
5999 proto_tree_get_parent(proto_tree *tree) {
6002 return (proto_item *)tree;
6006 proto_tree_get_parent_tree(proto_tree *tree) {
6010 /* we're the root tree, there's no parent
6011 return ourselves so the caller has at least a tree to attach to */
6015 return (proto_tree *)tree->parent;
6019 proto_tree_get_root(proto_tree *tree) {
6022 while (tree->parent) {
6023 tree = tree->parent;
6029 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
6030 proto_item *item_to_move)
6033 /* Revert part of: https://code.wireshark.org/review/gitweb?p=wireshark.git;a=commit;h=00c05ed3fdfa9287422e6e1fc9bd6ea8b31ca4ee
6034 * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5500
6036 /* This function doesn't generate any values. It only reorganizes the prococol tree
6037 * so we can bail out immediately if it isn't visible. */
6038 if (!tree || !PTREE_DATA(tree)->visible)
6041 DISSECTOR_ASSERT(item_to_move->parent == tree);
6042 DISSECTOR_ASSERT(fixed_item->parent == tree);
6044 /*** cut item_to_move out ***/
6046 /* is item_to_move the first? */
6047 if (tree->first_child == item_to_move) {
6048 /* simply change first child to next */
6049 tree->first_child = item_to_move->next;
6051 DISSECTOR_ASSERT(tree->last_child != item_to_move);
6053 proto_item *curr_item;
6054 /* find previous and change it's next */
6055 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
6056 if (curr_item->next == item_to_move) {
6061 DISSECTOR_ASSERT(curr_item);
6063 curr_item->next = item_to_move->next;
6065 /* fix last_child if required */
6066 if (tree->last_child == item_to_move) {
6067 tree->last_child = curr_item;
6071 /*** insert to_move after fixed ***/
6072 item_to_move->next = fixed_item->next;
6073 fixed_item->next = item_to_move;
6074 if (tree->last_child == fixed_item) {
6075 tree->last_child = item_to_move;
6080 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
6088 fi = PTREE_FINFO(tree);
6092 start += tvb_raw_offset(tvb);
6093 DISSECTOR_ASSERT(start >= 0);
6094 DISSECTOR_ASSERT(length >= 0);
6096 fi->appendix_start = start;
6097 fi->appendix_length = length;
6101 proto_register_protocol(const char *name, const char *short_name,
6102 const char *filter_name)
6104 protocol_t *protocol;
6105 const protocol_t *existing_protocol = NULL;
6106 header_field_info *hfinfo;
6108 const char *existing_name;
6112 gboolean found_invalid;
6115 * Make sure there's not already a protocol with any of those
6116 * names. Crash if there is, as that's an error in the code
6117 * or an inappropriate plugin.
6118 * This situation has to be fixed to not register more than one
6119 * protocol with the same name.
6121 * This is done by reducing the number of strcmp (and alike) calls
6122 * as much as possible, as this significally slows down startup time.
6124 * Drawback: As a hash value is used to reduce insert time,
6125 * this might lead to a hash collision.
6126 * However, although we have somewhat over 1000 protocols, we're using
6127 * a 32 bit int so this is very, very unlikely.
6130 key = (gint *)g_malloc (sizeof(gint));
6131 *key = wrs_str_hash(name);
6133 existing_name = (const char *)g_hash_table_lookup(proto_names, key);
6134 if (existing_name != NULL) {
6135 /* g_error will terminate the program */
6136 g_error("Duplicate protocol name \"%s\"!"
6137 " This might be caused by an inappropriate plugin or a development error.", name);
6139 g_hash_table_insert(proto_names, key, (gpointer)name);
6141 existing_protocol = (const protocol_t *)g_hash_table_lookup(proto_short_names, short_name);
6142 if (existing_protocol != NULL) {
6143 g_error("Duplicate protocol short_name \"%s\"!"
6144 " This might be caused by an inappropriate plugin or a development error.", short_name);
6147 found_invalid = FALSE;
6148 for (i = 0; filter_name[i]; i++) {
6150 if (!(g_ascii_islower(c) || g_ascii_isdigit(c) || c == '-' || c == '_' || c == '.')) {
6151 found_invalid = TRUE;
6154 if (found_invalid) {
6155 g_error("Protocol filter name \"%s\" has one or more invalid characters."
6156 " Allowed are lower characters, digits, '-', '_' and '.'."
6157 " This might be caused by an inappropriate plugin or a development error.", filter_name);
6159 existing_protocol = (const protocol_t *)g_hash_table_lookup(proto_filter_names, filter_name);
6160 if (existing_protocol != NULL) {
6161 g_error("Duplicate protocol filter_name \"%s\"!"
6162 " This might be caused by an inappropriate plugin or a development error.", filter_name);
6165 /* Add this protocol to the list of known protocols; the list
6166 is sorted by protocol short name. */
6167 protocol = g_new(protocol_t, 1);
6168 protocol->name = name;
6169 protocol->short_name = short_name;
6170 protocol->filter_name = filter_name;
6171 /*protocol->fields = g_ptr_array_new();*/
6172 /* Delegate until actually needed and use g_ptr_array_sized_new*/
6173 protocol->fields = NULL;
6174 protocol->is_enabled = TRUE; /* protocol is enabled by default */
6175 protocol->enabled_by_default = TRUE; /* see previous comment */
6176 protocol->can_toggle = TRUE;
6177 protocol->parent_proto_id = -1;
6178 protocol->heur_list = NULL;
6179 /* list will be sorted later by name, when all protocols completed registering */
6180 protocols = g_list_prepend(protocols, protocol);
6181 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, protocol);
6182 g_hash_table_insert(proto_short_names, (gpointer)short_name, protocol);
6184 /* Here we allocate a new header_field_info struct */
6185 hfinfo = g_slice_new(header_field_info);
6186 hfinfo->name = name;
6187 hfinfo->abbrev = filter_name;
6188 hfinfo->type = FT_PROTOCOL;
6189 hfinfo->display = BASE_NONE;
6190 hfinfo->strings = protocol;
6191 hfinfo->bitmask = 0;
6192 hfinfo->ref_type = HF_REF_TYPE_NONE;
6193 hfinfo->blurb = NULL;
6194 hfinfo->parent = -1; /* this field differentiates protos and fields */
6196 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
6197 protocol->proto_id = proto_id;
6202 proto_register_protocol_in_name_only(const char *name, const char *short_name, const char *filter_name, int parent_proto, enum ftenum field_type)
6204 protocol_t *protocol;
6205 header_field_info *hfinfo;
6208 gboolean found_invalid = FALSE;
6211 * Helper protocols don't need the strict rules as a "regular" protocol
6212 * Just register it in a list and make a hf_ field from it
6214 if ((field_type != FT_PROTOCOL) && (field_type != FT_BYTES)) {
6215 g_error("Pino \"%s\" must be of type FT_PROTOCOL or FT_BYTES.", name);
6218 if (parent_proto < 0) {
6219 g_error("Must have a valid parent protocol for helper protocol \"%s\"!"
6220 " This might be caused by an inappropriate plugin or a development error.", name);
6223 for (i = 0; filter_name[i]; i++) {
6225 if (!(g_ascii_islower(c) || g_ascii_isdigit(c) || c == '-' || c == '_' || c == '.')) {
6226 found_invalid = TRUE;
6229 if (found_invalid) {
6230 g_error("Protocol filter name \"%s\" has one or more invalid characters."
6231 " Allowed are lower characters, digits, '-', '_' and '.'."
6232 " This might be caused by an inappropriate plugin or a development error.", filter_name);
6235 /* Add this protocol to the list of helper protocols (just so it can be properly freed) */
6236 protocol = g_new(protocol_t, 1);
6237 protocol->name = name;
6238 protocol->short_name = short_name;
6239 protocol->filter_name = filter_name;
6240 protocol->fields = NULL;
6242 /* Enabling and toggling is really determined by parent protocol,
6243 but provide default values here */
6244 protocol->is_enabled = TRUE;
6245 protocol->enabled_by_default = TRUE;
6246 protocol->can_toggle = TRUE;
6248 protocol->parent_proto_id = parent_proto;
6249 protocol->heur_list = NULL;
6250 /* list will be sorted later by name, when all protocols completed registering */
6251 pino_protocols = g_list_prepend(pino_protocols, protocol);
6253 /* Here we allocate a new header_field_info struct */
6254 hfinfo = g_slice_new(header_field_info);
6255 hfinfo->name = name;
6256 hfinfo->abbrev = filter_name;
6257 hfinfo->type = field_type;
6258 hfinfo->display = BASE_NONE;
6259 if (field_type == FT_BYTES) {
6260 hfinfo->display |= (BASE_NO_DISPLAY_VALUE|BASE_PROTOCOL_INFO);
6262 hfinfo->strings = protocol;
6263 hfinfo->bitmask = 0;
6264 hfinfo->ref_type = HF_REF_TYPE_NONE;
6265 hfinfo->blurb = NULL;
6266 hfinfo->parent = -1; /* this field differentiates protos and fields */
6268 protocol->proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
6269 return protocol->proto_id;
6273 proto_deregister_protocol(const char *short_name)
6275 protocol_t *protocol;
6276 header_field_info *hfinfo;
6281 proto_id = proto_get_id_by_short_name(short_name);
6282 protocol = find_protocol_by_id(proto_id);
6283 if (protocol == NULL)
6286 key = wrs_str_hash(protocol->name);
6287 g_hash_table_remove(proto_names, &key);
6289 g_hash_table_remove(proto_short_names, (gpointer)short_name);
6290 g_hash_table_remove(proto_filter_names, (gpointer)protocol->filter_name);
6292 if (protocol->fields) {
6293 for (i = 0; i < protocol->fields->len; i++) {
6294 hfinfo = (header_field_info *)g_ptr_array_index(protocol->fields, i);
6295 hfinfo_remove_from_gpa_name_map(hfinfo);
6296 expert_deregister_expertinfo(hfinfo->abbrev);
6297 g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[hfinfo->id]);
6299 g_ptr_array_free(protocol->fields, TRUE);
6300 protocol->fields = NULL;
6303 /* Remove this protocol from the list of known protocols */
6304 protocols = g_list_remove(protocols, protocol);
6306 g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[proto_id]);
6307 g_hash_table_steal(gpa_name_map, protocol->filter_name);
6309 g_free(last_field_name);
6310 last_field_name = NULL;
6316 * Routines to use to iterate over the protocols.
6317 * The argument passed to the iterator routines is an opaque cookie to
6318 * their callers; it's the GList pointer for the current element in
6320 * The ID of the protocol is returned, or -1 if there is no protocol.
6323 proto_get_first_protocol(void **cookie)
6325 protocol_t *protocol;
6327 if (protocols == NULL)
6329 *cookie = protocols;
6330 protocol = (protocol_t *)protocols->data;
6331 return protocol->proto_id;
6335 proto_get_data_protocol(void *cookie)
6337 GList *list_item = (GList *)cookie;
6339 protocol_t *protocol = (protocol_t *)list_item->data;
6340 return protocol->proto_id;
6344 proto_get_next_protocol(void **cookie)
6346 GList *list_item = (GList *)*cookie;
6347 protocol_t *protocol;
6349 list_item = g_list_next(list_item);
6350 if (list_item == NULL)
6352 *cookie = list_item;
6353 protocol = (protocol_t *)list_item->data;
6354 return protocol->proto_id;
6357 /* XXX: Unfortunately certain functions in proto_hier_tree_model.c
6358 assume that the cookie stored by
6359 proto_get_(first|next)_protocol_field() will never have a
6360 value of NULL. So, to preserve this semantic, the cookie value
6361 below is adjusted so that the cookie value stored is 1 + the
6362 current (zero-based) array index.
6365 proto_get_first_protocol_field(const int proto_id, void **cookie)
6367 protocol_t *protocol = find_protocol_by_id(proto_id);
6369 if ((protocol == NULL) || (protocol->fields == NULL) || (protocol->fields->len == 0))
6372 *cookie = GUINT_TO_POINTER(0 + 1);
6373 return (header_field_info *)g_ptr_array_index(protocol->fields, 0);
6377 proto_get_next_protocol_field(const int proto_id, void **cookie)
6379 protocol_t *protocol = find_protocol_by_id(proto_id);
6380 guint i = GPOINTER_TO_UINT(*cookie) - 1;
6384 if ((protocol->fields == NULL) || (i >= protocol->fields->len))
6387 *cookie = GUINT_TO_POINTER(i + 1);
6388 return (header_field_info *)g_ptr_array_index(protocol->fields, i);
6392 find_protocol_by_id(const int proto_id)
6394 header_field_info *hfinfo;
6399 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
6400 if (hfinfo->type != FT_PROTOCOL) {
6401 DISSECTOR_ASSERT(hfinfo->display & BASE_PROTOCOL_INFO);
6403 return (protocol_t *)hfinfo->strings;
6407 proto_get_id(const protocol_t *protocol)
6409 return protocol->proto_id;
6413 proto_name_already_registered(const gchar *name)
6417 DISSECTOR_ASSERT_HINT(name, "No name present");
6419 key = wrs_str_hash(name);
6420 if (g_hash_table_lookup(proto_names, &key) != NULL)
6426 proto_get_id_by_filter_name(const gchar *filter_name)
6428 const protocol_t *protocol = NULL;
6430 DISSECTOR_ASSERT_HINT(filter_name, "No filter name present");
6432 protocol = (const protocol_t *)g_hash_table_lookup(proto_filter_names, filter_name);
6434 if (protocol == NULL)
6436 return protocol->proto_id;
6440 proto_get_id_by_short_name(const gchar *short_name)
6442 const protocol_t *protocol = NULL;
6444 DISSECTOR_ASSERT_HINT(short_name, "No short name present");
6446 protocol = (const protocol_t *)g_hash_table_lookup(proto_short_names, short_name);
6448 if (protocol == NULL)
6450 return protocol->proto_id;
6454 proto_get_protocol_name(const int proto_id)
6456 protocol_t *protocol;
6458 protocol = find_protocol_by_id(proto_id);
6460 if (protocol == NULL)
6462 return protocol->name;
6466 proto_get_protocol_short_name(const protocol_t *protocol)
6468 if (protocol == NULL)
6470 return protocol->short_name;
6474 proto_get_protocol_long_name(const protocol_t *protocol)
6476 if (protocol == NULL)
6478 return protocol->name;
6482 proto_get_protocol_filter_name(const int proto_id)
6484 protocol_t *protocol;
6486 protocol = find_protocol_by_id(proto_id);
6487 if (protocol == NULL)
6489 return protocol->filter_name;
6492 void proto_add_heuristic_dissector(protocol_t *protocol, const char *short_name)
6494 heur_dtbl_entry_t* heuristic_dissector;
6496 if (protocol == NULL)
6499 heuristic_dissector = find_heur_dissector_by_unique_short_name(short_name);
6500 if (heuristic_dissector != NULL)
6502 protocol->heur_list = g_list_prepend (protocol->heur_list, heuristic_dissector);
6506 void proto_heuristic_dissector_foreach(const protocol_t *protocol, GFunc func, gpointer user_data)
6508 if (protocol == NULL)
6511 g_list_foreach(protocol->heur_list, func, user_data);
6515 proto_get_frame_protocols(const wmem_list_t *layers, gboolean *is_ip,
6516 gboolean *is_tcp, gboolean *is_udp,
6517 gboolean *is_sctp, gboolean *is_ssl,
6519 gboolean *is_lte_rlc)
6521 wmem_list_frame_t *protos = wmem_list_head(layers);
6523 const char *proto_name;
6525 /* Walk the list of a available protocols in the packet and
6526 find "major" ones. */
6527 /* It might make more sense to assemble and return a bitfield. */
6528 while (protos != NULL)
6530 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
6531 proto_name = proto_get_protocol_filter_name(proto_id);
6533 if (is_ip && ((!strcmp(proto_name, "ip")) ||
6534 (!strcmp(proto_name, "ipv6")))) {
6536 } else if (is_tcp && !strcmp(proto_name, "tcp")) {
6538 } else if (is_udp && !strcmp(proto_name, "udp")) {
6540 } else if (is_sctp && !strcmp(proto_name, "sctp")) {
6542 } else if (is_ssl && !strcmp(proto_name, "ssl")) {
6544 } else if (is_rtp && !strcmp(proto_name, "rtp")) {
6546 } else if (is_lte_rlc && !strcmp(proto_name, "rlc-lte")) {
6550 protos = wmem_list_frame_next(protos);
6555 proto_is_frame_protocol(const wmem_list_t *layers, const char* proto_name)
6557 wmem_list_frame_t *protos = wmem_list_head(layers);
6561 /* Walk the list of a available protocols in the packet and
6562 find "major" ones. */
6563 /* It might make more sense to assemble and return a bitfield. */
6564 while (protos != NULL)
6566 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
6567 name = proto_get_protocol_filter_name(proto_id);
6569 if (!strcmp(name, proto_name))
6574 protos = wmem_list_frame_next(protos);
6581 proto_is_pino(const protocol_t *protocol)
6583 return (protocol->parent_proto_id != -1);
6587 proto_is_protocol_enabled(const protocol_t *protocol)
6589 //parent protocol determines enable/disable for helper dissectors
6590 if (proto_is_pino(protocol))
6591 return proto_is_protocol_enabled(find_protocol_by_id(protocol->parent_proto_id));
6593 return protocol->is_enabled;
6597 proto_is_protocol_enabled_by_default(const protocol_t *protocol)
6599 //parent protocol determines enable/disable for helper dissectors
6600 if (proto_is_pino(protocol))
6601 return proto_is_protocol_enabled_by_default(find_protocol_by_id(protocol->parent_proto_id));
6603 return protocol->enabled_by_default;
6607 proto_can_toggle_protocol(const int proto_id)
6609 protocol_t *protocol;
6611 protocol = find_protocol_by_id(proto_id);
6612 //parent protocol determines toggling for helper dissectors
6613 if (proto_is_pino(protocol))
6614 return proto_can_toggle_protocol(protocol->parent_proto_id);
6616 return protocol->can_toggle;
6620 proto_disable_by_default(const int proto_id)
6622 protocol_t *protocol;
6624 protocol = find_protocol_by_id(proto_id);
6625 DISSECTOR_ASSERT(protocol->can_toggle);
6626 DISSECTOR_ASSERT(proto_is_pino(protocol) == FALSE);
6627 protocol->is_enabled = FALSE;
6628 protocol->enabled_by_default = FALSE;
6632 proto_set_decoding(const int proto_id, const gboolean enabled)
6634 protocol_t *protocol;
6636 protocol = find_protocol_by_id(proto_id);
6637 DISSECTOR_ASSERT(protocol->can_toggle);
6638 DISSECTOR_ASSERT(proto_is_pino(protocol) == FALSE);
6639 protocol->is_enabled = enabled;
6643 proto_reenable_all(void)
6645 protocol_t *protocol;
6646 GList *list_item = protocols;
6648 if (protocols == NULL)
6652 protocol = (protocol_t *)list_item->data;
6653 if (protocol->can_toggle && protocol->enabled_by_default)
6654 protocol->is_enabled = TRUE;
6655 list_item = g_list_next(list_item);
6660 proto_set_cant_toggle(const int proto_id)
6662 protocol_t *protocol;
6664 protocol = find_protocol_by_id(proto_id);
6665 protocol->can_toggle = FALSE;
6669 proto_register_field_common(protocol_t *proto, header_field_info *hfi, const int parent)
6671 if (proto != NULL) {
6672 g_ptr_array_add(proto->fields, hfi);
6675 return proto_register_field_init(hfi, parent);
6678 /* for use with static arrays only, since we don't allocate our own copies
6679 of the header_field_info struct contained within the hf_register_info struct */
6681 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
6683 hf_register_info *ptr = hf;
6687 proto = find_protocol_by_id(parent);
6689 if (proto->fields == NULL) {
6690 proto->fields = g_ptr_array_sized_new(num_records);
6693 for (i = 0; i < num_records; i++, ptr++) {
6695 * Make sure we haven't registered this yet.
6696 * Most fields have variables associated with them
6697 * that are initialized to -1; some have array elements,
6698 * or possibly uninitialized variables, so we also allow
6699 * 0 (which is unlikely to be the field ID we get back
6700 * from "proto_register_field_init()").
6702 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
6704 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
6705 ptr->hfinfo.abbrev);
6709 *ptr->p_id = proto_register_field_common(proto, &ptr->hfinfo, parent);
6714 proto_register_fields_section(const int parent, header_field_info *hfi, const int num_records)
6719 proto = find_protocol_by_id(parent);
6721 if (proto->fields == NULL) {
6722 proto->fields = g_ptr_array_sized_new(num_records);
6725 for (i = 0; i < num_records; i++) {
6727 * Make sure we haven't registered this yet.
6729 if (hfi[i].id != -1) {
6731 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
6736 proto_register_field_common(proto, &hfi[i], parent);
6741 proto_register_fields_manual(const int parent, header_field_info **hfi, const int num_records)
6746 proto = find_protocol_by_id(parent);
6748 if (proto->fields == NULL) {
6749 proto->fields = g_ptr_array_sized_new(num_records);
6753 for (i = 0; i < num_records; i++) {
6755 * Make sure we haven't registered this yet.
6757 if (hfi[i]->id != -1) {
6759 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
6764 proto_register_field_common(proto, hfi[i], parent);
6768 /* deregister already registered fields */
6770 proto_deregister_field (const int parent, gint hf_id)
6772 header_field_info *hfi;
6776 g_free(last_field_name);
6777 last_field_name = NULL;
6779 if (hf_id == -1 || hf_id == 0)
6782 proto = find_protocol_by_id (parent);
6783 if (!proto || proto->fields == NULL) {
6787 for (i = 0; i < proto->fields->len; i++) {
6788 hfi = (header_field_info *)g_ptr_array_index(proto->fields, i);
6789 if (hfi->id == hf_id) {
6790 /* Found the hf_id in this protocol */
6791 g_hash_table_steal(gpa_name_map, hfi->abbrev);
6792 g_ptr_array_remove_index_fast(proto->fields, i);
6793 g_ptr_array_add(deregistered_fields, gpa_hfinfo.hfi[hf_id]);
6800 proto_add_deregistered_data (void *data)
6802 g_ptr_array_add(deregistered_data, data);
6806 free_deregistered_field (gpointer data, gpointer user_data _U_)
6808 header_field_info *hfi = (header_field_info *) data;
6809 gint hf_id = hfi->id;
6811 g_free((char *)hfi->name);
6812 g_free((char *)hfi->abbrev);
6813 g_free((char *)hfi->blurb);
6816 switch (hfi->type) {
6818 /* This is just an integer represented as a pointer */
6821 protocol_t *protocol = (protocol_t *)hfi->strings;
6822 g_free((gchar *)protocol->short_name);
6826 true_false_string *tf = (true_false_string *)hfi->strings;
6827 g_free ((gchar *)tf->true_string);
6828 g_free ((gchar *)tf->false_string);
6833 if (hfi->display & BASE_UNIT_STRING) {
6834 unit_name_string *unit = (unit_name_string*)hfi->strings;
6835 g_free ((gchar *)unit->singular);
6836 g_free ((gchar *)unit->plural);
6838 val64_string *vs64 = (val64_string *)hfi->strings;
6839 while (vs64->strptr) {
6840 g_free((gchar *)vs64->strptr);
6847 /* Other Integer types */
6848 if (hfi->display & BASE_UNIT_STRING) {
6849 unit_name_string *unit = (unit_name_string*)hfi->strings;
6850 g_free ((gchar *)unit->singular);
6851 g_free ((gchar *)unit->plural);
6853 value_string *vs = (value_string *)hfi->strings;
6854 while (vs->strptr) {
6855 g_free((gchar *)vs->strptr);
6862 if (hfi->type != FT_FRAMENUM) {
6863 g_free((void *)hfi->strings);
6867 if (hfi->parent == -1)
6868 g_slice_free(header_field_info, hfi);
6870 gpa_hfinfo.hfi[hf_id] = NULL; /* Invalidate this hf_id / proto_id */
6874 free_deregistered_data (gpointer data, gpointer user_data _U_)
6879 /* free deregistered fields and data */
6881 proto_free_deregistered_fields (void)
6883 expert_free_deregistered_expertinfos();
6885 g_ptr_array_foreach(deregistered_fields, free_deregistered_field, NULL);
6886 g_ptr_array_free(deregistered_fields, TRUE);
6887 deregistered_fields = g_ptr_array_new();
6889 g_ptr_array_foreach(deregistered_data, free_deregistered_data, NULL);
6890 g_ptr_array_free(deregistered_data, TRUE);
6891 deregistered_data = g_ptr_array_new();
6894 /* chars allowed in field abbrev */
6896 const guint8 fld_abbrev_chars[256] = {
6897 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
6898 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
6899 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
6900 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
6901 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
6902 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
6903 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
6904 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
6905 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
6906 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
6907 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
6908 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
6909 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
6910 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
6911 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
6912 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
6915 static const value_string hf_display[] = {
6916 { BASE_NONE, "BASE_NONE" },
6917 { BASE_DEC, "BASE_DEC" },
6918 { BASE_HEX, "BASE_HEX" },
6919 { BASE_OCT, "BASE_OCT" },
6920 { BASE_DEC_HEX, "BASE_DEC_HEX" },
6921 { BASE_HEX_DEC, "BASE_HEX_DEC" },
6922 { BASE_CUSTOM, "BASE_CUSTOM" },
6923 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
6924 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
6925 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
6926 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
6927 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
6928 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
6929 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
6930 { BASE_NONE|BASE_VAL64_STRING, "BASE_NONE|BASE_VAL64_STRING" },
6931 { BASE_DEC|BASE_VAL64_STRING, "BASE_DEC|BASE_VAL64_STRING" },
6932 { BASE_HEX|BASE_VAL64_STRING, "BASE_HEX|BASE_VAL64_STRING" },
6933 { BASE_OCT|BASE_VAL64_STRING, "BASE_OCT|BASE_VAL64_STRING" },
6934 { BASE_DEC_HEX|BASE_VAL64_STRING, "BASE_DEC_HEX|BASE_VAL64_STRING" },
6935 { BASE_HEX_DEC|BASE_VAL64_STRING, "BASE_HEX_DEC|BASE_VAL64_STRING" },
6936 { BASE_CUSTOM|BASE_VAL64_STRING, "BASE_CUSTOM|BASE_VAL64_STRING" },
6937 /* Alias: BASE_NONE { BASE_FLOAT, "BASE_FLOAT" }, */
6938 /* Alias: BASE_NONE { STR_ASCII, "STR_ASCII" }, */
6939 { STR_UNICODE, "STR_UNICODE" },
6940 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
6941 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_UTC" },
6942 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_DOY_UTC" },
6943 { BASE_PT_UDP, "BASE_PT_UDP" },
6944 { BASE_PT_TCP, "BASE_PT_TCP" },
6945 { BASE_PT_DCCP, "BASE_PT_DCCP" },
6946 { BASE_PT_SCTP, "BASE_PT_SCTP" },
6949 const char* proto_field_display_to_string(int field_display)
6951 return val_to_str_const(field_display, hf_display, "Unknown");
6954 static inline port_type
6955 display_to_port_type(field_display_e e)
6972 /* temporary function containing assert part for easier profiling */
6974 tmp_fld_check_assert(header_field_info *hfinfo)
6978 /* The field must have a name (with length > 0) */
6979 if (!hfinfo->name || !hfinfo->name[0]) {
6981 /* Try to identify the field */
6982 g_error("Field (abbrev='%s') does not have a name\n",
6986 g_error("Field does not have a name (nor an abbreviation)\n");
6989 /* fields with an empty string for an abbreviation aren't filterable */
6990 if (!hfinfo->abbrev || !hfinfo->abbrev[0])
6991 g_error("Field '%s' does not have an abbreviation\n", hfinfo->name);
6993 /* These types of fields are allowed to have value_strings,
6994 * true_false_strings or a protocol_t struct
6996 if (hfinfo->strings != NULL) {
6997 switch(hfinfo->type) {
7021 //allowed to support string if its a unit decsription
7022 if (hfinfo->display & BASE_UNIT_STRING)
7027 //allowed to support string if its a protocol (for pinos)
7028 if (hfinfo->display & BASE_PROTOCOL_INFO)
7033 g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
7034 " (which is not allowed to have strings)\n",
7035 hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type));
7039 /* TODO: This check may slow down startup, and output quite a few warnings.
7040 It would be good to be able to enable this (and possibly other checks?)
7041 in non-release builds. */
7043 /* Check for duplicate value_string values.
7044 There are lots that have the same value *and* string, so for now only
7045 report those that have same value but different string. */
7046 if ((hfinfo->strings != NULL) &&
7047 !(hfinfo->display & BASE_RANGE_STRING) &&
7048 !((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) &&
7050 (hfinfo->type == FT_CHAR) ||
7051 (hfinfo->type == FT_UINT8) ||
7052 (hfinfo->type == FT_UINT16) ||
7053 (hfinfo->type == FT_UINT24) ||
7054 (hfinfo->type == FT_UINT32) ||
7055 (hfinfo->type == FT_INT8) ||
7056 (hfinfo->type == FT_INT16) ||
7057 (hfinfo->type == FT_INT24) ||
7058 (hfinfo->type == FT_INT32) ||
7059 (hfinfo->type == FT_FRAMENUM) )) {
7062 const value_string *start_values;
7063 const value_string *current;
7065 if (hfinfo->display & BASE_EXT_STRING)
7066 start_values = VALUE_STRING_EXT_VS_P(((const value_string_ext*)hfinfo->strings));
7068 start_values = (const value_string*)hfinfo->strings;
7069 current = start_values;
7071 for (n=0; current; n++, current++) {
7072 /* Drop out if we reached the end. */
7073 if ((current->value == 0) && (current->strptr == NULL)) {
7077 /* Check value against all previous */
7078 for (m=0; m < n; m++) {
7079 /* There are lots of duplicates with the same string,
7080 so only report if different... */
7081 if ((start_values[m].value == current->value) &&
7082 (strcmp(start_values[m].strptr, current->strptr) != 0)) {
7083 ws_g_warning("Field '%s' (%s) has a conflicting entry in its"
7084 " value_string: %u is at indices %u (%s) and %u (%s))\n",
7085 hfinfo->name, hfinfo->abbrev,
7086 current->value, m, start_values[m].strptr, n, current->strptr);
7094 switch (hfinfo->type) {
7097 /* Require the char type to have BASE_HEX, BASE_OCT,
7098 * BASE_CUSTOM, or BASE_NONE as its base.
7100 * If the display value is BASE_NONE and there is a
7101 * strings conversion then the dissector writer is
7102 * telling us that the field's numerical value is
7103 * meaningless; we'll avoid showing the value to the
7106 switch (FIELD_DISPLAY(hfinfo->display)) {
7109 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
7112 if (hfinfo->strings == NULL)
7113 g_error("Field '%s' (%s) is an integral value (%s)"
7114 " but is being displayed as BASE_NONE but"
7115 " without a strings conversion",
7116 hfinfo->name, hfinfo->abbrev,
7117 ftype_name(hfinfo->type));
7120 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
7121 g_error("Field '%s' (%s) is a character value (%s)"
7122 " but is being displayed as %s\n",
7123 hfinfo->name, hfinfo->abbrev,
7124 ftype_name(hfinfo->type), tmp_str);
7125 wmem_free(NULL, tmp_str);
7127 if (hfinfo->display & BASE_UNIT_STRING) {
7128 g_error("Field '%s' (%s) is a character value (%s) but has a unit string\n",
7129 hfinfo->name, hfinfo->abbrev,
7130 ftype_name(hfinfo->type));
7141 /* Hexadecimal and octal are, in printf() and everywhere
7142 * else, unsigned so don't allow dissectors to register a
7143 * signed field to be displayed unsigned. (Else how would
7144 * we display negative values?)
7146 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
7151 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7152 g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
7153 hfinfo->name, hfinfo->abbrev,
7154 ftype_name(hfinfo->type), tmp_str);
7155 wmem_free(NULL, tmp_str);
7166 if (IS_BASE_PORT(hfinfo->display)) {
7167 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
7168 if (hfinfo->type != FT_UINT16) {
7169 g_error("Field '%s' (%s) has 'display' value %s but it can only be used with FT_UINT16, not %s\n",
7170 hfinfo->name, hfinfo->abbrev,
7171 tmp_str, ftype_name(hfinfo->type));
7173 if (hfinfo->strings != NULL) {
7174 g_error("Field '%s' (%s) is an %s (%s) but has a strings value\n",
7175 hfinfo->name, hfinfo->abbrev,
7176 ftype_name(hfinfo->type), tmp_str);
7178 if (hfinfo->bitmask != 0) {
7179 g_error("Field '%s' (%s) is an %s (%s) but has a bitmask\n",
7180 hfinfo->name, hfinfo->abbrev,
7181 ftype_name(hfinfo->type), tmp_str);
7183 wmem_free(NULL, tmp_str);
7187 /* Require integral types (other than frame number,
7188 * which is always displayed in decimal) to have a
7191 * If the display value is BASE_NONE and there is a
7192 * strings conversion then the dissector writer is
7193 * telling us that the field's numerical value is
7194 * meaningless; we'll avoid showing the value to the
7197 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
7203 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
7206 if (hfinfo->strings == NULL) {
7207 g_error("Field '%s' (%s) is an integral value (%s)"
7208 " but is being displayed as BASE_NONE but"
7209 " without a strings conversion",
7210 hfinfo->name, hfinfo->abbrev,
7211 ftype_name(hfinfo->type));
7213 if (hfinfo->display & BASE_SPECIAL_VALS) {
7214 g_error("Field '%s' (%s) is an integral value (%s)"
7215 " that is being displayed as BASE_NONE but"
7216 " with BASE_SPECIAL_VALS",
7217 hfinfo->name, hfinfo->abbrev,
7218 ftype_name(hfinfo->type));
7223 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
7224 g_error("Field '%s' (%s) is an integral value (%s)"
7225 " but is being displayed as %s\n",
7226 hfinfo->name, hfinfo->abbrev,
7227 ftype_name(hfinfo->type), tmp_str);
7228 wmem_free(NULL, tmp_str);
7233 /* Require bytes to have a "display type" that could
7234 * add a character between displayed bytes.
7236 switch (FIELD_DISPLAY(hfinfo->display)) {
7244 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7245 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",
7246 hfinfo->name, hfinfo->abbrev, tmp_str);
7247 wmem_free(NULL, tmp_str);
7249 if (hfinfo->bitmask != 0)
7250 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7251 hfinfo->name, hfinfo->abbrev,
7252 ftype_name(hfinfo->type));
7253 //allowed to support string if its a protocol (for pinos)
7254 if ((hfinfo->strings != NULL) && (!(hfinfo->display & BASE_PROTOCOL_INFO)))
7255 g_error("Field '%s' (%s) is an %s but has a strings value\n",
7256 hfinfo->name, hfinfo->abbrev,
7257 ftype_name(hfinfo->type));
7262 if (hfinfo->display != BASE_NONE) {
7263 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7264 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
7265 hfinfo->name, hfinfo->abbrev,
7266 ftype_name(hfinfo->type), tmp_str);
7267 wmem_free(NULL, tmp_str);
7269 if (hfinfo->bitmask != 0)
7270 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7271 hfinfo->name, hfinfo->abbrev,
7272 ftype_name(hfinfo->type));
7278 case FT_ABSOLUTE_TIME:
7279 if (!(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
7280 hfinfo->display == ABSOLUTE_TIME_UTC ||
7281 hfinfo->display == ABSOLUTE_TIME_DOY_UTC)) {
7282 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7283 g_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
7284 hfinfo->name, hfinfo->abbrev, ftype_name(hfinfo->type), tmp_str);
7285 wmem_free(NULL, tmp_str);
7287 if (hfinfo->bitmask != 0)
7288 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7289 hfinfo->name, hfinfo->abbrev,
7290 ftype_name(hfinfo->type));
7295 case FT_UINT_STRING:
7297 switch (hfinfo->display) {
7303 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
7304 g_error("Field '%s' (%s) is an string value (%s)"
7305 " but is being displayed as %s\n",
7306 hfinfo->name, hfinfo->abbrev,
7307 ftype_name(hfinfo->type), tmp_str);
7308 wmem_free(NULL, tmp_str);
7311 if (hfinfo->bitmask != 0)
7312 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7313 hfinfo->name, hfinfo->abbrev,
7314 ftype_name(hfinfo->type));
7315 if (hfinfo->strings != NULL)
7316 g_error("Field '%s' (%s) is an %s but has a strings value\n",
7317 hfinfo->name, hfinfo->abbrev,
7318 ftype_name(hfinfo->type));
7322 switch (hfinfo->display) {
7328 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Unknown: 0x%x)");
7329 g_error("Field '%s' (%s) is an IPv4 value (%s)"
7330 " but is being displayed as %s\n",
7331 hfinfo->name, hfinfo->abbrev,
7332 ftype_name(hfinfo->type), tmp_str);
7333 wmem_free(NULL, tmp_str);
7339 if (FIELD_DISPLAY(hfinfo->display) != BASE_NONE) {
7340 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7341 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
7342 hfinfo->name, hfinfo->abbrev,
7343 ftype_name(hfinfo->type),
7345 wmem_free(NULL, tmp_str);
7347 if (hfinfo->bitmask != 0)
7348 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7349 hfinfo->name, hfinfo->abbrev,
7350 ftype_name(hfinfo->type));
7351 if ((hfinfo->strings != NULL) && (!(hfinfo->display & BASE_UNIT_STRING)))
7352 g_error("Field '%s' (%s) is an %s but has a strings value\n",
7353 hfinfo->name, hfinfo->abbrev,
7354 ftype_name(hfinfo->type));
7357 if (hfinfo->display != BASE_NONE) {
7358 tmp_str = val_to_str_wmem(NULL, hfinfo->display, hf_display, "(Bit count: %d)");
7359 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
7360 hfinfo->name, hfinfo->abbrev,
7361 ftype_name(hfinfo->type),
7363 wmem_free(NULL, tmp_str);
7365 if (hfinfo->bitmask != 0)
7366 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
7367 hfinfo->name, hfinfo->abbrev,
7368 ftype_name(hfinfo->type));
7369 if (hfinfo->strings != NULL)
7370 g_error("Field '%s' (%s) is an %s but has a strings value\n",
7371 hfinfo->name, hfinfo->abbrev,
7372 ftype_name(hfinfo->type));
7377 #ifdef ENABLE_CHECK_FILTER
7379 _ftype_common(enum ftenum type)
7403 case FT_UINT_STRING:
7416 case FT_ABSOLUTE_TIME:
7417 case FT_RELATIVE_TIME:
7418 return FT_ABSOLUTE_TIME;
7427 register_type_length_mismatch(void)
7429 static ei_register_info ei[] = {
7430 { &ei_type_length_mismatch_error, { "_ws.type_length.mismatch", PI_MALFORMED, PI_ERROR, "Trying to fetch X with length Y", EXPFILL }},
7431 { &ei_type_length_mismatch_warn, { "_ws.type_length.mismatch", PI_MALFORMED, PI_WARN, "Trying to fetch X with length Y", EXPFILL }},
7434 expert_module_t* expert_type_length_mismatch;
7436 proto_type_length_mismatch = proto_register_protocol("Type Length Mismatch", "Type length mismatch", "_ws.type_length");
7438 expert_type_length_mismatch = expert_register_protocol(proto_type_length_mismatch);
7439 expert_register_field_array(expert_type_length_mismatch, ei, array_length(ei));
7441 /* "Type Length Mismatch" isn't really a protocol, it's an error indication;
7442 disabling them makes no sense. */
7443 proto_set_cant_toggle(proto_type_length_mismatch);
7447 register_number_string_decoding_error(void)
7449 static ei_register_info ei[] = {
7450 { &ei_number_string_decoding_failed_error,
7451 { "_ws.number_string.decoding_error.failed", PI_MALFORMED, PI_ERROR,
7452 "Failed to decode number from string", EXPFILL
7455 { &ei_number_string_decoding_erange_error,
7456 { "_ws.number_string.decoding_error.erange", PI_MALFORMED, PI_ERROR,
7457 "Decoded number from string is out of valid range", EXPFILL
7462 expert_module_t* expert_number_string_decoding_error;
7464 proto_number_string_decoding_error =
7465 proto_register_protocol("Number-String Decoding Error",
7466 "Number-string decoding error",
7467 "_ws.number_string.decoding_error");
7469 expert_number_string_decoding_error =
7470 expert_register_protocol(proto_number_string_decoding_error);
7471 expert_register_field_array(expert_number_string_decoding_error, ei, array_length(ei));
7473 /* "Number-String Decoding Error" isn't really a protocol, it's an error indication;
7474 disabling them makes no sense. */
7475 proto_set_cant_toggle(proto_number_string_decoding_error);
7478 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM (188000+PRE_ALLOC_EXPERT_FIELDS_MEM)
7480 proto_register_field_init(header_field_info *hfinfo, const int parent)
7483 tmp_fld_check_assert(hfinfo);
7485 hfinfo->parent = parent;
7486 hfinfo->same_name_next = NULL;
7487 hfinfo->same_name_prev_id = -1;
7489 /* if we always add and never delete, then id == len - 1 is correct */
7490 if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
7491 if (!gpa_hfinfo.hfi) {
7492 gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
7493 gpa_hfinfo.hfi = (header_field_info **)g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
7495 gpa_hfinfo.allocated_len += 1000;
7496 gpa_hfinfo.hfi = (header_field_info **)g_realloc(gpa_hfinfo.hfi,
7497 sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
7498 /*g_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
7501 gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
7503 hfinfo->id = gpa_hfinfo.len - 1;
7505 /* if we have real names, enter this field in the name tree */
7506 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
7508 header_field_info *same_name_next_hfinfo;
7511 /* Check that the filter name (abbreviation) is legal;
7512 * it must contain only alphanumerics, '-', "_", and ".". */
7513 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
7515 if (g_ascii_isprint(c))
7516 fprintf(stderr, "Invalid character '%c' in filter name '%s'\n", c, hfinfo->abbrev);
7518 fprintf(stderr, "Invalid byte \\%03o in filter name '%s'\n", c, hfinfo->abbrev);
7519 DISSECTOR_ASSERT_NOT_REACHED();
7522 /* We allow multiple hfinfo's to be registered under the same
7523 * abbreviation. This was done for X.25, as, depending
7524 * on whether it's modulo-8 or modulo-128 operation,
7525 * some bitfield fields may be in different bits of
7526 * a byte, and we want to be able to refer to that field
7527 * with one name regardless of whether the packets
7528 * are modulo-8 or modulo-128 packets. */
7530 same_name_hfinfo = NULL;
7532 g_hash_table_insert(gpa_name_map, (gpointer) (hfinfo->abbrev), hfinfo);
7533 /* GLIB 2.x - if it is already present
7534 * the previous hfinfo with the same name is saved
7535 * to same_name_hfinfo by value destroy callback */
7536 if (same_name_hfinfo) {
7537 /* There's already a field with this name.
7538 * Put the current field *before* that field
7539 * in the list of fields with this name, Thus,
7540 * we end up with an effectively
7541 * doubly-linked-list of same-named hfinfo's,
7542 * with the head of the list (stored in the
7543 * hash) being the last seen hfinfo.
7545 same_name_next_hfinfo =
7546 same_name_hfinfo->same_name_next;
7548 hfinfo->same_name_next = same_name_next_hfinfo;
7549 if (same_name_next_hfinfo)
7550 same_name_next_hfinfo->same_name_prev_id = hfinfo->id;
7552 same_name_hfinfo->same_name_next = hfinfo;
7553 hfinfo->same_name_prev_id = same_name_hfinfo->id;
7554 #ifdef ENABLE_CHECK_FILTER
7555 while (same_name_hfinfo) {
7556 if (_ftype_common(hfinfo->type) != _ftype_common(same_name_hfinfo->type))
7557 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));
7558 same_name_hfinfo = same_name_hfinfo->same_name_next;
7568 proto_register_subtree_array(gint *const *indices, const int num_indices)
7571 gint *const *ptr = indices;
7574 * If we've already allocated the array of tree types, expand
7575 * it; this lets plugins such as mate add tree types after
7576 * the initial startup. (If we haven't already allocated it,
7577 * we don't allocate it; on the first pass, we just assign
7578 * ett values and keep track of how many we've assigned, and
7579 * when we're finished registering all dissectors we allocate
7580 * the array, so that we do only one allocation rather than
7581 * wasting CPU time and memory by growing the array for each
7582 * dissector that registers ett values.)
7584 if (tree_is_expanded != NULL) {
7585 tree_is_expanded = (guint32 *)g_realloc(tree_is_expanded, (1+((num_tree_types + num_indices)/32)) * sizeof(guint32));
7587 /* set new items to 0 */
7588 /* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of guint32 to 0) */
7589 for (i = num_tree_types; i < num_tree_types + num_indices; i++)
7590 tree_is_expanded[i >> 5] &= ~(1U << (i & 31));
7594 * Assign "num_indices" subtree numbers starting at "num_tree_types",
7595 * returning the indices through the pointers in the array whose
7596 * first element is pointed to by "indices", and update
7597 * "num_tree_types" appropriately.
7599 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
7601 /* g_error will terminate the program */
7602 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
7603 " This is a development error:"
7604 " Either the subtree item type has already been assigned or"
7605 " was not initialized to -1.");
7607 **ptr = num_tree_types;
7612 label_concat(char *label_str, gsize pos, const char *str)
7614 if (pos < ITEM_LABEL_LENGTH)
7615 pos += g_strlcpy(label_str + pos, str, ITEM_LABEL_LENGTH - pos);
7621 label_mark_truncated(char *label_str, gsize name_pos)
7623 static const char trunc_str[] = " [truncated]";
7624 const size_t trunc_len = sizeof(trunc_str)-1;
7627 /* ..... field_name: dataaaaaaaaaaaaa
7631 * ..... field_name [truncated]: dataaaaaaaaaaaaa
7633 * name_pos==0 means that we have only data or only a field_name
7636 if (name_pos < ITEM_LABEL_LENGTH - trunc_len) {
7637 memmove(label_str + name_pos + trunc_len, label_str + name_pos, ITEM_LABEL_LENGTH - name_pos - trunc_len);
7638 memcpy(label_str + name_pos, trunc_str, trunc_len);
7640 /* in general, label_str is UTF-8
7641 we can truncate it only at the beginning of a new character
7642 we go backwards from the byte right after our buffer and
7643 find the next starting byte of a UTF-8 character, this is
7645 there's no need to use g_utf8_find_prev_char(), the search
7646 will always succeed since we copied trunc_str into the
7648 last_char = g_utf8_prev_char(&label_str[ITEM_LABEL_LENGTH]);
7651 } else if (name_pos < ITEM_LABEL_LENGTH)
7652 g_strlcpy(label_str + name_pos, trunc_str, ITEM_LABEL_LENGTH - name_pos);
7656 label_fill(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text)
7660 /* "%s: %s", hfinfo->name, text */
7661 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
7662 if (!(hfinfo->display & BASE_NO_DISPLAY_VALUE)) {
7663 pos = label_concat(label_str, pos, ": ");
7664 pos = label_concat(label_str, pos, text ? text : "(null)");
7667 if (pos >= ITEM_LABEL_LENGTH) {
7668 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
7669 label_mark_truncated(label_str, name_pos);
7676 label_fill_descr(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text, const char *descr)
7680 /* "%s: %s (%s)", hfinfo->name, text, descr */
7681 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
7682 if (!(hfinfo->display & BASE_NO_DISPLAY_VALUE)) {
7683 pos = label_concat(label_str, pos, ": ");
7684 if (hfinfo->display & BASE_UNIT_STRING) {
7685 pos = label_concat(label_str, pos, descr ? descr : "(null)");
7686 pos = label_concat(label_str, pos, text ? text : "(null)");
7688 pos = label_concat(label_str, pos, text ? text : "(null)");
7689 pos = label_concat(label_str, pos, " (");
7690 pos = label_concat(label_str, pos, descr ? descr : "(null)");
7691 pos = label_concat(label_str, pos, ")");
7695 if (pos >= ITEM_LABEL_LENGTH) {
7696 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
7697 label_mark_truncated(label_str, name_pos);
7704 proto_item_fill_label(field_info *fi, gchar *label_str)
7706 header_field_info *hfinfo;
7710 ipv4_addr_and_mask *ipv4;
7712 guint32 n_addr; /* network-order IPv4 address */
7721 /* XXX: Check validity of hfinfo->type */
7725 hfinfo = fi->hfinfo;
7727 switch (hfinfo->type) {
7730 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
7734 fill_label_boolean(fi, label_str);
7739 bytes = (guint8 *)fvalue_get(&fi->value);
7742 switch(hfinfo->display)
7745 str = bytestring_to_str(NULL, bytes, fvalue_length(&fi->value), '.');
7748 str = bytestring_to_str(NULL, bytes, fvalue_length(&fi->value), '-');
7751 str = bytestring_to_str(NULL, bytes, fvalue_length(&fi->value), ':');
7754 str = bytestring_to_str(NULL, bytes, fvalue_length(&fi->value), ' ');
7758 if (prefs.display_byte_fields_with_spaces)
7760 str = bytestring_to_str(NULL, bytes, fvalue_length(&fi->value), ' ');
7764 str = bytes_to_str(NULL, bytes, fvalue_length(&fi->value));
7768 label_fill(label_str, 0, hfinfo, str);
7769 wmem_free(NULL, str);
7771 if (hfinfo->display & BASE_ALLOW_ZERO) {
7772 label_fill(label_str, 0, hfinfo, "<none>");
7774 label_fill(label_str, 0, hfinfo, "<MISSING>");
7780 if (hfinfo->bitmask) {
7781 fill_label_bitfield_char(fi, label_str);
7783 fill_label_char(fi, label_str);
7787 /* Four types of integers to take care of:
7788 * Bitfield, with val_string
7789 * Bitfield, w/o val_string
7790 * Non-bitfield, with val_string
7791 * Non-bitfield, w/o val_string
7797 if (hfinfo->bitmask) {
7798 fill_label_bitfield(fi, label_str, FALSE);
7800 fill_label_number(fi, label_str, FALSE);
7805 fill_label_number(fi, label_str, FALSE);
7812 if (hfinfo->bitmask) {
7813 fill_label_bitfield64(fi, label_str, FALSE);
7815 fill_label_number64(fi, label_str, FALSE);
7823 if (hfinfo->bitmask) {
7824 fill_label_bitfield(fi, label_str, TRUE);
7826 fill_label_number(fi, label_str, TRUE);
7834 if (hfinfo->bitmask) {
7835 fill_label_bitfield64(fi, label_str, TRUE);
7837 fill_label_number64(fi, label_str, TRUE);
7842 double d_value = fvalue_get_floating(&fi->value);
7843 if (hfinfo->display & BASE_UNIT_STRING) {
7844 g_snprintf(label_str, ITEM_LABEL_LENGTH,
7845 "%s: %." G_STRINGIFY(FLT_DIG) "g%s",
7846 hfinfo->name, d_value,
7847 unit_name_string_get_double(d_value, (unit_name_string*)hfinfo->strings));
7849 g_snprintf(label_str, ITEM_LABEL_LENGTH,
7850 "%s: %." G_STRINGIFY(FLT_DIG) "g",
7851 hfinfo->name, d_value);
7857 double d_value = fvalue_get_floating(&fi->value);
7858 if (hfinfo->display & BASE_UNIT_STRING) {
7859 g_snprintf(label_str, ITEM_LABEL_LENGTH,
7860 "%s: %." G_STRINGIFY(DBL_DIG) "g%s",
7861 hfinfo->name, d_value,
7862 unit_name_string_get_double(d_value, (unit_name_string*)hfinfo->strings));
7864 g_snprintf(label_str, ITEM_LABEL_LENGTH,
7865 "%s: %." G_STRINGIFY(DBL_DIG) "g",
7866 hfinfo->name, d_value);
7871 case FT_ABSOLUTE_TIME:
7872 tmp = abs_time_to_str(NULL, (const nstime_t *)fvalue_get(&fi->value), (absolute_time_display_e)hfinfo->display, TRUE);
7873 label_fill(label_str, 0, hfinfo, tmp);
7874 wmem_free(NULL, tmp);
7877 case FT_RELATIVE_TIME:
7878 tmp = rel_time_to_secs_str(NULL, (const nstime_t *)fvalue_get(&fi->value));
7879 g_snprintf(label_str, ITEM_LABEL_LENGTH,
7880 "%s: %s seconds", hfinfo->name, tmp);
7881 wmem_free(NULL, tmp);
7885 integer = fvalue_get_uinteger(&fi->value);
7886 tmp = get_ipxnet_name(NULL, integer);
7887 g_snprintf(label_str, ITEM_LABEL_LENGTH,
7888 "%s: %s (0x%08X)", hfinfo->name,
7890 wmem_free(NULL, tmp);
7894 addr.type = AT_AX25;
7895 addr.len = AX25_ADDR_LEN;
7896 addr.data = (guint8 *)fvalue_get(&fi->value);
7898 addr_str = (char*)address_to_str(NULL, &addr);
7899 g_snprintf(label_str, ITEM_LABEL_LENGTH,
7900 "%s: %s", hfinfo->name, addr_str);
7901 wmem_free(NULL, addr_str);
7905 addr.type = vines_address_type;
7906 addr.len = VINES_ADDR_LEN;
7907 addr.data = (guint8 *)fvalue_get(&fi->value);
7909 addr_str = (char*)address_to_str(NULL, &addr);
7910 g_snprintf(label_str, ITEM_LABEL_LENGTH,
7911 "%s: %s", hfinfo->name, addr_str);
7912 wmem_free(NULL, addr_str);
7916 bytes = (guint8 *)fvalue_get(&fi->value);
7918 addr.type = AT_ETHER;
7922 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
7923 g_snprintf(label_str, ITEM_LABEL_LENGTH,
7924 "%s: %s", hfinfo->name, addr_str);
7925 wmem_free(NULL, addr_str);
7929 ipv4 = (ipv4_addr_and_mask *)fvalue_get(&fi->value);
7930 n_addr = ipv4_get_net_order_addr(ipv4);
7932 addr.type = AT_IPv4;
7934 addr.data = &n_addr;
7936 if (hfinfo->display == BASE_NETMASK)
7938 addr_str = (char*)address_to_str(NULL, &addr);
7942 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
7944 g_snprintf(label_str, ITEM_LABEL_LENGTH,
7945 "%s: %s", hfinfo->name, addr_str);
7946 wmem_free(NULL, addr_str);
7950 bytes = (guint8 *)fvalue_get(&fi->value);
7952 addr.type = AT_IPv6;
7956 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
7957 g_snprintf(label_str, ITEM_LABEL_LENGTH,
7958 "%s: %s", hfinfo->name, addr_str);
7959 wmem_free(NULL, addr_str);
7963 addr.type = AT_FCWWN;
7964 addr.len = FCWWN_ADDR_LEN;
7965 addr.data = (guint8 *)fvalue_get(&fi->value);
7967 addr_str = (char*)address_with_resolution_to_str(NULL, &addr);
7968 g_snprintf(label_str, ITEM_LABEL_LENGTH,
7969 "%s: %s", hfinfo->name, addr_str);
7970 wmem_free(NULL, addr_str);
7974 guid = (e_guid_t *)fvalue_get(&fi->value);
7975 tmp = guid_to_str(NULL, guid);
7976 label_fill(label_str, 0, hfinfo, tmp);
7977 wmem_free(NULL, tmp);
7981 bytes = (guint8 *)fvalue_get(&fi->value);
7982 name = oid_resolved_from_encoded(NULL, bytes, fvalue_length(&fi->value));
7983 tmp = oid_encoded2string(NULL, bytes, fvalue_length(&fi->value));
7985 label_fill_descr(label_str, 0, hfinfo, tmp, name);
7986 wmem_free(NULL, name);
7988 label_fill(label_str, 0, hfinfo, tmp);
7990 wmem_free(NULL, tmp);
7994 bytes = (guint8 *)fvalue_get(&fi->value);
7995 name = rel_oid_resolved_from_encoded(NULL, bytes, fvalue_length(&fi->value));
7996 tmp = rel_oid_encoded2string(NULL, bytes, fvalue_length(&fi->value));
7998 label_fill_descr(label_str, 0, hfinfo, tmp, name);
7999 wmem_free(NULL, name);
8001 label_fill(label_str, 0, hfinfo, tmp);
8003 wmem_free(NULL, tmp);
8007 bytes = (guint8 *)fvalue_get(&fi->value);
8008 tmp = print_system_id(NULL, bytes, fvalue_length(&fi->value));
8009 label_fill(label_str, 0, hfinfo, tmp);
8010 wmem_free(NULL, tmp);
8014 integer64 = fvalue_get_uinteger64(&fi->value);
8015 addr_str = eui64_to_str(NULL, integer64);
8016 tmp = (char*)eui64_to_display(NULL, integer64);
8017 label_fill_descr(label_str, 0, hfinfo, tmp, addr_str);
8018 wmem_free(NULL, tmp);
8019 wmem_free(NULL, addr_str);
8023 case FT_UINT_STRING:
8025 bytes = (guint8 *)fvalue_get(&fi->value);
8026 tmp = hfinfo_format_text(hfinfo, bytes);
8027 label_fill(label_str, 0, hfinfo, tmp);
8028 wmem_free(NULL, tmp);
8031 case FT_IEEE_11073_SFLOAT:
8032 tmp = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, hfinfo->display);
8033 g_snprintf(label_str, ITEM_LABEL_LENGTH,
8036 wmem_free(NULL, tmp);
8038 case FT_IEEE_11073_FLOAT:
8039 tmp = fvalue_to_string_repr(NULL, &fi->value, FTREPR_DISPLAY, hfinfo->display);
8040 g_snprintf(label_str, ITEM_LABEL_LENGTH,
8043 wmem_free(NULL, tmp);
8047 g_error("hfinfo->type %d (%s) not handled\n",
8048 hfinfo->type, ftype_name(hfinfo->type));
8049 DISSECTOR_ASSERT_NOT_REACHED();
8055 fill_label_boolean(field_info *fi, gchar *label_str)
8057 char *p = label_str;
8058 int bitfield_byte_length = 0, bitwidth;
8059 guint64 unshifted_value;
8062 header_field_info *hfinfo = fi->hfinfo;
8063 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
8065 if (hfinfo->strings) {
8066 tfstring = (const struct true_false_string*) hfinfo->strings;
8069 value = fvalue_get_uinteger64(&fi->value);
8070 if (hfinfo->bitmask) {
8071 /* Figure out the bit width */
8072 bitwidth = hfinfo_container_bitwidth(hfinfo);
8075 unshifted_value = value;
8076 unshifted_value <<= hfinfo_bitshift(hfinfo);
8078 /* Create the bitfield first */
8079 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
8080 bitfield_byte_length = (int) (p - label_str);
8083 /* Fill in the textual info */
8084 label_fill(label_str, bitfield_byte_length, hfinfo, value ? tfstring->true_string : tfstring->false_string);
8088 hf_try_val_to_str(guint32 value, const header_field_info *hfinfo)
8090 if (hfinfo->display & BASE_RANGE_STRING)
8091 return try_rval_to_str(value, (const range_string *) hfinfo->strings);
8093 if (hfinfo->display & BASE_EXT_STRING)
8094 return try_val_to_str_ext(value, (value_string_ext *) hfinfo->strings);
8096 if (hfinfo->display & BASE_VAL64_STRING)
8097 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
8099 if (hfinfo->display & BASE_UNIT_STRING)
8100 return unit_name_string_get_value(value, (struct unit_name_string*) hfinfo->strings);
8102 return try_val_to_str(value, (const value_string *) hfinfo->strings);
8106 hf_try_val64_to_str(guint64 value, const header_field_info *hfinfo)
8108 if (hfinfo->display & BASE_VAL64_STRING)
8109 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
8111 if (hfinfo->display & BASE_RANGE_STRING)
8112 return try_rval64_to_str(value, (const range_string *) hfinfo->strings);
8114 if (hfinfo->display & BASE_UNIT_STRING)
8115 return unit_name_string_get_value64(value, (struct unit_name_string*) hfinfo->strings);
8117 /* If this is reached somebody registered a 64-bit field with a 32-bit
8118 * value-string, which isn't right. */
8119 DISSECTOR_ASSERT_NOT_REACHED();
8121 /* This is necessary to squelch MSVC errors; is there
8122 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
8128 hf_try_val_to_str_const(guint32 value, const header_field_info *hfinfo, const char *unknown_str)
8130 const char *str = hf_try_val_to_str(value, hfinfo);
8132 return (str) ? str : unknown_str;
8136 hf_try_val64_to_str_const(guint64 value, const header_field_info *hfinfo, const char *unknown_str)
8138 const char *str = hf_try_val64_to_str(value, hfinfo);
8140 return (str) ? str : unknown_str;
8143 /* Fills data for bitfield chars with val_strings */
8145 fill_label_bitfield_char(field_info *fi, gchar *label_str)
8148 int bitfield_byte_length, bitwidth;
8149 guint32 unshifted_value;
8155 header_field_info *hfinfo = fi->hfinfo;
8157 /* Figure out the bit width */
8158 bitwidth = hfinfo_container_bitwidth(hfinfo);
8161 value = fvalue_get_uinteger(&fi->value);
8163 unshifted_value = value;
8164 if (hfinfo->bitmask) {
8165 unshifted_value <<= hfinfo_bitshift(hfinfo);
8168 /* Create the bitfield first */
8169 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
8170 bitfield_byte_length = (int) (p - label_str);
8172 /* Fill in the textual info using stored (shifted) value */
8173 if (hfinfo->display == BASE_CUSTOM) {
8174 gchar tmp[ITEM_LABEL_LENGTH];
8175 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
8177 DISSECTOR_ASSERT(fmtfunc);
8178 fmtfunc(tmp, value);
8179 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
8181 else if (hfinfo->strings) {
8182 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
8184 out = hfinfo_char_vals_format(hfinfo, buf, value);
8185 if (out == NULL) /* BASE_NONE so don't put integer in descr */
8186 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
8188 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
8191 out = hfinfo_char_value_format(hfinfo, buf, value);
8193 label_fill(label_str, bitfield_byte_length, hfinfo, out);
8197 /* Fills data for bitfield ints with val_strings */
8199 fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed)
8202 int bitfield_byte_length, bitwidth;
8203 guint32 unshifted_value;
8209 header_field_info *hfinfo = fi->hfinfo;
8211 /* Figure out the bit width */
8212 bitwidth = hfinfo_container_bitwidth(hfinfo);
8216 value = fvalue_get_sinteger(&fi->value);
8218 value = fvalue_get_uinteger(&fi->value);
8220 unshifted_value = value;
8221 if (hfinfo->bitmask) {
8222 unshifted_value <<= hfinfo_bitshift(hfinfo);
8225 /* Create the bitfield first */
8226 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
8227 bitfield_byte_length = (int) (p - label_str);
8229 /* Fill in the textual info using stored (shifted) value */
8230 if (hfinfo->display == BASE_CUSTOM) {
8231 gchar tmp[ITEM_LABEL_LENGTH];
8232 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
8234 DISSECTOR_ASSERT(fmtfunc);
8235 fmtfunc(tmp, value);
8236 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
8238 else if (hfinfo->strings) {
8239 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
8241 out = hfinfo_number_vals_format(hfinfo, buf, value);
8242 if (out == NULL) /* BASE_NONE so don't put integer in descr */
8243 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
8245 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
8248 out = hfinfo_number_value_format(hfinfo, buf, value);
8250 label_fill(label_str, bitfield_byte_length, hfinfo, out);
8255 fill_label_bitfield64(field_info *fi, gchar *label_str, gboolean is_signed)
8258 int bitfield_byte_length, bitwidth;
8259 guint64 unshifted_value;
8265 header_field_info *hfinfo = fi->hfinfo;
8267 /* Figure out the bit width */
8268 bitwidth = hfinfo_container_bitwidth(hfinfo);
8272 value = fvalue_get_sinteger64(&fi->value);
8274 value = fvalue_get_uinteger64(&fi->value);
8276 unshifted_value = value;
8277 if (hfinfo->bitmask) {
8278 unshifted_value <<= hfinfo_bitshift(hfinfo);
8281 /* Create the bitfield first */
8282 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
8283 bitfield_byte_length = (int) (p - label_str);
8285 /* Fill in the textual info using stored (shifted) value */
8286 if (hfinfo->display == BASE_CUSTOM) {
8287 gchar tmp[ITEM_LABEL_LENGTH];
8288 const custom_fmt_func_64_t fmtfunc64 = (const custom_fmt_func_64_t)hfinfo->strings;
8290 DISSECTOR_ASSERT(fmtfunc64);
8291 fmtfunc64(tmp, value);
8292 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
8294 else if (hfinfo->strings) {
8295 const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
8297 out = hfinfo_number_vals_format64(hfinfo, buf, value);
8298 if (out == NULL) /* BASE_NONE so don't put integer in descr */
8299 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
8301 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
8304 out = hfinfo_number_value_format64(hfinfo, buf, value);
8306 label_fill(label_str, bitfield_byte_length, hfinfo, out);
8311 fill_label_char(field_info *fi, gchar *label_str)
8313 header_field_info *hfinfo = fi->hfinfo;
8319 value = fvalue_get_uinteger(&fi->value);
8321 /* Fill in the textual info */
8322 if (hfinfo->display == BASE_CUSTOM) {
8323 gchar tmp[ITEM_LABEL_LENGTH];
8324 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
8326 DISSECTOR_ASSERT(fmtfunc);
8327 fmtfunc(tmp, value);
8328 label_fill(label_str, 0, hfinfo, tmp);
8330 else if (hfinfo->strings) {
8331 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
8333 out = hfinfo_char_vals_format(hfinfo, buf, value);
8334 label_fill_descr(label_str, 0, hfinfo, val_str, out);
8337 out = hfinfo_char_value_format(hfinfo, buf, value);
8339 label_fill(label_str, 0, hfinfo, out);
8344 fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
8346 header_field_info *hfinfo = fi->hfinfo;
8353 value = fvalue_get_sinteger(&fi->value);
8355 value = fvalue_get_uinteger(&fi->value);
8357 /* Fill in the textual info */
8358 if (hfinfo->display == BASE_CUSTOM) {
8359 gchar tmp[ITEM_LABEL_LENGTH];
8360 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
8362 DISSECTOR_ASSERT(fmtfunc);
8363 fmtfunc(tmp, value);
8364 label_fill(label_str, 0, hfinfo, tmp);
8366 else if (hfinfo->strings && hfinfo->type != FT_FRAMENUM) {
8368 * It makes no sense to have a value-string table for a
8369 * frame-number field - they're just integers giving
8370 * the ordinal frame number.
8372 const char *val_str = hf_try_val_to_str(value, hfinfo);
8374 out = hfinfo_number_vals_format(hfinfo, buf, value);
8375 if (hfinfo->display & BASE_SPECIAL_VALS) {
8377 * Unique values only display value_string string
8378 * if there is a match. Otherwise it's just a number
8381 label_fill_descr(label_str, 0, hfinfo, val_str, out);
8383 label_fill(label_str, 0, hfinfo, out);
8386 if (val_str == NULL)
8387 val_str = "Unknown";
8389 if (out == NULL) /* BASE_NONE so don't put integer in descr */
8390 label_fill(label_str, 0, hfinfo, val_str);
8392 label_fill_descr(label_str, 0, hfinfo, val_str, out);
8395 else if (IS_BASE_PORT(hfinfo->display)) {
8396 gchar tmp[ITEM_LABEL_LENGTH];
8398 port_with_resolution_to_str_buf(tmp, sizeof(tmp),
8399 display_to_port_type((field_display_e)hfinfo->display), value);
8400 label_fill(label_str, 0, hfinfo, tmp);
8403 out = hfinfo_number_value_format(hfinfo, buf, value);
8405 label_fill(label_str, 0, hfinfo, out);
8410 fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed)
8412 header_field_info *hfinfo = fi->hfinfo;
8419 value = fvalue_get_sinteger64(&fi->value);
8421 value = fvalue_get_uinteger64(&fi->value);
8423 /* Fill in the textual info */
8424 if (hfinfo->display == BASE_CUSTOM) {
8425 gchar tmp[ITEM_LABEL_LENGTH];
8426 const custom_fmt_func_64_t fmtfunc64 = (const custom_fmt_func_64_t)hfinfo->strings;
8428 DISSECTOR_ASSERT(fmtfunc64);
8429 fmtfunc64(tmp, value);
8430 label_fill(label_str, 0, hfinfo, tmp);
8432 else if (hfinfo->strings) {
8433 const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
8435 out = hfinfo_number_vals_format64(hfinfo, buf, value);
8436 if (out == NULL) /* BASE_NONE so don't put integer in descr */
8437 label_fill(label_str, 0, hfinfo, val_str);
8439 label_fill_descr(label_str, 0, hfinfo, val_str, out);
8442 out = hfinfo_number_value_format64(hfinfo, buf, value);
8444 label_fill(label_str, 0, hfinfo, out);
8449 hfinfo_bitshift(const header_field_info *hfinfo)
8451 return ws_ctz(hfinfo->bitmask);
8455 hfinfo_mask_bitwidth(const header_field_info *hfinfo)
8457 if (!hfinfo->bitmask) {
8461 /* ilog2 = first set bit, ctz = last set bit */
8462 return ws_ilog2(hfinfo->bitmask) - ws_ctz(hfinfo->bitmask) + 1;
8466 hfinfo_type_bitwidth(enum ftenum type)
8505 DISSECTOR_ASSERT_NOT_REACHED();
8513 hfinfo_container_bitwidth(const header_field_info *hfinfo)
8515 if (!hfinfo->bitmask) {
8519 if (hfinfo->type == FT_BOOLEAN) {
8520 return hfinfo->display; /* hacky? :) */
8523 return hfinfo_type_bitwidth(hfinfo->type);
8527 hfinfo_hex_digits(const header_field_info *hfinfo)
8531 /* If we have a bitmask, hfinfo->type is the width of the container, so not
8532 * appropriate to determine the number of hex digits for the field.
8533 * So instead, we compute it from the bitmask.
8535 if (hfinfo->bitmask != 0) {
8536 bitwidth = hfinfo_mask_bitwidth(hfinfo);
8538 bitwidth = hfinfo_type_bitwidth(hfinfo->type);
8541 /* Divide by 4, rounding up, to get number of hex digits. */
8542 return (bitwidth + 3) / 4;
8546 hfinfo_char_value_format_display(int display, char buf[7], guint32 value)
8548 char *ptr = &buf[6];
8549 static const gchar hex_digits[16] =
8550 { '0', '1', '2', '3', '4', '5', '6', '7',
8551 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
8555 /* Properly format value */
8556 if (g_ascii_isprint(value)) {
8558 * Printable, so just show the character, and, if it needs
8559 * to be escaped, escape it.
8562 if (value == '\\' || value == '\'')
8566 * Non-printable; show it as an escape sequence.
8572 * Show a NUL with only one digit.
8606 switch (display & FIELD_DISPLAY_E_MASK) {
8609 *(--ptr) = (value & 0x7) + '0';
8611 *(--ptr) = (value & 0x7) + '0';
8613 *(--ptr) = (value & 0x7) + '0';
8617 *(--ptr) = hex_digits[value & 0x0F];
8619 *(--ptr) = hex_digits[value & 0x0F];
8624 g_assert_not_reached();
8634 hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value)
8636 char *ptr = &buf[31];
8637 gboolean isint = IS_FT_INT(hfinfo->type);
8640 /* Properly format value */
8641 switch (display & FIELD_DISPLAY_E_MASK) {
8643 return isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
8647 ptr = hex_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
8650 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
8654 return oct_to_str_back(ptr, value);
8657 return hex_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
8661 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
8664 ptr = hex_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
8671 port_with_resolution_to_str_buf(buf, 32,
8672 display_to_port_type((field_display_e)display), value);
8676 g_assert_not_reached();
8682 hfinfo_number_value_format_display64(const header_field_info *hfinfo, int display, char buf[48], guint64 value)
8684 char *ptr = &buf[47];
8685 gboolean isint = IS_FT_INT(hfinfo->type);
8688 /* Properly format value */
8691 return isint ? int64_to_str_back(ptr, (gint64) value) : uint64_to_str_back(ptr, value);
8695 ptr = hex64_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
8698 ptr = isint ? int64_to_str_back(ptr, (gint64) value) : uint64_to_str_back(ptr, value);
8702 return oct64_to_str_back(ptr, value);
8705 return hex64_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
8709 ptr = isint ? int64_to_str_back(ptr, (gint64) value) : uint64_to_str_back(ptr, value);
8712 ptr = hex64_to_str_back(ptr, hfinfo_hex_digits(hfinfo), value);
8716 g_assert_not_reached();
8722 hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
8724 int display = hfinfo->display;
8726 if (hfinfo->type == FT_FRAMENUM) {
8728 * Frame numbers are always displayed in decimal.
8733 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
8737 hfinfo_number_value_format64(const header_field_info *hfinfo, char buf[64], guint64 value)
8739 int display = hfinfo->display;
8741 if (hfinfo->type == FT_FRAMENUM) {
8743 * Frame numbers are always displayed in decimal.
8748 return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
8752 hfinfo_char_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
8754 /* Get the underlying BASE_ value */
8755 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
8757 return hfinfo_char_value_format_display(display, buf, value);
8761 hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
8763 /* Get the underlying BASE_ value */
8764 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
8766 if (hfinfo->type == FT_FRAMENUM) {
8768 * Frame numbers are always displayed in decimal.
8773 if (IS_BASE_PORT(display)) {
8779 /* case BASE_DEC: */
8781 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
8786 /* case BASE_HEX: */
8792 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
8796 hfinfo_numeric_value_format64(const header_field_info *hfinfo, char buf[64], guint64 value)
8798 /* Get the underlying BASE_ value */
8799 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
8801 if (hfinfo->type == FT_FRAMENUM) {
8803 * Frame numbers are always displayed in decimal.
8810 /* case BASE_DEC: */
8812 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
8817 /* case BASE_HEX: */
8823 return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
8827 hfinfo_char_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
8829 /* Get the underlying BASE_ value */
8830 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
8832 return hfinfo_char_value_format_display(display, buf, value);
8836 hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
8838 /* Get the underlying BASE_ value */
8839 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
8841 if (display == BASE_NONE)
8844 if (display == BASE_DEC_HEX)
8846 if (display == BASE_HEX_DEC)
8849 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
8853 hfinfo_number_vals_format64(const header_field_info *hfinfo, char buf[64], guint64 value)
8855 /* Get the underlying BASE_ value */
8856 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
8858 if (display == BASE_NONE)
8861 if (display == BASE_DEC_HEX)
8863 if (display == BASE_HEX_DEC)
8866 return hfinfo_number_value_format_display64(hfinfo, display, buf, value);
8870 proto_registrar_get_name(const int n)
8872 header_field_info *hfinfo;
8874 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
8875 return hfinfo->name;
8879 proto_registrar_get_abbrev(const int n)
8881 header_field_info *hfinfo;
8883 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
8884 return hfinfo->abbrev;
8888 proto_registrar_get_ftype(const int n)
8890 header_field_info *hfinfo;
8892 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
8893 return hfinfo->type;
8897 proto_registrar_get_parent(const int n)
8899 header_field_info *hfinfo;
8901 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
8902 return hfinfo->parent;
8906 proto_registrar_is_protocol(const int n)
8908 header_field_info *hfinfo;
8910 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
8911 return (((hfinfo->id != hf_text_only) && (hfinfo->parent == -1)) ? TRUE : FALSE);
8914 /* Returns length of field in packet (not necessarily the length
8915 * in our internal representation, as in the case of IPv4).
8916 * 0 means undeterminable at time of registration
8917 * -1 means the field is not registered. */
8919 proto_registrar_get_length(const int n)
8921 header_field_info *hfinfo;
8923 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
8924 return ftype_length(hfinfo->type);
8927 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
8928 * it exists anywhere, or FALSE if it exists nowhere. */
8930 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
8932 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
8934 if (g_ptr_array_len(ptrs) > 0) {
8942 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
8943 * This only works if the hfindex was "primed" before the dissection
8944 * took place, as we just pass back the already-created GPtrArray*.
8945 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
8948 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
8953 if (PTREE_DATA(tree)->interesting_hfids != NULL)
8954 return (GPtrArray *)g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
8955 GINT_TO_POINTER(id));
8961 proto_tracking_interesting_fields(const proto_tree *tree)
8963 GHashTable *interesting_hfids;
8968 interesting_hfids = PTREE_DATA(tree)->interesting_hfids;
8970 return (interesting_hfids != NULL) && g_hash_table_size(interesting_hfids);
8973 /* Helper struct for proto_find_info() and proto_all_finfos() */
8979 /* Helper function for proto_find_info() */
8981 find_finfo(proto_node *node, gpointer data)
8983 field_info *fi = PNODE_FINFO(node);
8984 if (fi && fi->hfinfo) {
8985 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
8986 g_ptr_array_add(((ffdata_t*)data)->array, fi);
8990 /* Don't stop traversing. */
8994 /* Helper function for proto_find_first_info() */
8996 find_first_finfo(proto_node *node, gpointer data)
8998 field_info *fi = PNODE_FINFO(node);
8999 if (fi && fi->hfinfo) {
9000 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
9001 g_ptr_array_add(((ffdata_t*)data)->array, fi);
9005 /* Stop traversing. */
9009 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
9010 * This works on any proto_tree, primed or unprimed, but actually searches
9011 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
9012 * The caller does need to free the returned GPtrArray with
9013 * g_ptr_array_free(<array>, TRUE).
9016 proto_find_finfo(proto_tree *tree, const int id)
9020 ffdata.array = g_ptr_array_new();
9023 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
9025 return ffdata.array;
9028 /* Return GPtrArray* of first field_info pointers for the searched hfindex that appear in a tree.
9029 * This works on any proto_tree, primed or unprimed, but actually searches
9030 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
9031 * The caller does need to free the returned GPtrArray with
9032 * g_ptr_array_free(<array>, TRUE).
9035 proto_find_first_finfo(proto_tree *tree, const int id)
9039 ffdata.array = g_ptr_array_new();
9042 proto_tree_traverse_pre_order(tree, find_first_finfo, &ffdata);
9044 return ffdata.array;
9047 /* Helper function for proto_all_finfos() */
9049 every_finfo(proto_node *node, gpointer data)
9051 field_info *fi = PNODE_FINFO(node);
9052 if (fi && fi->hfinfo) {
9053 g_ptr_array_add(((ffdata_t*)data)->array, fi);
9056 /* Don't stop traversing. */
9060 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
9062 proto_all_finfos(proto_tree *tree)
9066 /* Pre allocate enough space to hold all fields in most cases */
9067 ffdata.array = g_ptr_array_sized_new(512);
9070 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
9072 return ffdata.array;
9083 check_for_offset(proto_node *node, gpointer data)
9085 field_info *fi = PNODE_FINFO(node);
9086 offset_search_t *offsearch = (offset_search_t *)data;
9088 /* !fi == the top most container node which holds nothing */
9089 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && !PROTO_ITEM_IS_GENERATED(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
9090 if (offsearch->offset >= (guint) fi->start &&
9091 offsearch->offset < (guint) (fi->start + fi->length)) {
9093 offsearch->finfo = fi;
9094 return FALSE; /* keep traversing */
9097 return FALSE; /* keep traversing */
9100 /* Search a proto_tree backwards (from leaves to root) looking for the field
9101 * whose start/length occupies 'offset' */
9102 /* XXX - I couldn't find an easy way to search backwards, so I search
9103 * forwards, w/o stopping. Therefore, the last finfo I find will the be
9104 * the one I want to return to the user. This algorithm is inefficient
9105 * and could be re-done, but I'd have to handle all the children and
9106 * siblings of each node myself. When I have more time I'll do that.
9109 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
9111 offset_search_t offsearch;
9113 offsearch.offset = offset;
9114 offsearch.finfo = NULL;
9115 offsearch.tvb = tvb;
9117 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
9119 return offsearch.finfo;
9124 check_for_undecoded(proto_node *node, gpointer data)
9126 field_info *fi = PNODE_FINFO(node);
9127 gchar* decoded = (gchar*)data;
9132 if (fi && fi->hfinfo->type != FT_PROTOCOL) {
9133 for (i = fi->start; i < fi->start + fi->length; i++) {
9136 decoded[byte] |= (1 << bit);
9144 proto_find_undecoded_data(proto_tree *tree, guint length)
9146 gchar* decoded = (gchar*)wmem_alloc0(wmem_packet_scope(), length / 8 + 1);
9148 proto_tree_traverse_pre_order(tree, check_for_undecoded, decoded);
9152 /* Dumps the protocols in the registration database to stdout. An independent
9153 * program can take this output and format it into nice tables or HTML or
9156 * There is one record per line. The fields are tab-delimited.
9158 * Field 1 = protocol name
9159 * Field 2 = protocol short name
9160 * Field 3 = protocol filter name
9163 proto_registrar_dump_protocols(void)
9165 protocol_t *protocol;
9167 void *cookie = NULL;
9170 i = proto_get_first_protocol(&cookie);
9172 protocol = find_protocol_by_id(i);
9173 ws_debug_printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
9174 protocol->filter_name);
9175 i = proto_get_next_protocol(&cookie);
9179 /* Dumps the value_strings, extended value string headers, range_strings
9180 * or true/false strings for fields that have them.
9181 * There is one record per line. Fields are tab-delimited.
9182 * There are four types of records: Value String, Extended Value String Header,
9183 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
9184 * the type of record.
9186 * Note that a record will be generated only if the value_string,... is referenced
9187 * in a registered hfinfo entry.
9193 * Field 2 = Field abbreviation to which this value string corresponds
9194 * Field 3 = Integer value
9197 * Extended Value String Headers
9198 * -----------------------------
9200 * Field 2 = Field abbreviation to which this extended value string header corresponds
9201 * Field 3 = Extended Value String "Name"
9202 * Field 4 = Number of entries in the associated value_string array
9203 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
9208 * Field 2 = Field abbreviation to which this range string corresponds
9209 * Field 3 = Integer value: lower bound
9210 * Field 4 = Integer value: upper bound
9213 * True/False Strings
9214 * ------------------
9216 * Field 2 = Field abbreviation to which this true/false string corresponds
9217 * Field 3 = True String
9218 * Field 4 = False String
9221 proto_registrar_dump_values(void)
9223 header_field_info *hfinfo;
9225 const value_string *vals;
9226 const val64_string *vals64;
9227 const range_string *range;
9228 const true_false_string *tfs;
9229 const unit_name_string *units;
9231 len = gpa_hfinfo.len;
9232 for (i = 0; i < len ; i++) {
9233 if (gpa_hfinfo.hfi[i] == NULL)
9234 continue; /* This is a deregistered protocol or field */
9236 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
9238 if (hfinfo->id == hf_text_only) {
9242 /* ignore protocols */
9243 if (proto_registrar_is_protocol(i)) {
9246 /* process header fields */
9247 #if 0 /* XXX: We apparently allow fields with the same name but with differing "strings" content */
9249 * If this field isn't at the head of the list of
9250 * fields with this name, skip this field - all
9251 * fields with the same name are really just versions
9252 * of the same field stored in different bits, and
9253 * should have the same type/radix/value list, and
9254 * just differ in their bit masks. (If a field isn't
9255 * a bitfield, but can be, say, 1 or 2 bytes long,
9256 * it can just be made FT_UINT16, meaning the
9257 * *maximum* length is 2 bytes, and be used
9260 if (hfinfo->same_name_prev_id != -1)
9269 if (hfinfo->strings != NULL) {
9270 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) != BASE_CUSTOM &&
9271 (hfinfo->type == FT_CHAR ||
9272 hfinfo->type == FT_UINT8 ||
9273 hfinfo->type == FT_UINT16 ||
9274 hfinfo->type == FT_UINT24 ||
9275 hfinfo->type == FT_UINT32 ||
9276 hfinfo->type == FT_UINT40 ||
9277 hfinfo->type == FT_UINT48 ||
9278 hfinfo->type == FT_UINT56 ||
9279 hfinfo->type == FT_UINT64 ||
9280 hfinfo->type == FT_INT8 ||
9281 hfinfo->type == FT_INT16 ||
9282 hfinfo->type == FT_INT24 ||
9283 hfinfo->type == FT_INT32 ||
9284 hfinfo->type == FT_INT40 ||
9285 hfinfo->type == FT_INT48 ||
9286 hfinfo->type == FT_INT56 ||
9287 hfinfo->type == FT_INT64)) {
9289 if (hfinfo->display & BASE_RANGE_STRING) {
9290 range = (const range_string *)hfinfo->strings;
9291 } else if (hfinfo->display & BASE_EXT_STRING) {
9292 vals = VALUE_STRING_EXT_VS_P((value_string_ext *)hfinfo->strings);
9293 } else if (hfinfo->display & BASE_VAL64_STRING) {
9294 vals64 = (const val64_string *)hfinfo->strings;
9295 } else if (hfinfo->display & BASE_UNIT_STRING) {
9296 units = (const unit_name_string *)hfinfo->strings;
9298 vals = (const value_string *)hfinfo->strings;
9301 else if (hfinfo->type == FT_BOOLEAN) {
9302 tfs = (const struct true_false_string *)hfinfo->strings;
9306 /* Print value strings? */
9308 if (hfinfo->display & BASE_EXT_STRING) {
9309 value_string_ext *vse_p = (value_string_ext *)hfinfo->strings;
9310 if (!value_string_ext_validate(vse_p)) {
9311 ws_g_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
9314 try_val_to_str_ext(0, vse_p); /* "prime" the extended value_string */
9315 ws_debug_printf("E\t%s\t%u\t%s\t%s\n",
9317 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
9318 VALUE_STRING_EXT_VS_NAME(vse_p),
9319 value_string_ext_match_type_str(vse_p));
9322 while (vals[vi].strptr) {
9323 /* Print in the proper base */
9324 if (hfinfo->type == FT_CHAR) {
9325 if (g_ascii_isprint(vals[vi].value)) {
9326 ws_debug_printf("V\t%s\t'%c'\t%s\n",
9331 if (hfinfo->display == BASE_HEX) {
9332 ws_debug_printf("V\t%s\t'\\x%02x'\t%s\n",
9338 ws_debug_printf("V\t%s\t'\\%03o'\t%s\n",
9345 if (hfinfo->display == BASE_HEX) {
9346 ws_debug_printf("V\t%s\t0x%x\t%s\n",
9352 ws_debug_printf("V\t%s\t%u\t%s\n",
9363 while (vals64[vi].strptr) {
9364 ws_debug_printf("V64\t%s\t%" G_GINT64_MODIFIER "u\t%s\n",
9372 /* print range strings? */
9375 while (range[vi].strptr) {
9376 /* Print in the proper base */
9377 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_HEX) {
9378 ws_debug_printf("R\t%s\t0x%x\t0x%x\t%s\n",
9380 range[vi].value_min,
9381 range[vi].value_max,
9385 ws_debug_printf("R\t%s\t%u\t%u\t%s\n",
9387 range[vi].value_min,
9388 range[vi].value_max,
9395 /* Print true/false strings? */
9397 ws_debug_printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
9398 tfs->true_string, tfs->false_string);
9400 /* Print unit strings? */
9402 ws_debug_printf("U\t%s\t%s\t%s\n", hfinfo->abbrev,
9403 units->singular, units->plural ? units->plural : "(no plural)");
9408 /* Prints the number of registered fields.
9409 * Useful for determining an appropriate value for
9410 * PROTO_PRE_ALLOC_HF_FIELDS_MEM.
9412 * Returns FALSE if PROTO_PRE_ALLOC_HF_FIELDS_MEM is larger than or equal to
9413 * the number of fields, TRUE otherwise.
9416 proto_registrar_dump_fieldcount(void)
9419 header_field_info *hfinfo;
9420 guint32 deregistered_count = 0;
9421 guint32 same_name_count = 0;
9422 guint32 protocol_count = 0;
9424 for (i = 0; i < gpa_hfinfo.len; i++) {
9425 if (gpa_hfinfo.hfi[i] == NULL) {
9426 deregistered_count++;
9427 continue; /* This is a deregistered protocol or header field */
9430 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
9432 if (proto_registrar_is_protocol(i))
9435 if (hfinfo->same_name_prev_id != -1)
9439 ws_debug_printf("There are %u header fields registered, of which:\n"
9440 "\t%u are deregistered\n"
9441 "\t%u are protocols\n"
9442 "\t%u have the same name as another field\n\n",
9443 gpa_hfinfo.len, deregistered_count, protocol_count,
9446 ws_debug_printf("%d fields were pre-allocated.\n%s", PROTO_PRE_ALLOC_HF_FIELDS_MEM,
9447 (gpa_hfinfo.allocated_len > PROTO_PRE_ALLOC_HF_FIELDS_MEM) ?
9448 "* * Please increase PROTO_PRE_ALLOC_HF_FIELDS_MEM (in epan/proto.c)! * *\n\n" :
9451 ws_debug_printf("The header field table consumes %u KiB of memory.\n",
9452 (unsigned int)(gpa_hfinfo.allocated_len * sizeof(header_field_info *) / 1024));
9453 ws_debug_printf("The fields themselves consume %u KiB of memory.\n",
9454 (unsigned int)(gpa_hfinfo.len * sizeof(header_field_info) / 1024));
9456 return (gpa_hfinfo.allocated_len > PROTO_PRE_ALLOC_HF_FIELDS_MEM);
9460 /* Dumps the contents of the registration database to stdout. An independent
9461 * program can take this output and format it into nice tables or HTML or
9464 * There is one record per line. Each record is either a protocol or a header
9465 * field, differentiated by the first field. The fields are tab-delimited.
9470 * Field 2 = descriptive protocol name
9471 * Field 3 = protocol abbreviation
9476 * Field 2 = descriptive field name
9477 * Field 3 = field abbreviation
9478 * Field 4 = type ( textual representation of the the ftenum type )
9479 * Field 5 = parent protocol abbreviation
9480 * Field 6 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
9481 * Field 7 = bitmask: format: hex: 0x....
9482 * Field 8 = blurb describing field
9485 proto_registrar_dump_fields(void)
9487 header_field_info *hfinfo, *parent_hfinfo;
9489 const char *enum_name;
9490 const char *base_name;
9494 len = gpa_hfinfo.len;
9495 for (i = 0; i < len ; i++) {
9496 if (gpa_hfinfo.hfi[i] == NULL)
9497 continue; /* This is a deregistered protocol or header field */
9499 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
9502 * Skip the pseudo-field for "proto_tree_add_text()" since
9503 * we don't want it in the list of filterable fields.
9505 if (hfinfo->id == hf_text_only)
9508 /* format for protocols */
9509 if (proto_registrar_is_protocol(i)) {
9510 ws_debug_printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
9512 /* format for header fields */
9515 * If this field isn't at the head of the list of
9516 * fields with this name, skip this field - all
9517 * fields with the same name are really just versions
9518 * of the same field stored in different bits, and
9519 * should have the same type/radix/value list, and
9520 * just differ in their bit masks. (If a field isn't
9521 * a bitfield, but can be, say, 1 or 2 bytes long,
9522 * it can just be made FT_UINT16, meaning the
9523 * *maximum* length is 2 bytes, and be used
9526 if (hfinfo->same_name_prev_id != -1)
9529 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
9531 enum_name = ftype_name(hfinfo->type);
9534 if (hfinfo->type == FT_CHAR ||
9535 hfinfo->type == FT_UINT8 ||
9536 hfinfo->type == FT_UINT16 ||
9537 hfinfo->type == FT_UINT24 ||
9538 hfinfo->type == FT_UINT32 ||
9539 hfinfo->type == FT_UINT40 ||
9540 hfinfo->type == FT_UINT48 ||
9541 hfinfo->type == FT_UINT56 ||
9542 hfinfo->type == FT_UINT64 ||
9543 hfinfo->type == FT_INT8 ||
9544 hfinfo->type == FT_INT16 ||
9545 hfinfo->type == FT_INT24 ||
9546 hfinfo->type == FT_INT32 ||
9547 hfinfo->type == FT_INT40 ||
9548 hfinfo->type == FT_INT48 ||
9549 hfinfo->type == FT_INT56 ||
9550 hfinfo->type == FT_INT64) {
9552 switch (FIELD_DISPLAY(hfinfo->display)) {
9564 base_name = val_to_str_const(FIELD_DISPLAY(hfinfo->display), hf_display, "????");
9570 } else if (hfinfo->type == FT_BOOLEAN) {
9571 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
9572 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
9576 blurb = hfinfo->blurb;
9579 else if (strlen(blurb) == 0)
9582 ws_debug_printf("F\t%s\t%s\t%s\t%s\t%s\t0x%" G_GINT64_MODIFIER "x\t%s\n",
9583 hfinfo->name, hfinfo->abbrev, enum_name,
9584 parent_hfinfo->abbrev, base_name,
9585 hfinfo->bitmask, blurb);
9590 /* Dumps field types and descriptive names to stdout. An independent
9591 * program can take this output and format it into nice tables or HTML or
9594 * There is one record per line. The fields are tab-delimited.
9596 * Field 1 = field type name, e.g. FT_UINT8
9597 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
9600 proto_registrar_dump_ftypes(void)
9604 for (fte = 0; fte < FT_NUM_TYPES; fte++) {
9605 ws_debug_printf("%s\t%s\n", ftype_name((ftenum_t)fte), ftype_pretty_name((ftenum_t)fte));
9609 /* This function indicates whether it's possible to construct a
9610 * "match selected" display filter string for the specified field,
9611 * returns an indication of whether it's possible, and, if it's
9612 * possible and "filter" is non-null, constructs the filter and
9613 * sets "*filter" to point to it.
9614 * You do not need to [g_]free() this string since it will be automatically
9615 * freed once the next packet is dissected.
9618 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
9621 header_field_info *hfinfo;
9626 gint start, length, length_remaining;
9628 gchar is_signed_num = FALSE;
9633 hfinfo = finfo->hfinfo;
9634 DISSECTOR_ASSERT(hfinfo);
9635 abbrev_len = (int) strlen(hfinfo->abbrev);
9637 if (hfinfo->strings && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
9638 const gchar *str = NULL;
9640 switch (hfinfo->type) {
9646 str = hf_try_val_to_str(fvalue_get_sinteger(&finfo->value), hfinfo);
9654 str = hf_try_val_to_str(fvalue_get_uinteger(&finfo->value), hfinfo);
9661 if (str != NULL && filter != NULL) {
9662 *filter = wmem_strdup_printf(NULL, "%s == \"%s\"", hfinfo->abbrev, str);
9668 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
9669 * functions for FT_UINT and FT_INT types, as we choose the base in
9670 * the string expression based on the display base of the field.
9672 * Note that the base does matter, as this is also used for
9673 * the protocolinfo tap.
9675 * It might be nice to use them in "proto_item_fill_label()"
9676 * as well, although, there, you'd have to deal with the base
9677 * *and* with resolved values for addresses.
9679 * Perhaps we need two different val_to_string routines, one
9680 * to generate items for display filters and one to generate
9681 * strings for display, and pass to both of them the
9682 * "display" and "strings" values in the header_field_info
9683 * structure for the field, so they can get the base and,
9684 * if the field is Boolean or an enumerated integer type,
9685 * the tables used to generate human-readable values.
9687 switch (hfinfo->type) {
9690 if (filter != NULL) {
9696 number = fvalue_get_uinteger(&finfo->value);
9698 out = hfinfo_char_value_format(hfinfo, buf, number);
9700 *filter = wmem_strdup_printf(NULL, "%s == %s", hfinfo->abbrev, out);
9708 is_signed_num = TRUE;
9715 if (filter != NULL) {
9722 number = fvalue_get_sinteger(&finfo->value);
9724 number = fvalue_get_uinteger(&finfo->value);
9726 out = hfinfo_numeric_value_format(hfinfo, buf, number);
9728 *filter = wmem_strdup_printf(NULL, "%s == %s", hfinfo->abbrev, out);
9736 is_signed_num = TRUE;
9742 if (filter != NULL) {
9749 number = fvalue_get_sinteger64(&finfo->value);
9751 number = fvalue_get_uinteger64(&finfo->value);
9753 out = hfinfo_numeric_value_format64(hfinfo, buf, number);
9755 *filter = wmem_strdup_printf(NULL, "%s == %s", hfinfo->abbrev, out);
9761 *filter = wmem_strdup(NULL, finfo->hfinfo->abbrev);
9766 * If the length is 0, just match the name of the
9769 * (Also check for negative values, just in case,
9770 * as we'll cast it to an unsigned value later.)
9772 length = finfo->length;
9775 *filter = wmem_strdup(NULL, finfo->hfinfo->abbrev);
9782 * This doesn't have a value, so we'd match
9783 * on the raw bytes at this address.
9785 * Should we be allowed to access to the raw bytes?
9786 * If "edt" is NULL, the answer is "no".
9792 * Is this field part of the raw frame tvbuff?
9793 * If not, we can't use "frame[N:M]" to match
9796 * XXX - should this be frame-relative, or
9797 * protocol-relative?
9799 * XXX - does this fallback for non-registered
9800 * fields even make sense?
9802 if (finfo->ds_tvb != edt->tvb)
9803 return FALSE; /* you lose */
9806 * Don't go past the end of that tvbuff.
9808 length_remaining = tvb_captured_length_remaining(finfo->ds_tvb, finfo->start);
9809 if (length > length_remaining)
9810 length = length_remaining;
9814 if (filter != NULL) {
9815 start = finfo->start;
9816 buf_len = 32 + length * 3;
9817 *filter = (char *)wmem_alloc0(NULL, buf_len);
9820 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
9821 "frame[%d:%d] == ", finfo->start, length);
9822 for (i=0; i<length; i++) {
9823 c = tvb_get_guint8(finfo->ds_tvb, start);
9826 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
9829 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
9836 /* FT_PCRE never appears as a type for a registered field. It is
9837 * only used internally. */
9838 DISSECTOR_ASSERT_NOT_REACHED();
9841 /* By default, use the fvalue's "to_string_repr" method. */
9843 /* Figure out the string length needed.
9844 * The ft_repr length.
9845 * 4 bytes for " == ".
9846 * 1 byte for trailing NUL.
9848 if (filter != NULL) {
9850 dfilter_len = fvalue_string_repr_len(&finfo->value,
9851 FTREPR_DFILTER, finfo->hfinfo->display);
9852 dfilter_len += abbrev_len + 4 + 1;
9853 *filter = (char *)wmem_alloc0(NULL, dfilter_len);
9855 /* Create the string */
9856 str = fvalue_to_string_repr(NULL, &finfo->value, FTREPR_DFILTER, finfo->hfinfo->display);
9857 g_snprintf(*filter, dfilter_len, "%s == %s", hfinfo->abbrev, str);
9858 wmem_free(NULL, str);
9867 * Returns TRUE if we can do a "match selected" on the field, FALSE
9871 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
9873 return construct_match_selected_string(finfo, edt, NULL);
9876 /* This function attempts to construct a "match selected" display filter
9877 * string for the specified field; if it can do so, it returns a pointer
9878 * to the string, otherwise it returns NULL.
9880 * The string is allocated with packet lifetime scope.
9881 * You do not need to [g_]free() this string since it will be automatically
9882 * freed once the next packet is dissected.
9885 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
9887 char *filter = NULL;
9889 if (!construct_match_selected_string(finfo, edt, &filter))
9891 wmem_free(NULL, filter);
9897 /* This function is common code for all proto_tree_add_bitmask... functions.
9901 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
9902 const int len, const gint ett, const int **fields,
9903 const int flags, gboolean first,
9904 gboolean use_parent_tree,
9905 proto_tree* tree, guint64 value)
9908 guint64 available_bits = 0;
9910 header_field_info *hf;
9914 if (len < 0 || len > 8)
9915 g_assert_not_reached();
9916 bitshift = (8 - (guint)len)*8;
9917 available_bits = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF) >> bitshift;
9919 if (use_parent_tree == FALSE)
9920 tree = proto_item_add_subtree(item, ett);
9923 guint64 present_bits;
9924 PROTO_REGISTRAR_GET_NTH(**fields,hf);
9925 DISSECTOR_ASSERT_HINT(hf->bitmask != 0, hf->abbrev);
9927 /* Skip fields that aren't fully present */
9928 present_bits = available_bits & hf->bitmask;
9929 if (present_bits != hf->bitmask) {
9940 proto_tree_add_uint(tree, **fields, tvb, offset, len, (guint32)value);
9947 proto_tree_add_int(tree, **fields, tvb, offset, len, (gint32)value);
9954 proto_tree_add_uint64(tree, **fields, tvb, offset, len, value);
9961 proto_tree_add_int64(tree, **fields, tvb, offset, len, (gint64)value);
9965 proto_tree_add_boolean64(tree, **fields, tvb, offset, len, value);
9969 DISSECTOR_ASSERT_NOT_REACHED();
9972 if (flags & BMT_NO_APPEND) {
9976 tmpval = (value & hf->bitmask) >> hfinfo_bitshift(hf);
9980 if (hf->display == BASE_CUSTOM) {
9981 gchar lbl[ITEM_LABEL_LENGTH];
9982 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
9984 DISSECTOR_ASSERT(fmtfunc);
9985 fmtfunc(lbl, (guint32) tmpval);
9986 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
9990 else if (hf->strings) {
9991 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
9992 hf->name, hf_try_val_to_str_const((guint32) tmpval, hf, "Unknown"));
9995 else if (!(flags & BMT_NO_INT)) {
10000 proto_item_append_text(item, ", ");
10003 out = hfinfo_char_value_format(hf, buf, (guint32) tmpval);
10004 proto_item_append_text(item, "%s: %s", hf->name, out);
10014 if (hf->display == BASE_CUSTOM) {
10015 gchar lbl[ITEM_LABEL_LENGTH];
10016 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
10018 DISSECTOR_ASSERT(fmtfunc);
10019 fmtfunc(lbl, (guint32) tmpval);
10020 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10024 else if ((hf->strings) &&(!(hf->display & BASE_UNIT_STRING))) {
10025 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10026 hf->name, hf_try_val_to_str_const((guint32) tmpval, hf, "Unknown"));
10029 else if (!(flags & BMT_NO_INT)) {
10034 proto_item_append_text(item, ", ");
10037 out = hfinfo_number_value_format(hf, buf, (guint32) tmpval);
10038 if (hf->display & BASE_UNIT_STRING) {
10039 proto_item_append_text(item, "%s: %s%s", hf->name, out, unit_name_string_get_value((guint32) tmpval, (unit_name_string*)hf->strings));
10041 proto_item_append_text(item, "%s: %s", hf->name, out);
10052 integer32 = (guint32) tmpval;
10054 no_of_bits = ws_count_ones(hf->bitmask);
10055 integer32 = ws_sign_ext32(integer32, no_of_bits);
10057 if (hf->display == BASE_CUSTOM) {
10058 gchar lbl[ITEM_LABEL_LENGTH];
10059 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
10061 DISSECTOR_ASSERT(fmtfunc);
10062 fmtfunc(lbl, (gint32) integer32);
10063 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10067 else if ((hf->strings) &&(!(hf->display & BASE_UNIT_STRING))) {
10068 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10069 hf->name, hf_try_val_to_str_const((gint32) integer32, hf, "Unknown"));
10072 else if (!(flags & BMT_NO_INT)) {
10077 proto_item_append_text(item, ", ");
10080 out = hfinfo_number_value_format(hf, buf, (gint32) integer32);
10081 if ((hf->strings) &&(!(hf->display & BASE_UNIT_STRING))) {
10082 proto_item_append_text(item, "%s: %s%s", hf->name, out, unit_name_string_get_value((guint32) tmpval, (unit_name_string*)hf->strings));
10084 proto_item_append_text(item, "%s: %s", hf->name, out);
10095 if (hf->display == BASE_CUSTOM) {
10096 gchar lbl[ITEM_LABEL_LENGTH];
10097 const custom_fmt_func_64_t fmtfunc = (const custom_fmt_func_64_t)hf->strings;
10099 DISSECTOR_ASSERT(fmtfunc);
10100 fmtfunc(lbl, tmpval);
10101 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10105 else if (hf->strings) {
10106 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10107 hf->name, hf_try_val64_to_str_const(tmpval, hf, "Unknown"));
10110 else if (!(flags & BMT_NO_INT)) {
10115 proto_item_append_text(item, ", ");
10118 out = hfinfo_number_value_format64(hf, buf, tmpval);
10119 proto_item_append_text(item, "%s: %s", hf->name, out);
10130 no_of_bits = ws_count_ones(hf->bitmask);
10131 tmpval = ws_sign_ext64(tmpval, no_of_bits);
10133 if (hf->display == BASE_CUSTOM) {
10134 gchar lbl[ITEM_LABEL_LENGTH];
10135 const custom_fmt_func_64_t fmtfunc = (const custom_fmt_func_64_t)hf->strings;
10137 DISSECTOR_ASSERT(fmtfunc);
10138 fmtfunc(lbl, (gint64) tmpval);
10139 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10143 else if (hf->strings) {
10144 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10145 hf->name, hf_try_val64_to_str_const((gint64) tmpval, hf, "Unknown"));
10148 else if (!(flags & BMT_NO_INT)) {
10153 proto_item_append_text(item, ", ");
10156 out = hfinfo_number_value_format64(hf, buf, (gint64) tmpval);
10157 proto_item_append_text(item, "%s: %s", hf->name, out);
10164 if (hf->strings && !(flags & BMT_NO_TFS)) {
10165 /* If we have true/false strings, emit full - otherwise messages
10166 might look weird */
10167 const struct true_false_string *tfs =
10168 (const struct true_false_string *)hf->strings;
10171 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10172 hf->name, tfs->true_string);
10174 } else if (!(flags & BMT_NO_FALSE)) {
10175 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
10176 hf->name, tfs->false_string);
10179 } else if (hf->bitmask & value) {
10180 /* If the flag is set, show the name */
10181 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
10186 DISSECTOR_ASSERT_NOT_REACHED();
10196 /* This function will dissect a sequence of bytes that describe a
10197 * bitmask and supply the value of that sequence through a pointer.
10198 * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
10200 * This field will form an expansion under which the individual fields of the
10201 * bitmask is dissected and displayed.
10202 * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
10204 * fields is an array of pointers to int that lists all the fields of the
10205 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
10206 * or another integer of the same type/size as hf_hdr with a mask specified.
10207 * This array is terminated by a NULL entry.
10209 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
10210 * FT_integer fields that have a value_string attached will have the
10211 * matched string displayed on the expansion line.
10214 proto_tree_add_bitmask_ret_uint64(proto_tree *parent_tree, tvbuff_t *tvb,
10215 const guint offset, const int hf_hdr,
10216 const gint ett, const int **fields,
10217 const guint encoding, guint64 *retval)
10219 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);
10222 /* This function will dissect a sequence of bytes that describe a
10224 * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
10226 * This field will form an expansion under which the individual fields of the
10227 * bitmask is dissected and displayed.
10228 * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
10230 * fields is an array of pointers to int that lists all the fields of the
10231 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
10232 * or another integer of the same type/size as hf_hdr with a mask specified.
10233 * This array is terminated by a NULL entry.
10235 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
10236 * FT_integer fields that have a value_string attached will have the
10237 * matched string displayed on the expansion line.
10240 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
10241 const guint offset, const int hf_hdr,
10242 const gint ett, const int **fields,
10243 const guint encoding)
10245 return proto_tree_add_bitmask_with_flags(parent_tree, tvb, offset, hf_hdr, ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS);
10248 /* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
10249 * what data is appended to the header.
10252 proto_tree_add_bitmask_with_flags_ret_uint64(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
10253 const int hf_hdr, const gint ett, const int **fields, const guint encoding, const int flags,
10256 proto_item *item = NULL;
10257 header_field_info *hf;
10261 PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
10262 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
10263 len = ftype_length(hf->type);
10264 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
10267 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
10268 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
10269 flags, FALSE, FALSE, NULL, value);
10274 /* Mask out irrelevant portions */
10275 *retval &= hf->bitmask;
10277 *retval >>= hfinfo_bitshift(hf);
10283 /* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
10284 * what data is appended to the header.
10287 proto_tree_add_bitmask_with_flags(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
10288 const int hf_hdr, const gint ett, const int **fields, const guint encoding, const int flags)
10290 proto_item *item = NULL;
10291 header_field_info *hf;
10295 PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
10296 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
10299 len = ftype_length(hf->type);
10300 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
10301 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
10302 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
10303 flags, FALSE, FALSE, NULL, value);
10309 /* Similar to proto_tree_add_bitmask(), but with a passed in value (presumably because it
10310 can't be retrieved directly from tvb) */
10312 proto_tree_add_bitmask_value(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
10313 const int hf_hdr, const gint ett, const int **fields, const guint64 value)
10315 return proto_tree_add_bitmask_value_with_flags(parent_tree, tvb, offset,
10316 hf_hdr, ett, fields, value, BMT_NO_INT|BMT_NO_TFS);
10319 /* Similar to proto_tree_add_bitmask_value(), but with control of flag values */
10320 WS_DLL_PUBLIC proto_item *
10321 proto_tree_add_bitmask_value_with_flags(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
10322 const int hf_hdr, const gint ett, const int **fields, const guint64 value, const int flags)
10324 proto_item *item = NULL;
10325 header_field_info *hf;
10328 PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
10329 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
10330 /* the proto_tree_add_uint/_uint64() calls below
10331 will fail if tvb==NULL and len!=0 */
10332 len = tvb ? ftype_length(hf->type) : 0;
10336 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len, (guint32)value);
10338 item = proto_tree_add_uint64(parent_tree, hf_hdr, tvb, offset, len, value);
10340 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
10341 flags, FALSE, FALSE, NULL, value);
10347 /* Similar to proto_tree_add_bitmask(), but with no "header" item to group all of the fields */
10349 proto_tree_add_bitmask_list(proto_tree *tree, tvbuff_t *tvb, const guint offset,
10350 const int len, const int **fields, const guint encoding)
10355 value = get_uint64_value(tree, tvb, offset, len, encoding);
10356 proto_item_add_bitmask_tree(NULL, tvb, offset, len, -1, fields,
10357 BMT_NO_APPEND, FALSE, TRUE, tree, value);
10362 proto_tree_add_bitmask_list_value(proto_tree *tree, tvbuff_t *tvb, const guint offset,
10363 const int len, const int **fields, const guint64 value)
10366 proto_item_add_bitmask_tree(NULL, tvb, offset, len, -1, fields,
10367 BMT_NO_APPEND, FALSE, TRUE, tree, value);
10372 /* The same as proto_tree_add_bitmask(), but using a caller-supplied length.
10373 * This is intended to support bitmask fields whose lengths can vary, perhaps
10374 * as the underlying standard evolves over time.
10375 * With this API there is the possibility of being called to display more or
10376 * less data than the dissector was coded to support.
10377 * In such cases, it is assumed that bitmasks are extended on the MSb end.
10378 * Thus when presented with "too much" or "too little" data, MSbits will be
10379 * ignored or MSfields sacrificed.
10381 * Only fields for which all defined bits are available are displayed.
10384 proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb,
10385 const guint offset, const guint len, const int hf_hdr,
10386 const gint ett, const int **fields, struct expert_field* exp,
10387 const guint encoding)
10389 proto_item *item = NULL;
10390 header_field_info *hf;
10391 guint decodable_len;
10392 guint decodable_offset;
10393 guint32 decodable_value;
10396 PROTO_REGISTRAR_GET_NTH(hf_hdr, hf);
10397 DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
10399 decodable_offset = offset;
10400 decodable_len = MIN(len, (guint) ftype_length(hf->type));
10402 /* If we are ftype_length-limited,
10403 * make sure we decode as many LSBs as possible.
10405 if (encoding == ENC_BIG_ENDIAN) {
10406 decodable_offset += (len - decodable_len);
10410 decodable_value = get_uint_value(parent_tree, tvb, decodable_offset,
10411 decodable_len, encoding);
10413 /* The root item covers all the bytes even if we can't decode them all */
10414 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len,
10418 if (decodable_len < len) {
10419 /* Dissector likely requires updating for new protocol revision */
10420 expert_add_info_format(NULL, item, exp,
10421 "Only least-significant %d of %d bytes decoded",
10422 decodable_len, len);
10426 value = get_uint64_value(parent_tree, tvb, decodable_offset, decodable_len, encoding);
10427 proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len,
10428 ett, fields, BMT_NO_INT|BMT_NO_TFS, FALSE, FALSE, NULL, value);
10434 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
10436 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
10437 const guint offset, const guint len,
10438 const char *name, const char *fallback,
10439 const gint ett, const int **fields,
10440 const guint encoding, const int flags)
10442 proto_item *item = NULL;
10446 item = proto_tree_add_text_internal(parent_tree, tvb, offset, len, "%s", name ? name : "");
10447 value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
10448 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
10449 flags, TRUE, FALSE, NULL, value) && fallback) {
10450 /* Still at first item - append 'fallback' text if any */
10451 proto_item_append_text(item, "%s", fallback);
10459 proto_tree_add_bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
10460 const guint bit_offset, const gint no_of_bits,
10461 const guint encoding)
10463 header_field_info *hfinfo;
10467 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
10469 octet_length = (no_of_bits + 7) >> 3;
10470 octet_offset = bit_offset >> 3;
10471 test_length(hfinfo, tvb, octet_offset, octet_length);
10473 /* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
10474 * but only after doing a bunch more work (which we can, in the common
10475 * case, shortcut here).
10477 CHECK_FOR_NULL_TREE(tree);
10478 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
10480 return proto_tree_add_bits_ret_val(tree, hfindex, tvb, bit_offset, no_of_bits, NULL, encoding);
10484 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
10485 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
10486 * Offset should be given in bits from the start of the tvb.
10489 static proto_item *
10490 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
10491 const guint bit_offset, const gint no_of_bits,
10492 guint64 *return_value, const guint encoding)
10496 guint8 tot_no_bits;
10498 char lbl_str[ITEM_LABEL_LENGTH];
10502 header_field_info *hf_field;
10504 const true_false_string *tfstring;
10506 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
10507 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
10509 if (hf_field->bitmask != 0) {
10510 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
10511 "Incompatible use of proto_tree_add_bits_ret_val"
10512 " with field '%s' (%s) with bitmask != 0",
10513 hf_field->abbrev, hf_field->name));
10516 DISSECTOR_ASSERT(no_of_bits > 0);
10518 /* Byte align offset */
10519 offset = bit_offset>>3;
10522 * Calculate the number of octets used to hold the bits
10524 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
10525 length = (tot_no_bits + 7) >> 3;
10527 if (no_of_bits < 65) {
10528 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
10530 DISSECTOR_ASSERT_NOT_REACHED();
10534 /* Sign extend for signed types */
10535 switch (hf_field->type) {
10544 value = ws_sign_ext64(value, no_of_bits);
10551 if (return_value) {
10552 *return_value = value;
10555 /* Coast clear. Try and fake it */
10556 CHECK_FOR_NULL_TREE(tree);
10557 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
10559 bf_str = decode_bits_in_field(bit_offset, no_of_bits, value);
10561 switch (hf_field->type) {
10563 /* Boolean field */
10564 tfstring = (const true_false_string *) &tfs_true_false;
10565 if (hf_field->strings)
10566 tfstring = (const true_false_string *)hf_field->strings;
10567 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, (guint32)value,
10569 bf_str, hf_field->name,
10570 (guint64)value ? tfstring->true_string : tfstring->false_string);
10574 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
10575 fill_label_char(PITEM_FINFO(pi), lbl_str);
10582 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
10583 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
10590 pi = proto_tree_add_int(tree, hfindex, tvb, offset, length, (gint32)value);
10591 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
10598 pi = proto_tree_add_uint64(tree, hfindex, tvb, offset, length, value);
10599 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
10606 pi = proto_tree_add_int64(tree, hfindex, tvb, offset, length, (gint64)value);
10607 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
10611 DISSECTOR_ASSERT_NOT_REACHED();
10616 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
10621 proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
10622 const guint bit_offset, const crumb_spec_t *crumb_spec,
10623 guint64 *return_value)
10628 guint mask_initial_bit_offset;
10629 guint mask_greatest_bit_offset;
10630 guint octet_length;
10633 char lbl_str[ITEM_LABEL_LENGTH];
10635 guint64 composite_bitmask;
10636 guint64 composite_bitmap;
10638 header_field_info *hf_field;
10639 const true_false_string *tfstring;
10641 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
10642 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
10644 if (hf_field->bitmask != 0) {
10645 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
10646 "Incompatible use of proto_tree_add_split_bits_item_ret_val"
10647 " with field '%s' (%s) with bitmask != 0",
10648 hf_field->abbrev, hf_field->name));
10651 mask_initial_bit_offset = bit_offset % 8;
10656 mask_greatest_bit_offset = 0;
10657 composite_bitmask = 0;
10658 composite_bitmap = 0;
10660 while (crumb_spec[i].crumb_bit_length != 0) {
10661 guint64 crumb_mask, crumb_value;
10662 guint8 crumb_end_bit_offset;
10664 DISSECTOR_ASSERT(i < 64);
10665 crumb_value = tvb_get_bits64(tvb,
10666 bit_offset + crumb_spec[i].crumb_bit_offset,
10667 crumb_spec[i].crumb_bit_length,
10669 value += crumb_value;
10670 no_of_bits += crumb_spec[i].crumb_bit_length;
10672 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
10673 octet containing the initial offset.
10674 If the mask is beyond 32 bits, then give up on bit map display.
10675 This could be improved in future, probably showing a table
10676 of 32 or 64 bits per row */
10677 if (mask_greatest_bit_offset < 32) {
10678 crumb_end_bit_offset = mask_initial_bit_offset
10679 + crumb_spec[i].crumb_bit_offset
10680 + crumb_spec[i].crumb_bit_length;
10681 crumb_mask = (G_GUINT64_CONSTANT(1) << crumb_spec[i].crumb_bit_length) - 1;
10683 if (crumb_end_bit_offset > mask_greatest_bit_offset) {
10684 mask_greatest_bit_offset = crumb_end_bit_offset;
10686 composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset));
10687 composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset));
10689 /* Shift left for the next segment */
10690 value <<= crumb_spec[++i].crumb_bit_length;
10693 /* Sign extend for signed types */
10694 switch (hf_field->type) {
10703 value = ws_sign_ext64(value, no_of_bits);
10709 if (return_value) {
10710 *return_value = value;
10713 /* Coast clear. Try and fake it */
10714 CHECK_FOR_NULL_TREE(tree);
10715 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
10717 /* initialise the format string */
10720 octet_offset = bit_offset >> 3;
10722 /* Round up mask length to nearest octet */
10723 octet_length = ((mask_greatest_bit_offset + 7) >> 3);
10724 mask_greatest_bit_offset = octet_length << 3;
10726 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
10727 It would be a useful enhancement to eliminate this restriction. */
10728 if (mask_greatest_bit_offset > 0 && mask_greatest_bit_offset <= 32) {
10729 other_decode_bitfield_value(bf_str,
10730 (guint32)(composite_bitmap >> (64 - mask_greatest_bit_offset)),
10731 (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
10732 mask_greatest_bit_offset);
10735 switch (hf_field->type) {
10736 case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
10737 /* Boolean field */
10738 tfstring = (const true_false_string *) &tfs_true_false;
10739 if (hf_field->strings)
10740 tfstring = (const true_false_string *) hf_field->strings;
10741 return proto_tree_add_boolean_format(tree, hfindex,
10742 tvb, octet_offset, octet_length, (guint32)value,
10744 bf_str, hf_field->name,
10745 (guint64)value ? tfstring->true_string : tfstring->false_string);
10749 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
10750 fill_label_char(PITEM_FINFO(pi), lbl_str);
10757 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
10758 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
10765 pi = proto_tree_add_int(tree, hfindex, tvb, octet_offset, octet_length, (gint32)value);
10766 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
10773 pi = proto_tree_add_uint64(tree, hfindex, tvb, octet_offset, octet_length, value);
10774 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
10781 pi = proto_tree_add_int64(tree, hfindex, tvb, octet_offset, octet_length, (gint64)value);
10782 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
10786 DISSECTOR_ASSERT_NOT_REACHED();
10790 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
10795 proto_tree_add_split_bits_crumb(proto_tree *tree, const int hfindex, tvbuff_t *tvb, const guint bit_offset,
10796 const crumb_spec_t *crumb_spec, guint16 crumb_index)
10798 header_field_info *hfinfo;
10800 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
10801 proto_tree_add_text_internal(tree, tvb,
10803 ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1,
10804 "%s crumb %d of %s (decoded above)",
10805 decode_bits_in_field(bit_offset, crumb_spec[crumb_index].crumb_bit_length,
10808 crumb_spec[crumb_index].crumb_bit_length,
10815 proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
10816 const guint bit_offset, const gint no_of_bits,
10817 guint64 *return_value, const guint encoding)
10821 if ((item = _proto_tree_add_bits_ret_val(tree, hfindex, tvb,
10822 bit_offset, no_of_bits,
10823 return_value, encoding))) {
10824 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
10825 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
10830 static proto_item *
10831 _proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
10832 tvbuff_t *tvb, const guint bit_offset,
10833 const gint no_of_bits, void *value_ptr,
10838 guint8 tot_no_bits;
10841 header_field_info *hf_field;
10843 /* We do not have to return a value, try to fake it as soon as possible */
10844 CHECK_FOR_NULL_TREE(tree);
10845 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
10847 if (hf_field->bitmask != 0) {
10848 REPORT_DISSECTOR_BUG(wmem_strdup_printf(wmem_packet_scope(),
10849 "Incompatible use of proto_tree_add_bits_format_value"
10850 " with field '%s' (%s) with bitmask != 0",
10851 hf_field->abbrev, hf_field->name));
10854 DISSECTOR_ASSERT(no_of_bits > 0);
10856 /* Byte align offset */
10857 offset = bit_offset>>3;
10860 * Calculate the number of octets used to hold the bits
10862 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
10863 length = tot_no_bits>>3;
10864 /* If we are using part of the next octet, increase length by 1 */
10865 if (tot_no_bits & 0x07)
10868 if (no_of_bits < 65) {
10869 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
10871 DISSECTOR_ASSERT_NOT_REACHED();
10875 str = decode_bits_in_field(bit_offset, no_of_bits, value);
10877 g_strlcat(str, " = ", 256+64);
10878 g_strlcat(str, hf_field->name, 256+64);
10881 * This function does not receive an actual value but a dimensionless pointer to that value.
10882 * For this reason, the type of the header field is examined in order to determine
10883 * what kind of value we should read from this address.
10884 * The caller of this function must make sure that for the specific header field type the address of
10885 * a compatible value is provided.
10887 switch (hf_field->type) {
10889 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
10890 "%s: %s", str, value_str);
10898 return proto_tree_add_uint_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
10899 "%s: %s", str, value_str);
10906 return proto_tree_add_uint64_format(tree, hfindex, tvb, offset, length, *(guint64 *)value_ptr,
10907 "%s: %s", str, value_str);
10914 return proto_tree_add_int_format(tree, hfindex, tvb, offset, length, *(gint32 *)value_ptr,
10915 "%s: %s", str, value_str);
10922 return proto_tree_add_int64_format(tree, hfindex, tvb, offset, length, *(gint64 *)value_ptr,
10923 "%s: %s", str, value_str);
10927 return proto_tree_add_float_format(tree, hfindex, tvb, offset, length, *(float *)value_ptr,
10928 "%s: %s", str, value_str);
10932 DISSECTOR_ASSERT_NOT_REACHED();
10938 static proto_item *
10939 proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
10940 tvbuff_t *tvb, const guint bit_offset,
10941 const gint no_of_bits, void *value_ptr,
10946 if ((item = _proto_tree_add_bits_format_value(tree, hfindex,
10947 tvb, bit_offset, no_of_bits,
10948 value_ptr, value_str))) {
10949 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
10950 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
10955 #define CREATE_VALUE_STRING(dst,format,ap) \
10956 va_start(ap, format); \
10957 dst = wmem_strdup_vprintf(wmem_packet_scope(), format, ap); \
10961 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hfindex,
10962 tvbuff_t *tvb, const guint bit_offset,
10963 const gint no_of_bits, guint32 value,
10964 const char *format, ...)
10968 header_field_info *hf_field;
10970 CHECK_FOR_NULL_TREE(tree);
10972 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
10974 switch (hf_field->type) {
10982 DISSECTOR_ASSERT_NOT_REACHED();
10987 CREATE_VALUE_STRING(dst, format, ap);
10989 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
10993 proto_tree_add_uint64_bits_format_value(proto_tree *tree, const int hfindex,
10994 tvbuff_t *tvb, const guint bit_offset,
10995 const gint no_of_bits, guint64 value,
10996 const char *format, ...)
11000 header_field_info *hf_field;
11002 CHECK_FOR_NULL_TREE(tree);
11004 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11006 switch (hf_field->type) {
11014 DISSECTOR_ASSERT_NOT_REACHED();
11019 CREATE_VALUE_STRING(dst, format, ap);
11021 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11025 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hfindex,
11026 tvbuff_t *tvb, const guint bit_offset,
11027 const gint no_of_bits, float value,
11028 const char *format, ...)
11032 header_field_info *hf_field;
11034 CHECK_FOR_NULL_TREE(tree);
11036 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11038 DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_FLOAT);
11040 CREATE_VALUE_STRING(dst, format, ap);
11042 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11046 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hfindex,
11047 tvbuff_t *tvb, const guint bit_offset,
11048 const gint no_of_bits, gint32 value,
11049 const char *format, ...)
11053 header_field_info *hf_field;
11055 CHECK_FOR_NULL_TREE(tree);
11057 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11059 switch (hf_field->type) {
11067 DISSECTOR_ASSERT_NOT_REACHED();
11072 CREATE_VALUE_STRING(dst, format, ap);
11074 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11078 proto_tree_add_int64_bits_format_value(proto_tree *tree, const int hfindex,
11079 tvbuff_t *tvb, const guint bit_offset,
11080 const gint no_of_bits, gint64 value,
11081 const char *format, ...)
11085 header_field_info *hf_field;
11087 CHECK_FOR_NULL_TREE(tree);
11089 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11091 switch (hf_field->type) {
11099 DISSECTOR_ASSERT_NOT_REACHED();
11104 CREATE_VALUE_STRING(dst, format, ap);
11106 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11110 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hfindex,
11111 tvbuff_t *tvb, const guint bit_offset,
11112 const gint no_of_bits, guint32 value,
11113 const char *format, ...)
11117 header_field_info *hf_field;
11119 CHECK_FOR_NULL_TREE(tree);
11121 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11123 DISSECTOR_ASSERT_FIELD_TYPE(hf_field, FT_BOOLEAN);
11125 CREATE_VALUE_STRING(dst, format, ap);
11127 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11131 proto_tree_add_boolean_bits_format_value64(proto_tree *tree, const int hfindex,
11132 tvbuff_t *tvb, const guint bit_offset,
11133 const gint no_of_bits, guint64 value,
11134 const char *format, ...)
11138 header_field_info *hf_field;
11140 CHECK_FOR_NULL_TREE(tree);
11142 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
11144 DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
11146 CREATE_VALUE_STRING(dst, format, ap);
11148 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
11152 proto_tree_add_ts_23_038_7bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
11153 const guint bit_offset, const gint no_of_chars)
11156 header_field_info *hfinfo;
11161 CHECK_FOR_NULL_TREE(tree);
11163 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
11165 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_STRING);
11167 byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3;
11168 byte_offset = bit_offset >> 3;
11170 string = tvb_get_ts_23_038_7bits_string(wmem_packet_scope(), tvb, bit_offset, no_of_chars);
11172 if (hfinfo->display == STR_UNICODE) {
11173 DISSECTOR_ASSERT(g_utf8_validate(string, -1, NULL));
11176 pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length);
11177 DISSECTOR_ASSERT(byte_length >= 0);
11178 proto_tree_set_string(PNODE_FINFO(pi), string);
11184 proto_tree_add_ascii_7bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
11185 const guint bit_offset, const gint no_of_chars)
11188 header_field_info *hfinfo;
11193 CHECK_FOR_NULL_TREE(tree);
11195 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
11197 DISSECTOR_ASSERT_FIELD_TYPE(hfinfo, FT_STRING);
11199 byte_length = (((no_of_chars + 1) * 7) + (bit_offset & 0x07)) >> 3;
11200 byte_offset = bit_offset >> 3;
11202 string = tvb_get_ascii_7bits_string(wmem_packet_scope(), tvb, bit_offset, no_of_chars);
11204 if (hfinfo->display == STR_UNICODE) {
11205 DISSECTOR_ASSERT(g_utf8_validate(string, -1, NULL));
11208 pi = proto_tree_add_pi(tree, hfinfo, tvb, byte_offset, &byte_length);
11209 DISSECTOR_ASSERT(byte_length >= 0);
11210 proto_tree_set_string(PNODE_FINFO(pi), string);
11215 const value_string proto_checksum_vals[] = {
11216 { PROTO_CHECKSUM_E_BAD, "Bad" },
11217 { PROTO_CHECKSUM_E_GOOD, "Good" },
11218 { PROTO_CHECKSUM_E_UNVERIFIED, "Unverified" },
11219 { PROTO_CHECKSUM_E_NOT_PRESENT, "Not present" },
11225 proto_tree_add_checksum(proto_tree *tree, tvbuff_t *tvb, const guint offset,
11226 const int hf_checksum, const int hf_checksum_status, struct expert_field* bad_checksum_expert,
11227 packet_info *pinfo, guint32 computed_checksum, const guint encoding, const guint flags)
11229 header_field_info *hfinfo = proto_registrar_get_nth(hf_checksum);
11232 proto_item* ti = NULL;
11234 gboolean incorrect_checksum = TRUE;
11236 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
11238 if (flags & PROTO_CHECKSUM_NOT_PRESENT) {
11239 ti = proto_tree_add_uint_format_value(tree, hf_checksum, tvb, offset, 0, 0, "[missing]");
11240 PROTO_ITEM_SET_GENERATED(ti);
11241 if (hf_checksum_status != -1) {
11242 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_NOT_PRESENT);
11243 PROTO_ITEM_SET_GENERATED(ti2);
11248 switch (hfinfo->type){
11262 DISSECTOR_ASSERT_NOT_REACHED();
11265 if (flags & PROTO_CHECKSUM_GENERATED) {
11266 ti = proto_tree_add_uint(tree, hf_checksum, tvb, offset, 0, computed_checksum);
11267 PROTO_ITEM_SET_GENERATED(ti);
11269 ti = proto_tree_add_item_ret_uint(tree, hf_checksum, tvb, offset, len, encoding, &checksum);
11270 if (flags & PROTO_CHECKSUM_VERIFY) {
11271 if (flags & (PROTO_CHECKSUM_IN_CKSUM|PROTO_CHECKSUM_ZERO)) {
11272 if (computed_checksum == 0) {
11273 proto_item_append_text(ti, " [correct]");
11274 if (hf_checksum_status != -1) {
11275 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
11276 PROTO_ITEM_SET_GENERATED(ti2);
11278 incorrect_checksum = FALSE;
11279 } else if (flags & PROTO_CHECKSUM_IN_CKSUM) {
11280 computed_checksum = in_cksum_shouldbe(checksum, computed_checksum);
11283 if (checksum == computed_checksum) {
11284 proto_item_append_text(ti, " [correct]");
11285 if (hf_checksum_status != -1) {
11286 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
11287 PROTO_ITEM_SET_GENERATED(ti2);
11289 incorrect_checksum = FALSE;
11293 if (incorrect_checksum) {
11294 if (hf_checksum_status != -1) {
11295 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_BAD);
11296 PROTO_ITEM_SET_GENERATED(ti2);
11298 if (flags & PROTO_CHECKSUM_ZERO) {
11299 proto_item_append_text(ti, " [incorrect]");
11300 if (bad_checksum_expert != NULL)
11301 expert_add_info_format(pinfo, ti, bad_checksum_expert, "Bad checksum");
11303 proto_item_append_text(ti, " incorrect, should be 0x%0*x", len*2, computed_checksum);
11304 if (bad_checksum_expert != NULL)
11305 expert_add_info_format(pinfo, ti, bad_checksum_expert, "Bad checksum [should be 0x%0*x]", len*2, computed_checksum);
11309 if (hf_checksum_status != -1) {
11310 proto_item_append_text(ti, " [unverified]");
11311 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, 0, PROTO_CHECKSUM_E_UNVERIFIED);
11312 PROTO_ITEM_SET_GENERATED(ti2);
11321 proto_check_field_name(const gchar *field_name)
11323 return wrs_check_charset(fld_abbrev_chars, field_name);
11327 tree_expanded(int tree_type)
11329 g_assert(tree_type >= 0 && tree_type < num_tree_types);
11330 return tree_is_expanded[tree_type >> 5] & (1U << (tree_type & 31));
11334 tree_expanded_set(int tree_type, gboolean value)
11336 g_assert(tree_type >= 0 && tree_type < num_tree_types);
11339 tree_is_expanded[tree_type >> 5] |= (1U << (tree_type & 31));
11341 tree_is_expanded[tree_type >> 5] &= ~(1U << (tree_type & 31));
11345 * Editor modelines - http://www.wireshark.org/tools/modelines.html
11348 * c-basic-offset: 8
11350 * indent-tabs-mode: t
11353 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
11354 * :indentSize=8:tabSize=8:noTabs=false: