2 * Routines for protocol tree
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
33 #include <wsutil/bits_ctz.h>
34 #include <wsutil/bits_count_ones.h>
36 #include <ftypes/ftypes-int.h>
39 #include "exceptions.h"
40 #include "ptvcursor.h"
42 #include "addr_resolv.h"
45 #include "epan_dissect.h"
48 #include "wmem/wmem.h"
50 #include "asm_utils.h"
51 #include "column-utils.h"
52 #include "to_str-int.h"
55 #include "show_exception.h"
57 #include "wspython/wspy_register.h"
59 #include <wsutil/plugins.h>
61 #define SUBTREE_ONCE_ALLOCATION_NUMBER 8
62 #define SUBTREE_MAX_LEVELS 256
63 /* Throw an exception if we exceed this many tree items. */
64 /* XXX - This should probably be a preference */
65 #define MAX_TREE_ITEMS (1 * 1000 * 1000)
68 typedef struct __subtree_lvl {
75 subtree_lvl *pushed_tree;
76 guint8 pushed_tree_index;
77 guint8 pushed_tree_max;
83 #define cVALS(x) (const value_string*)(x)
85 /** See inlined comments.
86 @param tree the tree to append this item to
87 @param hfindex field index
88 @param hfinfo header_field
89 @return the header field matching 'hfinfo' */
90 #define TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo) \
91 /* If this item is not referenced we dont have to do much work \
92 at all but we should still return a node so that field items \
93 below this node (think proto_item_add_subtree()) will still \
94 have somewhere to attach to or else filtering will not work \
95 (they would be ignored since tree would be NULL). \
96 DONT try to fake a node where PTREE_FINFO(tree) is NULL \
97 since dissectors that want to do proto_item_set_len() or \
98 other operations that dereference this would crash. \
99 We fake FT_PROTOCOL unless some clients have requested us \
104 PTREE_DATA(tree)->count++; \
105 if (PTREE_DATA(tree)->count > MAX_TREE_ITEMS) { \
106 if (getenv("WIRESHARK_ABORT_ON_TOO_MANY_ITEMS") != NULL) \
107 g_error("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS); \
108 /* Let the exception handler add items to the tree */ \
109 PTREE_DATA(tree)->count = 0; \
110 THROW_MESSAGE(DissectorError, \
111 ep_strdup_printf("More than %d items in the tree -- possible infinite loop", MAX_TREE_ITEMS)); \
113 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo); \
114 if (!(PTREE_DATA(tree)->visible)) { \
115 if (PTREE_FINFO(tree)) { \
116 if ((hfinfo->ref_type != HF_REF_TYPE_DIRECT) \
117 && (hfinfo->type != FT_PROTOCOL || \
118 PTREE_DATA(tree)->fake_protocols)) { \
119 /* just return tree back to the caller */\
125 /** See inlined comments.
126 @param pi the created protocol item we're about to return */
127 #define TRY_TO_FAKE_THIS_REPR(pi) \
129 if (!(PTREE_DATA(pi)->visible)) { \
130 /* If the tree (GUI) isn't visible it's pointless for us to generate the protocol \
131 * items string representation */ \
135 static const char *hf_try_val_to_str(guint32 value, const header_field_info *hfinfo);
137 static void fill_label_boolean(field_info *fi, gchar *label_str);
138 static void fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed);
139 static void fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed);
140 static void fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed);
142 static const char *hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value);
143 static const char *hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value);
144 static const char *hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
145 static const char *hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value);
147 static const char* hfinfo_uint64_format(const header_field_info *hfinfo);
148 static const char* hfinfo_int64_format(const header_field_info *hfinfo);
151 proto_tree_add_node(proto_tree *tree, field_info *fi);
154 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
158 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
159 const gint start, const gint item_length);
162 alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
163 const gint start, gint *length);
166 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
167 gint start, gint *length);
170 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap);
172 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap);
175 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb);
177 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length);
179 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length);
181 proto_tree_set_time(field_info *fi, nstime_t *value_ptr);
183 proto_tree_set_string(field_info *fi, const char* value);
185 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding);
187 proto_tree_set_ax25(field_info *fi, const guint8* value);
189 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start);
191 proto_tree_set_vines(field_info *fi, const guint8* value);
193 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start);
195 proto_tree_set_ether(field_info *fi, const guint8* value);
197 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start);
199 proto_tree_set_ipxnet(field_info *fi, guint32 value);
201 proto_tree_set_ipv4(field_info *fi, guint32 value);
203 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr);
205 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
207 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr);
209 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
211 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length);
213 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length);
215 proto_tree_set_boolean(field_info *fi, guint32 value);
217 proto_tree_set_float(field_info *fi, float value);
219 proto_tree_set_double(field_info *fi, double value);
221 proto_tree_set_uint(field_info *fi, guint32 value);
223 proto_tree_set_int(field_info *fi, gint32 value);
225 proto_tree_set_uint64(field_info *fi, guint64 value);
227 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start, guint length, const guint encoding);
229 proto_tree_set_eui64(field_info *fi, const guint64 value);
231 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding);
233 /* Handle type length mismatch (now filterable) expert info */
234 static int proto_type_length_mismatch = -1;
235 static expert_field ei_type_length_mismatch_error = EI_INIT;
236 static expert_field ei_type_length_mismatch_warn = EI_INIT;
237 static void register_type_length_mismatch(void);
239 static int proto_register_field_init(header_field_info *hfinfo, const int parent);
241 /* special-case header field used within proto.c */
242 static header_field_info hfi_text_only =
243 { "Text item", "text", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL };
244 int hf_text_only = -1;
246 /* Structure for information about a protocol */
248 const char *name; /* long description */
249 const char *short_name; /* short description */
250 const char *filter_name; /* name of this protocol in filters */
251 GSList *fields; /* fields for this protocol */
252 GSList *last_field; /* pointer to end of list of fields */
253 int proto_id; /* field ID for this protocol */
254 gboolean is_enabled; /* TRUE if protocol is enabled */
255 gboolean can_toggle; /* TRUE if is_enabled can be changed */
256 gboolean is_private; /* TRUE is protocol is private */
259 /* List of all protocols */
260 static GList *protocols = NULL;
262 /* Contains information about a field when a dissector calls
263 * proto_tree_add_item. */
264 #define FIELD_INFO_NEW(pool, fi) fi = wmem_new(pool, field_info)
265 #define FIELD_INFO_FREE(pool, fi) wmem_free(pool, fi)
267 /* Contains the space for proto_nodes. */
268 #define PROTO_NODE_INIT(node) \
269 node->first_child = NULL; \
270 node->last_child = NULL; \
273 #define PROTO_NODE_FREE(pool, node) \
274 wmem_free(pool, node)
276 /* String space for protocol and field items for the GUI */
277 #define ITEM_LABEL_NEW(pool, il) \
278 il = wmem_new(pool, item_label_t);
279 #define ITEM_LABEL_FREE(pool, il) \
282 #define PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo) \
283 if((guint)hfindex >= gpa_hfinfo.len && getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG")) \
284 g_error("Unregistered hf! index=%d", hfindex); \
285 DISSECTOR_ASSERT_HINT((guint)hfindex < gpa_hfinfo.len, "Unregistered hf!"); \
286 hfinfo = gpa_hfinfo.hfi[hfindex];
288 /* List which stores protocols and fields that have been registered */
289 typedef struct _gpa_hfinfo_t {
291 guint32 allocated_len;
292 header_field_info **hfi;
295 static gpa_hfinfo_t gpa_hfinfo;
297 /* Balanced tree of abbreviations and IDs */
298 static GTree *gpa_name_tree = NULL;
299 static header_field_info *same_name_hfinfo;
301 static void save_same_name_hfinfo(gpointer data)
303 same_name_hfinfo = (header_field_info*)data;
306 /* Points to the first element of an array of bits, indexed by
307 a subtree item type; that array element is TRUE if subtrees of
308 an item of that type are to be expanded. */
309 static guint32 *tree_is_expanded;
311 /* Number of elements in that array. */
314 /* Name hashtables for fast detection of duplicate names */
315 static GHashTable* proto_names = NULL;
316 static GHashTable* proto_short_names = NULL;
317 static GHashTable* proto_filter_names = NULL;
320 proto_compare_name(gconstpointer p1_arg, gconstpointer p2_arg)
322 const protocol_t *p1 = (const protocol_t *)p1_arg;
323 const protocol_t *p2 = (const protocol_t *)p2_arg;
325 return g_ascii_strcasecmp(p1->short_name, p2->short_name);
330 * List of dissector plugins.
333 void (*register_protoinfo)(void); /* routine to call to register protocol information */
334 void (*reg_handoff)(void); /* routine to call to register dissector handoff */
337 static GSList *dissector_plugins = NULL;
340 * Callback for each plugin found.
343 check_for_dissector_plugin(GModule *handle)
346 void (*register_protoinfo)(void);
347 void (*reg_handoff)(void);
348 dissector_plugin *plugin;
351 * Do we have a register routine?
353 if (g_module_symbol(handle, "plugin_register", &gp))
354 register_protoinfo = (void (*)(void))gp;
356 register_protoinfo = NULL;
359 * Do we have a reg_handoff routine?
361 if (g_module_symbol(handle, "plugin_reg_handoff", &gp))
362 reg_handoff = (void (*)(void))gp;
367 * If we have neither, we're not a dissector plugin.
369 if (register_protoinfo == NULL && reg_handoff == NULL)
373 * Add this one to the list of dissector plugins.
375 plugin = (dissector_plugin *)g_malloc(sizeof (dissector_plugin));
376 plugin->register_protoinfo = register_protoinfo;
377 plugin->reg_handoff = reg_handoff;
378 dissector_plugins = g_slist_append(dissector_plugins, plugin);
383 register_dissector_plugin(gpointer data, gpointer user_data _U_)
385 dissector_plugin *plugin = (dissector_plugin *)data;
387 if (plugin->register_protoinfo)
388 (plugin->register_protoinfo)();
392 reg_handoff_dissector_plugin(gpointer data, gpointer user_data _U_)
394 dissector_plugin *plugin = (dissector_plugin *)data;
396 if (plugin->reg_handoff)
397 (plugin->reg_handoff)();
401 * Register dissector plugin type.
404 register_dissector_plugin_type(void)
406 add_plugin_type("dissector", check_for_dissector_plugin);
408 #endif /* HAVE_PLUGINS */
410 /* initialize data structures and register protocols and fields */
412 proto_init(void (register_all_protocols_func)(register_cb cb, gpointer client_data),
413 void (register_all_handoffs_func)(register_cb cb, gpointer client_data),
415 gpointer client_data)
419 proto_names = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, NULL);
420 proto_short_names = g_hash_table_new(wrs_str_hash, g_str_equal);
421 proto_filter_names = g_hash_table_new(wrs_str_hash, g_str_equal);
424 gpa_hfinfo.allocated_len = 0;
425 gpa_hfinfo.hfi = NULL;
426 gpa_name_tree = g_tree_new_full(wrs_strcmp_with_data, NULL, NULL, save_same_name_hfinfo);
428 /* Initialize the ftype subsystem */
431 /* Register one special-case FT_TEXT_ONLY field for use when
432 converting wireshark to new-style proto_tree. These fields
433 are merely strings on the GUI tree; they are not filterable */
434 hf_text_only = proto_register_field_init(&hfi_text_only, -1);
436 /* Register the pseudo-protocols used for exceptions. */
437 register_show_exception();
438 register_type_length_mismatch();
440 /* Have each built-in dissector register its protocols, fields,
441 dissector tables, and dissectors to be called through a
442 handle, and do whatever one-time initialization it needs to
444 register_all_protocols_func(cb, client_data);
446 /* Now scan for python protocols */
448 (*cb)(RA_PYTHON_REGISTER, NULL, client_data);
449 register_all_py_protocols_func();
453 /* Now call the registration routines for all disssector
456 (*cb)(RA_PLUGIN_REGISTER, NULL, client_data);
457 g_slist_foreach(dissector_plugins, register_dissector_plugin, NULL);
460 /* Now call the "handoff registration" routines of all built-in
461 dissectors; those routines register the dissector in other
462 dissectors' handoff tables, and fetch any dissector handles
464 register_all_handoffs_func(cb, client_data);
467 /* Now do the same with python dissectors */
469 (*cb)(RA_PYTHON_HANDOFF, NULL, client_data);
470 register_all_py_handoffs_func();
474 /* Now do the same with plugins. */
476 (*cb)(RA_PLUGIN_HANDOFF, NULL, client_data);
477 g_slist_foreach(dissector_plugins, reg_handoff_dissector_plugin, NULL);
480 /* sort the protocols by protocol name */
481 protocols = g_list_sort(protocols, proto_compare_name);
483 /* We've assigned all the subtree type values; allocate the array
484 for them, and zero it out. */
485 tree_is_expanded = g_new0(guint32, (num_tree_types/32)+1);
491 /* Free the abbrev/ID GTree */
493 g_tree_destroy(gpa_name_tree);
494 gpa_name_tree = NULL;
498 protocol_t *protocol = (protocol_t *)protocols->data;
499 header_field_info *hfinfo;
500 PROTO_REGISTRAR_GET_NTH(protocol->proto_id, hfinfo);
501 DISSECTOR_ASSERT(protocol->proto_id == hfinfo->id);
503 g_slice_free(header_field_info, hfinfo);
504 g_slist_free(protocol->fields);
505 protocols = g_list_remove(protocols, protocol);
510 g_hash_table_destroy(proto_names);
514 if (proto_short_names) {
515 g_hash_table_destroy(proto_short_names);
516 proto_short_names = NULL;
519 if (proto_filter_names) {
520 g_hash_table_destroy(proto_filter_names);
521 proto_filter_names = NULL;
524 if (gpa_hfinfo.allocated_len) {
526 gpa_hfinfo.allocated_len = 0;
527 g_free(gpa_hfinfo.hfi);
528 gpa_hfinfo.hfi = NULL;
530 g_free(tree_is_expanded);
531 tree_is_expanded = NULL;
535 proto_tree_traverse_pre_order(proto_tree *tree, proto_tree_traverse_func func,
538 proto_node *pnode = tree;
542 if (func(pnode, data))
545 child = pnode->first_child;
546 while (child != NULL) {
548 * The routine we call might modify the child, e.g. by
549 * freeing it, so we get the child's successor before
550 * calling that routine.
553 child = current->next;
554 if (proto_tree_traverse_pre_order((proto_tree *)current, func, data))
562 proto_tree_traverse_post_order(proto_tree *tree, proto_tree_traverse_func func,
565 proto_node *pnode = tree;
569 child = pnode->first_child;
570 while (child != NULL) {
572 * The routine we call might modify the child, e.g. by
573 * freeing it, so we get the child's successor before
574 * calling that routine.
577 child = current->next;
578 if (proto_tree_traverse_post_order((proto_tree *)current, func, data))
581 if (func(pnode, data))
588 proto_tree_children_foreach(proto_tree *tree, proto_tree_foreach_func func,
591 proto_node *node = tree;
597 node = node->first_child;
598 while (node != NULL) {
600 node = current->next;
601 func((proto_tree *)current, data);
606 free_GPtrArray_value(gpointer key, gpointer value, gpointer user_data _U_)
608 GPtrArray *ptrs = (GPtrArray *)value;
609 gint hfid = (gint)(long)key;
610 header_field_info *hfinfo;
612 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
613 if (hfinfo->ref_type != HF_REF_TYPE_NONE) {
614 /* when a field is referenced by a filter this also
615 affects the refcount for the parent protocol so we need
616 to adjust the refcount for the parent as well
618 if (hfinfo->parent != -1) {
619 header_field_info *parent_hfinfo;
620 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
621 parent_hfinfo->ref_type = HF_REF_TYPE_NONE;
623 hfinfo->ref_type = HF_REF_TYPE_NONE;
626 g_ptr_array_free(ptrs, TRUE);
630 proto_tree_free_node(proto_node *node, gpointer data _U_)
632 field_info *finfo = PNODE_FINFO(node);
634 proto_tree_children_foreach(node, proto_tree_free_node, NULL);
636 FVALUE_CLEANUP(&finfo->value);
640 proto_tree_reset(proto_tree *tree)
642 tree_data_t *tree_data = PTREE_DATA(tree);
644 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
647 if (tree_data->interesting_hfids) {
648 /* Free all the GPtrArray's in the interesting_hfids hash. */
649 g_hash_table_foreach(tree_data->interesting_hfids,
650 free_GPtrArray_value, NULL);
652 /* And then destroy the hash. */
653 g_hash_table_destroy(tree_data->interesting_hfids);
655 tree_data->interesting_hfids = NULL;
658 /* Reset track of the number of children */
659 tree_data->count = 0;
661 PROTO_NODE_INIT(tree);
664 /* frees the resources that the dissection a proto_tree uses */
666 proto_tree_free(proto_tree *tree)
668 tree_data_t *tree_data = PTREE_DATA(tree);
670 proto_tree_children_foreach(tree, proto_tree_free_node, NULL);
673 if (tree_data->interesting_hfids) {
674 /* Free all the GPtrArray's in the interesting_hfids hash. */
675 g_hash_table_foreach(tree_data->interesting_hfids,
676 free_GPtrArray_value, NULL);
678 /* And then destroy the hash. */
679 g_hash_table_destroy(tree_data->interesting_hfids);
682 g_slice_free(tree_data_t, tree_data);
684 g_slice_free(proto_tree, tree);
687 /* Is the parsing being done for a visible proto_tree or an invisible one?
688 * By setting this correctly, the proto_tree creation is sped up by not
689 * having to call g_vsnprintf and copy strings around.
692 proto_tree_set_visible(proto_tree *tree, gboolean visible)
694 gboolean old_visible = PTREE_DATA(tree)->visible;
696 PTREE_DATA(tree)->visible = visible;
702 proto_tree_set_fake_protocols(proto_tree *tree, gboolean fake_protocols)
704 PTREE_DATA(tree)->fake_protocols = fake_protocols;
707 /* Assume dissector set only its protocol fields.
708 This function is called by dissectors and allows the speeding up of filtering
709 in wireshark; if this function returns FALSE it is safe to reset tree to NULL
710 and thus skip calling most of the expensive proto_tree_add_...()
712 If the tree is visible we implicitly assume the field is referenced.
715 proto_field_is_referenced(proto_tree *tree, int proto_id)
717 register header_field_info *hfinfo;
723 if (PTREE_DATA(tree)->visible)
726 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
727 if (hfinfo->ref_type != HF_REF_TYPE_NONE)
730 if (hfinfo->type == FT_PROTOCOL && !PTREE_DATA(tree)->fake_protocols)
737 /* Finds a record in the hfinfo array by id. */
739 proto_registrar_get_nth(guint hfindex)
741 register header_field_info *hfinfo;
743 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
748 /* Prefix initialization
749 * this allows for a dissector to register a display filter name prefix
750 * so that it can delay the initialization of the hf array as long as
754 /* compute a hash for the part before the dot of a display filter */
756 prefix_hash (gconstpointer key) {
757 /* end the string at the dot and compute its hash */
758 gchar* copy = ep_strdup((const gchar *)key);
768 return g_str_hash(copy);
771 /* are both strings equal up to the end or the dot? */
773 prefix_equal (gconstpointer ap, gconstpointer bp) {
774 const gchar* a = (const gchar *)ap;
775 const gchar* b = (const gchar *)bp;
781 if ( (ac == '.' || ac == '\0') && (bc == '.' || bc == '\0') ) return TRUE;
783 if ( (ac == '.' || ac == '\0') && ! (bc == '.' || bc == '\0') ) return FALSE;
784 if ( (bc == '.' || bc == '\0') && ! (ac == '.' || ac == '\0') ) return FALSE;
786 if (ac != bc) return FALSE;
793 /* indexed by prefix, contains initializers */
794 static GHashTable* prefixes = NULL;
797 /* Register a new prefix for "delayed" initialization of field arrays */
799 proto_register_prefix(const char *prefix, prefix_initializer_t pi ) {
801 prefixes = g_hash_table_new(prefix_hash, prefix_equal);
804 g_hash_table_insert(prefixes, (gpointer)prefix, pi);
807 /* helper to call all prefix initializers */
809 initialize_prefix(gpointer k, gpointer v, gpointer u _U_) {
810 ((prefix_initializer_t)v)((const char *)k);
814 /** Initialize every remaining uninitialized prefix. */
816 proto_initialize_all_prefixes(void) {
817 g_hash_table_foreach_remove(prefixes, initialize_prefix, NULL);
820 /* Finds a record in the hfinfo array by name.
821 * If it fails to find it in the already registered fields,
822 * it tries to find and call an initializer in the prefixes
823 * table and if so it looks again.
826 proto_registrar_get_byname(const char *field_name)
828 header_field_info *hfinfo;
829 prefix_initializer_t pi;
834 hfinfo = (header_field_info *)g_tree_lookup(gpa_name_tree, field_name);
842 if ((pi = (prefix_initializer_t)g_hash_table_lookup(prefixes, field_name) ) != NULL) {
844 g_hash_table_remove(prefixes, field_name);
849 return (header_field_info *)g_tree_lookup(gpa_name_tree, field_name);
853 proto_registrar_get_id_byname(const char *field_name)
855 header_field_info *hfinfo;
857 hfinfo = proto_registrar_get_byname(field_name);
867 ptvcursor_new_subtree_levels(ptvcursor_t *ptvc)
869 subtree_lvl *pushed_tree;
871 DISSECTOR_ASSERT(ptvc->pushed_tree_max <= SUBTREE_MAX_LEVELS-SUBTREE_ONCE_ALLOCATION_NUMBER);
872 ptvc->pushed_tree_max += SUBTREE_ONCE_ALLOCATION_NUMBER;
874 pushed_tree = (subtree_lvl *)ep_alloc(sizeof(subtree_lvl) * ptvc->pushed_tree_max);
875 DISSECTOR_ASSERT(pushed_tree != NULL);
876 if (ptvc->pushed_tree)
877 memcpy(pushed_tree, ptvc->pushed_tree, ptvc->pushed_tree_max - SUBTREE_ONCE_ALLOCATION_NUMBER);
878 ptvc->pushed_tree = pushed_tree;
882 ptvcursor_free_subtree_levels(ptvcursor_t *ptvc)
884 ptvc->pushed_tree = NULL;
885 ptvc->pushed_tree_max = 0;
886 DISSECTOR_ASSERT(ptvc->pushed_tree_index == 0);
887 ptvc->pushed_tree_index = 0;
890 /* Allocates an initializes a ptvcursor_t with 3 variables:
891 * proto_tree, tvbuff, and offset. */
893 ptvcursor_new(proto_tree *tree, tvbuff_t *tvb, gint offset)
897 ptvc = (ptvcursor_t *)ep_alloc(sizeof(ptvcursor_t));
900 ptvc->offset = offset;
901 ptvc->pushed_tree = NULL;
902 ptvc->pushed_tree_max = 0;
903 ptvc->pushed_tree_index = 0;
908 /* Frees memory for ptvcursor_t, but nothing deeper than that. */
910 ptvcursor_free(ptvcursor_t *ptvc)
912 ptvcursor_free_subtree_levels(ptvc);
916 /* Returns tvbuff. */
918 ptvcursor_tvbuff(ptvcursor_t *ptvc)
923 /* Returns current offset. */
925 ptvcursor_current_offset(ptvcursor_t *ptvc)
931 ptvcursor_tree(ptvcursor_t *ptvc)
940 ptvcursor_set_tree(ptvcursor_t *ptvc, proto_tree *tree)
945 /* creates a subtree, sets it as the working tree and pushes the old working tree */
947 ptvcursor_push_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
949 subtree_lvl *subtree;
950 if (ptvc->pushed_tree_index >= ptvc->pushed_tree_max)
951 ptvcursor_new_subtree_levels(ptvc);
953 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
954 subtree->tree = ptvc->tree;
956 ptvc->pushed_tree_index++;
957 return ptvcursor_set_subtree(ptvc, it, ett_subtree);
962 ptvcursor_pop_subtree(ptvcursor_t *ptvc)
964 subtree_lvl *subtree;
966 if (ptvc->pushed_tree_index <= 0)
969 ptvc->pushed_tree_index--;
970 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index;
971 if (subtree->it != NULL)
972 proto_item_set_len(subtree->it, ptvcursor_current_offset(ptvc) - subtree->cursor_offset);
974 ptvc->tree = subtree->tree;
977 /* saves the current tvb offset and the item in the current subtree level */
979 ptvcursor_subtree_set_item(ptvcursor_t *ptvc, proto_item *it)
981 subtree_lvl *subtree;
983 DISSECTOR_ASSERT(ptvc->pushed_tree_index > 0);
985 subtree = ptvc->pushed_tree + ptvc->pushed_tree_index - 1;
987 subtree->cursor_offset = ptvcursor_current_offset(ptvc);
990 /* Creates a subtree and adds it to the cursor as the working tree but does not
991 * save the old working tree */
993 ptvcursor_set_subtree(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree)
995 ptvc->tree = proto_item_add_subtree(it, ett_subtree);
1000 ptvcursor_add_subtree_item(ptvcursor_t *ptvc, proto_item *it, gint ett_subtree, gint length)
1002 ptvcursor_push_subtree(ptvc, it, ett_subtree);
1003 if (length == SUBTREE_UNDEFINED_LENGTH)
1004 ptvcursor_subtree_set_item(ptvc, it);
1005 return ptvcursor_tree(ptvc);
1008 /* Add an item to the tree and create a subtree
1009 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1010 * In this case, when the subtree will be closed, the parent item length will
1011 * be equal to the advancement of the cursor since the creation of the subtree.
1014 ptvcursor_add_with_subtree(ptvcursor_t *ptvc, int hfindex, gint length,
1015 const guint encoding, gint ett_subtree)
1019 it = ptvcursor_add_no_advance(ptvc, hfindex, length, encoding);
1020 return ptvcursor_add_subtree_item(ptvc, it, ett_subtree, length);
1024 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length);
1026 /* Add a text node to the tree and create a subtree
1027 * If the length is unknown, length may be defined as SUBTREE_UNDEFINED_LENGTH.
1028 * In this case, when the subtree will be closed, the item length will be equal
1029 * to the advancement of the cursor since the creation of the subtree.
1032 ptvcursor_add_text_with_subtree(ptvcursor_t *ptvc, gint length,
1033 gint ett_subtree, const char *format, ...)
1037 header_field_info *hfinfo;
1040 tree = ptvcursor_tree(ptvc);
1042 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1044 pi = proto_tree_add_text_node(tree, ptvcursor_tvbuff(ptvc),
1045 ptvcursor_current_offset(ptvc), length);
1047 TRY_TO_FAKE_THIS_REPR(pi);
1049 va_start(ap, format);
1050 proto_tree_set_representation(pi, format, ap);
1053 return ptvcursor_add_subtree_item(ptvc, pi, ett_subtree, length);
1056 /* Add a text-only node, leaving it to our caller to fill the text in */
1058 proto_tree_add_text_node(proto_tree *tree, tvbuff_t *tvb, gint start, gint length)
1065 pi = proto_tree_add_pi(tree, &hfi_text_only, tvb, start, &length);
1070 /* Add a text-only node to the proto_tree */
1072 proto_tree_add_text(proto_tree *tree, tvbuff_t *tvb, gint start, gint length,
1073 const char *format, ...)
1077 header_field_info *hfinfo;
1079 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1081 pi = proto_tree_add_text_node(tree, tvb, start, length);
1083 TRY_TO_FAKE_THIS_REPR(pi);
1085 va_start(ap, format);
1086 proto_tree_set_representation(pi, format, ap);
1092 /* Add a text-only node to the proto_tree (va_list version) */
1094 proto_tree_add_text_valist(proto_tree *tree, tvbuff_t *tvb, gint start,
1095 gint length, const char *format, va_list ap)
1098 header_field_info *hfinfo;
1100 TRY_TO_FAKE_THIS_ITEM(tree, hf_text_only, hfinfo);
1102 pi = proto_tree_add_text_node(tree, tvb, start, length);
1104 TRY_TO_FAKE_THIS_REPR(pi);
1106 proto_tree_set_representation(pi, format, ap);
1111 /* Add a text-only node for debugging purposes. The caller doesn't need
1112 * to worry about tvbuff, start, or length. Debug message gets sent to
1115 proto_tree_add_debug_text(proto_tree *tree, const char *format, ...)
1120 pi = proto_tree_add_text_node(tree, NULL, 0, 0);
1123 va_start(ap, format);
1124 proto_tree_set_representation(pi, format, ap);
1127 va_start(ap, format);
1128 vprintf(format, ap);
1135 void proto_report_dissector_bug(const char *message)
1137 if (getenv("WIRESHARK_ABORT_ON_DISSECTOR_BUG") != NULL)
1140 THROW_MESSAGE(DissectorError, message);
1143 /* We could probably get away with changing is_error to a minimum length value. */
1145 report_type_length_mismatch(proto_tree *tree, const gchar *descr, int length, gboolean is_error) {
1148 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_error, "Trying to fetch %s with length %d", descr, length);
1150 expert_add_info_format(NULL, tree, &ei_type_length_mismatch_warn, "Trying to fetch %s with length %d", descr, length);
1154 THROW(ReportedBoundsError);
1159 get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1162 gboolean length_error;
1167 value = tvb_get_guint8(tvb, offset);
1171 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohs(tvb, offset)
1172 : tvb_get_ntohs(tvb, offset);
1176 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letoh24(tvb, offset)
1177 : tvb_get_ntoh24(tvb, offset);
1181 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1182 : tvb_get_ntohl(tvb, offset);
1187 length_error = TRUE;
1190 length_error = FALSE;
1191 value = (encoding & ENC_LITTLE_ENDIAN) ? tvb_get_letohl(tvb, offset)
1192 : tvb_get_ntohl(tvb, offset);
1194 report_type_length_mismatch(tree, "an unsigned integer", length, length_error);
1201 * NOTE: to support code written when proto_tree_add_item() took a
1202 * gboolean as its last argument, with FALSE meaning "big-endian"
1203 * and TRUE meaning "little-endian", we treat any non-zero value of
1204 * "encoding" as meaning "little-endian".
1207 get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
1210 gboolean length_error;
1215 value = (gint8)tvb_get_guint8(tvb, offset);
1219 value = (gint16) (encoding ? tvb_get_letohs(tvb, offset)
1220 : tvb_get_ntohs(tvb, offset));
1224 value = encoding ? tvb_get_letoh24(tvb, offset)
1225 : tvb_get_ntoh24(tvb, offset);
1226 if (value & 0x00800000) {
1227 /* Sign bit is set; sign-extend it. */
1228 value |= 0xFF000000;
1233 value = encoding ? tvb_get_letohl(tvb, offset)
1234 : tvb_get_ntohl(tvb, offset);
1239 length_error = TRUE;
1242 length_error = FALSE;
1243 value = encoding ? tvb_get_letohl(tvb, offset)
1244 : tvb_get_ntohl(tvb, offset);
1246 report_type_length_mismatch(tree, "a signed integer", length, length_error);
1253 tree_data_add_maybe_interesting_field(tree_data_t *tree_data, field_info *fi)
1255 const header_field_info *hfinfo = fi->hfinfo;
1257 if (hfinfo->ref_type == HF_REF_TYPE_DIRECT) {
1258 GPtrArray *ptrs = NULL;
1260 if (tree_data->interesting_hfids == NULL) {
1261 /* Initialize the hash because we now know that it is needed */
1262 tree_data->interesting_hfids =
1263 g_hash_table_new(g_direct_hash, NULL /* g_direct_equal */);
1265 ptrs = (GPtrArray *)g_hash_table_lookup(tree_data->interesting_hfids,
1266 GINT_TO_POINTER(hfinfo->id));
1268 /* First element triggers the creation of pointer array */
1269 ptrs = g_ptr_array_new();
1270 g_hash_table_insert(tree_data->interesting_hfids,
1271 GINT_TO_POINTER(hfinfo->id), ptrs);
1274 g_ptr_array_add(ptrs, fi);
1278 /* Add an item to a proto_tree, using the text label registered to that item;
1279 the item is extracted from the tvbuff handed to it. */
1281 proto_tree_new_item(field_info *new_fi, proto_tree *tree,
1282 tvbuff_t *tvb, gint start, gint length,
1290 nstime_t time_stamp;
1293 gboolean length_error;
1295 switch (new_fi->hfinfo->type) {
1297 /* no value to set for FT_NONE */
1301 proto_tree_set_protocol_tvb(new_fi, tvb);
1305 proto_tree_set_bytes_tvb(new_fi, tvb, start, length);
1310 * Map all non-zero values to little-endian for
1311 * backwards compatibility.
1314 encoding = ENC_LITTLE_ENDIAN;
1315 n = get_uint_value(tree, tvb, start, length, encoding);
1316 proto_tree_set_bytes_tvb(new_fi, tvb, start + length, n);
1318 /* Instead of calling proto_item_set_len(), since we don't yet
1319 * have a proto_item, we set the field_info's length ourselves. */
1320 new_fi->length = n + length;
1325 * Map all non-zero values to little-endian for
1326 * backwards compatibility.
1329 encoding = ENC_LITTLE_ENDIAN;
1330 proto_tree_set_boolean(new_fi,
1331 get_uint_value(tree, tvb, start, length, encoding));
1334 /* XXX - make these just FT_UINT? */
1340 * Map all non-zero values to little-endian for
1341 * backwards compatibility.
1344 encoding = ENC_LITTLE_ENDIAN;
1345 proto_tree_set_uint(new_fi,
1346 get_uint_value(tree, tvb, start, length, encoding));
1352 * Map all non-zero values to little-endian for
1353 * backwards compatibility.
1356 encoding = ENC_LITTLE_ENDIAN;
1357 if (length < 1 || length > 8) {
1358 length_error = length < 1 ? TRUE : FALSE;
1359 report_type_length_mismatch(tree, "a 64-bit integer", length, length_error);
1361 proto_tree_set_uint64_tvb(new_fi, tvb, start, length, encoding);
1364 /* XXX - make these just FT_INT? */
1370 * Map all non-zero values to little-endian for
1371 * backwards compatibility.
1374 encoding = ENC_LITTLE_ENDIAN;
1375 proto_tree_set_int(new_fi,
1376 get_int_value(tree, tvb, start, length, encoding));
1381 * Map all non-zero values to little-endian for
1382 * backwards compatibility.
1385 encoding = ENC_LITTLE_ENDIAN;
1386 if (length != FT_IPv4_LEN) {
1387 length_error = length < FT_IPv4_LEN ? TRUE : FALSE;
1388 report_type_length_mismatch(tree, "an IPv4 address", length, length_error);
1390 value = tvb_get_ipv4(tvb, start);
1392 * NOTE: to support code written when
1393 * proto_tree_add_item() took a gboolean as its
1394 * last argument, with FALSE meaning "big-endian"
1395 * and TRUE meaning "little-endian", we treat any
1396 * non-zero value of "encoding" as meaning
1399 proto_tree_set_ipv4(new_fi, encoding ? GUINT32_SWAP_LE_BE(value) : value);
1403 if (length != FT_IPXNET_LEN) {
1404 length_error = length < FT_IPXNET_LEN ? TRUE : FALSE;
1405 report_type_length_mismatch(tree, "an IPXNET address", length, length_error);
1407 proto_tree_set_ipxnet(new_fi,
1408 get_uint_value(tree, tvb, start, FT_IPXNET_LEN, ENC_BIG_ENDIAN));
1412 if (length != FT_IPv6_LEN) {
1413 length_error = length < FT_IPv6_LEN ? TRUE : FALSE;
1414 report_type_length_mismatch(tree, "an IPv6 address", length, length_error);
1416 proto_tree_set_ipv6_tvb(new_fi, tvb, start, length);
1421 length_error = length < 7 ? TRUE : FALSE;
1422 report_type_length_mismatch(tree, "an AX.25 address", length, length_error);
1424 proto_tree_set_ax25_tvb(new_fi, tvb, start);
1428 if (length != VINES_ADDR_LEN) {
1429 length_error = length < VINES_ADDR_LEN ? TRUE : FALSE;
1430 report_type_length_mismatch(tree, "a Vines address", length, length_error);
1432 proto_tree_set_vines_tvb(new_fi, tvb, start);
1436 if (length != FT_ETHER_LEN) {
1437 length_error = length < FT_ETHER_LEN ? TRUE : FALSE;
1438 report_type_length_mismatch(tree, "an Ethernet", length, length_error);
1440 proto_tree_set_ether_tvb(new_fi, tvb, start);
1445 * Map all non-zero values to little-endian for
1446 * backwards compatibility.
1449 encoding = ENC_LITTLE_ENDIAN;
1450 if (length != FT_EUI64_LEN) {
1451 length_error = length < FT_EUI64_LEN ? TRUE : FALSE;
1452 report_type_length_mismatch(tree, "an EUI-64 address", length, length_error);
1454 proto_tree_set_eui64_tvb(new_fi, tvb, start, encoding);
1458 * Map all non-zero values to little-endian for
1459 * backwards compatibility.
1462 encoding = ENC_LITTLE_ENDIAN;
1463 if (length != FT_GUID_LEN) {
1464 length_error = length < FT_GUID_LEN ? TRUE : FALSE;
1465 report_type_length_mismatch(tree, "a GUID", length, length_error);
1467 proto_tree_set_guid_tvb(new_fi, tvb, start, encoding);
1472 proto_tree_set_oid_tvb(new_fi, tvb, start, length);
1477 * NOTE: to support code written when
1478 * proto_tree_add_item() took a gboolean as its
1479 * last argument, with FALSE meaning "big-endian"
1480 * and TRUE meaning "little-endian", we treat any
1481 * non-zero value of "encoding" as meaning
1484 * At some point in the future, we might
1485 * support non-IEEE-binary floating-point
1486 * formats in the encoding as well
1487 * (IEEE decimal, System/3x0, VAX).
1490 encoding = ENC_LITTLE_ENDIAN;
1492 length_error = length < 4 ? TRUE : FALSE;
1493 report_type_length_mismatch(tree, "a single-precision floating point number", length, length_error);
1496 floatval = tvb_get_letohieee_float(tvb, start);
1498 floatval = tvb_get_ntohieee_float(tvb, start);
1499 proto_tree_set_float(new_fi, floatval);
1504 * NOTE: to support code written when
1505 * proto_tree_add_item() took a gboolean as its
1506 * last argument, with FALSE meaning "big-endian"
1507 * and TRUE meaning "little-endian", we treat any
1508 * non-zero value of "encoding" as meaning
1511 * At some point in the future, we might
1512 * support non-IEEE-binary floating-point
1513 * formats in the encoding as well
1514 * (IEEE decimal, System/3x0, VAX).
1516 if (encoding == TRUE)
1517 encoding = ENC_LITTLE_ENDIAN;
1519 length_error = length < 8 ? TRUE : FALSE;
1520 report_type_length_mismatch(tree, "a double-precision floating point number", length, length_error);
1523 doubleval = tvb_get_letohieee_double(tvb, start);
1525 doubleval = tvb_get_ntohieee_double(tvb, start);
1526 proto_tree_set_double(new_fi, doubleval);
1530 proto_tree_set_string_tvb(new_fi, tvb, start, length,
1536 report_type_length_mismatch(tree, "a string", length, TRUE);
1538 /* Instead of calling proto_item_set_len(),
1539 * since we don't yet have a proto_item, we
1540 * set the field_info's length ourselves.
1542 * XXX - our caller can't use that length to
1543 * advance an offset unless they arrange that
1544 * there always be a protocol tree into which
1545 * we're putting this item.
1548 /* This can throw an exception */
1549 string = tvb_get_stringz_enc(wmem_packet_scope(), tvb, start, &length, encoding);
1550 } else if (length == 0) {
1553 /* In this case, length signifies
1554 * the length of the string.
1556 * This could either be a null-padded
1557 * string, which doesn't necessarily
1558 * have a '\0' at the end, or a
1559 * null-terminated string, with a
1560 * trailing '\0'. (Yes, there are
1561 * cases where you have a string
1562 * that's both counted and null-
1565 * In the first case, we must
1566 * allocate a buffer of length
1567 * "length+1", to make room for
1570 * In the second case, we don't
1571 * assume that there is a trailing
1572 * '\0' there, as the packet might
1573 * be malformed. (XXX - should we
1574 * throw an exception if there's no
1575 * trailing '\0'?) Therefore, we
1576 * allocate a buffer of length
1577 * "length+1", and put in a trailing
1578 * '\0', just to be safe.
1580 * (XXX - this would change if
1581 * we made string values counted
1582 * rather than null-terminated.)
1584 string = tvb_get_string_enc(wmem_packet_scope(), tvb, start, length, encoding);
1586 new_fi->length = length;
1587 proto_tree_set_string(new_fi, string);
1590 case FT_UINT_STRING:
1592 * NOTE: to support code written when
1593 * proto_tree_add_item() took a gboolean as its
1594 * last argument, with FALSE meaning "big-endian"
1595 * and TRUE meaning "little-endian", if the
1596 * encoding value is TRUE, treat that as
1597 * ASCII with a little-endian length.
1599 * This won't work for code that passes
1600 * arbitrary non-zero values; that code
1601 * will need to be fixed.
1603 if (encoding == TRUE)
1604 encoding = ENC_ASCII|ENC_LITTLE_ENDIAN;
1605 n = get_uint_value(tree, tvb, start, length, encoding & ~ENC_CHARENCODING_MASK);
1606 proto_tree_set_string_tvb(new_fi, tvb, start + length, n,
1609 /* Instead of calling proto_item_set_len(), since we
1610 * don't yet have a proto_item, we set the
1611 * field_info's length ourselves.
1613 * XXX - our caller can't use that length to
1614 * advance an offset unless they arrange that
1615 * there always be a protocol tree into which
1616 * we're putting this item.
1618 new_fi->length = n + length;
1621 case FT_ABSOLUTE_TIME:
1623 * Absolute times can be in any of a number of
1624 * formats, and they can be big-endian or
1627 * Historically FT_TIMEs were only timespecs;
1628 * the only question was whether they were stored
1629 * in big- or little-endian format.
1631 * For backwards compatibility, we interpret an
1632 * encoding of 1 as meaning "little-endian timespec",
1633 * so that passing TRUE is interpreted as that.
1635 if (encoding == TRUE)
1636 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1638 if (length != 8 && length != 4) {
1639 length_error = length < 4 ? TRUE : FALSE;
1640 report_type_length_mismatch(tree, "an absolute time value", length, length_error);
1645 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1647 * 4-byte UNIX epoch, possibly followed by
1648 * 4-byte fractional time in nanoseconds,
1651 time_stamp.secs = tvb_get_ntohl(tvb, start);
1653 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1655 time_stamp.nsecs = 0;
1658 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1660 * 4-byte UNIX epoch, possibly followed by
1661 * 4-byte fractional time in nanoseconds,
1662 * both little-endian.
1664 time_stamp.secs = tvb_get_letohl(tvb, start);
1666 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1668 time_stamp.nsecs = 0;
1671 case ENC_TIME_TOD|ENC_BIG_ENDIAN:
1673 * TOD time stamp, big-endian.
1675 /* XXX - where should this go? */
1676 #define TOD_BASETIME 2208988800ul
1678 todsecs = tvb_get_ntoh64(tvb, start) >> 12;
1679 time_stamp.secs = (time_t)((todsecs / 1000000) - TOD_BASETIME);
1680 time_stamp.nsecs = (int)((todsecs % 1000000) * 1000);
1683 case ENC_TIME_TOD|ENC_LITTLE_ENDIAN:
1685 * TOD time stamp, big-endian.
1687 todsecs = tvb_get_letoh64(tvb, start) >> 12 ;
1688 time_stamp.secs = (time_t)((todsecs / 1000000) - TOD_BASETIME);
1689 time_stamp.nsecs = (int)((todsecs % 1000000) * 1000);
1692 case ENC_TIME_NTP|ENC_BIG_ENDIAN:
1694 * NTP time stamp, big-endian.
1697 /* XXX - where should this go? */
1698 #define NTP_BASETIME 2208988800ul
1700 /* We need a temporary variable here so the unsigned math
1701 * works correctly (for years > 2036 according to RFC 2030
1704 tmpsecs = tvb_get_ntohl(tvb, start);
1706 time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1708 time_stamp.secs = tmpsecs; /* 0 */
1712 * We're using nanoseconds here (and we will
1713 * display nanoseconds), but NTP's timestamps
1714 * have a precision in microseconds or greater.
1715 * Round to 1 microsecond.
1717 time_stamp.nsecs = (int)(1000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0));
1718 time_stamp.nsecs *= 1000;
1720 time_stamp.nsecs = 0;
1724 case ENC_TIME_NTP|ENC_LITTLE_ENDIAN:
1726 * NTP time stamp, big-endian.
1728 tmpsecs = tvb_get_letohl(tvb, start);
1730 time_stamp.secs = tmpsecs - (guint32)NTP_BASETIME;
1732 time_stamp.secs = tmpsecs; /* 0 */
1736 * We're using nanoseconds here (and we will
1737 * display nanoseconds), but NTP's timestamps
1738 * have a precision in microseconds or greater.
1739 * Round to 1 microsecond.
1741 time_stamp.nsecs = (int)(1000000*(tvb_get_letohl(tvb, start+4)/4294967296.0));
1742 time_stamp.nsecs *= 1000;
1744 time_stamp.nsecs = 0;
1749 DISSECTOR_ASSERT_NOT_REACHED();
1750 time_stamp.secs = 0;
1751 time_stamp.nsecs = 0;
1754 proto_tree_set_time(new_fi, &time_stamp);
1757 case FT_RELATIVE_TIME:
1759 * Relative times can be in any of a number of
1760 * formats, and they can be big-endian or
1763 * Historically FT_TIMEs were only timespecs;
1764 * the only question was whether they were stored
1765 * in big- or little-endian format.
1767 * For backwards compatibility, we interpret an
1768 * encoding of 1 as meaning "little-endian timespec",
1769 * so that passing TRUE is interpreted as that.
1771 if (encoding == TRUE)
1772 encoding = ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN;
1775 if (length != 8 && length != 4) {
1776 length_error = length < 4 ? TRUE : FALSE;
1777 report_type_length_mismatch(tree, "a relative time value", length, length_error);
1780 case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN:
1782 * 4-byte UNIX epoch, possibly followed by
1783 * 4-byte fractional time in nanoseconds,
1786 time_stamp.secs = tvb_get_ntohl(tvb, start);
1788 time_stamp.nsecs = tvb_get_ntohl(tvb, start+4);
1790 time_stamp.nsecs = 0;
1793 case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN:
1795 * 4-byte UNIX epoch, possibly followed by
1796 * 4-byte fractional time in nanoseconds,
1797 * both little-endian.
1799 time_stamp.secs = tvb_get_letohl(tvb, start);
1801 time_stamp.nsecs = tvb_get_letohl(tvb, start+4);
1803 time_stamp.nsecs = 0;
1806 proto_tree_set_time(new_fi, &time_stamp);
1810 g_error("new_fi->hfinfo->type %d (%s) not handled\n",
1811 new_fi->hfinfo->type,
1812 ftype_name(new_fi->hfinfo->type));
1813 DISSECTOR_ASSERT_NOT_REACHED();
1816 FI_SET_FLAG(new_fi, (encoding & ENC_LITTLE_ENDIAN) ? FI_LITTLE_ENDIAN : FI_BIG_ENDIAN);
1818 /* Don't add new node to proto_tree until now so that any exceptions
1819 * raised by a tvbuff access method doesn't leave junk in the proto_tree. */
1820 /* XXX. wouldn't be better to add this item to tree, with some special flag (FI_EXCEPTION?)
1821 * to know which item caused exception? */
1822 pi = proto_tree_add_node(tree, new_fi);
1827 /* Gets data from tvbuff, adds it to proto_tree, increments offset,
1828 and returns proto_item* */
1830 ptvcursor_add(ptvcursor_t *ptvc, int hfindex, gint length,
1831 const guint encoding)
1834 header_field_info *hfinfo;
1839 /* We can't fake it just yet. We have to advance the cursor
1840 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo); */
1842 offset = ptvc->offset;
1843 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
1844 get_hfi_length(hfinfo, ptvc->tvb, offset, &length, &item_length);
1845 ptvc->offset += length;
1846 if (hfinfo->type == FT_UINT_BYTES || hfinfo->type == FT_UINT_STRING) {
1848 * The length of the rest of the item is in the first N
1849 * bytes of the item.
1851 n = get_uint_value(ptvc->tree, ptvc->tvb, offset, length, encoding);
1855 /* Coast clear. Try and fake it */
1856 TRY_TO_FAKE_THIS_ITEM(ptvc->tree, hfindex, hfinfo);
1858 new_fi = new_field_info(ptvc->tree, hfinfo, ptvc->tvb, offset, item_length);
1860 return proto_tree_new_item(new_fi, ptvc->tree, ptvc->tvb,
1861 offset, length, encoding);
1865 * Validates that field length bytes are available starting from
1866 * start (pos/neg). Throws an exception if they aren't.
1869 test_length(header_field_info *hfinfo, tvbuff_t *tvb,
1870 gint start, gint length)
1877 if (hfinfo->type == FT_STRINGZ) {
1878 /* If we're fetching until the end of the TVB, only validate
1879 * that the offset is within range.
1885 tvb_ensure_bytes_exist(tvb, start, size);
1888 /* Add an item to a proto_tree, using the text label registered to that item;
1889 the item is extracted from the tvbuff handed to it. */
1891 proto_tree_add_item_new(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
1892 const gint start, gint length, const guint encoding)
1897 DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
1899 get_hfi_length(hfinfo, tvb, start, &length, &item_length);
1900 test_length(hfinfo, tvb, start, item_length);
1902 TRY_TO_FAKE_THIS_ITEM(tree, hfinfo->id, hfinfo);
1904 new_fi = new_field_info(tree, hfinfo, tvb, start, item_length);
1909 return proto_tree_new_item(new_fi, tree, tvb, start, length, encoding);
1913 proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1914 const gint start, gint length, const guint encoding)
1916 return proto_tree_add_item_new(tree, proto_registrar_get_nth(hfindex), tvb, start, length, encoding);
1919 /* Add a FT_NONE to a proto_tree */
1921 proto_tree_add_none_format(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
1922 const gint start, gint length, const char *format,
1927 header_field_info *hfinfo;
1929 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1931 DISSECTOR_ASSERT(hfinfo->type == FT_NONE);
1933 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
1935 TRY_TO_FAKE_THIS_REPR(pi);
1937 va_start(ap, format);
1938 proto_tree_set_representation(pi, format, ap);
1941 /* no value to set for FT_NONE */
1945 /* Gets data from tvbuff, adds it to proto_tree, *DOES NOT* increment
1946 * offset, and returns proto_item* */
1948 ptvcursor_add_no_advance(ptvcursor_t* ptvc, int hf, gint length,
1949 const guint encoding)
1953 item = proto_tree_add_item(ptvc->tree, hf, ptvc->tvb, ptvc->offset,
1959 /* Advance the ptvcursor's offset within its tvbuff without
1960 * adding anything to the proto_tree. */
1962 ptvcursor_advance(ptvcursor_t* ptvc, gint length)
1964 ptvc->offset += length;
1969 proto_tree_set_protocol_tvb(field_info *fi, tvbuff_t *tvb)
1971 fvalue_set(&fi->value, tvb, TRUE);
1974 /* Add a FT_PROTOCOL to a proto_tree */
1976 proto_tree_add_protocol_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1977 gint start, gint length, const char *format, ...)
1981 header_field_info *hfinfo;
1983 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
1985 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
1987 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
1989 proto_tree_set_protocol_tvb(PNODE_FINFO(pi), (start == 0 ? tvb : tvb_new_subset(tvb, start, length, length)));
1991 TRY_TO_FAKE_THIS_REPR(pi);
1993 va_start(ap, format);
1994 proto_tree_set_representation(pi, format, ap);
2001 /* Add a FT_BYTES to a proto_tree */
2003 proto_tree_add_bytes(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2004 gint length, const guint8 *start_ptr)
2007 header_field_info *hfinfo;
2009 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2011 DISSECTOR_ASSERT(hfinfo->type == FT_BYTES);
2013 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2014 proto_tree_set_bytes(PNODE_FINFO(pi), start_ptr, length);
2020 proto_tree_add_bytes_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2021 gint start, gint length,
2022 const guint8 *start_ptr,
2023 const char *format, ...)
2027 header_field_info *hfinfo;
2029 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2032 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
2035 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
2036 tvb_get_ptr(tvb, start, length));
2038 va_start(ap, format);
2039 proto_tree_set_representation_value(pi, format, ap);
2046 proto_tree_add_bytes_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2047 gint start, gint length, const guint8 *start_ptr,
2048 const char *format, ...)
2052 header_field_info *hfinfo;
2054 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2057 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
2060 pi = proto_tree_add_bytes(tree, hfindex, tvb, start, length,
2061 tvb_get_ptr(tvb, start, length));
2063 TRY_TO_FAKE_THIS_REPR(pi);
2065 va_start(ap, format);
2066 proto_tree_set_representation(pi, format, ap);
2073 proto_tree_set_bytes(field_info *fi, const guint8* start_ptr, gint length)
2077 DISSECTOR_ASSERT(start_ptr != NULL || length == 0);
2079 bytes = g_byte_array_new();
2081 g_byte_array_append(bytes, start_ptr, length);
2083 fvalue_set(&fi->value, bytes, TRUE);
2088 proto_tree_set_bytes_tvb(field_info *fi, tvbuff_t *tvb, gint offset, gint length)
2090 proto_tree_set_bytes(fi, tvb_get_ptr(tvb, offset, length), length);
2093 /* Add a FT_*TIME to a proto_tree */
2095 proto_tree_add_time(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2096 gint length, nstime_t *value_ptr)
2099 header_field_info *hfinfo;
2101 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2103 DISSECTOR_ASSERT(hfinfo->type == FT_ABSOLUTE_TIME ||
2104 hfinfo->type == FT_RELATIVE_TIME);
2106 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2107 proto_tree_set_time(PNODE_FINFO(pi), value_ptr);
2113 proto_tree_add_time_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2114 gint start, gint length, nstime_t *value_ptr,
2115 const char *format, ...)
2120 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2122 va_start(ap, format);
2123 proto_tree_set_representation_value(pi, format, ap);
2131 proto_tree_add_time_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2132 gint start, gint length, nstime_t *value_ptr,
2133 const char *format, ...)
2138 pi = proto_tree_add_time(tree, hfindex, tvb, start, length, value_ptr);
2140 TRY_TO_FAKE_THIS_REPR(pi);
2142 va_start(ap, format);
2143 proto_tree_set_representation(pi, format, ap);
2150 /* Set the FT_*TIME value */
2152 proto_tree_set_time(field_info *fi, nstime_t *value_ptr)
2154 DISSECTOR_ASSERT(value_ptr != NULL);
2156 fvalue_set(&fi->value, value_ptr, FALSE);
2159 /* Add a FT_IPXNET to a proto_tree */
2161 proto_tree_add_ipxnet(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2162 gint length, guint32 value)
2165 header_field_info *hfinfo;
2167 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2169 DISSECTOR_ASSERT(hfinfo->type == FT_IPXNET);
2171 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2172 proto_tree_set_ipxnet(PNODE_FINFO(pi), value);
2178 proto_tree_add_ipxnet_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2179 gint start, gint length, guint32 value,
2180 const char *format, ...)
2185 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2187 va_start(ap, format);
2188 proto_tree_set_representation_value(pi, format, ap);
2196 proto_tree_add_ipxnet_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2197 gint start, gint length, guint32 value,
2198 const char *format, ...)
2203 pi = proto_tree_add_ipxnet(tree, hfindex, tvb, start, length, value);
2205 TRY_TO_FAKE_THIS_REPR(pi);
2207 va_start(ap, format);
2208 proto_tree_set_representation(pi, format, ap);
2215 /* Set the FT_IPXNET value */
2217 proto_tree_set_ipxnet(field_info *fi, guint32 value)
2219 fvalue_set_uinteger(&fi->value, value);
2222 /* Add a FT_IPv4 to a proto_tree */
2224 proto_tree_add_ipv4(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2225 gint length, guint32 value)
2228 header_field_info *hfinfo;
2230 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2232 DISSECTOR_ASSERT(hfinfo->type == FT_IPv4);
2234 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2235 proto_tree_set_ipv4(PNODE_FINFO(pi), value);
2241 proto_tree_add_ipv4_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2242 gint start, gint length, guint32 value,
2243 const char *format, ...)
2248 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2250 va_start(ap, format);
2251 proto_tree_set_representation_value(pi, format, ap);
2259 proto_tree_add_ipv4_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2260 gint start, gint length, guint32 value,
2261 const char *format, ...)
2266 pi = proto_tree_add_ipv4(tree, hfindex, tvb, start, length, value);
2268 TRY_TO_FAKE_THIS_REPR(pi);
2270 va_start(ap, format);
2271 proto_tree_set_representation(pi, format, ap);
2278 /* Set the FT_IPv4 value */
2280 proto_tree_set_ipv4(field_info *fi, guint32 value)
2282 fvalue_set_uinteger(&fi->value, value);
2285 /* Add a FT_IPv6 to a proto_tree */
2287 proto_tree_add_ipv6(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2288 gint length, const guint8* value_ptr)
2291 header_field_info *hfinfo;
2293 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2295 DISSECTOR_ASSERT(hfinfo->type == FT_IPv6);
2297 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2298 proto_tree_set_ipv6(PNODE_FINFO(pi), value_ptr);
2304 proto_tree_add_ipv6_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2305 gint start, gint length,
2306 const guint8* value_ptr,
2307 const char *format, ...)
2312 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2314 va_start(ap, format);
2315 proto_tree_set_representation_value(pi, format, ap);
2323 proto_tree_add_ipv6_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2324 gint start, gint length, const guint8* value_ptr,
2325 const char *format, ...)
2330 pi = proto_tree_add_ipv6(tree, hfindex, tvb, start, length, value_ptr);
2332 TRY_TO_FAKE_THIS_REPR(pi);
2334 va_start(ap, format);
2335 proto_tree_set_representation(pi, format, ap);
2342 /* Set the FT_IPv6 value */
2344 proto_tree_set_ipv6(field_info *fi, const guint8* value_ptr)
2346 DISSECTOR_ASSERT(value_ptr != NULL);
2347 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2351 proto_tree_set_ipv6_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2353 proto_tree_set_ipv6(fi, tvb_get_ptr(tvb, start, length));
2356 /* Add a FT_GUID to a proto_tree */
2358 proto_tree_add_guid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2359 gint length, const e_guid_t *value_ptr)
2362 header_field_info *hfinfo;
2364 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2366 DISSECTOR_ASSERT(hfinfo->type == FT_GUID);
2368 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2369 proto_tree_set_guid(PNODE_FINFO(pi), value_ptr);
2375 proto_tree_add_guid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2376 gint start, gint length,
2377 const e_guid_t *value_ptr,
2378 const char *format, ...)
2383 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2385 va_start(ap, format);
2386 proto_tree_set_representation_value(pi, format, ap);
2394 proto_tree_add_guid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2395 gint start, gint length, const e_guid_t *value_ptr,
2396 const char *format, ...)
2401 pi = proto_tree_add_guid(tree, hfindex, tvb, start, length, value_ptr);
2403 TRY_TO_FAKE_THIS_REPR(pi);
2405 va_start(ap, format);
2406 proto_tree_set_representation(pi, format, ap);
2413 /* Set the FT_GUID value */
2415 proto_tree_set_guid(field_info *fi, const e_guid_t *value_ptr)
2417 DISSECTOR_ASSERT(value_ptr != NULL);
2418 fvalue_set(&fi->value, (gpointer) value_ptr, FALSE);
2422 proto_tree_set_guid_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2423 const guint encoding)
2427 tvb_get_guid(tvb, start, &guid, encoding);
2428 proto_tree_set_guid(fi, &guid);
2431 /* Add a FT_OID to a proto_tree */
2433 proto_tree_add_oid(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2434 gint length, const guint8* value_ptr)
2437 header_field_info *hfinfo;
2439 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2441 DISSECTOR_ASSERT(hfinfo->type == FT_OID);
2443 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2444 proto_tree_set_oid(PNODE_FINFO(pi), value_ptr, length);
2450 proto_tree_add_oid_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2451 gint start, gint length,
2452 const guint8* value_ptr,
2453 const char *format, ...)
2458 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2460 va_start(ap, format);
2461 proto_tree_set_representation_value(pi, format, ap);
2469 proto_tree_add_oid_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2470 gint start, gint length, const guint8* value_ptr,
2471 const char *format, ...)
2476 pi = proto_tree_add_oid(tree, hfindex, tvb, start, length, value_ptr);
2478 TRY_TO_FAKE_THIS_REPR(pi);
2480 va_start(ap, format);
2481 proto_tree_set_representation(pi, format, ap);
2488 /* Set the FT_OID value */
2490 proto_tree_set_oid(field_info *fi, const guint8* value_ptr, gint length)
2494 DISSECTOR_ASSERT(value_ptr != NULL || length == 0);
2496 bytes = g_byte_array_new();
2498 g_byte_array_append(bytes, value_ptr, length);
2500 fvalue_set(&fi->value, bytes, TRUE);
2504 proto_tree_set_oid_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length)
2506 proto_tree_set_oid(fi, tvb_get_ptr(tvb, start, length), length);
2510 proto_tree_set_uint64(field_info *fi, guint64 value)
2512 fvalue_set_integer64(&fi->value, value);
2516 * NOTE: to support code written when proto_tree_add_item() took a
2517 * gboolean as its last argument, with FALSE meaning "big-endian"
2518 * and TRUE meaning "little-endian", we treat any non-zero value of
2519 * "encoding" as meaning "little-endian".
2522 proto_tree_set_uint64_tvb(field_info *fi, tvbuff_t *tvb, gint start,
2523 guint length, const guint encoding)
2526 guint8* b = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, start, length);
2531 default: DISSECTOR_ASSERT_NOT_REACHED();
2532 case 8: value <<= 8; value += *--b;
2533 case 7: value <<= 8; value += *--b;
2534 case 6: value <<= 8; value += *--b;
2535 case 5: value <<= 8; value += *--b;
2536 case 4: value <<= 8; value += *--b;
2537 case 3: value <<= 8; value += *--b;
2538 case 2: value <<= 8; value += *--b;
2539 case 1: value <<= 8; value += *--b;
2544 default: DISSECTOR_ASSERT_NOT_REACHED();
2545 case 8: value <<= 8; value += *b++;
2546 case 7: value <<= 8; value += *b++;
2547 case 6: value <<= 8; value += *b++;
2548 case 5: value <<= 8; value += *b++;
2549 case 4: value <<= 8; value += *b++;
2550 case 3: value <<= 8; value += *b++;
2551 case 2: value <<= 8; value += *b++;
2552 case 1: value <<= 8; value += *b++;
2557 proto_tree_set_uint64(fi, value);
2560 /* Add a FT_STRING or FT_STRINGZ to a proto_tree. Creates own copy of string,
2561 * and frees it when the proto_tree is destroyed. */
2563 proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2564 gint length, const char* value)
2567 header_field_info *hfinfo;
2569 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2571 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2573 if (hfinfo->display == STR_UNICODE) {
2574 DISSECTOR_ASSERT(g_utf8_validate(value, -1, NULL));
2577 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2578 DISSECTOR_ASSERT(length >= 0);
2579 proto_tree_set_string(PNODE_FINFO(pi), value);
2585 proto_tree_add_string_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2586 gint start, gint length, const char* value,
2593 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2595 va_start(ap, format);
2596 proto_tree_set_representation_value(pi, format, ap);
2604 proto_tree_add_string_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2605 gint start, gint length, const char* value,
2606 const char *format, ...)
2611 pi = proto_tree_add_string(tree, hfindex, tvb, start, length, value);
2613 TRY_TO_FAKE_THIS_REPR(pi);
2615 va_start(ap, format);
2616 proto_tree_set_representation(pi, format, ap);
2623 /* Appends string data to a FT_STRING or FT_STRINGZ, allowing progressive
2624 * field info update instead of only updating the representation as does
2625 * proto_item_append_text()
2627 /* NOTE: this function will break with the TRY_TO_FAKE_THIS_ITEM()
2628 * speed optimization.
2629 * Currently only WSP use this function so it is not that bad but try to
2630 * avoid using this one if possible.
2631 * IF you must use this function you MUST also disable the
2632 * TRY_TO_FAKE_THIS_ITEM() optimization for your dissector/function
2633 * using proto_item_append_string().
2634 * Do that by faking that the tree is visible by calling
2635 * proto_tree_set_visible(tree, TRUE) (see packet-wsp.c)
2636 * BEFORE you create the item you are later going to use
2637 * proto_item_append_string() on.
2640 proto_item_append_string(proto_item *pi, const char *str)
2643 header_field_info *hfinfo;
2644 const gchar *old_str, *new_str;
2651 fi = PITEM_FINFO(pi);
2652 DISSECTOR_ASSERT_HINT(fi, "proto_tree_set_visible(tree, TRUE) should have been called previously");
2654 hfinfo = fi->hfinfo;
2655 if (hfinfo->type == FT_PROTOCOL) {
2656 /* TRY_TO_FAKE_THIS_ITEM() speed optimization: silently skip */
2659 DISSECTOR_ASSERT(hfinfo->type == FT_STRING || hfinfo->type == FT_STRINGZ);
2660 old_str = (guint8 *)fvalue_get(&fi->value);
2661 if (old_str && old_str[0])
2662 new_str = ep_strconcat(old_str, str, NULL);
2665 fvalue_set(&fi->value, (gpointer) new_str, FALSE);
2668 /* Set the FT_STRING value */
2670 proto_tree_set_string(field_info *fi, const char* value)
2673 fvalue_set(&fi->value, (gpointer) value, FALSE);
2675 fvalue_set(&fi->value, (gpointer) "[ Null ]", FALSE);
2680 proto_tree_set_string_tvb(field_info *fi, tvbuff_t *tvb, gint start, gint length, gint encoding)
2685 length = tvb_ensure_length_remaining(tvb, start);
2688 string = tvb_get_string_enc(wmem_packet_scope(), tvb, start, length, encoding);
2689 proto_tree_set_string(fi, string);
2693 /* Add a FT_AX25 to a proto_tree */
2695 proto_tree_add_ax25(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length,
2696 const guint8* value)
2699 header_field_info *hfinfo;
2701 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2703 DISSECTOR_ASSERT(hfinfo->type == FT_AX25);
2705 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2706 proto_tree_set_ax25(PNODE_FINFO(pi), value);
2711 /* Set the FT_AX25 value */
2713 proto_tree_set_ax25(field_info *fi, const guint8* value)
2715 fvalue_set(&fi->value, (gpointer) value, FALSE);
2719 proto_tree_set_ax25_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2721 proto_tree_set_ax25(fi, tvb_get_ptr(tvb, start, 7));
2724 /* Set the FT_VINES value */
2726 proto_tree_set_vines(field_info *fi, const guint8* value)
2728 fvalue_set(&fi->value, (gpointer) value, FALSE);
2732 proto_tree_set_vines_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2734 proto_tree_set_vines(fi, tvb_get_ptr(tvb, start, FT_VINES_ADDR_LEN));
2737 /* Add a FT_ETHER to a proto_tree */
2739 proto_tree_add_ether(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2740 gint length, const guint8* value)
2743 header_field_info *hfinfo;
2745 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2747 DISSECTOR_ASSERT(hfinfo->type == FT_ETHER);
2749 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2750 proto_tree_set_ether(PNODE_FINFO(pi), value);
2756 proto_tree_add_ether_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2757 gint start, gint length, const guint8* value,
2758 const char *format, ...)
2763 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2765 va_start(ap, format);
2766 proto_tree_set_representation_value(pi, format, ap);
2774 proto_tree_add_ether_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2775 gint start, gint length, const guint8* value,
2776 const char *format, ...)
2781 pi = proto_tree_add_ether(tree, hfindex, tvb, start, length, value);
2783 TRY_TO_FAKE_THIS_REPR(pi);
2785 va_start(ap, format);
2786 proto_tree_set_representation(pi, format, ap);
2793 /* Set the FT_ETHER value */
2795 proto_tree_set_ether(field_info *fi, const guint8* value)
2797 fvalue_set(&fi->value, (gpointer) value, FALSE);
2801 proto_tree_set_ether_tvb(field_info *fi, tvbuff_t *tvb, gint start)
2803 proto_tree_set_ether(fi, tvb_get_ptr(tvb, start, FT_ETHER_LEN));
2806 /* Add a FT_BOOLEAN to a proto_tree */
2808 proto_tree_add_boolean(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2809 gint length, guint32 value)
2812 header_field_info *hfinfo;
2814 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2816 DISSECTOR_ASSERT(hfinfo->type == FT_BOOLEAN);
2818 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2819 proto_tree_set_boolean(PNODE_FINFO(pi), value);
2825 proto_tree_add_boolean_format_value(proto_tree *tree, int hfindex,
2826 tvbuff_t *tvb, gint start, gint length,
2827 guint32 value, const char *format, ...)
2832 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2834 va_start(ap, format);
2835 proto_tree_set_representation_value(pi, format, ap);
2843 proto_tree_add_boolean_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2844 gint start, gint length, guint32 value,
2845 const char *format, ...)
2850 pi = proto_tree_add_boolean(tree, hfindex, tvb, start, length, value);
2852 TRY_TO_FAKE_THIS_REPR(pi);
2854 va_start(ap, format);
2855 proto_tree_set_representation(pi, format, ap);
2862 /* Set the FT_BOOLEAN value */
2864 proto_tree_set_boolean(field_info *fi, guint32 value)
2866 proto_tree_set_uint(fi, value);
2869 /* Add a FT_FLOAT to a proto_tree */
2871 proto_tree_add_float(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2872 gint length, float value)
2875 header_field_info *hfinfo;
2877 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2879 DISSECTOR_ASSERT(hfinfo->type == FT_FLOAT);
2881 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2882 proto_tree_set_float(PNODE_FINFO(pi), value);
2888 proto_tree_add_float_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2889 gint start, gint length, float value,
2890 const char *format, ...)
2895 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2897 va_start(ap, format);
2898 proto_tree_set_representation_value(pi, format, ap);
2906 proto_tree_add_float_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2907 gint start, gint length, float value,
2908 const char *format, ...)
2913 pi = proto_tree_add_float(tree, hfindex, tvb, start, length, value);
2915 TRY_TO_FAKE_THIS_REPR(pi);
2917 va_start(ap, format);
2918 proto_tree_set_representation(pi, format, ap);
2925 /* Set the FT_FLOAT value */
2927 proto_tree_set_float(field_info *fi, float value)
2929 fvalue_set_floating(&fi->value, value);
2932 /* Add a FT_DOUBLE to a proto_tree */
2934 proto_tree_add_double(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2935 gint length, double value)
2938 header_field_info *hfinfo;
2940 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
2942 DISSECTOR_ASSERT(hfinfo->type == FT_DOUBLE);
2944 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
2945 proto_tree_set_double(PNODE_FINFO(pi), value);
2951 proto_tree_add_double_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2952 gint start, gint length, double value,
2953 const char *format, ...)
2958 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2960 va_start(ap, format);
2961 proto_tree_set_representation_value(pi, format, ap);
2969 proto_tree_add_double_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
2970 gint start, gint length, double value,
2971 const char *format, ...)
2976 pi = proto_tree_add_double(tree, hfindex, tvb, start, length, value);
2978 TRY_TO_FAKE_THIS_REPR(pi);
2980 va_start(ap, format);
2981 proto_tree_set_representation(pi, format, ap);
2988 /* Set the FT_DOUBLE value */
2990 proto_tree_set_double(field_info *fi, double value)
2992 fvalue_set_floating(&fi->value, value);
2995 /* Add FT_UINT{8,16,24,32} to a proto_tree */
2997 proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
2998 gint length, guint32 value)
3000 proto_item *pi = NULL;
3001 header_field_info *hfinfo;
3003 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3005 switch (hfinfo->type) {
3011 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3012 proto_tree_set_uint(PNODE_FINFO(pi), value);
3016 DISSECTOR_ASSERT_NOT_REACHED();
3023 proto_tree_add_uint_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3024 gint start, gint length, guint32 value,
3025 const char *format, ...)
3030 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
3032 va_start(ap, format);
3033 proto_tree_set_representation_value(pi, format, ap);
3041 proto_tree_add_uint_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3042 gint start, gint length, guint32 value,
3043 const char *format, ...)
3048 pi = proto_tree_add_uint(tree, hfindex, tvb, start, length, value);
3050 TRY_TO_FAKE_THIS_REPR(pi);
3052 va_start(ap, format);
3053 proto_tree_set_representation(pi, format, ap);
3060 /* Set the FT_UINT{8,16,24,32} value */
3062 proto_tree_set_uint(field_info *fi, guint32 value)
3064 header_field_info *hfinfo;
3067 hfinfo = fi->hfinfo;
3070 if (hfinfo->bitmask) {
3071 /* Mask out irrelevant portions */
3072 integer &= hfinfo->bitmask;
3075 integer >>= hfinfo_bitshift(hfinfo);
3078 fvalue_set_uinteger(&fi->value, integer);
3081 /* Add FT_UINT64 to a proto_tree */
3083 proto_tree_add_uint64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3084 gint length, guint64 value)
3087 header_field_info *hfinfo;
3089 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3091 DISSECTOR_ASSERT(hfinfo->type == FT_UINT64);
3093 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3094 proto_tree_set_uint64(PNODE_FINFO(pi), value);
3100 proto_tree_add_uint64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3101 gint start, gint length, guint64 value,
3102 const char *format, ...)
3107 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3109 va_start(ap, format);
3110 proto_tree_set_representation_value(pi, format, ap);
3118 proto_tree_add_uint64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3119 gint start, gint length, guint64 value,
3120 const char *format, ...)
3125 pi = proto_tree_add_uint64(tree, hfindex, tvb, start, length, value);
3127 TRY_TO_FAKE_THIS_REPR(pi);
3129 va_start(ap, format);
3130 proto_tree_set_representation(pi, format, ap);
3137 /* Add FT_INT{8,16,24,32} to a proto_tree */
3139 proto_tree_add_int(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3140 gint length, gint32 value)
3142 proto_item *pi = NULL;
3143 header_field_info *hfinfo;
3145 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3147 switch (hfinfo->type) {
3152 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3153 proto_tree_set_int(PNODE_FINFO(pi), value);
3157 DISSECTOR_ASSERT_NOT_REACHED();
3164 proto_tree_add_int_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3165 gint start, gint length, gint32 value,
3166 const char *format, ...)
3171 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3173 va_start(ap, format);
3174 proto_tree_set_representation_value(pi, format, ap);
3182 proto_tree_add_int_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3183 gint start, gint length, gint32 value,
3184 const char *format, ...)
3189 pi = proto_tree_add_int(tree, hfindex, tvb, start, length, value);
3191 TRY_TO_FAKE_THIS_REPR(pi);
3193 va_start(ap, format);
3194 proto_tree_set_representation(pi, format, ap);
3201 /* Set the FT_INT{8,16,24,32} value */
3203 proto_tree_set_int(field_info *fi, gint32 value)
3205 header_field_info *hfinfo;
3209 hfinfo = fi->hfinfo;
3210 integer = (guint32) value;
3212 if (hfinfo->bitmask) {
3213 /* Mask out irrelevant portions */
3214 integer &= hfinfo->bitmask;
3217 integer >>= hfinfo_bitshift(hfinfo);
3219 no_of_bits = ws_count_ones(hfinfo->bitmask);
3220 if (integer & (1 << (no_of_bits-1)))
3221 integer |= (-1 << no_of_bits);
3224 fvalue_set_sinteger(&fi->value, integer);
3227 /* Add FT_INT64 to a proto_tree */
3229 proto_tree_add_int64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3230 gint length, gint64 value)
3233 header_field_info *hfinfo;
3235 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3237 DISSECTOR_ASSERT(hfinfo->type == FT_INT64);
3239 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3240 proto_tree_set_uint64(PNODE_FINFO(pi), (guint64)value);
3246 proto_tree_add_int64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3247 gint start, gint length, gint64 value,
3248 const char *format, ...)
3253 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3255 va_start(ap, format);
3256 proto_tree_set_representation_value(pi, format, ap);
3264 proto_tree_add_int64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3265 gint start, gint length, gint64 value,
3266 const char *format, ...)
3271 pi = proto_tree_add_int64(tree, hfindex, tvb, start, length, value);
3273 TRY_TO_FAKE_THIS_REPR(pi);
3275 va_start(ap, format);
3276 proto_tree_set_representation(pi, format, ap);
3282 /* Add a FT_EUI64 to a proto_tree */
3284 proto_tree_add_eui64(proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start,
3285 gint length, const guint64 value)
3288 header_field_info *hfinfo;
3290 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
3292 DISSECTOR_ASSERT(hfinfo->type == FT_EUI64);
3294 pi = proto_tree_add_pi(tree, hfinfo, tvb, start, &length);
3295 proto_tree_set_eui64(PNODE_FINFO(pi), value);
3301 proto_tree_add_eui64_format_value(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3302 gint start, gint length, const guint64 value,
3303 const char *format, ...)
3308 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3310 va_start(ap, format);
3311 proto_tree_set_representation_value(pi, format, ap);
3319 proto_tree_add_eui64_format(proto_tree *tree, int hfindex, tvbuff_t *tvb,
3320 gint start, gint length, const guint64 value,
3321 const char *format, ...)
3326 pi = proto_tree_add_eui64(tree, hfindex, tvb, start, length, value);
3328 TRY_TO_FAKE_THIS_REPR(pi);
3330 va_start(ap, format);
3331 proto_tree_set_representation(pi, format, ap);
3338 /* Set the FT_EUI64 value */
3340 proto_tree_set_eui64(field_info *fi, const guint64 value)
3342 fvalue_set_integer64(&fi->value, value);
3345 proto_tree_set_eui64_tvb(field_info *fi, tvbuff_t *tvb, gint start, const guint encoding)
3349 proto_tree_set_eui64(fi, tvb_get_letoh64(tvb, start));
3351 proto_tree_set_eui64(fi, tvb_get_ntoh64(tvb, start));
3355 /* Add a field_info struct to the proto_tree, encapsulating it in a proto_node */
3357 proto_tree_add_node(proto_tree *tree, field_info *fi)
3359 proto_node *pnode, *tnode, *sibling;
3363 * Make sure "tree" is ready to have subtrees under it, by
3364 * checking whether it's been given an ett_ value.
3366 * "PNODE_FINFO(tnode)" may be null; that's the case for the root
3367 * node of the protocol tree. That node is not displayed,
3368 * so it doesn't need an ett_ value to remember whether it
3372 tfi = PNODE_FINFO(tnode);
3373 if (tfi != NULL && (tfi->tree_type < 0 || tfi->tree_type >= num_tree_types)) {
3374 REPORT_DISSECTOR_BUG(ep_strdup_printf("\"%s\" - \"%s\" tfi->tree_type: %u invalid (%s:%u)",
3375 fi->hfinfo->name, fi->hfinfo->abbrev, tfi->tree_type, __FILE__, __LINE__));
3376 /* XXX - is it safe to continue here? */
3379 pnode = wmem_new(PNODE_POOL(tree), proto_node);
3380 PROTO_NODE_INIT(pnode);
3381 pnode->parent = tnode;
3382 PNODE_FINFO(pnode) = fi;
3383 pnode->tree_data = PTREE_DATA(tree);
3385 if (tnode->last_child != NULL) {
3386 sibling = tnode->last_child;
3387 DISSECTOR_ASSERT(sibling->next == NULL);
3388 sibling->next = pnode;
3390 tnode->first_child = pnode;
3391 tnode->last_child = pnode;
3393 tree_data_add_maybe_interesting_field(pnode->tree_data, fi);
3395 return (proto_item *)pnode;
3399 /* Generic way to allocate field_info and add to proto_tree.
3400 * Sets *pfi to address of newly-allocated field_info struct */
3402 proto_tree_add_pi(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, gint start,
3408 fi = alloc_field_info(tree, hfinfo, tvb, start, length);
3409 pi = proto_tree_add_node(tree, fi);
3416 get_hfi_length(header_field_info *hfinfo, tvbuff_t *tvb, const gint start, gint *length,
3419 gint length_remaining;
3422 * We only allow a null tvbuff if the item has a zero length,
3423 * i.e. if there's no data backing it.
3425 DISSECTOR_ASSERT(tvb != NULL || *length == 0);
3428 * XXX - in some protocols, there are 32-bit unsigned length
3429 * fields, so lengths in protocol tree and tvbuff routines
3430 * should really be unsigned. We should have, for those
3431 * field types for which "to the end of the tvbuff" makes sense,
3432 * additional routines that take no length argument and
3433 * add fields that run to the end of the tvbuff.
3435 if (*length == -1) {
3437 * For FT_NONE, FT_PROTOCOL, FT_BYTES, and FT_STRING fields,
3438 * a length of -1 means "set the length to what remains in
3441 * The assumption is either that
3443 * 1) the length of the item can only be determined
3444 * by dissection (typically true of items with
3445 * subitems, which are probably FT_NONE or
3450 * 2) if the tvbuff is "short" (either due to a short
3451 * snapshot length or due to lack of reassembly of
3452 * fragments/segments/whatever), we want to display
3453 * what's available in the field (probably FT_BYTES
3454 * or FT_STRING) and then throw an exception later
3458 * 3) the field is defined to be "what's left in the
3461 * so we set the length to what remains in the tvbuff so
3462 * that, if we throw an exception while dissecting, it
3463 * has what is probably the right value.
3465 * For FT_STRINGZ, it means "the string is null-terminated,
3466 * not null-padded; set the length to the actual length
3467 * of the string", and if the tvbuff if short, we just
3468 * throw an exception.
3470 * It's not valid for any other type of field.
3472 switch (hfinfo->type) {
3476 * We allow this to be zero-length - for
3477 * example, an ONC RPC NULL procedure has
3478 * neither arguments nor reply, so the
3479 * payload for that protocol is empty.
3481 * However, if the length is negative, the
3482 * start offset is *past* the byte past the
3483 * end of the tvbuff, so we throw an
3486 *length = tvb_length_remaining(tvb, start);
3489 * Use "tvb_ensure_bytes_exist()"
3490 * to force the appropriate exception
3493 tvb_ensure_bytes_exist(tvb, start, 0);
3495 DISSECTOR_ASSERT(*length >= 0);
3501 *length = tvb_ensure_length_remaining(tvb, start);
3502 DISSECTOR_ASSERT(*length >= 0);
3507 * Leave the length as -1, so our caller knows
3513 DISSECTOR_ASSERT_NOT_REACHED();
3515 *item_length = *length;
3517 *item_length = *length;
3518 if (hfinfo->type == FT_PROTOCOL || hfinfo->type == FT_NONE) {
3520 * These types are for interior nodes of the
3521 * tree, and don't have data associated with
3522 * them; if the length is negative (XXX - see
3523 * above) or goes past the end of the tvbuff,
3524 * cut it short at the end of the tvbuff.
3525 * That way, if this field is selected in
3526 * Wireshark, we don't highlight stuff past
3527 * the end of the data.
3529 /* XXX - what to do, if we don't have a tvb? */
3531 length_remaining = tvb_length_remaining(tvb, start);
3532 if (*item_length < 0 ||
3533 (*item_length > 0 &&
3534 (length_remaining < *item_length)))
3535 *item_length = length_remaining;
3538 if (*item_length < 0) {
3539 THROW(ReportedBoundsError);
3545 new_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb,
3546 const gint start, const gint item_length)
3550 FIELD_INFO_NEW(PNODE_POOL(tree), fi);
3552 fi->hfinfo = hfinfo;
3554 fi->start += (tvb)?tvb_raw_offset(tvb):0;
3555 fi->length = item_length;
3558 if (!PTREE_DATA(tree)->visible)
3559 FI_SET_FLAG(fi, FI_HIDDEN);
3560 fvalue_init(&fi->value, fi->hfinfo->type);
3563 /* add the data source tvbuff */
3564 fi->ds_tvb = tvb ? tvb_get_ds_tvb(tvb) : NULL;
3566 fi->appendix_start = 0;
3567 fi->appendix_length = 0;
3573 alloc_field_info(proto_tree *tree, header_field_info *hfinfo, tvbuff_t *tvb, const gint start,
3578 get_hfi_length(hfinfo, tvb, start, length, &item_length);
3579 return new_field_info(tree, hfinfo, tvb, start, item_length);
3583 label_mark_truncated_start(char *label_str)
3585 static const char trunc_str[] = "[truncated] ";
3586 const size_t trunc_len = sizeof(trunc_str)-1;
3588 memmove(label_str + trunc_len, label_str, ITEM_LABEL_LENGTH - trunc_len);
3589 memcpy(label_str, trunc_str, trunc_len);
3590 label_str[ITEM_LABEL_LENGTH-1] = '\0';
3593 /* If the protocol tree is to be visible, set the representation of a
3594 proto_tree entry with the name of the field for the item and with
3595 the value formatted with the supplied printf-style format and
3598 proto_tree_set_representation_value(proto_item *pi, const char *format, va_list ap)
3602 /* If the tree (GUI) or item isn't visible it's pointless for us to generate the protocol
3603 * items string representation */
3604 if (PTREE_DATA(pi)->visible && !PROTO_ITEM_IS_HIDDEN(pi)) {
3606 field_info *fi = PITEM_FINFO(pi);
3607 header_field_info *hf;
3609 DISSECTOR_ASSERT(fi);
3613 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
3614 if (hf->bitmask && (hf->type == FT_BOOLEAN || IS_FT_UINT(hf->type))) {
3618 val = fvalue_get_uinteger(&fi->value);
3619 val <<= hfinfo_bitshift(hf);
3621 p = decode_bitfield_value(fi->rep->representation, val, hf->bitmask, hfinfo_bitwidth(hf));
3622 ret = (int) (p - fi->rep->representation);
3625 /* put in the hf name */
3626 ret += g_snprintf(fi->rep->representation + ret, ITEM_LABEL_LENGTH - ret, "%s: ", hf->name);
3628 /* If possible, Put in the value of the string */
3629 if (ret < ITEM_LABEL_LENGTH) {
3630 ret += g_vsnprintf(fi->rep->representation + ret,
3631 ITEM_LABEL_LENGTH - ret, format, ap);
3633 if (ret >= ITEM_LABEL_LENGTH) {
3634 /* Uh oh, we don't have enough room. Tell the user
3635 * that the field is truncated.
3637 /* XXX, label_mark_truncated() ? */
3638 label_mark_truncated_start(fi->rep->representation);
3643 /* If the protocol tree is to be visible, set the representation of a
3644 proto_tree entry with the representation formatted with the supplied
3645 printf-style format and argument list. */
3647 proto_tree_set_representation(proto_item *pi, const char *format, va_list ap)
3649 int ret; /*tmp return value */
3650 field_info *fi = PITEM_FINFO(pi);
3652 DISSECTOR_ASSERT(fi);
3654 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
3655 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
3656 ret = g_vsnprintf(fi->rep->representation, ITEM_LABEL_LENGTH,
3658 if (ret >= ITEM_LABEL_LENGTH) {
3659 /* Uh oh, we don't have enough room. Tell the user
3660 * that the field is truncated.
3662 label_mark_truncated_start(fi->rep->representation);
3668 hfinfo_format_text(const header_field_info *hfinfo, const guchar *string)
3670 switch (hfinfo->display) {
3672 return format_text(string, strlen(string));
3675 return format_text_wsp(string, strlen(string));
3678 /* XXX, format_unicode_text() */
3682 return format_text(string, strlen(string));
3686 protoo_strlcpy(gchar *dest, const gchar *src, gsize dest_size)
3688 gsize res = g_strlcpy(dest, src, dest_size);
3690 if (res > dest_size)
3695 static header_field_info *
3696 hfinfo_same_name_get_prev(const header_field_info *hfinfo)
3698 if (hfinfo->same_name_prev_id == -1)
3700 return proto_registrar_get_nth(hfinfo->same_name_prev_id);
3703 /* -------------------------- */
3705 proto_custom_set(proto_tree* tree, const int field_id, gint occurrence,
3706 gchar *result, gchar *expr, const int size)
3711 struct e_in6_addr *ipv6;
3713 guint32 n_addr; /* network-order IPv4 address */
3715 const true_false_string *tfstring;
3717 int len, prev_len = 0, last, i, offset_r = 0, offset_e = 0;
3719 field_info *finfo = NULL;
3720 header_field_info* hfinfo;
3721 const gchar *abbrev = NULL;
3723 const char *hf_str_val;
3724 char number_buf[32];
3725 const char *number_out;
3727 g_assert(field_id >= 0);
3729 hfinfo = proto_registrar_get_nth((guint)field_id);
3731 /* do we need to rewind ? */
3735 if (occurrence < 0) {
3736 /* Search other direction */
3737 while (hfinfo->same_name_prev_id != -1) {
3738 hfinfo = proto_registrar_get_nth(hfinfo->same_name_prev_id);
3743 finfos = proto_get_finfo_ptr_array(tree, hfinfo->id);
3745 if (!finfos || !(len = g_ptr_array_len(finfos))) {
3746 if (occurrence < 0) {
3747 hfinfo = hfinfo->same_name_next;
3749 hfinfo = hfinfo_same_name_get_prev(hfinfo);
3754 /* Are there enough occurrences of the field? */
3755 if (((occurrence - prev_len) > len) || ((occurrence + prev_len) < -len)) {
3756 if (occurrence < 0) {
3757 hfinfo = hfinfo->same_name_next;
3759 hfinfo = hfinfo_same_name_get_prev(hfinfo);
3765 /* Calculate single index or set outer bounderies */
3766 if (occurrence < 0) {
3767 i = occurrence + len + prev_len;
3769 } else if (occurrence > 0) {
3770 i = occurrence - 1 - prev_len;
3777 prev_len += len; /* Count handled occurrences */
3780 finfo = (field_info *)g_ptr_array_index(finfos, i);
3782 if (offset_r && (offset_r < (size - 2)))
3783 result[offset_r++] = ',';
3785 if (offset_e && (offset_e < (size - 2)))
3786 expr[offset_e++] = ',';
3788 switch (hfinfo->type) {
3790 case FT_NONE: /* Nothing to add */
3791 if (offset_r == 0) {
3793 } else if (result[offset_r-1] == ',') {
3794 result[offset_r-1] = '\0';
3799 /* prevent multiple "yes" entries by setting result directly */
3800 g_strlcpy(result, "Yes", size);
3805 bytes = (guint8 *)fvalue_get(&finfo->value);
3806 offset_r += protoo_strlcpy(result+offset_r,
3808 fvalue_length(&finfo->value)),
3812 case FT_ABSOLUTE_TIME:
3813 offset_r += protoo_strlcpy(result+offset_r,
3814 abs_time_to_str((const nstime_t *)fvalue_get(&finfo->value),
3815 (absolute_time_display_e)hfinfo->display, TRUE),
3819 case FT_RELATIVE_TIME:
3820 offset_r += protoo_strlcpy(result+offset_r,
3821 rel_time_to_secs_str((const nstime_t *)fvalue_get(&finfo->value)),
3826 number = fvalue_get_uinteger(&finfo->value);
3827 tfstring = (const true_false_string *)&tfs_true_false;
3828 if (hfinfo->strings) {
3829 tfstring = (const struct true_false_string*) hfinfo->strings;
3831 offset_r += protoo_strlcpy(result+offset_r,
3833 tfstring->true_string :
3834 tfstring->false_string, size-offset_r);
3836 offset_e += protoo_strlcpy(expr+offset_e,
3837 number ? "1" : "0", size-offset_e);
3840 /* XXX - make these just FT_NUMBER? */
3851 number = IS_FT_INT(hfinfo->type) ?
3852 (guint32) fvalue_get_sinteger(&finfo->value) :
3853 fvalue_get_uinteger(&finfo->value);
3855 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) {
3856 gchar tmp[ITEM_LABEL_LENGTH];
3857 custom_fmt_func_t fmtfunc = (custom_fmt_func_t)hfinfo->strings;
3859 DISSECTOR_ASSERT(fmtfunc);
3860 fmtfunc(tmp, number);
3862 offset_r += protoo_strlcpy(result+offset_r, tmp, size-offset_r);
3864 } else if (hfinfo->strings) {
3865 number_out = hf_str_val = hf_try_val_to_str(number, hfinfo);
3868 number_out = hfinfo_number_value_format_display(hfinfo, BASE_DEC, number_buf, number);
3870 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
3873 number_out = hfinfo_number_value_format(hfinfo, number_buf, number);
3875 offset_r += protoo_strlcpy(result+offset_r, number_out, size-offset_r);
3878 if (hf_str_val && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
3879 g_snprintf(expr+offset_e, size-offset_e, "\"%s\"", hf_str_val);
3881 number_out = hfinfo_numeric_value_format(hfinfo, number_buf, number);
3883 g_strlcpy(expr+offset_e, number_out, size-offset_e);
3886 offset_e = (int)strlen(expr);
3890 /* XXX: Should handle BASE_CUSTOM ? */
3891 g_snprintf(result+offset_r, size-offset_r,
3892 "%" G_GINT64_MODIFIER "d",
3893 fvalue_get_integer64(&finfo->value));
3894 offset_r = (int)strlen(result);
3897 g_snprintf(result+offset_r, size-offset_r,
3898 /* XXX: Should handle BASE_CUSTOM ? */
3899 "%" G_GINT64_MODIFIER "u",
3900 fvalue_get_integer64(&finfo->value));
3901 offset_r = (int)strlen(result);
3904 offset_r += protoo_strlcpy(result+offset_r,
3905 eui64_to_str(fvalue_get_integer64(&finfo->value)),
3910 ipv4 = (ipv4_addr *)fvalue_get(&finfo->value);
3911 n_addr = ipv4_get_net_order_addr(ipv4);
3912 offset_r += protoo_strlcpy(result+offset_r,
3913 ip_to_str((guint8 *)&n_addr),
3918 ipv6 = (struct e_in6_addr *)fvalue_get(&finfo->value);
3919 SET_ADDRESS (&addr, AT_IPv6, sizeof(struct e_in6_addr), ipv6);
3920 address_to_str_buf(&addr, result+offset_r, size-offset_r);
3921 offset_r = (int)strlen(result);
3925 offset_r += protoo_strlcpy(result+offset_r,
3926 bytes_to_str_punct((const guint8 *)fvalue_get(&finfo->value),
3932 offset_r += protoo_strlcpy(result+offset_r,
3933 guid_to_str((e_guid_t *)fvalue_get(&finfo->value)),
3938 bytes = (guint8 *)fvalue_get(&finfo->value);
3939 offset_r += protoo_strlcpy(result+offset_r,
3940 rel_oid_resolved_from_encoded(bytes,
3941 fvalue_length(&finfo->value)),
3943 offset_e += protoo_strlcpy(expr+offset_e,
3944 rel_oid_encoded2string(bytes, fvalue_length(&finfo->value)),
3949 bytes = (guint8 *)fvalue_get(&finfo->value);
3950 offset_r += protoo_strlcpy(result+offset_r,
3951 oid_resolved_from_encoded(bytes,
3952 fvalue_length(&finfo->value)),
3954 offset_e += protoo_strlcpy(expr+offset_e,
3955 oid_encoded2string(bytes, fvalue_length(&finfo->value)),
3960 g_snprintf(result+offset_r, size-offset_r,
3961 "%." G_STRINGIFY(FLT_DIG) "g", fvalue_get_floating(&finfo->value));
3962 offset_r = (int)strlen(result);
3966 g_snprintf(result+offset_r, size-offset_r,
3967 "%." G_STRINGIFY(DBL_DIG) "g", fvalue_get_floating(&finfo->value));
3968 offset_r = (int)strlen(result);
3973 case FT_UINT_STRING:
3974 bytes = (guint8 *)fvalue_get(&finfo->value);
3975 offset_r += protoo_strlcpy(result+offset_r,
3976 hfinfo_format_text(hfinfo, bytes),
3980 case FT_IPXNET: /*XXX really No column custom ?*/
3983 g_error("hfinfo->type %d (%s) not handled\n",
3985 ftype_name(hfinfo->type));
3986 DISSECTOR_ASSERT_NOT_REACHED();
3992 switch (hfinfo->type) {
4006 /* for these types, "expr" is filled in the loop above */
4010 /* for all others, just copy "result" to "expr" */
4011 g_strlcpy(expr, result, size);
4016 /* Store abbrev for return value */
4017 abbrev = hfinfo->abbrev;
4020 if (occurrence == 0) {
4021 /* Fetch next hfinfo with same name (abbrev) */
4022 hfinfo = hfinfo_same_name_get_prev(hfinfo);
4028 return abbrev ? abbrev : "";
4032 /* Set text of proto_item after having already been created. */
4034 proto_item_set_text(proto_item *pi, const char *format, ...)
4036 field_info *fi = NULL;
4043 fi = PITEM_FINFO(pi);
4048 ITEM_LABEL_FREE(PNODE_POOL(pi), fi->rep);
4052 va_start(ap, format);
4053 proto_tree_set_representation(pi, format, ap);
4057 /* Append to text of proto_item after having already been created. */
4059 proto_item_append_text(proto_item *pi, const char *format, ...)
4061 field_info *fi = NULL;
4069 fi = PITEM_FINFO(pi);
4074 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4076 * If we don't already have a representation,
4077 * generate the default representation.
4079 if (fi->rep == NULL) {
4080 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
4081 proto_item_fill_label(fi, fi->rep->representation);
4084 curlen = strlen(fi->rep->representation);
4085 if (ITEM_LABEL_LENGTH > curlen) {
4086 va_start(ap, format);
4087 g_vsnprintf(fi->rep->representation + curlen,
4088 ITEM_LABEL_LENGTH - (gulong) curlen, format, ap);
4094 /* Prepend to text of proto_item after having already been created. */
4096 proto_item_prepend_text(proto_item *pi, const char *format, ...)
4098 field_info *fi = NULL;
4099 char representation[ITEM_LABEL_LENGTH];
4106 fi = PITEM_FINFO(pi);
4111 if (!PROTO_ITEM_IS_HIDDEN(pi)) {
4113 * If we don't already have a representation,
4114 * generate the default representation.
4116 if (fi->rep == NULL) {
4117 ITEM_LABEL_NEW(PNODE_POOL(pi), fi->rep);
4118 proto_item_fill_label(fi, representation);
4120 g_strlcpy(representation, fi->rep->representation, ITEM_LABEL_LENGTH);
4122 va_start(ap, format);
4123 g_vsnprintf(fi->rep->representation,
4124 ITEM_LABEL_LENGTH, format, ap);
4126 g_strlcat(fi->rep->representation, representation, ITEM_LABEL_LENGTH);
4131 proto_item_set_len(proto_item *pi, const gint length)
4138 fi = PITEM_FINFO(pi);
4142 DISSECTOR_ASSERT(length >= 0);
4143 fi->length = length;
4146 * You cannot just make the "len" field of a GByteArray
4147 * larger, if there's no data to back that length;
4148 * you can only make it smaller.
4150 if (fi->value.ftype->ftype == FT_BYTES && length <= (gint)fi->value.value.bytes->len)
4151 fi->value.value.bytes->len = length;
4155 * Sets the length of the item based on its start and on the specified
4156 * offset, which is the offset past the end of the item; as the start
4157 * in the item is relative to the beginning of the data source tvbuff,
4158 * we need to pass in a tvbuff - the end offset is relative to the beginning
4162 proto_item_set_end(proto_item *pi, tvbuff_t *tvb, gint end)
4169 fi = PITEM_FINFO(pi);
4173 end += tvb_raw_offset(tvb);
4174 DISSECTOR_ASSERT(end >= fi->start);
4175 fi->length = end - fi->start;
4179 proto_item_get_len(const proto_item *pi)
4181 field_info *fi = PITEM_FINFO(pi);
4182 return fi ? fi->length : -1;
4186 proto_tree_create_root(packet_info *pinfo)
4190 /* Initialize the proto_node */
4191 pnode = g_slice_new(proto_tree);
4192 PROTO_NODE_INIT(pnode);
4193 pnode->parent = NULL;
4194 PNODE_FINFO(pnode) = NULL;
4195 pnode->tree_data = g_slice_new(tree_data_t);
4197 /* Make sure we can access pinfo everywhere */
4198 pnode->tree_data->pinfo = pinfo;
4200 /* Don't initialize the tree_data_t. Wait until we know we need it */
4201 pnode->tree_data->interesting_hfids = NULL;
4203 /* Set the default to FALSE so it's easier to
4204 * find errors; if we expect to see the protocol tree
4205 * but for some reason the default 'visible' is not
4206 * changed, then we'll find out very quickly. */
4207 pnode->tree_data->visible = FALSE;
4209 /* Make sure that we fake protocols (if possible) */
4210 pnode->tree_data->fake_protocols = TRUE;
4212 /* Keep track of the number of children */
4213 pnode->tree_data->count = 0;
4215 return (proto_tree *)pnode;
4219 /* "prime" a proto_tree with a single hfid that a dfilter
4220 * is interested in. */
4222 proto_tree_prime_hfid(proto_tree *tree _U_, const gint hfid)
4224 header_field_info *hfinfo;
4226 PROTO_REGISTRAR_GET_NTH(hfid, hfinfo);
4227 /* this field is referenced by a filter so increase the refcount.
4228 also increase the refcount for the parent, i.e the protocol.
4230 hfinfo->ref_type = HF_REF_TYPE_DIRECT;
4231 /* only increase the refcount if there is a parent.
4232 if this is a protocol and not a field then parent will be -1
4233 and there is no parent to add any refcounting for.
4235 if (hfinfo->parent != -1) {
4236 header_field_info *parent_hfinfo;
4237 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
4239 /* Mark parent as indirectly referenced unless it is already directly
4240 * referenced, i.e. the user has specified the parent in a filter.
4242 if (parent_hfinfo->ref_type != HF_REF_TYPE_DIRECT)
4243 parent_hfinfo->ref_type = HF_REF_TYPE_INDIRECT;
4248 proto_item_add_subtree(proto_item *pi, const gint idx) {
4254 DISSECTOR_ASSERT(idx >= 0 && idx < num_tree_types);
4256 fi = PITEM_FINFO(pi);
4258 return (proto_tree *)pi;
4260 fi->tree_type = idx;
4262 return (proto_tree *)pi;
4266 proto_item_get_subtree(const proto_item *pi) {
4271 fi = PITEM_FINFO(pi);
4272 if ( (!fi) || (fi->tree_type == -1) )
4274 return (proto_tree *)pi;
4278 proto_item_get_parent(const proto_item *ti) {
4285 proto_item_get_parent_nth(proto_item *ti, int gen) {
4298 proto_tree_get_parent(const proto_tree *tree) {
4301 return (proto_item *)tree;
4305 proto_tree_get_root(proto_tree *tree) {
4308 while (tree->parent) {
4309 tree = tree->parent;
4315 proto_tree_move_item(proto_tree *tree, proto_item *fixed_item,
4316 proto_item *item_to_move)
4319 /* Revert part of: http://anonsvn.wireshark.org/viewvc?view=rev&revision=32443
4320 * See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5500
4322 /* This function doesn't generate any values. It only reorganizes the prococol tree
4323 * so we can bail out immediately if it isn't visible. */
4324 if (!tree || !PTREE_DATA(tree)->visible)
4327 DISSECTOR_ASSERT(item_to_move->parent == tree);
4328 DISSECTOR_ASSERT(fixed_item->parent == tree);
4330 /*** cut item_to_move out ***/
4332 /* is item_to_move the first? */
4333 if (tree->first_child == item_to_move) {
4334 /* simply change first child to next */
4335 tree->first_child = item_to_move->next;
4337 DISSECTOR_ASSERT(tree->last_child != item_to_move);
4339 proto_item *curr_item;
4340 /* find previous and change it's next */
4341 for(curr_item = tree->first_child; curr_item != NULL; curr_item = curr_item->next) {
4342 if (curr_item->next == item_to_move) {
4347 DISSECTOR_ASSERT(curr_item);
4349 curr_item->next = item_to_move->next;
4351 /* fix last_child if required */
4352 if (tree->last_child == item_to_move) {
4353 tree->last_child = curr_item;
4357 /*** insert to_move after fixed ***/
4358 item_to_move->next = fixed_item->next;
4359 fixed_item->next = item_to_move;
4360 if (tree->last_child == fixed_item) {
4361 tree->last_child = item_to_move;
4366 proto_tree_set_appendix(proto_tree *tree, tvbuff_t *tvb, gint start,
4374 fi = PTREE_FINFO(tree);
4378 start += tvb_raw_offset(tvb);
4379 DISSECTOR_ASSERT(start >= 0);
4380 DISSECTOR_ASSERT(length >= 0);
4382 fi->appendix_start = start;
4383 fi->appendix_length = length;
4387 proto_register_protocol(const char *name, const char *short_name,
4388 const char *filter_name)
4390 protocol_t *protocol, *existing_protocol = NULL;
4391 header_field_info *hfinfo;
4393 char *existing_name;
4397 gboolean found_invalid;
4400 * Make sure there's not already a protocol with any of those
4401 * names. Crash if there is, as that's an error in the code
4402 * or an inappropriate plugin.
4403 * This situation has to be fixed to not register more than one
4404 * protocol with the same name.
4406 * This is done by reducing the number of strcmp (and alike) calls
4407 * as much as possible, as this significally slows down startup time.
4409 * Drawback: As a hash value is used to reduce insert time,
4410 * this might lead to a hash collision.
4411 * However, although we have somewhat over 1000 protocols, we're using
4412 * a 32 bit int so this is very, very unlikely.
4415 key = (gint *)g_malloc (sizeof(gint));
4416 *key = wrs_str_hash(name);
4418 existing_name = (char *)g_hash_table_lookup(proto_names, key);
4419 if (existing_name != NULL) {
4420 /* g_error will terminate the program */
4421 g_error("Duplicate protocol name \"%s\"!"
4422 " This might be caused by an inappropriate plugin or a development error.", name);
4424 g_hash_table_insert(proto_names, key, (gpointer)name);
4426 existing_name = (char *)g_hash_table_lookup(proto_short_names, (gpointer)short_name);
4427 if (existing_name != NULL) {
4428 g_error("Duplicate protocol short_name \"%s\"!"
4429 " This might be caused by an inappropriate plugin or a development error.", short_name);
4431 g_hash_table_insert(proto_short_names, (gpointer)short_name, (gpointer)short_name);
4433 found_invalid = FALSE;
4434 for (i = 0; filter_name[i]; i++) {
4436 if (!(islower(c) || isdigit(c) || c == '-' || c == '_' || c == '.')) {
4437 found_invalid = TRUE;
4440 if (found_invalid) {
4441 g_error("Protocol filter name \"%s\" has one or more invalid characters."
4442 " Allowed are lower characters, digits, '-', '_' and '.'."
4443 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4445 existing_protocol = (protocol_t *)g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
4446 if (existing_protocol != NULL) {
4447 g_error("Duplicate protocol filter_name \"%s\"!"
4448 " This might be caused by an inappropriate plugin or a development error.", filter_name);
4451 /* Add this protocol to the list of known protocols; the list
4452 is sorted by protocol short name. */
4453 protocol = g_new(protocol_t, 1);
4454 protocol->name = name;
4455 protocol->short_name = short_name;
4456 protocol->filter_name = filter_name;
4457 protocol->fields = NULL;
4458 protocol->is_enabled = TRUE; /* protocol is enabled by default */
4459 protocol->can_toggle = TRUE;
4460 protocol->is_private = FALSE;
4461 /* list will be sorted later by name, when all protocols completed registering */
4462 protocols = g_list_prepend(protocols, protocol);
4463 g_hash_table_insert(proto_filter_names, (gpointer)filter_name, protocol);
4465 /* Here we allocate a new header_field_info struct */
4466 hfinfo = g_slice_new(header_field_info);
4467 hfinfo->name = name;
4468 hfinfo->abbrev = filter_name;
4469 hfinfo->type = FT_PROTOCOL;
4470 hfinfo->display = BASE_NONE;
4471 hfinfo->strings = protocol;
4472 hfinfo->bitmask = 0;
4473 hfinfo->ref_type = HF_REF_TYPE_NONE;
4474 hfinfo->blurb = NULL;
4475 hfinfo->parent = -1; /* this field differentiates protos and fields */
4477 proto_id = proto_register_field_init(hfinfo, hfinfo->parent);
4478 protocol->proto_id = proto_id;
4483 proto_mark_private(const int proto_id)
4485 protocol_t *protocol = find_protocol_by_id(proto_id);
4487 protocol->is_private = TRUE;
4491 proto_is_private(const int proto_id)
4493 protocol_t *protocol = find_protocol_by_id(proto_id);
4495 return protocol->is_private;
4501 * Routines to use to iterate over the protocols.
4502 * The argument passed to the iterator routines is an opaque cookie to
4503 * their callers; it's the GList pointer for the current element in
4505 * The ID of the protocol is returned, or -1 if there is no protocol.
4508 proto_get_first_protocol(void **cookie)
4510 protocol_t *protocol;
4512 if (protocols == NULL)
4514 *cookie = protocols;
4515 protocol = (protocol_t *)protocols->data;
4516 return protocol->proto_id;
4520 proto_get_data_protocol(void *cookie)
4522 GList *list_item = (GList *)cookie;
4524 protocol_t *protocol = (protocol_t *)list_item->data;
4525 return protocol->proto_id;
4529 proto_get_next_protocol(void **cookie)
4531 GList *list_item = (GList *)*cookie;
4532 protocol_t *protocol;
4534 list_item = g_list_next(list_item);
4535 if (list_item == NULL)
4537 *cookie = list_item;
4538 protocol = (protocol_t *)list_item->data;
4539 return protocol->proto_id;
4543 proto_get_first_protocol_field(const int proto_id, void **cookie)
4545 protocol_t *protocol = find_protocol_by_id(proto_id);
4547 if ((protocol == NULL) || (protocol->fields == NULL))
4550 *cookie = protocol->fields;
4551 return (header_field_info *)protocol->fields->data;
4555 proto_get_next_protocol_field(void **cookie)
4557 GSList *list_item = (GSList *)*cookie;
4559 list_item = g_slist_next(list_item);
4560 if (list_item == NULL)
4563 *cookie = list_item;
4564 return (header_field_info *)list_item->data;
4568 find_protocol_by_id(const int proto_id)
4570 header_field_info *hfinfo;
4575 PROTO_REGISTRAR_GET_NTH(proto_id, hfinfo);
4576 DISSECTOR_ASSERT(hfinfo->type == FT_PROTOCOL);
4577 return (protocol_t *)hfinfo->strings;
4581 proto_get_id(const protocol_t *protocol)
4583 return protocol->proto_id;
4586 int proto_get_id_by_filter_name(const gchar* filter_name)
4588 protocol_t *protocol = NULL;
4591 fprintf(stderr, "No filter name present");
4592 DISSECTOR_ASSERT(filter_name);
4595 protocol = (protocol_t *)g_hash_table_lookup(proto_filter_names, (gpointer)filter_name);
4597 if (protocol == NULL)
4599 return protocol->proto_id;
4603 proto_get_protocol_name(const int proto_id)
4605 protocol_t *protocol;
4607 protocol = find_protocol_by_id(proto_id);
4609 if (protocol == NULL)
4611 return protocol->name;
4615 proto_get_protocol_short_name(const protocol_t *protocol)
4617 if (protocol == NULL)
4619 return protocol->short_name;
4623 proto_get_protocol_long_name(const protocol_t *protocol)
4625 if (protocol == NULL)
4627 return protocol->name;
4631 proto_get_protocol_filter_name(const int proto_id)
4633 protocol_t *protocol;
4635 protocol = find_protocol_by_id(proto_id);
4636 if (protocol == NULL)
4638 return protocol->filter_name;
4642 proto_get_frame_protocols(const wmem_list_t *layers, gboolean *is_ip, gboolean *is_tcp, gboolean *is_udp, gboolean *is_sctp) {
4643 wmem_list_frame_t* protos = wmem_list_head(layers);
4645 const char* proto_name;
4647 /* Walk the list of a available protocols in the packet and
4648 find "major" ones. */
4649 /* It might make more sense to assemble and return a bitfield. */
4650 while (protos != NULL)
4652 proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
4653 proto_name = proto_get_protocol_filter_name(proto_id);
4655 if (is_ip && ((!strcmp(proto_name, "ip")) ||
4656 (!strcmp(proto_name, "ipv6")))) {
4658 } else if (is_tcp && !strcmp(proto_name, "tcp")) {
4660 } else if (is_udp && !strcmp(proto_name, "udp")) {
4662 } else if (is_sctp && !strcmp(proto_name, "sctp")) {
4666 protos = wmem_list_frame_next(protos);
4671 proto_is_protocol_enabled(const protocol_t *protocol)
4673 return protocol->is_enabled;
4677 proto_can_toggle_protocol(const int proto_id)
4679 protocol_t *protocol;
4681 protocol = find_protocol_by_id(proto_id);
4682 return protocol->can_toggle;
4686 proto_set_decoding(const int proto_id, const gboolean enabled)
4688 protocol_t *protocol;
4690 protocol = find_protocol_by_id(proto_id);
4691 DISSECTOR_ASSERT(protocol->can_toggle);
4692 protocol->is_enabled = enabled;
4696 proto_enable_all(void)
4698 protocol_t *protocol;
4699 GList *list_item = protocols;
4701 if (protocols == NULL)
4705 protocol = (protocol_t *)list_item->data;
4706 if (protocol->can_toggle)
4707 protocol->is_enabled = TRUE;
4708 list_item = g_list_next(list_item);
4713 proto_set_cant_toggle(const int proto_id)
4715 protocol_t *protocol;
4717 protocol = find_protocol_by_id(proto_id);
4718 protocol->can_toggle = FALSE;
4722 proto_register_field_common(protocol_t *proto, header_field_info *hfi, const int parent)
4724 if (proto != NULL) {
4725 if (proto->fields == NULL) {
4726 proto->fields = g_slist_append(NULL, hfi);
4727 proto->last_field = proto->fields;
4730 g_slist_append(proto->last_field, hfi)->next;
4734 return proto_register_field_init(hfi, parent);
4737 /* for use with static arrays only, since we don't allocate our own copies
4738 of the header_field_info struct contained within the hf_register_info struct */
4740 proto_register_field_array(const int parent, hf_register_info *hf, const int num_records)
4742 hf_register_info *ptr = hf;
4746 proto = find_protocol_by_id(parent);
4747 for (i = 0; i < num_records; i++, ptr++) {
4749 * Make sure we haven't registered this yet.
4750 * Most fields have variables associated with them
4751 * that are initialized to -1; some have array elements,
4752 * or possibly uninitialized variables, so we also allow
4753 * 0 (which is unlikely to be the field ID we get back
4754 * from "proto_register_field_init()").
4756 if (*ptr->p_id != -1 && *ptr->p_id != 0) {
4758 "Duplicate field detected in call to proto_register_field_array: %s is already registered\n",
4759 ptr->hfinfo.abbrev);
4763 *ptr->p_id = proto_register_field_common(proto, &ptr->hfinfo, parent);
4768 proto_register_fields_section(const int parent, header_field_info *hfi, const int num_records)
4773 proto = find_protocol_by_id(parent);
4774 for (i = 0; i < num_records; i++) {
4776 * Make sure we haven't registered this yet.
4778 if (hfi[i].id != -1) {
4780 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
4785 proto_register_field_common(proto, &hfi[i], parent);
4790 proto_register_fields_manual(const int parent, header_field_info **hfi, const int num_records)
4795 proto = find_protocol_by_id(parent);
4796 for (i = 0; i < num_records; i++) {
4798 * Make sure we haven't registered this yet.
4800 if (hfi[i]->id != -1) {
4802 "Duplicate field detected in call to proto_register_fields: %s is already registered\n",
4807 proto_register_field_common(proto, hfi[i], parent);
4811 /* unregister already registered fields */
4813 proto_unregister_field (const int parent, gint hf_id)
4815 hf_register_info *hf;
4819 if (hf_id == -1 || hf_id == 0)
4822 proto = find_protocol_by_id (parent);
4823 if (!proto || !proto->fields) {
4827 for (field = proto->fields; field; field = field->next) {
4828 hf = (hf_register_info *)field->data;
4829 if (*hf->p_id == hf_id) {
4830 /* Found the hf_id in this protocol */
4831 g_tree_steal (gpa_name_tree, hf->hfinfo.abbrev);
4832 /* XXX, memleak? g_slist_delete_link() */
4833 proto->fields = g_slist_remove_link (proto->fields, field);
4834 proto->last_field = g_slist_last (proto->fields);
4840 /* chars allowed in field abbrev */
4842 const guchar fld_abbrev_chars[256] = {
4843 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x0F */
4844 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x1F */
4845 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, /* 0x20-0x2F '-', '.' */
4846 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0x30-0x3F '0'-'9' */
4847 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F 'A'-'O' */
4848 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 0x50-0x5F 'P'-'Z', '_' */
4849 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F 'a'-'o' */
4850 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 0x70-0x7F 'p'-'z' */
4851 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */
4852 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */
4853 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */
4854 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */
4855 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0-0xCF */
4856 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0-0xDF */
4857 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0-0xEF */
4858 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */
4861 static const value_string hf_types[] = {
4862 { FT_NONE, "FT_NONE" },
4863 { FT_PROTOCOL, "FT_PROTOCOL" },
4864 { FT_BOOLEAN, "FT_BOOLEAN" },
4865 { FT_UINT8, "FT_UINT8" },
4866 { FT_UINT16, "FT_UINT16" },
4867 { FT_UINT24, "FT_UINT24" },
4868 { FT_UINT32, "FT_UINT32" },
4869 { FT_UINT64, "FT_UINT64" },
4870 { FT_INT8, "FT_INT8" },
4871 { FT_INT16, "FT_INT16" },
4872 { FT_INT24, "FT_INT24" },
4873 { FT_INT32, "FT_INT32" },
4874 { FT_INT64, "FT_INT64" },
4875 { FT_EUI64, "FT_EUI64" },
4876 { FT_FLOAT, "FT_FLOAT" },
4877 { FT_DOUBLE, "FT_DOUBLE" },
4878 { FT_ABSOLUTE_TIME, "FT_ABSOLUTE_TIME" },
4879 { FT_RELATIVE_TIME, "FT_RELATIVE_TIME" },
4880 { FT_STRING, "FT_STRING" },
4881 { FT_STRINGZ, "FT_STRINGZ" },
4882 { FT_UINT_STRING, "FT_UINT_STRING" },
4883 { FT_ETHER, "FT_ETHER" },
4884 { FT_BYTES, "FT_BYTES" },
4885 { FT_UINT_BYTES, "FT_UINT_BYTES" },
4886 { FT_IPv4, "FT_IPv4" },
4887 { FT_IPv6, "FT_IPv6" },
4888 { FT_IPXNET, "FT_IPXNET" },
4889 { FT_FRAMENUM, "FT_FRAMENUM" },
4890 { FT_PCRE, "FT_PCR" },
4891 { FT_GUID, "FT_GUID" },
4892 { FT_OID, "FT_OID" },
4893 { FT_REL_OID, "FT_REL_OID" },
4896 static const value_string hf_display[] = {
4897 { BASE_NONE, "BASE_NONE" },
4898 { BASE_DEC, "BASE_DEC" },
4899 { BASE_HEX, "BASE_HEX" },
4900 { BASE_OCT, "BASE_OCT" },
4901 { BASE_DEC_HEX, "BASE_DEC_HEX" },
4902 { BASE_HEX_DEC, "BASE_HEX_DEC" },
4903 { BASE_CUSTOM, "BASE_CUSTOM" },
4904 { BASE_NONE|BASE_RANGE_STRING, "BASE_NONE|BASE_RANGE_STRING" },
4905 { BASE_DEC|BASE_RANGE_STRING, "BASE_DEC|BASE_RANGE_STRING" },
4906 { BASE_HEX|BASE_RANGE_STRING, "BASE_HEX|BASE_RANGE_STRING" },
4907 { BASE_OCT|BASE_RANGE_STRING, "BASE_OCT|BASE_RANGE_STRING" },
4908 { BASE_DEC_HEX|BASE_RANGE_STRING, "BASE_DEC_HEX|BASE_RANGE_STRING" },
4909 { BASE_HEX_DEC|BASE_RANGE_STRING, "BASE_HEX_DEC|BASE_RANGE_STRING" },
4910 { BASE_CUSTOM|BASE_RANGE_STRING, "BASE_CUSTOM|BASE_RANGE_STRING" },
4911 { BASE_NONE|BASE_VAL64_STRING, "BASE_NONE|BASE_VAL64_STRING" },
4912 { BASE_DEC|BASE_VAL64_STRING, "BASE_DEC|BASE_VAL64_STRING" },
4913 { BASE_HEX|BASE_VAL64_STRING, "BASE_HEX|BASE_VAL64_STRING" },
4914 { BASE_OCT|BASE_VAL64_STRING, "BASE_OCT|BASE_VAL64_STRING" },
4915 { BASE_DEC_HEX|BASE_VAL64_STRING, "BASE_DEC_HEX|BASE_VAL64_STRING" },
4916 { BASE_HEX_DEC|BASE_VAL64_STRING, "BASE_HEX_DEC|BASE_VAL64_STRING" },
4917 { BASE_CUSTOM|BASE_VAL64_STRING, "BASE_CUSTOM|BASE_VAL64_STRING" },
4918 /* { STR_ASCII, "STR_ASCII" }, */
4919 { STR_UNICODE, "STR_UNICODE" },
4920 { ABSOLUTE_TIME_LOCAL, "ABSOLUTE_TIME_LOCAL" },
4921 { ABSOLUTE_TIME_UTC, "ABSOLUTE_TIME_UTC" },
4922 { ABSOLUTE_TIME_DOY_UTC, "ABSOLUTE_TIME_DOY_UTC" },
4925 /* temporary function containing assert part for easier profiling */
4927 tmp_fld_check_assert(header_field_info *hfinfo)
4930 /* The field must have a name (with length > 0) */
4931 if (!hfinfo->name || !hfinfo->name[0]) {
4933 /* Try to identify the field */
4934 g_error("Field (abbrev='%s') does not have a name\n",
4938 g_error("Field does not have a name (nor an abbreviation)\n");
4941 /* fields with an empty string for an abbreviation aren't filterable */
4942 if (!hfinfo->abbrev || !hfinfo->abbrev[0])
4943 g_error("Field '%s' does not have an abbreviation\n", hfinfo->name);
4945 /* These types of fields are allowed to have value_strings,
4946 * true_false_strings or a protocol_t struct
4948 if (hfinfo->strings != NULL && !(
4949 (hfinfo->type == FT_UINT8) ||
4950 (hfinfo->type == FT_UINT16) ||
4951 (hfinfo->type == FT_UINT24) ||
4952 (hfinfo->type == FT_UINT32) ||
4953 (hfinfo->type == FT_UINT64) ||
4954 (hfinfo->type == FT_INT8) ||
4955 (hfinfo->type == FT_INT16) ||
4956 (hfinfo->type == FT_INT24) ||
4957 (hfinfo->type == FT_INT32) ||
4958 (hfinfo->type == FT_INT64) ||
4959 (hfinfo->type == FT_BOOLEAN) ||
4960 (hfinfo->type == FT_PROTOCOL) ))
4961 g_error("Field '%s' (%s) has a 'strings' value but is of type %s"
4962 " (which is not allowed to have strings)\n",
4963 hfinfo->name, hfinfo->abbrev,
4964 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
4966 /* TODO: This check may slow down startup, and output quite a few warnings.
4967 It would be good to be able to enable this (and possibly other checks?)
4968 in non-release builds. */
4970 /* Check for duplicate value_string values.
4971 There are lots that have the same value *and* string, so for now only
4972 report those that have same value but different string. */
4973 if ((hfinfo->strings != NULL) &&
4974 !(hfinfo->display & BASE_RANGE_STRING) &&
4975 !((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_CUSTOM) &&
4977 (hfinfo->type == FT_UINT8) ||
4978 (hfinfo->type == FT_UINT16) ||
4979 (hfinfo->type == FT_UINT24) ||
4980 (hfinfo->type == FT_UINT32) ||
4981 (hfinfo->type == FT_INT8) ||
4982 (hfinfo->type == FT_INT16) ||
4983 (hfinfo->type == FT_INT24) ||
4984 (hfinfo->type == FT_INT32) ||
4985 (hfinfo->type == FT_FRAMENUM) )) {
4988 const value_string *start_values;
4989 const value_string *current;
4991 if (hfinfo->display & BASE_EXT_STRING)
4992 start_values = VALUE_STRING_EXT_VS_P(((const value_string_ext*)hfinfo->strings));
4994 start_values = (const value_string*)hfinfo->strings;
4995 current = start_values;
4997 for (n=0; current; n++, current++) {
4998 /* Drop out if we reached the end. */
4999 if ((current->value == 0) && (current->strptr == NULL)) {
5003 /* Check value against all previous */
5004 for (m=0; m < n; m++) {
5005 /* There are lots of duplicates with the same string,
5006 so only report if different... */
5007 if ((start_values[m].value == current->value) &&
5008 (strcmp(start_values[m].strptr, current->strptr) != 0)) {
5009 g_warning("Field '%s' (%s) has a conflicting entry in its"
5010 " value_string: %u is at indices %u (%s) and %u (%s))\n",
5011 hfinfo->name, hfinfo->abbrev,
5012 current->value, m, start_values[m].strptr, n, current->strptr);
5020 switch (hfinfo->type) {
5027 /* Hexadecimal and octal are, in printf() and everywhere
5028 * else, unsigned so don't allow dissectors to register a
5029 * signed field to be displayed unsigned. (Else how would
5030 * we display negative values?)
5032 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
5037 g_error("Field '%s' (%s) is signed (%s) but is being displayed unsigned (%s)\n",
5038 hfinfo->name, hfinfo->abbrev,
5039 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5040 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5048 /* Require integral types (other than frame number,
5049 * which is always displayed in decimal) to have a
5051 * If there is a strings value then this base is not
5052 * normally used except when constructing a display
5053 * filter for a value not found in the strings lookup.
5055 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
5061 case BASE_CUSTOM: /* hfinfo_numeric_value_format() treats this as decimal */
5064 g_error("Field '%s' (%s) is an integral value (%s)"
5065 " but is being displayed as %s\n",
5066 hfinfo->name, hfinfo->abbrev,
5067 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5068 val_to_str(hfinfo->display, hf_display, "(Unknown: 0x%x)"));
5074 if (hfinfo->display != BASE_NONE)
5075 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
5076 hfinfo->name, hfinfo->abbrev,
5077 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5078 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5079 if (hfinfo->bitmask != 0)
5080 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5081 hfinfo->name, hfinfo->abbrev,
5082 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5088 case FT_ABSOLUTE_TIME:
5089 if (!(hfinfo->display == ABSOLUTE_TIME_LOCAL ||
5090 hfinfo->display == ABSOLUTE_TIME_UTC ||
5091 hfinfo->display == ABSOLUTE_TIME_DOY_UTC))
5092 g_error("Field '%s' (%s) is a %s but is being displayed as %s instead of as a time\n",
5093 hfinfo->name, hfinfo->abbrev,
5094 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5095 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5096 if (hfinfo->bitmask != 0)
5097 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5098 hfinfo->name, hfinfo->abbrev,
5099 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5104 case FT_UINT_STRING:
5105 switch (hfinfo->display) {
5111 g_error("Field '%s' (%s) is an string value (%s)"
5112 " but is being displayed as %s\n",
5113 hfinfo->name, hfinfo->abbrev,
5114 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5115 val_to_str(hfinfo->display, hf_display, "(Unknown: 0x%x)"));
5118 if (hfinfo->bitmask != 0)
5119 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5120 hfinfo->name, hfinfo->abbrev,
5121 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5122 if (hfinfo->strings != NULL)
5123 g_error("Field '%s' (%s) is an %s but has a strings value\n",
5124 hfinfo->name, hfinfo->abbrev,
5125 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5129 if (hfinfo->display != BASE_NONE)
5130 g_error("Field '%s' (%s) is an %s but is being displayed as %s instead of BASE_NONE\n",
5131 hfinfo->name, hfinfo->abbrev,
5132 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"),
5133 val_to_str(hfinfo->display, hf_display, "(Bit count: %d)"));
5134 if (hfinfo->bitmask != 0)
5135 g_error("Field '%s' (%s) is an %s but has a bitmask\n",
5136 hfinfo->name, hfinfo->abbrev,
5137 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5138 if (hfinfo->strings != NULL)
5139 g_error("Field '%s' (%s) is an %s but has a strings value\n",
5140 hfinfo->name, hfinfo->abbrev,
5141 val_to_str(hfinfo->type, hf_types, "(Unknown: %d)"));
5147 register_type_length_mismatch(void)
5149 static ei_register_info ei[] = {
5150 { &ei_type_length_mismatch_error, { "_ws.type_length.mismatch", PI_MALFORMED, PI_ERROR, "Trying to fetch X with length Y", EXPFILL }},
5151 { &ei_type_length_mismatch_warn, { "_ws.type_length.mismatch", PI_MALFORMED, PI_WARN, "Trying to fetch X with length Y", EXPFILL }},
5154 expert_module_t* expert_type_length_mismatch;
5156 proto_type_length_mismatch = proto_register_protocol("Type Length Mismatch", "Type length mismatch", "_ws.type_length");
5158 expert_type_length_mismatch = expert_register_protocol(proto_type_length_mismatch);
5159 expert_register_field_array(expert_type_length_mismatch, ei, array_length(ei));
5161 /* "Type Length Mismatch" isn't really a protocol, it's an error indication;
5162 disabling them makes no sense. */
5163 proto_set_cant_toggle(proto_type_length_mismatch);
5166 #define PROTO_PRE_ALLOC_HF_FIELDS_MEM (144000+PRE_ALLOC_EXPERT_FIELDS_MEM)
5168 proto_register_field_init(header_field_info *hfinfo, const int parent)
5171 tmp_fld_check_assert(hfinfo);
5173 hfinfo->parent = parent;
5174 hfinfo->same_name_next = NULL;
5175 hfinfo->same_name_prev_id = -1;
5177 /* if we always add and never delete, then id == len - 1 is correct */
5178 if (gpa_hfinfo.len >= gpa_hfinfo.allocated_len) {
5179 if (!gpa_hfinfo.hfi) {
5180 gpa_hfinfo.allocated_len = PROTO_PRE_ALLOC_HF_FIELDS_MEM;
5181 gpa_hfinfo.hfi = (header_field_info **)g_malloc(sizeof(header_field_info *)*PROTO_PRE_ALLOC_HF_FIELDS_MEM);
5183 gpa_hfinfo.allocated_len += 1000;
5184 gpa_hfinfo.hfi = (header_field_info **)g_realloc(gpa_hfinfo.hfi,
5185 sizeof(header_field_info *)*gpa_hfinfo.allocated_len);
5186 /*g_warning("gpa_hfinfo.allocated_len %u", gpa_hfinfo.allocated_len);*/
5189 gpa_hfinfo.hfi[gpa_hfinfo.len] = hfinfo;
5191 hfinfo->id = gpa_hfinfo.len - 1;
5193 /* if we have real names, enter this field in the name tree */
5194 if ((hfinfo->name[0] != 0) && (hfinfo->abbrev[0] != 0 )) {
5196 header_field_info *same_name_next_hfinfo;
5199 /* Check that the filter name (abbreviation) is legal;
5200 * it must contain only alphanumerics, '-', "_", and ".". */
5201 c = wrs_check_charset(fld_abbrev_chars, hfinfo->abbrev);
5203 fprintf(stderr, "Invalid character '%c' in filter name '%s'\n", c, hfinfo->abbrev);
5204 DISSECTOR_ASSERT(!c);
5207 /* We allow multiple hfinfo's to be registered under the same
5208 * abbreviation. This was done for X.25, as, depending
5209 * on whether it's modulo-8 or modulo-128 operation,
5210 * some bitfield fields may be in different bits of
5211 * a byte, and we want to be able to refer to that field
5212 * with one name regardless of whether the packets
5213 * are modulo-8 or modulo-128 packets. */
5215 same_name_hfinfo = NULL;
5217 g_tree_insert(gpa_name_tree, (gpointer) (hfinfo->abbrev), hfinfo);
5218 /* GLIB 2.x - if it is already present
5219 * the previous hfinfo with the same name is saved
5220 * to same_name_hfinfo by value destroy callback */
5221 if (same_name_hfinfo) {
5222 /* There's already a field with this name.
5223 * Put it after that field in the list of
5224 * fields with this name, then allow the code
5225 * after this if{} block to replace the old
5226 * hfinfo with the new hfinfo in the GTree. Thus,
5227 * we end up with a linked-list of same-named hfinfo's,
5228 * with the root of the list being the hfinfo in the GTree */
5229 same_name_next_hfinfo =
5230 same_name_hfinfo->same_name_next;
5232 hfinfo->same_name_next = same_name_next_hfinfo;
5233 if (same_name_next_hfinfo)
5234 same_name_next_hfinfo->same_name_prev_id = hfinfo->id;
5236 same_name_hfinfo->same_name_next = hfinfo;
5237 hfinfo->same_name_prev_id = same_name_hfinfo->id;
5245 proto_register_subtree_array(gint *const *indices, const int num_indices)
5248 gint *const *ptr = indices;
5251 * If we've already allocated the array of tree types, expand
5252 * it; this lets plugins such as mate add tree types after
5253 * the initial startup. (If we haven't already allocated it,
5254 * we don't allocate it; on the first pass, we just assign
5255 * ett values and keep track of how many we've assigned, and
5256 * when we're finished registering all dissectors we allocate
5257 * the array, so that we do only one allocation rather than
5258 * wasting CPU time and memory by growing the array for each
5259 * dissector that registers ett values.)
5261 if (tree_is_expanded != NULL) {
5262 tree_is_expanded = (guint32 *)g_realloc(tree_is_expanded, (1+((num_tree_types + num_indices)/32)) * sizeof(guint32));
5264 /* set new items to 0 */
5265 /* XXX, slow!!! optimize when needed (align 'i' to 32, and set rest of guint32 to 0) */
5266 for (i = num_tree_types; i < num_tree_types + num_indices; i++)
5267 tree_is_expanded[i >> 5] &= ~(1 << (i & 31));
5271 * Assign "num_indices" subtree numbers starting at "num_tree_types",
5272 * returning the indices through the pointers in the array whose
5273 * first element is pointed to by "indices", and update
5274 * "num_tree_types" appropriately.
5276 for (i = 0; i < num_indices; i++, ptr++, num_tree_types++) {
5278 /* g_error will terminate the program */
5279 g_error("register_subtree_array: subtree item type (ett_...) not -1 !"
5280 " This is a development error:"
5281 " Either the subtree item type has already been assigned or"
5282 " was not initialized to -1.");
5284 **ptr = num_tree_types;
5289 label_concat(char *label_str, gsize pos, const char *str)
5291 if (pos < ITEM_LABEL_LENGTH)
5292 pos += g_strlcpy(label_str + pos, str, ITEM_LABEL_LENGTH - pos);
5298 label_mark_truncated(char *label_str, gsize name_pos)
5300 static const char trunc_str[] = " [truncated]";
5301 const size_t trunc_len = sizeof(trunc_str)-1;
5303 /* ..... field_name: dataaaaaaaaaaaaa
5307 * ..... field_name [truncated]: dataaaaaaaaaaaaa */
5309 if (name_pos < ITEM_LABEL_LENGTH - trunc_len) {
5310 memmove(label_str + name_pos + trunc_len, label_str + name_pos, ITEM_LABEL_LENGTH - name_pos - trunc_len);
5311 memcpy(label_str + name_pos, trunc_str, trunc_len);
5312 label_str[ITEM_LABEL_LENGTH-1] = '\0';
5314 } else if (name_pos < ITEM_LABEL_LENGTH)
5315 g_strlcpy(label_str + name_pos, trunc_str, ITEM_LABEL_LENGTH - name_pos);
5319 label_fill(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text)
5323 /* "%s: %s", hfinfo->name, text */
5324 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
5325 pos = label_concat(label_str, pos, ": ");
5326 pos = label_concat(label_str, pos, text ? text : "(null)");
5328 if (pos >= ITEM_LABEL_LENGTH) {
5329 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5330 label_mark_truncated(label_str, name_pos);
5337 label_fill_descr(char *label_str, gsize pos, const header_field_info *hfinfo, const char *text, const char *descr)
5341 /* "%s: %s (%s)", hfinfo->name, text, descr */
5342 name_pos = pos = label_concat(label_str, pos, hfinfo->name);
5343 pos = label_concat(label_str, pos, ": ");
5344 pos = label_concat(label_str, pos, text ? text : "(null)");
5345 pos = label_concat(label_str, pos, " (");
5346 pos = label_concat(label_str, pos, descr ? descr : "(null)");
5347 pos = label_concat(label_str, pos, ")");
5349 if (pos >= ITEM_LABEL_LENGTH) {
5350 /* Uh oh, we don't have enough room. Tell the user that the field is truncated. */
5351 label_mark_truncated(label_str, name_pos);
5358 proto_item_fill_label(field_info *fi, gchar *label_str)
5360 header_field_info *hfinfo;
5366 guint32 n_addr; /* network-order IPv4 address */
5373 /* XXX: Check validity of hfinfo->type */
5377 hfinfo = fi->hfinfo;
5379 switch (hfinfo->type) {
5382 g_strlcpy(label_str, hfinfo->name, ITEM_LABEL_LENGTH);
5386 fill_label_boolean(fi, label_str);
5391 bytes = (guint8 *)fvalue_get(&fi->value);
5392 label_fill(label_str, 0, hfinfo,
5393 (bytes) ? bytes_to_str(bytes, fvalue_length(&fi->value)) : "<MISSING>");
5396 /* Four types of integers to take care of:
5397 * Bitfield, with val_string
5398 * Bitfield, w/o val_string
5399 * Non-bitfield, with val_string
5400 * Non-bitfield, w/o val_string
5406 if (hfinfo->bitmask) {
5407 fill_label_bitfield(fi, label_str, FALSE);
5409 fill_label_number(fi, label_str, FALSE);
5414 fill_label_number(fi, label_str, FALSE);
5418 fill_label_number64(fi, label_str, FALSE);
5425 if (hfinfo->bitmask) {
5426 fill_label_bitfield(fi, label_str, TRUE);
5428 fill_label_number(fi, label_str, TRUE);
5433 fill_label_number64(fi, label_str, TRUE);
5437 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5438 "%s: %." G_STRINGIFY(FLT_DIG) "g",
5439 hfinfo->name, fvalue_get_floating(&fi->value));
5443 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5444 "%s: %." G_STRINGIFY(DBL_DIG) "g",
5445 hfinfo->name, fvalue_get_floating(&fi->value));
5448 case FT_ABSOLUTE_TIME:
5449 label_fill(label_str, 0, hfinfo,
5450 abs_time_to_str((const nstime_t *)fvalue_get(&fi->value),
5451 (absolute_time_display_e)hfinfo->display, TRUE));
5454 case FT_RELATIVE_TIME:
5455 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5456 "%s: %s seconds", hfinfo->name,
5457 rel_time_to_secs_str((const nstime_t *)fvalue_get(&fi->value)));
5461 integer = fvalue_get_uinteger(&fi->value);
5462 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5463 "%s: %s (0x%08X)", hfinfo->name,
5464 get_ipxnet_name(integer), integer);
5468 bytes = (guint8 *)fvalue_get(&fi->value);
5469 label_fill_descr(label_str, 0, hfinfo,
5470 get_ax25_name(bytes),
5471 ax25_to_str(bytes));
5475 addr.type = AT_VINES;
5476 addr.len = VINES_ADDR_LEN;
5477 addr.data = (guint8 *)fvalue_get(&fi->value);
5479 g_snprintf(label_str, ITEM_LABEL_LENGTH,
5480 "%s: %s", hfinfo->name,
5481 ep_address_to_str( &addr ));
5485 bytes = (guint8 *)fvalue_get(&fi->value);
5486 label_fill_descr(label_str, 0, hfinfo,
5487 get_ether_name(bytes),
5488 ether_to_str(bytes));
5492 ipv4 = (ipv4_addr *)fvalue_get(&fi->value);
5493 n_addr = ipv4_get_net_order_addr(ipv4);
5494 label_fill_descr(label_str, 0, hfinfo,
5495 get_hostname(n_addr),
5496 ip_to_str((guint8*)&n_addr));
5500 bytes = (guint8 *)fvalue_get(&fi->value);
5501 label_fill_descr(label_str, 0, hfinfo,
5502 get_hostname6((struct e_in6_addr *)bytes),
5503 ip6_to_str((struct e_in6_addr*)bytes));
5507 guid = (e_guid_t *)fvalue_get(&fi->value);
5508 label_fill(label_str, 0, hfinfo, guid_to_str(guid));
5512 bytes = (guint8 *)fvalue_get(&fi->value);
5513 name = oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5515 label_fill_descr(label_str, 0, hfinfo,
5516 oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5518 label_fill(label_str, 0, hfinfo,
5519 oid_encoded2string(bytes, fvalue_length(&fi->value)));
5524 bytes = (guint8 *)fvalue_get(&fi->value);
5525 name = rel_oid_resolved_from_encoded(bytes, fvalue_length(&fi->value));
5527 label_fill_descr(label_str, 0, hfinfo,
5528 rel_oid_encoded2string(bytes, fvalue_length(&fi->value)), name);
5530 label_fill(label_str, 0, hfinfo,
5531 rel_oid_encoded2string(bytes, fvalue_length(&fi->value)));
5536 integer64 = fvalue_get_integer64(&fi->value);
5537 label_fill_descr(label_str, 0, hfinfo,
5538 get_eui64_name(integer64),
5539 eui64_to_str(integer64));
5543 case FT_UINT_STRING:
5544 bytes = (guint8 *)fvalue_get(&fi->value);
5545 label_fill(label_str, 0, hfinfo, hfinfo_format_text(hfinfo, bytes));
5549 g_error("hfinfo->type %d (%s) not handled\n",
5550 hfinfo->type, ftype_name(hfinfo->type));
5551 DISSECTOR_ASSERT_NOT_REACHED();
5557 fill_label_boolean(field_info *fi, gchar *label_str)
5559 char *p = label_str;
5560 int bitfield_byte_length = 0, bitwidth;
5561 guint32 unshifted_value;
5564 header_field_info *hfinfo = fi->hfinfo;
5565 const true_false_string *tfstring = (const true_false_string *)&tfs_true_false;
5567 if (hfinfo->strings) {
5568 tfstring = (const struct true_false_string*) hfinfo->strings;
5571 value = fvalue_get_uinteger(&fi->value);
5572 if (hfinfo->bitmask) {
5573 /* Figure out the bit width */
5574 bitwidth = hfinfo_bitwidth(hfinfo);
5577 unshifted_value = value;
5578 unshifted_value <<= hfinfo_bitshift(hfinfo);
5580 /* Create the bitfield first */
5581 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5582 bitfield_byte_length = (int) (p - label_str);
5585 /* Fill in the textual info */
5586 label_fill(label_str, bitfield_byte_length, hfinfo, value ? tfstring->true_string : tfstring->false_string);
5590 hf_try_val_to_str(guint32 value, const header_field_info *hfinfo)
5592 if (hfinfo->display & BASE_RANGE_STRING)
5593 return try_rval_to_str(value, (const range_string *) hfinfo->strings);
5595 if (hfinfo->display & BASE_EXT_STRING)
5596 return try_val_to_str_ext(value, (const value_string_ext *) hfinfo->strings);
5598 if (hfinfo->display & BASE_VAL64_STRING)
5599 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
5601 return try_val_to_str(value, (const value_string *) hfinfo->strings);
5605 hf_try_val64_to_str(guint64 value, const header_field_info *hfinfo)
5607 if (hfinfo->display & BASE_VAL64_STRING)
5608 return try_val64_to_str(value, (const val64_string *) hfinfo->strings);
5610 /* If this is reached somebody registered a 64-bit field with a 32-bit
5611 * value-string, which isn't right. */
5612 DISSECTOR_ASSERT_NOT_REACHED();
5614 /* This is necessary to squelch MSVC errors; is there
5615 any way to tell it that DISSECTOR_ASSERT_NOT_REACHED()
5621 hf_try_val_to_str_const(guint32 value, const header_field_info *hfinfo, const char *unknown_str)
5623 const char *str = hf_try_val_to_str(value, hfinfo);
5625 return (str) ? str : unknown_str;
5629 hf_try_val64_to_str_const(guint64 value, const header_field_info *hfinfo, const char *unknown_str)
5631 const char *str = hf_try_val64_to_str(value, hfinfo);
5633 return (str) ? str : unknown_str;
5636 /* Fills data for bitfield ints with val_strings */
5638 fill_label_bitfield(field_info *fi, gchar *label_str, gboolean is_signed)
5641 int bitfield_byte_length, bitwidth;
5642 guint32 unshifted_value;
5648 header_field_info *hfinfo = fi->hfinfo;
5650 /* Figure out the bit width */
5651 bitwidth = hfinfo_bitwidth(hfinfo);
5655 unshifted_value = fvalue_get_sinteger(&fi->value);
5657 unshifted_value = fvalue_get_uinteger(&fi->value);
5659 value = unshifted_value;
5660 if (hfinfo->bitmask) {
5661 unshifted_value <<= hfinfo_bitshift(hfinfo);
5664 /* Create the bitfield first */
5665 p = decode_bitfield_value(label_str, unshifted_value, hfinfo->bitmask, bitwidth);
5666 bitfield_byte_length = (int) (p - label_str);
5668 /* Fill in the textual info using stored (shifted) value */
5669 if (hfinfo->display == BASE_CUSTOM) {
5670 gchar tmp[ITEM_LABEL_LENGTH];
5671 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
5673 DISSECTOR_ASSERT(fmtfunc);
5674 fmtfunc(tmp, value);
5675 label_fill(label_str, bitfield_byte_length, hfinfo, tmp);
5677 else if (hfinfo->strings) {
5678 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
5680 out = hfinfo_number_vals_format(hfinfo, buf, value);
5681 if (out == NULL) /* BASE_NONE so don't put integer in descr */
5682 label_fill(label_str, bitfield_byte_length, hfinfo, val_str);
5684 label_fill_descr(label_str, bitfield_byte_length, hfinfo, val_str, out);
5687 out = hfinfo_number_value_format(hfinfo, buf, value);
5689 label_fill(label_str, bitfield_byte_length, hfinfo, out);
5694 fill_label_number(field_info *fi, gchar *label_str, gboolean is_signed)
5696 header_field_info *hfinfo = fi->hfinfo;
5703 value = fvalue_get_sinteger(&fi->value);
5705 value = fvalue_get_uinteger(&fi->value);
5707 /* Fill in the textual info */
5708 if (hfinfo->display == BASE_CUSTOM) {
5709 gchar tmp[ITEM_LABEL_LENGTH];
5710 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hfinfo->strings;
5712 DISSECTOR_ASSERT(fmtfunc);
5713 fmtfunc(tmp, value);
5714 label_fill(label_str, 0, hfinfo, tmp);
5716 else if (hfinfo->strings) {
5717 const char *val_str = hf_try_val_to_str_const(value, hfinfo, "Unknown");
5719 out = hfinfo_number_vals_format(hfinfo, buf, value);
5720 if (out == NULL) /* BASE_NONE so don't put integer in descr */
5721 label_fill(label_str, 0, hfinfo, val_str);
5723 label_fill_descr(label_str, 0, hfinfo, val_str, out);
5726 out = hfinfo_number_value_format(hfinfo, buf, value);
5728 label_fill(label_str, 0, hfinfo, out);
5733 fill_label_number64(field_info *fi, gchar *label_str, gboolean is_signed)
5735 const char *format = NULL;
5736 header_field_info *hfinfo = fi->hfinfo;
5738 char tmp[ITEM_LABEL_LENGTH+1];
5740 /* Pick the proper format string */
5742 format = hfinfo_int64_format(hfinfo);
5744 format = hfinfo_uint64_format(hfinfo);
5746 value = fvalue_get_integer64(&fi->value);
5748 /* Format the temporary string */
5749 if (IS_BASE_DUAL(hfinfo->display))
5750 g_snprintf(tmp, ITEM_LABEL_LENGTH, format, value, value);
5752 g_snprintf(tmp, ITEM_LABEL_LENGTH, format, value);
5754 if (hfinfo->strings) {
5755 const char *val_str = hf_try_val64_to_str_const(value, hfinfo, "Unknown");
5757 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
5758 label_fill(label_str, 0, hfinfo, val_str);
5761 label_fill_descr(label_str, 0, hfinfo, val_str, tmp);
5765 label_fill(label_str, 0, hfinfo, tmp);
5770 hfinfo_bitshift(const header_field_info *hfinfo)
5772 return ws_ctz(hfinfo->bitmask);
5776 hfinfo_bitwidth(const header_field_info *hfinfo)
5780 if (!hfinfo->bitmask) {
5784 switch (hfinfo->type) {
5802 bitwidth = hfinfo->display; /* hacky? :) */
5805 DISSECTOR_ASSERT_NOT_REACHED();
5812 _hfinfo_type_hex_octet(int type)
5832 DISSECTOR_ASSERT_NOT_REACHED();
5839 hfinfo_number_value_format_display(const header_field_info *hfinfo, int display, char buf[32], guint32 value)
5841 char *ptr = &buf[31];
5842 gboolean isint = IS_FT_INT(hfinfo->type);
5845 /* Properly format value */
5848 return isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5852 ptr = hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5855 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5859 return oct_to_str_back(ptr, value);
5862 return hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5866 ptr = isint ? int_to_str_back(ptr, (gint32) value) : uint_to_str_back(ptr, value);
5869 ptr = hex_to_str_back(ptr, _hfinfo_type_hex_octet(hfinfo->type), value);
5873 DISSECTOR_ASSERT_NOT_REACHED();
5880 hfinfo_number_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
5882 int display = hfinfo->display;
5884 if (hfinfo->type == FT_FRAMENUM) {
5886 * Frame numbers are always displayed in decimal.
5891 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5895 hfinfo_numeric_value_format(const header_field_info *hfinfo, char buf[32], guint32 value)
5897 /* Get the underlying BASE_ value */
5898 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
5900 if (hfinfo->type == FT_FRAMENUM) {
5902 * Frame numbers are always displayed in decimal.
5909 /* case BASE_DEC: */
5911 case BASE_OCT: /* XXX, why we're changing BASE_OCT to BASE_DEC? */
5916 /* case BASE_HEX: */
5922 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5926 hfinfo_number_vals_format(const header_field_info *hfinfo, char buf[32], guint32 value)
5928 /* Get the underlying BASE_ value */
5929 int display = hfinfo->display & FIELD_DISPLAY_E_MASK;
5931 if (display == BASE_NONE)
5934 if (display == BASE_DEC_HEX)
5936 if (display == BASE_HEX_DEC)
5939 return hfinfo_number_value_format_display(hfinfo, display, buf, value);
5943 hfinfo_uint64_format(const header_field_info *hfinfo)
5945 const char *format = NULL;
5947 /* Pick the proper format string */
5948 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
5950 format = "%" G_GINT64_MODIFIER "u";
5953 format = "%" G_GINT64_MODIFIER "u (0x%016" G_GINT64_MODIFIER "x)";
5955 case BASE_OCT: /* I'm lazy */
5956 format = "%#" G_GINT64_MODIFIER "o";
5959 format = "0x%016" G_GINT64_MODIFIER "x";
5962 format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "u)";
5965 DISSECTOR_ASSERT_NOT_REACHED();
5972 hfinfo_int64_format(const header_field_info *hfinfo)
5974 const char *format = NULL;
5976 /* Pick the proper format string */
5977 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
5979 format = "%" G_GINT64_MODIFIER "d";
5982 format = "%" G_GINT64_MODIFIER "d (0x%016" G_GINT64_MODIFIER "x)";
5984 case BASE_OCT: /* I'm lazy */
5985 format = "%#" G_GINT64_MODIFIER "o";
5988 format = "0x%016" G_GINT64_MODIFIER "x";
5991 format = "0x%016" G_GINT64_MODIFIER "x (%" G_GINT64_MODIFIER "d)";
5994 DISSECTOR_ASSERT_NOT_REACHED();
6001 proto_registrar_n(void)
6003 return gpa_hfinfo.len;
6007 proto_registrar_get_name(const int n)
6009 header_field_info *hfinfo;
6011 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6012 return hfinfo->name;
6016 proto_registrar_get_abbrev(const int n)
6018 header_field_info *hfinfo;
6020 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6021 return hfinfo->abbrev;
6025 proto_registrar_get_ftype(const int n)
6027 header_field_info *hfinfo;
6029 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6030 return hfinfo->type;
6034 proto_registrar_get_parent(const int n)
6036 header_field_info *hfinfo;
6038 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6039 return hfinfo->parent;
6043 proto_registrar_is_protocol(const int n)
6045 header_field_info *hfinfo;
6047 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6048 return (hfinfo->parent == -1 ? TRUE : FALSE);
6051 /* Returns length of field in packet (not necessarily the length
6052 * in our internal representation, as in the case of IPv4).
6053 * 0 means undeterminable at time of registration
6054 * -1 means the field is not registered. */
6056 proto_registrar_get_length(const int n)
6058 header_field_info *hfinfo;
6060 PROTO_REGISTRAR_GET_NTH(n, hfinfo);
6061 return ftype_length(hfinfo->type);
6064 /* Looks for a protocol or a field in a proto_tree. Returns TRUE if
6065 * it exists anywhere, or FALSE if it exists nowhere. */
6067 proto_check_for_protocol_or_field(const proto_tree* tree, const int id)
6069 GPtrArray *ptrs = proto_get_finfo_ptr_array(tree, id);
6074 else if (g_ptr_array_len(ptrs) > 0) {
6082 /* Return GPtrArray* of field_info pointers for all hfindex that appear in tree.
6083 * This only works if the hfindex was "primed" before the dissection
6084 * took place, as we just pass back the already-created GPtrArray*.
6085 * The caller should *not* free the GPtrArray*; proto_tree_free_node()
6088 proto_get_finfo_ptr_array(const proto_tree *tree, const int id)
6093 if (PTREE_DATA(tree)->interesting_hfids != NULL)
6094 return (GPtrArray *)g_hash_table_lookup(PTREE_DATA(tree)->interesting_hfids,
6095 GINT_TO_POINTER(id));
6101 proto_tracking_interesting_fields(const proto_tree *tree)
6106 return (PTREE_DATA(tree)->interesting_hfids != NULL);
6109 /* Helper struct for proto_find_info() and proto_all_finfos() */
6115 /* Helper function for proto_find_info() */
6117 find_finfo(proto_node *node, gpointer data)
6119 field_info *fi = PNODE_FINFO(node);
6120 if (fi && fi->hfinfo) {
6121 if (fi->hfinfo->id == ((ffdata_t*)data)->id) {
6122 g_ptr_array_add(((ffdata_t*)data)->array, fi);
6126 /* Don't stop traversing. */
6130 /* Return GPtrArray* of field_info pointers for all hfindex that appear in a tree.
6131 * This works on any proto_tree, primed or unprimed, but actually searches
6132 * the tree, so it is slower than using proto_get_finfo_ptr_array on a primed tree.
6133 * The caller does need to free the returned GPtrArray with
6134 * g_ptr_array_free(<array>, TRUE).
6137 proto_find_finfo(proto_tree *tree, const int id)
6141 ffdata.array = g_ptr_array_new();
6144 proto_tree_traverse_pre_order(tree, find_finfo, &ffdata);
6146 return ffdata.array;
6149 /* Helper function for proto_all_finfos() */
6151 every_finfo(proto_node *node, gpointer data)
6153 field_info *fi = PNODE_FINFO(node);
6154 if (fi && fi->hfinfo) {
6155 g_ptr_array_add(((ffdata_t*)data)->array, fi);
6158 /* Don't stop traversing. */
6162 /* Return GPtrArray* of field_info pointers containing all hfindexes that appear in a tree. */
6164 proto_all_finfos(proto_tree *tree)
6168 ffdata.array = g_ptr_array_new();
6171 proto_tree_traverse_pre_order(tree, every_finfo, &ffdata);
6173 return ffdata.array;
6184 check_for_offset(proto_node *node, const gpointer data)
6186 field_info *fi = PNODE_FINFO(node);
6187 offset_search_t *offsearch = (offset_search_t *)data;
6189 /* !fi == the top most container node which holds nothing */
6190 if (fi && !PROTO_ITEM_IS_HIDDEN(node) && fi->ds_tvb && offsearch->tvb == fi->ds_tvb) {
6191 if (offsearch->offset >= (guint) fi->start &&
6192 offsearch->offset < (guint) (fi->start + fi->length)) {
6194 offsearch->finfo = fi;
6195 return FALSE; /* keep traversing */
6198 return FALSE; /* keep traversing */
6201 /* Search a proto_tree backwards (from leaves to root) looking for the field
6202 * whose start/length occupies 'offset' */
6203 /* XXX - I couldn't find an easy way to search backwards, so I search
6204 * forwards, w/o stopping. Therefore, the last finfo I find will the be
6205 * the one I want to return to the user. This algorithm is inefficient
6206 * and could be re-done, but I'd have to handle all the children and
6207 * siblings of each node myself. When I have more time I'll do that.
6210 proto_find_field_from_offset(proto_tree *tree, guint offset, tvbuff_t *tvb)
6212 offset_search_t offsearch;
6214 offsearch.offset = offset;
6215 offsearch.finfo = NULL;
6216 offsearch.tvb = tvb;
6218 proto_tree_traverse_pre_order(tree, check_for_offset, &offsearch);
6220 return offsearch.finfo;
6223 /* Dumps the protocols in the registration database to stdout. An independent
6224 * program can take this output and format it into nice tables or HTML or
6227 * There is one record per line. The fields are tab-delimited.
6229 * Field 1 = protocol name
6230 * Field 2 = protocol short name
6231 * Field 3 = protocol filter name
6234 proto_registrar_dump_protocols(void)
6236 protocol_t *protocol;
6238 void *cookie = NULL;
6241 i = proto_get_first_protocol(&cookie);
6243 protocol = find_protocol_by_id(i);
6244 printf("%s\t%s\t%s\n", protocol->name, protocol->short_name,
6245 protocol->filter_name);
6246 i = proto_get_next_protocol(&cookie);
6250 /* Dumps the value_strings, extended value string headers, range_strings
6251 * or true/false strings for fields that have them.
6252 * There is one record per line. Fields are tab-delimited.
6253 * There are four types of records: Value String, Extended Value String Header,
6254 * Range String and True/False String. The first field, 'V', 'E', 'R' or 'T', indicates
6255 * the type of record.
6257 * Note that a record will be generated only if the value_string,... is referenced
6258 * in a registered hfinfo entry.
6264 * Field 2 = Field abbreviation to which this value string corresponds
6265 * Field 3 = Integer value
6268 * Extended Value String Headers
6269 * -----------------------------
6271 * Field 2 = Field abbreviation to which this extended value string header corresponds
6272 * Field 3 = Extended Value String "Name"
6273 * Field 4 = Number of entries in the associated value_string array
6274 * Field 5 = Access Type: "Linear Search", "Binary Search", "Direct (indexed) Access"
6279 * Field 2 = Field abbreviation to which this range string corresponds
6280 * Field 3 = Integer value: lower bound
6281 * Field 4 = Integer value: upper bound
6284 * True/False Strings
6285 * ------------------
6287 * Field 2 = Field abbreviation to which this true/false string corresponds
6288 * Field 3 = True String
6289 * Field 4 = False String
6292 proto_registrar_dump_values(void)
6294 header_field_info *hfinfo;
6296 const value_string *vals;
6297 const val64_string *vals64;
6298 const range_string *range;
6299 const true_false_string *tfs;
6301 len = gpa_hfinfo.len;
6302 for (i = 0; i < len ; i++) {
6303 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6305 if (hfinfo->id == hf_text_only) {
6309 /* ignore protocols */
6310 if (proto_registrar_is_protocol(i)) {
6313 /* process header fields */
6316 * If this field isn't at the head of the list of
6317 * fields with this name, skip this field - all
6318 * fields with the same name are really just versions
6319 * of the same field stored in different bits, and
6320 * should have the same type/radix/value list, and
6321 * just differ in their bit masks. (If a field isn't
6322 * a bitfield, but can be, say, 1 or 2 bytes long,
6323 * it can just be made FT_UINT16, meaning the
6324 * *maximum* length is 2 bytes, and be used
6327 if (hfinfo->same_name_prev_id != -1)
6335 if (hfinfo->strings != NULL) {
6336 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) != BASE_CUSTOM &&
6337 (hfinfo->type == FT_UINT8 ||
6338 hfinfo->type == FT_UINT16 ||
6339 hfinfo->type == FT_UINT24 ||
6340 hfinfo->type == FT_UINT32 ||
6341 hfinfo->type == FT_UINT64 ||
6342 hfinfo->type == FT_INT8 ||
6343 hfinfo->type == FT_INT16 ||
6344 hfinfo->type == FT_INT24 ||
6345 hfinfo->type == FT_INT32 ||
6346 hfinfo->type == FT_INT64)) {
6348 if (hfinfo->display & BASE_RANGE_STRING) {
6349 range = (const range_string *)hfinfo->strings;
6350 } else if (hfinfo->display & BASE_EXT_STRING) {
6351 vals = VALUE_STRING_EXT_VS_P((const value_string_ext *)hfinfo->strings);
6352 } else if (hfinfo->display & BASE_VAL64_STRING) {
6353 vals64 = (const val64_string *)hfinfo->strings;
6355 vals = (const value_string *)hfinfo->strings;
6358 else if (hfinfo->type == FT_BOOLEAN) {
6359 tfs = (const struct true_false_string *)hfinfo->strings;
6363 /* Print value strings? */
6365 if (hfinfo->display & BASE_EXT_STRING) {
6366 const value_string_ext *vse_p = (const value_string_ext *)hfinfo->strings;
6367 if (!value_string_ext_validate(vse_p)) {
6368 g_warning("Invalid value_string_ext ptr for: %s", hfinfo->abbrev);
6371 try_val_to_str_ext(0, vse_p); /* "prime" the extended value_string */
6372 printf("E\t%s\t%d\t%s\t%s\n",
6374 VALUE_STRING_EXT_VS_NUM_ENTRIES(vse_p),
6375 VALUE_STRING_EXT_VS_NAME(vse_p),
6376 value_string_ext_match_type_str(vse_p));
6379 while (vals[vi].strptr) {
6380 /* Print in the proper base */
6381 if (hfinfo->display == BASE_HEX) {
6382 printf("V\t%s\t0x%x\t%s\n",
6388 printf("V\t%s\t%u\t%s\n",
6398 while (vals64[vi].strptr) {
6399 printf("V64\t%s\t%" G_GINT64_MODIFIER "u\t%s\n",
6407 /* print range strings? */
6410 while (range[vi].strptr) {
6411 /* Print in the proper base */
6412 if ((hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_HEX) {
6413 printf("R\t%s\t0x%x\t0x%x\t%s\n",
6415 range[vi].value_min,
6416 range[vi].value_max,
6420 printf("R\t%s\t%u\t%u\t%s\n",
6422 range[vi].value_min,
6423 range[vi].value_max,
6430 /* Print true/false strings? */
6432 printf("T\t%s\t%s\t%s\n", hfinfo->abbrev,
6433 tfs->true_string, tfs->false_string);
6439 /* Dumps the contents of the registration database to stdout. An independent
6440 * program can take this output and format it into nice tables or HTML or
6443 * There is one record per line. Each record is either a protocol or a header
6444 * field, differentiated by the first field. The fields are tab-delimited.
6449 * Field 2 = descriptive protocol name
6450 * Field 3 = protocol abbreviation
6455 * Field 2 = descriptive field name
6456 * Field 3 = field abbreviation
6457 * Field 4 = type ( textual representation of the the ftenum type )
6458 * Field 5 = parent protocol abbreviation
6459 * Field 6 = base for display (for integer types); "parent bitfield width" for FT_BOOLEAN
6460 * Field 7 = bitmask: format: hex: 0x....
6461 * Field 8 = blurb describing field
6464 proto_registrar_dump_fields(void)
6466 header_field_info *hfinfo, *parent_hfinfo;
6468 const char *enum_name;
6469 const char *base_name;
6473 len = gpa_hfinfo.len;
6474 for (i = 0; i < len ; i++) {
6475 PROTO_REGISTRAR_GET_NTH(i, hfinfo);
6478 * Skip the pseudo-field for "proto_tree_add_text()" since
6479 * we don't want it in the list of filterable fields.
6481 if (hfinfo->id == hf_text_only)
6484 /* format for protocols */
6485 if (proto_registrar_is_protocol(i)) {
6486 printf("P\t%s\t%s\n", hfinfo->name, hfinfo->abbrev);
6488 /* format for header fields */
6491 * If this field isn't at the head of the list of
6492 * fields with this name, skip this field - all
6493 * fields with the same name are really just versions
6494 * of the same field stored in different bits, and
6495 * should have the same type/radix/value list, and
6496 * just differ in their bit masks. (If a field isn't
6497 * a bitfield, but can be, say, 1 or 2 bytes long,
6498 * it can just be made FT_UINT16, meaning the
6499 * *maximum* length is 2 bytes, and be used
6502 if (hfinfo->same_name_prev_id != -1)
6505 PROTO_REGISTRAR_GET_NTH(hfinfo->parent, parent_hfinfo);
6507 enum_name = ftype_name(hfinfo->type);
6510 if (hfinfo->type == FT_UINT8 ||
6511 hfinfo->type == FT_UINT16 ||
6512 hfinfo->type == FT_UINT24 ||
6513 hfinfo->type == FT_UINT32 ||
6514 hfinfo->type == FT_UINT64 ||
6515 hfinfo->type == FT_INT8 ||
6516 hfinfo->type == FT_INT16 ||
6517 hfinfo->type == FT_INT24 ||
6518 hfinfo->type == FT_INT32 ||
6519 hfinfo->type == FT_INT64) {
6521 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
6523 base_name = "BASE_NONE";
6526 base_name = "BASE_DEC";
6529 base_name = "BASE_HEX";
6532 base_name = "BASE_OCT";
6535 base_name = "BASE_DEC_HEX";
6538 base_name = "BASE_HEX_DEC";
6541 base_name = "BASE_CUSTOM";
6547 } else if (hfinfo->type == FT_BOOLEAN) {
6548 /* For FT_BOOLEAN: 'display' can be "parent bitfield width" */
6549 g_snprintf(width, sizeof(width), "%d", hfinfo->display);
6553 blurb = hfinfo->blurb;
6556 else if (strlen(blurb) == 0)
6559 printf("F\t%s\t%s\t%s\t%s\t%s\t0x%x\t%s\n",
6560 hfinfo->name, hfinfo->abbrev, enum_name,
6561 parent_hfinfo->abbrev, base_name, hfinfo->bitmask, blurb);
6566 /* Dumps field types and descriptive names to stdout. An independent
6567 * program can take this output and format it into nice tables or HTML or
6570 * There is one record per line. The fields are tab-delimited.
6572 * Field 1 = field type name, e.g. FT_UINT8
6573 * Field 2 = descriptive name, e.g. "Unsigned, 1 byte"
6576 proto_registrar_dump_ftypes(void)
6580 for (fte = 0; fte < FT_NUM_TYPES; fte++) {
6581 printf("%s\t%s\n", ftype_name((ftenum_t)fte), ftype_pretty_name((ftenum_t)fte));
6586 hfinfo_numeric_format(const header_field_info *hfinfo)
6588 const char *format = NULL;
6590 /* Get the underlying BASE_ value */
6591 switch (hfinfo->display & FIELD_DISPLAY_E_MASK) {
6594 case BASE_OCT: /* I'm lazy */
6596 switch (hfinfo->type) {
6598 format = "%s == %" G_GINT64_MODIFIER "u";
6601 format = "%s == %" G_GINT64_MODIFIER "d";
6604 DISSECTOR_ASSERT_NOT_REACHED();
6610 switch (hfinfo->type) {
6613 format = "%s == 0x%016" G_GINT64_MODIFIER "x";
6616 DISSECTOR_ASSERT_NOT_REACHED();
6621 DISSECTOR_ASSERT_NOT_REACHED();
6627 /* This function indicates whether it's possible to construct a
6628 * "match selected" display filter string for the specified field,
6629 * returns an indication of whether it's possible, and, if it's
6630 * possible and "filter" is non-null, constructs the filter and
6631 * sets "*filter" to point to it.
6632 * You do not need to [g_]free() this string since it will be automatically
6633 * freed once the next packet is dissected.
6636 construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
6639 header_field_info *hfinfo;
6644 gint start, length, length_remaining;
6646 gchar is_signed_num = FALSE;
6651 hfinfo = finfo->hfinfo;
6652 DISSECTOR_ASSERT(hfinfo);
6653 abbrev_len = (int) strlen(hfinfo->abbrev);
6655 if (hfinfo->strings && (hfinfo->display & FIELD_DISPLAY_E_MASK) == BASE_NONE) {
6656 const gchar *str = NULL;
6658 switch (hfinfo->type) {
6664 str = hf_try_val_to_str(fvalue_get_sinteger(&finfo->value), hfinfo);
6671 str = hf_try_val_to_str(fvalue_get_uinteger(&finfo->value), hfinfo);
6678 if (str != NULL && filter != NULL) {
6679 *filter = ep_strdup_printf("%s == \"%s\"", hfinfo->abbrev, str);
6685 * XXX - we can't use the "val_to_string_repr" and "string_repr_len"
6686 * functions for FT_UINT and FT_INT types, as we choose the base in
6687 * the string expression based on the display base of the field.
6689 * Note that the base does matter, as this is also used for
6690 * the protocolinfo tap.
6692 * It might be nice to use them in "proto_item_fill_label()"
6693 * as well, although, there, you'd have to deal with the base
6694 * *and* with resolved values for addresses.
6696 * Perhaps we need two different val_to_string routines, one
6697 * to generate items for display filters and one to generate
6698 * strings for display, and pass to both of them the
6699 * "display" and "strings" values in the header_field_info
6700 * structure for the field, so they can get the base and,
6701 * if the field is Boolean or an enumerated integer type,
6702 * the tables used to generate human-readable values.
6704 switch (hfinfo->type) {
6710 is_signed_num = TRUE;
6717 if (filter != NULL) {
6724 number = fvalue_get_sinteger(&finfo->value);
6726 number = fvalue_get_uinteger(&finfo->value);
6728 out = hfinfo_numeric_value_format(hfinfo, buf, number);
6730 *filter = ep_strdup_printf("%s == %s", hfinfo->abbrev, out);
6736 if (filter != NULL) {
6737 const char *format = hfinfo_numeric_format(hfinfo);
6739 *filter = ep_strdup_printf(format,
6741 fvalue_get_integer64(&finfo->value));
6747 *filter = ep_strdup(finfo->hfinfo->abbrev);
6752 * If the length is 0, just match the name of the
6755 * (Also check for negative values, just in case,
6756 * as we'll cast it to an unsigned value later.)
6758 length = finfo->length;
6761 *filter = ep_strdup(finfo->hfinfo->abbrev);
6768 * This doesn't have a value, so we'd match
6769 * on the raw bytes at this address.
6771 * Should we be allowed to access to the raw bytes?
6772 * If "edt" is NULL, the answer is "no".
6778 * Is this field part of the raw frame tvbuff?
6779 * If not, we can't use "frame[N:M]" to match
6782 * XXX - should this be frame-relative, or
6783 * protocol-relative?
6785 * XXX - does this fallback for non-registered
6786 * fields even make sense?
6788 if (finfo->ds_tvb != edt->tvb)
6789 return FALSE; /* you lose */
6792 * Don't go past the end of that tvbuff.
6794 length_remaining = tvb_length_remaining(finfo->ds_tvb, finfo->start);
6795 if (length > length_remaining)
6796 length = length_remaining;
6800 if (filter != NULL) {
6801 start = finfo->start;
6802 buf_len = 32 + length * 3;
6803 *filter = (char *)ep_alloc0(buf_len);
6806 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)),
6807 "frame[%d:%d] == ", finfo->start, length);
6808 for (i=0; i<length; i++) {
6809 c = tvb_get_guint8(finfo->ds_tvb, start);
6812 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), "%02x", c);
6815 ptr += g_snprintf(ptr, (gulong) (buf_len-(ptr-*filter)), ":%02x", c);
6822 /* FT_PCRE never appears as a type for a registered field. It is
6823 * only used internally. */
6824 DISSECTOR_ASSERT_NOT_REACHED();
6827 /* By default, use the fvalue's "to_string_repr" method. */
6829 /* Figure out the string length needed.
6830 * The ft_repr length.
6831 * 4 bytes for " == ".
6832 * 1 byte for trailing NUL.
6834 if (filter != NULL) {
6835 dfilter_len = fvalue_string_repr_len(&finfo->value,
6837 dfilter_len += abbrev_len + 4 + 1;
6838 *filter = (char *)ep_alloc0(dfilter_len);
6840 /* Create the string */
6841 g_snprintf(*filter, dfilter_len, "%s == ",
6843 fvalue_to_string_repr(&finfo->value,
6845 &(*filter)[abbrev_len + 4]);
6854 * Returns TRUE if we can do a "match selected" on the field, FALSE
6858 proto_can_match_selected(field_info *finfo, epan_dissect_t *edt)
6860 return construct_match_selected_string(finfo, edt, NULL);
6863 /* This function attempts to construct a "match selected" display filter
6864 * string for the specified field; if it can do so, it returns a pointer
6865 * to the string, otherwise it returns NULL.
6867 * The string is allocated with packet lifetime scope.
6868 * You do not need to [g_]free() this string since it will be automatically
6869 * freed once the next packet is dissected.
6872 proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
6876 if (!construct_match_selected_string(finfo, edt, &filter))
6881 /* This function is common code for both proto_tree_add_bitmask() and
6882 * proto_tree_add_bitmask_text() functions.
6885 /* NOTE: to support code written when proto_tree_add_bitmask() and
6886 * proto_tree_add_bitmask_text took a
6887 * gboolean as its last argument, with FALSE meaning "big-endian"
6888 * and TRUE meaning "little-endian", we treat any non-zero value of
6889 * "encoding" as meaning "little-endian".
6892 proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
6893 const int len, const gint ett, const int **fields,
6894 const guint encoding, const int flags,
6898 guint32 available_bits = 0;
6900 proto_tree *tree = NULL;
6901 header_field_info *hf;
6905 value = tvb_get_guint8(tvb, offset);
6906 available_bits = 0xFF;
6909 value = encoding ? tvb_get_letohs(tvb, offset) :
6910 tvb_get_ntohs(tvb, offset);
6911 available_bits = 0xFFFF;
6914 value = encoding ? tvb_get_letoh24(tvb, offset) :
6915 tvb_get_ntoh24(tvb, offset);
6916 available_bits = 0xFFFFFF;
6919 value = encoding ? tvb_get_letohl(tvb, offset) :
6920 tvb_get_ntohl(tvb, offset);
6921 available_bits = 0xFFFFFFFF;
6924 g_assert_not_reached();
6927 tree = proto_item_add_subtree(item, ett);
6929 guint32 present_bits;
6930 hf = proto_registrar_get_nth(**fields);
6931 DISSECTOR_ASSERT(hf->bitmask != 0);
6933 /* Skip fields that aren't fully present */
6934 present_bits = available_bits & hf->bitmask;
6935 if (present_bits != hf->bitmask) {
6940 proto_tree_add_item(tree, **fields, tvb, offset, len, encoding);
6941 if (flags & BMT_NO_APPEND) {
6945 tmpval = (value & hf->bitmask) >> hfinfo_bitshift(hf);
6956 if (hf->display == BASE_CUSTOM) {
6957 gchar lbl[ITEM_LABEL_LENGTH];
6958 const custom_fmt_func_t fmtfunc = (const custom_fmt_func_t)hf->strings;
6960 DISSECTOR_ASSERT(fmtfunc);
6961 fmtfunc(lbl, tmpval);
6962 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6966 else if (hf->strings) {
6967 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6968 hf->name, hf_try_val_to_str_const(tmpval, hf, "Unknown"));
6971 else if (!(flags & BMT_NO_INT)) {
6976 proto_item_append_text(item, ", ");
6979 out = hfinfo_number_value_format(hf, buf, tmpval);
6980 proto_item_append_text(item, "%s: %s", hf->name, out);
6986 if (hf->strings && !(flags & BMT_NO_TFS)) {
6987 /* If we have true/false strings, emit full - otherwise messages
6989 const struct true_false_string *tfs =
6990 (const struct true_false_string *)hf->strings;
6993 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6994 hf->name, tfs->true_string);
6996 } else if (!(flags & BMT_NO_FALSE)) {
6997 proto_item_append_text(item, "%s%s: %s", first ? "" : ", ",
6998 hf->name, tfs->false_string);
7001 } else if (hf->bitmask & value) {
7002 /* If the flag is set, show the name */
7003 proto_item_append_text(item, "%s%s", first ? "" : ", ", hf->name);
7008 g_assert_not_reached();
7017 /* This function will dissect a sequence of bytes that describe a
7019 * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
7020 * This field will form an expansion under which the individual fields of the
7021 * bitmask is dissected and displayed.
7022 * This field must be of the type FT_[U]INT{8|16|24|32}.
7024 * fields is an array of pointers to int that lists all the fields of the
7025 * bitmask. These fields can be either of the type FT_BOOLEAN for flags
7026 * or another integer of the same type/size as hf_hdr with a mask specified.
7027 * This array is terminated by a NULL entry.
7029 * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
7030 * FT_integer fields that have a value_string attached will have the
7031 * matched string displayed on the expansion line.
7034 proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
7035 const guint offset, const int hf_hdr,
7036 const gint ett, const int **fields,
7037 const guint encoding)
7039 proto_item *item = NULL;
7040 header_field_info *hf;
7043 hf = proto_registrar_get_nth(hf_hdr);
7044 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
7045 len = ftype_length(hf->type);
7048 item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
7049 proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
7050 BMT_NO_INT|BMT_NO_TFS, FALSE);
7056 /* The same as proto_tree_add_bitmask(), but using a caller-supplied length.
7057 * This is intended to support bitmask fields whose lengths can vary, perhaps
7058 * as the underlying standard evolves over time.
7059 * With this API there is the possibility of being called to display more or
7060 * less data than the dissector was coded to support.
7061 * In such cases, it is assumed that bitmasks are extended on the MSb end.
7062 * Thus when presented with "too much" or "too little" data, MSbits will be
7063 * ignored or MSfields sacrificed.
7065 * Only fields for which all defined bits are available are displayed.
7068 proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb,
7069 const guint offset, const guint len, const int hf_hdr,
7070 const gint ett, const int **fields, struct expert_field* exp,
7071 const guint encoding)
7073 proto_item *item = NULL;
7074 header_field_info *hf;
7075 guint decodable_len;
7076 guint decodable_offset;
7077 guint32 decodable_value;
7079 hf = proto_registrar_get_nth(hf_hdr);
7080 DISSECTOR_ASSERT(IS_FT_INT(hf->type) || IS_FT_UINT(hf->type));
7082 decodable_offset = offset;
7083 decodable_len = MIN(len, (guint) ftype_length(hf->type));
7085 /* If we are ftype_length-limited,
7086 * make sure we decode as many LSBs as possible.
7088 if (encoding == ENC_BIG_ENDIAN) {
7089 decodable_offset += (len - decodable_len);
7093 decodable_value = get_uint_value(parent_tree, tvb, decodable_offset,
7094 decodable_len, encoding);
7096 /* The root item covers all the bytes even if we can't decode them all */
7097 item = proto_tree_add_uint(parent_tree, hf_hdr, tvb, offset, len,
7101 if (decodable_len < len) {
7102 /* Dissector likely requires updating for new protocol revision */
7103 expert_add_info_format(NULL, item, exp,
7104 "Only least-significant %d of %d bytes decoded",
7105 decodable_len, len);
7109 proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len,
7110 ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS, FALSE);
7116 /* The same as proto_tree_add_bitmask(), but using an arbitrary text as a top-level item */
7118 proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
7119 const guint offset, const guint len,
7120 const char *name, const char *fallback,
7121 const gint ett, const int **fields,
7122 const guint encoding, const int flags)
7124 proto_item *item = NULL;
7127 item = proto_tree_add_text(parent_tree, tvb, offset, len, "%s", name ? name : "");
7128 if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
7129 flags, TRUE) && fallback) {
7130 /* Still at first item - append 'fallback' text if any */
7131 proto_item_append_text(item, "%s", fallback);
7139 proto_tree_add_bits_item(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7140 const guint bit_offset, const gint no_of_bits,
7141 const guint encoding)
7143 header_field_info *hfinfo;
7147 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
7149 octet_length = (no_of_bits + 7) >> 3;
7150 octet_offset = bit_offset >> 3;
7151 test_length(hfinfo, tvb, octet_offset, octet_length);
7153 /* Yes, we try to fake this item again in proto_tree_add_bits_ret_val()
7154 * but only after doing a bunch more work (which we can, in the common
7155 * case, shortcut here).
7157 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hfinfo);
7159 return proto_tree_add_bits_ret_val(tree, hfindex, tvb, bit_offset, no_of_bits, NULL, encoding);
7163 * This function will dissect a sequence of bits that does not need to be byte aligned; the bits
7164 * set will be shown in the tree as ..10 10.. and the integer value returned if return_value is set.
7165 * Offset should be given in bits from the start of the tvb.
7169 _proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7170 const guint bit_offset, const gint no_of_bits,
7171 guint64 *return_value, const guint encoding)
7177 char lbl_str[ITEM_LABEL_LENGTH];
7181 header_field_info *hf_field;
7183 const true_false_string *tfstring;
7185 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7186 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
7188 if (hf_field->bitmask != 0) {
7189 REPORT_DISSECTOR_BUG(ep_strdup_printf("Incompatible use of proto_tree_add_bits_ret_val"
7190 " with field '%s' (%s) with bitmask != 0",
7191 hf_field->abbrev, hf_field->name));
7194 DISSECTOR_ASSERT(no_of_bits > 0);
7196 /* Byte align offset */
7197 offset = bit_offset>>3;
7200 * Calculate the number of octets used to hold the bits
7202 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7203 length = (tot_no_bits + 7) >> 3;
7205 if (no_of_bits < 65) {
7206 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, encoding);
7208 DISSECTOR_ASSERT_NOT_REACHED();
7212 /* Sign extend for signed types */
7213 switch (hf_field->type) {
7219 if (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1)))
7220 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7228 *return_value = value;
7231 /* Coast clear. Try and fake it */
7232 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7234 bf_str = decode_bits_in_field(bit_offset, no_of_bits, value);
7236 switch (hf_field->type) {
7239 tfstring = (const true_false_string *) &tfs_true_false;
7240 if (hf_field->strings)
7241 tfstring = (const true_false_string *)hf_field->strings;
7242 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, (guint32)value,
7244 bf_str, hf_field->name,
7245 (guint32)value ? tfstring->true_string : tfstring->false_string);
7252 pi = proto_tree_add_uint(tree, hfindex, tvb, offset, length, (guint32)value);
7253 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
7260 pi = proto_tree_add_int(tree, hfindex, tvb, offset, length, (gint32)value);
7261 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
7265 pi = proto_tree_add_uint64(tree, hfindex, tvb, offset, length, value);
7266 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
7270 pi = proto_tree_add_int64(tree, hfindex, tvb, offset, length, (gint64)value);
7271 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
7275 DISSECTOR_ASSERT_NOT_REACHED();
7280 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7285 proto_tree_add_split_bits_item_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7286 const guint bit_offset, const crumb_spec_t *crumb_spec,
7287 guint64 *return_value)
7292 guint mask_initial_bit_offset;
7293 guint mask_greatest_bit_offset;
7297 char lbl_str[ITEM_LABEL_LENGTH];
7299 guint64 composite_bitmask;
7300 guint64 composite_bitmap;
7302 header_field_info *hf_field;
7303 const true_false_string *tfstring;
7305 /* We can't fake it just yet. We have to fill in the 'return_value' parameter */
7306 PROTO_REGISTRAR_GET_NTH(hfindex, hf_field);
7308 if (hf_field->bitmask != 0) {
7309 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7310 "Incompatible use of proto_tree_add_split_bits_item_ret_val"
7311 " with field '%s' (%s) with bitmask != 0",
7312 hf_field->abbrev, hf_field->name));
7315 mask_initial_bit_offset = bit_offset % 8;
7320 mask_greatest_bit_offset = 0;
7321 composite_bitmask = 0;
7322 composite_bitmap = 0;
7324 while (crumb_spec[i].crumb_bit_length != 0) {
7325 guint64 crumb_mask, crumb_value;
7326 guint8 crumb_end_bit_offset;
7328 DISSECTOR_ASSERT(i < 64);
7329 crumb_value = tvb_get_bits64(tvb,
7330 bit_offset + crumb_spec[i].crumb_bit_offset,
7331 crumb_spec[i].crumb_bit_length,
7333 value += crumb_value;
7334 no_of_bits += crumb_spec[i].crumb_bit_length;
7336 /* The bitmask is 64 bit, left-aligned, starting at the first bit of the
7337 octet containing the initial offset.
7338 If the mask is beyond 32 bits, then give up on bit map display.
7339 This could be improved in future, probably showing a table
7340 of 32 or 64 bits per row */
7341 if (mask_greatest_bit_offset < 32) {
7342 crumb_end_bit_offset = mask_initial_bit_offset
7343 + crumb_spec[i].crumb_bit_offset
7344 + crumb_spec[i].crumb_bit_length;
7345 crumb_mask = (G_GUINT64_CONSTANT(1) << crumb_spec[i].crumb_bit_length) - 1;
7347 if (crumb_end_bit_offset > mask_greatest_bit_offset) {
7348 mask_greatest_bit_offset = crumb_end_bit_offset;
7350 composite_bitmask |= (crumb_mask << (64 - crumb_end_bit_offset));
7351 composite_bitmap |= (crumb_value << (64 - crumb_end_bit_offset));
7353 /* Shift left for the next segment */
7354 value <<= crumb_spec[++i].crumb_bit_length;
7357 /* Sign extend for signed types */
7358 switch (hf_field->type) {
7364 if (no_of_bits && (value & (G_GINT64_CONSTANT(1) << (no_of_bits-1))))
7365 value |= (G_GINT64_CONSTANT(-1) << no_of_bits);
7372 *return_value = value;
7375 /* Coast clear. Try and fake it */
7376 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7378 /* initialise the format string */
7379 bf_str = (char *)ep_alloc(256);
7382 octet_offset = bit_offset >> 3;
7384 /* Round up mask length to nearest octet */
7385 octet_length = ((mask_greatest_bit_offset + 7) >> 3);
7386 mask_greatest_bit_offset = octet_length << 3;
7388 /* As noted above, we currently only produce a bitmap if the crumbs span less than 4 octets of the tvb.
7389 It would be a useful enhancement to eliminate this restriction. */
7390 if (mask_greatest_bit_offset <= 32) {
7391 other_decode_bitfield_value(bf_str,
7392 (guint32)(composite_bitmap >> (64 - mask_greatest_bit_offset)),
7393 (guint32)(composite_bitmask >> (64 - mask_greatest_bit_offset)),
7394 mask_greatest_bit_offset);
7397 switch (hf_field->type) {
7398 case FT_BOOLEAN: /* it is a bit odd to have a boolean encoded as split-bits, but possible, I suppose? */
7400 tfstring = (const true_false_string *) &tfs_true_false;
7401 if (hf_field->strings)
7402 tfstring = (const true_false_string *) hf_field->strings;
7403 return proto_tree_add_boolean_format(tree, hfindex,
7404 tvb, octet_offset, octet_length, (guint32)value,
7406 bf_str, hf_field->name,
7407 (guint32)value ? tfstring->true_string : tfstring->false_string);
7414 pi = proto_tree_add_uint(tree, hfindex, tvb, octet_offset, octet_length, (guint32)value);
7415 fill_label_number(PITEM_FINFO(pi), lbl_str, FALSE);
7422 pi = proto_tree_add_int(tree, hfindex, tvb, octet_offset, octet_length, (gint32)value);
7423 fill_label_number(PITEM_FINFO(pi), lbl_str, TRUE);
7427 pi = proto_tree_add_uint64(tree, hfindex, tvb, octet_offset, octet_length, value);
7428 fill_label_number64(PITEM_FINFO(pi), lbl_str, FALSE);
7432 pi = proto_tree_add_int64(tree, hfindex, tvb, octet_offset, octet_length, (gint64)value);
7433 fill_label_number64(PITEM_FINFO(pi), lbl_str, TRUE);
7437 DISSECTOR_ASSERT_NOT_REACHED();
7441 proto_item_set_text(pi, "%s = %s", bf_str, lbl_str);
7446 proto_tree_add_split_bits_crumb(proto_tree *tree, const int hfindex, tvbuff_t *tvb, const guint bit_offset,
7447 const crumb_spec_t *crumb_spec, guint16 crumb_index)
7449 header_field_info *hfinfo;
7451 PROTO_REGISTRAR_GET_NTH(hfindex, hfinfo);
7452 proto_tree_add_text(tree, tvb,
7454 ((bit_offset + crumb_spec[crumb_index].crumb_bit_length - 1) >> 3) - (bit_offset >> 3) + 1,
7455 "%s crumb %d of %s (decoded above)",
7456 decode_bits_in_field(bit_offset, crumb_spec[crumb_index].crumb_bit_length,
7459 crumb_spec[crumb_index].crumb_bit_length,
7466 proto_tree_add_bits_ret_val(proto_tree *tree, const int hfindex, tvbuff_t *tvb,
7467 const guint bit_offset, const gint no_of_bits,
7468 guint64 *return_value, const guint encoding)
7472 if ((item = _proto_tree_add_bits_ret_val(tree, hfindex, tvb,
7473 bit_offset, no_of_bits,
7474 return_value, encoding))) {
7475 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7476 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7482 _proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
7483 tvbuff_t *tvb, const guint bit_offset,
7484 const gint no_of_bits, void *value_ptr,
7492 header_field_info *hf_field;
7494 /* We do not have to return a value, try to fake it as soon as possible */
7495 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7497 if (hf_field->bitmask != 0) {
7498 REPORT_DISSECTOR_BUG(ep_strdup_printf(
7499 "Incompatible use of proto_tree_add_bits_format_value"
7500 " with field '%s' (%s) with bitmask != 0",
7501 hf_field->abbrev, hf_field->name));
7504 DISSECTOR_ASSERT(no_of_bits > 0);
7506 /* Byte align offset */
7507 offset = bit_offset>>3;
7510 * Calculate the number of octets used to hold the bits
7512 tot_no_bits = ((bit_offset&0x7) + no_of_bits);
7513 length = tot_no_bits>>3;
7514 /* If we are using part of the next octet, increase length by 1 */
7515 if (tot_no_bits & 0x07)
7518 if (no_of_bits < 65) {
7519 value = tvb_get_bits64(tvb, bit_offset, no_of_bits, ENC_BIG_ENDIAN);
7521 DISSECTOR_ASSERT_NOT_REACHED();
7525 str = decode_bits_in_field(bit_offset, no_of_bits, value);
7528 strcat(str, hf_field->name);
7531 * This function does not receive an actual value but a dimensionless pointer to that value.
7532 * For this reason, the type of the header field is examined in order to determine
7533 * what kind of value we should read from this address.
7534 * The caller of this function must make sure that for the specific header field type the address of
7535 * a compatible value is provided.
7537 switch (hf_field->type) {
7539 return proto_tree_add_boolean_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
7540 "%s: %s", str, value_str);
7547 return proto_tree_add_uint_format(tree, hfindex, tvb, offset, length, *(guint32 *)value_ptr,
7548 "%s: %s", str, value_str);
7552 return proto_tree_add_uint64_format(tree, hfindex, tvb, offset, length, *(guint64 *)value_ptr,
7553 "%s: %s", str, value_str);
7560 return proto_tree_add_int_format(tree, hfindex, tvb, offset, length, *(gint32 *)value_ptr,
7561 "%s: %s", str, value_str);
7565 return proto_tree_add_int64_format(tree, hfindex, tvb, offset, length, *(gint64 *)value_ptr,
7566 "%s: %s", str, value_str);
7570 return proto_tree_add_float_format(tree, hfindex, tvb, offset, length, *(float *)value_ptr,
7571 "%s: %s", str, value_str);
7575 DISSECTOR_ASSERT_NOT_REACHED();
7582 proto_tree_add_bits_format_value(proto_tree *tree, const int hfindex,
7583 tvbuff_t *tvb, const guint bit_offset,
7584 const gint no_of_bits, void *value_ptr,
7589 if ((item = _proto_tree_add_bits_format_value(tree, hfindex,
7590 tvb, bit_offset, no_of_bits,
7591 value_ptr, value_str))) {
7592 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_OFFSET(bit_offset));
7593 FI_SET_FLAG(PNODE_FINFO(item), FI_BITS_SIZE(no_of_bits));
7598 #define CREATE_VALUE_STRING(dst,format,ap) \
7599 va_start(ap, format); \
7600 dst = ep_strdup_vprintf(format, ap); \
7604 proto_tree_add_uint_bits_format_value(proto_tree *tree, const int hfindex,
7605 tvbuff_t *tvb, const guint bit_offset,
7606 const gint no_of_bits, guint32 value,
7607 const char *format, ...)
7611 header_field_info *hf_field;
7613 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7615 switch (hf_field->type) {
7623 DISSECTOR_ASSERT_NOT_REACHED();
7628 CREATE_VALUE_STRING(dst, format, ap);
7630 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7634 proto_tree_add_float_bits_format_value(proto_tree *tree, const int hfindex,
7635 tvbuff_t *tvb, const guint bit_offset,
7636 const gint no_of_bits, float value,
7637 const char *format, ...)
7641 header_field_info *hf_field;
7643 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7645 DISSECTOR_ASSERT(hf_field->type == FT_FLOAT);
7647 CREATE_VALUE_STRING(dst, format, ap);
7649 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7653 proto_tree_add_int_bits_format_value(proto_tree *tree, const int hfindex,
7654 tvbuff_t *tvb, const guint bit_offset,
7655 const gint no_of_bits, gint32 value,
7656 const char *format, ...)
7660 header_field_info *hf_field;
7662 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7664 switch (hf_field->type) {
7672 DISSECTOR_ASSERT_NOT_REACHED();
7677 CREATE_VALUE_STRING(dst, format, ap);
7679 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7683 proto_tree_add_boolean_bits_format_value(proto_tree *tree, const int hfindex,
7684 tvbuff_t *tvb, const guint bit_offset,
7685 const gint no_of_bits, guint32 value,
7686 const char *format, ...)
7690 header_field_info *hf_field;
7692 TRY_TO_FAKE_THIS_ITEM(tree, hfindex, hf_field);
7694 DISSECTOR_ASSERT(hf_field->type == FT_BOOLEAN);
7696 CREATE_VALUE_STRING(dst, format, ap);
7698 return proto_tree_add_bits_format_value(tree, hfindex, tvb, bit_offset, no_of_bits, &value, dst);
7702 proto_check_field_name(const gchar *field_name)
7704 return wrs_check_charset(fld_abbrev_chars, field_name);
7708 tree_expanded(int tree_type)
7710 g_assert(tree_type >= 0 && tree_type < num_tree_types);
7711 return tree_is_expanded[tree_type >> 5] & (1 << (tree_type & 31));
7715 tree_expanded_set(int tree_type, gboolean value)
7717 g_assert(tree_type >= 0 && tree_type < num_tree_types);
7720 tree_is_expanded[tree_type >> 5] |= (1 << (tree_type & 31));
7722 tree_is_expanded[tree_type >> 5] &= ~(1 << (tree_type & 31));
7726 * Editor modelines - http://www.wireshark.org/tools/modelines.html
7731 * indent-tabs-mode: t
7734 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
7735 * :indentSize=8:tabSize=8:noTabs=false: